By Nick McIntyre, Jason Alderman, Tega Brain, Taeyoon Choi, Luisa Pereira, Layla Quiñones, Portia Morrell
デバッグ
これは、コーディングを始めたばかりの人から長年コーディングを行っている人まで、すべての人のためのデバッグフィールドガイドです。コードの問題を解決する神秘的なプロセスを分解します。
0. デバッグは創造的な行為です
あらゆるレベルのプログラマーがバグに遭遇し、多くの場合、実際のアプリケーションのプログラミングよりもデバッグに多くの時間を費やします。これに多くの時間を費やすことを予想しておくべきです。p5.jsでプログラミングを学ぶ際に、バグを特定し、それに取り組むための良い戦略を開発することが重要です。
バグとは、あなたのシステムが行っていると思っていることと、実際に行っていることとの間のギャップです。Clay Shirkyは適切に説明しています。バグとは、「コードに技術的な問題があると同時に、コードで何が起こっているかについてのあなたの心的イメージにも問題がある瞬間」です。
あなたはコンピューターに一つのことを指示していると思っていますが、コンピューターは別のことを行っています。クラッシュしたりエラーを投げたりしているかもしれません。このギャップを埋めるために調査する必要があります。
プロジェクトに取り組む際、あなたは多くの異なる役割を果たすかもしれません。プログラムを設計し計画する際には建築家であり、それを開発する際にはエンジニアです。そして、その問題やエラーを発見する探検家になります。あなたのコードが動作する必要があるすべての状況でテストし、どこで壊れる可能性があるかを見つけようとします。最後に、あなたは探偵でもあり、どのようにしてなぜ物事が失敗したかを突き止めようとします。
では、どうすれば優れた探偵になり、プログラムをデバッグできるでしょうか?以下に、優れたコード探偵になるための10のステップを紹介します。
1. 視点を変える
パニックにならないでください。
解決方法がわからないバグに遭遇したら、立ち止まり、一息つき、深呼吸をしてください。立ち上がって、ペットに挨拶したり、散歩に行ったり、夜遅い場合は少し休んだりしてください。フラストレーションがたまっていたり、疲れていたり、動揺していたりすると、学習や問題解決に適した心理状態ではありません。
エラーを見つけるためには、視点を変えて探偵になる必要があります。目標は、プログラムがなぜ期待通りに動作しないかを知ることではなく、実際に何をしているかを知ることです。 コンピューターに何をしているかを示してもらう必要があります。
手がかりは、変数の値とプログラムの流れの中にあります。
2. 問題を観察する
たとえその人自身がプログラミングを知らなくても、誰かに問題について説明してみてください。誰もいない場合は、信頼できる人にメールやダイレクトメッセージを下書きしてみてください。あなたが書いたコードを詳細に説明し、プログラムを実行したときに何が起こるかを説明し、遭遇した問題を分解してください。
このメールを実際に送る必要はないでしょう!多くの場合、書くという行為が次に何をすべきかを特定し、識別するのに役立ちます。プログラマーの中には、ゴム製のアヒルのような親しみやすい無生物に問題を説明することで知られている人もいます。
これは、コードに各行が何をするかを正確に説明するコメントを追加するのにも良い機会です。コーダーの中には、コード(またはその一部)を印刷し、1行ずつ変数の変化をたどりながらメモを取る人もいます。
3. 変更を加える前に…
コードに何かを行う前に、元に戻せるコピーを保存してください。デバッグ中に他の問題を引き起こしたり、物事を壊したり、良い作業を誤って削除したりする可能性があります。
デバッグの過程でより大きなバグを作りたくはありません。
間違いを犯したり問題が悪化したりした場合は、常に元に戻すか保存したファイルに戻ることができます。
GitHubのようなバージョン管理を試すこともできます。
試していることのリストを書いて、まだチェックする必要があるものを追跡できるようにしてください。体系的に行動することで、長期的には多くの時間を節約できます。
一度に1つのことだけを変更してください。
デバッグ中は、コードの一部をオンオフにすることになります。変更するたびに、プログラムをテストしてください。テストする前に複数の変更を加えると、どの変更がどのような効果を持つかを判断するのが難しくなり、さらに物事を壊す可能性が高くなります。
4. 基本をチェックする
多くのバグは、家電製品の電源コードを差し忘れるような非常に基本的なミスであることがよくあります!これらのミスはしばしば「見えない」もので、チェックする必要があります。以下のような単純なことをチェックしてください:
正しいファイルを編集していますか?
基本的なスケッチでは、通常sketch.jsファイルにコードを書きます。他のプロジェクトでは、他のファイルにもコードを書くかもしれないので、プロセスの様々な段階で正しいファイルを編集し保存していることを確認してください。
ファイルの依存関係は正しいですか?
基本的なスケッチは、コンピューターにインストールされているか、p5.jsプロジェクトのHTMLファイルにリンクされているp5.jsのバージョンに依存しています。他のライブラリを使用する場合は、それらがHTMLファイルにリンクされているか、コンピューターに適切に保存されていることを確認してください。
ファイルパスにタイプミスはありませんか?
ファイルの読み書きや他のライブラリの含め方をチェックする際、ファイルパスやURLのスペルミスがないか確認してください。プロジェクトでファイルをアップロードして使用する際は、スペルミスの可能性を減らすために、シンプルなファイル名を使用してください。アップロードしているファイルの種類が、使用している関数と一致していることを再確認してください。
すべての外部ファイルとサービスにアクセスできますか?
インターネット接続に影響を与えている可能性のあるネットワークの問題がないか確認してください。ローカルサーバーで作業している場合、プロジェクトで使用するための正しいファイルに、すべての外部ライブラリが正しくインストールされていることを確認してください。APIエンドポイント、リンク、URL、ファイルパスがすべて正しいことを、基本的なプログラムでテストして確認してください。
5. ブラックボックスをチェックする
ブラックボックスとは、システムの中で内部の仕組みを理解していない部分のことを指します。例えば、あなたが書いておらず、1行ずつ説明できない関数は、ブラックボックスと見なすことができます。特定の入力が特定の出力を生成する理由がわからない場合、あなたは本当にそのコードを理解していないのです。これらをチェックするには、各ブラックボックスを1つずつ体系的に取り除いてプログラムを実行してください。
6. エラー報告を追加する
エラー報告は、プログラムがあなたに何をしているかを伝える方法です。p5.jsには、特定の構文エラーを犯した場合にそれを伝えるビルトインのエラー報告機能があります。このガイドの後半でエラーメッセージについてさらに学ぶことができます。
また、console.log()
関数を使用してメッセージを出力する独自のエラー報告を追加することも有用です。
コンソールを見ると、物事が起こる順序と問題に遭遇する場所を確認できます。console.log()
は、変数の値を出力してプログラムの異なる時点で何をしているかを確認するのにも役立ちます。
7. さらなるヘルプを探す
これらすべてが機能しない場合、オンラインで更なるヘルプを探すことができる場所がたくさんあります:
- インターネットで検索してください。あなたがこの問題を抱えているなら、他の多くの人々も同様の問題を抱えている可能性が高いです。
- Processing Discourseとp5.js Discordを検索してください。
- Stack Overflowのような開発者フォーラムを検索してください。
より一般的なリソース:
- MozillaのJavaScript ガイド、JavaScript、およびJavaScript エラーリファレンスは、文字列などのオブジェクトのすべての組み込みメソッドを見つけたり、JavaScriptのエラーメッセージについて学んだりするのに本当に役立ちます。
- MozillaのHTMLのデバッグ、CSSのデバッグ、およびクロスブラウザテストリファレンスは、HTMLとCSSファイルのバグを見つけるのに役立ちます。
- Marjin Haverbekeのインタラクティブな教科書Eloquent JavaScript。
8. 他の人に聞く
まだうまくいかない場合は?
他の人に助けを求めることもできます!彼らはあなたを助け、デバッグ経験を共有することを喜んでくれるかもしれません。
問題を説明し、知りたいことを書いたメールを送ってください。Processing Discourseやp5.js Discord、その他のコミュニティフォーラムに投稿してください。
9. 良いコーディング習慣とバグの予防方法!
一部のバグは、良いコーディング習慣で予防できます。以下はいくつかの例です:
- 疑似コードをコメントとして始め、その後各ステップの下にコードを追加します。
- 小さな問題から解決し始めましょう!一度に1つのことを行います。1つのことをテストするために小さなスケッチを作成し、それらが機能することを確認してから、より大きなスケッチに組み合わせるのは問題ありません!例えば、雲を描いてから天気をチェックします!その後、雨が降りそうなときに暗くなる雲を描きます!
- 開発中にコードに
console.log()
を入れます。 - 頻繁にテストして、何かが変わった場合、最後にテストしてから何をしたかがわかるようにします。
- コードの異なるバージョンをテストしながら保存し、後で何かが壊れた場合に元に戻せるようにします。
- 早期に最適化しないでください。最適化されたコードは往々にして読みにくくなります。プログラムを構築する際は、高性能なコードよりも明確なコードの方が重要です。すべてが期待通りに動作することを確認してから、パフォーマンスのために最適化することができます!
- 早期に抽象化しないでください。複数回使用すると思われるものに対して関数やオブジェクトを作成する必要はありません。実際に複数回使用する必要が出てくるまで待ちましょう。
10. さらなるリソース
このガイドは、コーディング時のデバッグに関する他のいくつかの素晴らしいリソースに触発されています。そのいくつかをここに紹介します:
- Clay Shirky, デバッグの簡単な紹介
- Eric Steven Raymond, 賢明な質問の仕方
エラーメッセージ
Webブラウザには、テキストを使用してプログラマーと通信するコンソール領域があります。それは、p5.jsが理解できないコード行を説明する有用なエラーメッセージを表示します。コードのバグを見つけるために、様々なJavaScriptエラーメッセージを使用することができます。以下の例は、p5.js Web Editorでこれがどのように機能するかを示しています。
注意: p5.js Web Editorのフレンドリーエラーシステム(FES)も、デバッグを支援するためにコンソールにメッセージを送信します!
例1: SyntaxError
(括弧の欠落)
このコードでは、プログラマーはキャンバスに長方形が表示されることを期待していましたが、代わりにp5.js Web Editorがコンソールにエラーメッセージを表示し、何も表示されませんでした(空白のキャンバスさえも表示されません)。
エラーメッセージ:
SyntaxError: missing ) after argument list
バグ:
コンソールのメッセージによると、プログラマーはSyntaxError
を犯しています。これは、コードのどこかに文字が誤って配置されているか、欠落していることを意味します。
p5.js Web Editorは9行目を赤で強調表示し、エラーの場所を示しています。コンソールのメッセージも、エラーがsketch.js
ファイルの9行目にあることを指定しています(SyntaxError
の横の矢印をクリックしてください)。
コード:
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
// rectangle
rect(200,200,200,100;
}
解決策:
プログラマーは、最後の引数と セミコロンの間に括弧を追加することで問題を解決しました。彼らはrect()
のp5.jsリファレンスページを訪れ、コードを比較することでこれを発見しました。
プロのヒント:
- 常にp5.jsリファレンスを参照して、コードが正しい構文で書かれていることを確認してください。
- エラーメッセージが表示され、その意味がわからない場合は、Googleにコピー&ペーストして、理解しようとしてみてください!
コード:
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
// rectangle
rect(200,200,200,100);
}
例2: 引数の欠落
このコードでは、プログラマーはキャンバスに円が表示されることを期待していましたが、代わりに以下のエラーがコンソールに表示され、キャンバスには何も表示されませんでした。
エラーメッセージ:
p5.js says: [sketch.js, line 9] circle() was expecting at least 3 arguments but received only 2.canvas.
バグ:
コンソールのメッセージによると、circle()
は3つの入力を期待していたのに対し、2つしか受け取りませんでした。メッセージはまた、エラーがスケッチの9行目にあることを指定しています。
コード:
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
// circle
circle(200,200);
}
解決策:
プログラマーは、circle()
に3つ目の引数を追加することで問題を解決しました。
彼らはcircle()
のp5.jsリファレンスページを訪れ、コードを比較することでこれを発見しました。
プロのヒント:
- 常にp5.jsリファレンスを参照して、コードが正しい構文で書かれていることを確認してください。
- エラーメッセージが表示され、その意味がわからない場合は、Googleにコピー&ペーストして、理解しようとしてみてください!
コード:
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
// circle
circle(200,200,200);
}
例3: SyntaxError
(中括弧の欠落の例)
このコードでは、プログラマーは絵文字がキャンバスに表示されることを期待していました。
エラーメッセージ:
SyntaxError: Unexpected end of input
バグ:
コンソールのメッセージによると、p5.jsはSyntaxError
を指摘しています。これは、コードのどこかに文字が誤って配置されているか、欠落していることを意味します。メッセージはまた、エラーがスケッチの11行目にあることを指定しています。
p5.js Web Editorは11行目を赤で強調表示し、エラーの場所を示しています。コンソールのメッセージも、エラーがsketch.js
ファイルの11行目にあることを指定しています(SyntaxError
の横の矢印をクリックしてください)。
コード:
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
// happy emoji
text("😎", 180, 200);
}
解決策:
プログラマーは、11行目に閉じ中括弧(}
)を追加してdraw()
関数を閉じることで問題を解決しました。
彼らはdraw()
のp5.jsリファレンスページを訪れ、コードを比較することでこれを発見しました。
プロのヒント:
- 常にp5.jsリファレンスを参照して、コードが正しい構文で書かれていることを確認してください。
- エラーメッセージが表示され、その意味がわからない場合は、Googleにコピー&ペーストして、理解しようとしてみてください!
コード:
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
// happy emoji
text("😎", 180, 200);
}
例4. ReferenceError
このコードでは、プログラマーはキャンバスに円が表示されることを期待していましたが、代わりに以下のエラーがコンソールに表示されました。
エラーメッセージ:
ReferenceError: myX is not defined
バグ:
コンソールのメッセージによると、プログラマーはReferenceError
を犯しています。これは、現在のスコープに存在しない(またはまだ初期化されていない)変数を使用しようとしたことを意味します。
p5.js Web Editorは8行目を赤で強調表示し、エラーの原因としてそこを示しています。
コード:
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
circle(myX, 200, 200);
}
解決策:
プログラマーは、8行目に表示される変数myX
がスケッチ内で宣言または初期化されていないことに気づきました。バグを修正するために、setup()
の前にmyX
を宣言し初期化しました。
プロのヒント:
エラーメッセージが表示され、その意味がわからない場合は、先生や友人に聞く前にGoogleにコピー&ペーストして、理解しようとしてみてください。
コード:
let myX = 200;
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
circle(myX, 200, 200);
}
例5. TypeError
このコードでは、プログラマーはキャンバスに円が表示されることを期待していましたが、代わりに以下のエラーがコンソールに表示されました。
エラーメッセージ:
p5.js says: [sketch.js, line 10] circle() was expecting Number for the first parameter, received string instead.
バグ:
コンソールのメッセージによると、プログラマーは10行目でエラーを犯しています - circle()関数は最初のパラメータとして数値を必要としていますが、代わりに文字列が与えられました。
コード:
let myX = "forty-five";
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
circle(myX, 200, 200);
}
解決策:
プログラマーは、変数myX
が"forty-five"
で初期化されていることに気づきました。これは数値として認識されません。p5.jsはこれを文字列データ型の単なる単語だと考えています。
プロのヒント:
エラーメッセージが表示され、その意味がわからない場合は、先生や友人に聞く前にGoogleにコピー&ペーストして、理解しようとしてみてください。
コード:
let myX = 200;
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
circle(myX, 200, 200);
}
例6. ReferenceError
このコードでは、プログラマーはキャンバスに円が表示されることを期待していましたが、代わりに以下のエラーがコンソールに表示されました。
エラーメッセージ:
ReferenceError: localVariable is not defined.
p5.js says: [sketch.js, line 10] "localVariable" is not defined in the current scope. If you have defined it in your code, you should check its scope, spelling, and letter-casing (JavaScript is case-sensitive).
バグ:
コンソールのメッセージによると、プログラマーはReferenceError: localVariable
が定義されていないというエラーを犯しています。
また、10行目でlocalVariable
が現在のスコープで定義されていないとも述べています。
これは、draw()
で使用されているlocalVariable
がdraw()
に対して定義されていない - 認識できない!ということを意味します。これはローカルスコープを持ち、定義されたsetup()
内でのみ認識可能です。
コード:
function setup() {
createCanvas(400, 400);
let localVariable = 200;
}
function draw() {
background(220);
circle(localVariable, 200, 200);
}
解決策:
プログラマーは、setup()
とdraw()
の外部でlocalVariable
を宣言し、setup()
内で初期化することで問題を解決しました。
プロのヒント:
エラーメッセージが表示され、その意味がわからない場合は、先生や友人に聞く前にGoogleにコピー&ペーストして、理解しようとしてみてください。
コード:
// グローバルに変数を宣言
let localVariable;
function setup() {
createCanvas(400, 400);
localVariable = 200;
}
function draw() {
background(220);
circle(localVariable, 200, 200);
}
例7: SyntaxError
(関数呼び出しの引数の欠落)
このコードでは、プログラマーはキャンバスに蝶が表示されることを期待していましたが、代わりに以下のエラーがコンソールに表示されました。
エラーメッセージ:
🌸 p5.js says: [sketch.js, line 14] textSize() was expecting Number for the first parameter but received an empty variable instead. If not intentional, this is often a problem with scope.
バグ:
コンソールのメッセージによると、textSize()
にbutterfly()
関数宣言からの引数が欠落しています。エラーはbutterfly()
関数が呼び出される14行目で示されています。
これは、関数呼び出しに、関数宣言からtextSize()
に渡されるべき引数が欠落していることを意味します。
コード:
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
//左側の蝶
butterfly(50,50);
}
/* x、y、サイズをカスタマイズできる蝶の関数 */
function butterfly(x, y, size){
textSize(size);
text(`🦋`, x, y);
}
解決策:
プログラマーは、butterfly(50, 50, 50);
の関数呼び出しに3つの引数を含めることで問題を解決しました。
プロのヒント:
関数呼び出しの引数の数は、その宣言のパラメータの数と一致する必要があります。
コード:
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
//左側の蝶
butterfly(50,50, 50);
}
/* x、y、サイズをカスタマイズできる蝶の関数 */
function butterfly(x, y, size){
textSize(size);
text(`🦋`, x, y);
}