はじめに
最近、デバッグに向き合うことが多いです。課題に取り組むたび、どのようにすればスムーズに原因特定できるのか、トライアンドエラーを続けています。
ここでは、今までの経験を踏まえて、デバッグするときに心がけたいことを言語化しておこうと思い、内容をまとめてみました。
そもそもデバッグとは
デバッグとは - IT用語辞典 e-Words から引用します。
デバッグとは、コンピュータプログラムに潜む欠陥を探し出して取り除くこと。
プログラムが仕様や開発者の意図に照らして誤った動作をする際に、そのような動作を引き起こすプログラム上の欠陥、誤りをバグ(bug:虫)という。
テストなどによって発見された誤作動・不具合について、その原因やプログラム上での位置を探索・特定し、意図したとおり動作するように修正する作業のことをデバッグという。
なんとなくプログラム上の不具合を探し出す作業という認識でしたが、不具合を探し出して修正するまでをデバッグと言うようです。
デバッグを始めるタイミング
思いつく限り列挙してみました。大まかに言うと、プログラムが想定通りに動かないという状況に直面したときが、デバッグを始めるタイミングと言えるのでは無いでしょうか。
- 開発中、プログラム想定通りに動作しない
- プログラムを利用するユーザーから、想定通りに動作していないと連絡を受ける
- 自分自身で、プログラムが想定どおりに動作していないことを発見する
デバッグの手順
以下、プログラムが想定どおりに動かない不具合 = バグ という用語を使います。
バグによる問題発生を再現する
まず、他の人から連絡を受けたり、自分で発見したバグによる問題が、どんな入力値、どんなデータのインプットで発生するかを再現します。
バグによる問題発生を再現する中で、バグの原因特定のための最低限の情報を収集します。
バグの位置を特定する
問題発生の再現ができたら、プログラムのどの部分でバグが発生しているかを特定します。
二分探索法で探す範囲を絞り込む
どこにバグがあるか全くわからない状態からバグの位置を特定するための方法として、二分探索を利用するのが常套手段です。
二分探索とは、データ検索アルゴリズムの一つで、ソート(整列)済みのデータ群の探索範囲を半分に絞り込むを操作を繰り返すことで高速に探索を行う手法。
単純に最初から処理を追って探すという方法よりも、高速に原因にたどり着くことができます。
プログラムの処理を見える化する
二分探索でバグの位置を特定するにあたり、重要になるのがプログラムの処理を見える化することです。
プログラムの処理を見える化できないと、当てずっぽうでバグを探す方法しか取れなくなります。
例えばお医者さんが患者さんの腫瘍の位置を特定するとき、当てずっぽうでメスを入れるということはしないでしょう。その前にレントゲンや MRI といった、腫瘍の位置を見える化する装置を使うと思います。
それと同じように、プログラムの処理を見える化することで、バグの位置を特定しやすくなります。
具体的には、以下の手段が有効です。
print デバッグを使う
JavaScript でいうと console.log
といった、標準出力にログを出力できるようなメソッドを、怪しい処理の前後に置いてみるのはいい方法です。
ログ出力が難しい場合は、これも JavaScript の例ですが document.getElementById('#test').innerHTML = 'xxx'
といった処理を使い、画面上に表示させるのもいいかもしれません。
デバッガーを使う
デバッガーを使うのも有効です。
プログラムにブレークポイントをおいて、その時点から処理をステップ実行したり、その時点での変数の状態を確認するのも、手がかりを掴むのに役立つと思います。
バグの原因を特定する
バグの位置を特定できたら、その次はなぜバグが発生するのか、原因を特定します。ここでは今まで得た情報を踏まえ、仮説と検証を繰り返して原因を探ります。
原因特定のプロセスは状況によって違うと思うので、以下では個人的に役立ったと思うアクションを書いておきます。
正常に動作する似た環境と比較して仮説立案の参考にする
検証するために必要な仮説を考える際に、正常に動作する類似の環境を準備し、それと比較するという方法が有効だなと思っています。
処理中のデータが見える化できるようになっても、それが問題の原因につながっているかどうか判断するのが難しい場合があります。
その時は、正常に動作する類似の環境を準備し、その処理と比較して原因特定の仮説を考える参考にしてみましょう。
愚直に仮説と検証を繰り返して事実となる情報を集める
仮説と検証を繰り返しても、なかなか原因が見つからないこともあります。しかし原因特定のための情報は仮説と検証を繰り返すことで徐々に集まってきます。
ときには当てずっぽうな仮説で検証することがあっても、得た事実は次の仮説を考える上での貴重な材料になるので、整理しておくといいかもしれません。
他の人に調査状況を話す
原因特定のための調査を繰り返していると、「あれ、今自分は何を調査していたんだっけ?」と露頭に迷うこともあるかもしれません。
そんなときは、他の人に調査の状況を口頭で話してみるのも有効です。他人に状況を話す中で、そもそも何を調査していたのかを再確認できますし、仮説検証で得た情報を整理することもできます。また、見落としていたポイントに気づくかもしれません。
バグを修正する
バグの原因を特定できれば、あとは原因を解消できるような修正をいれ、問題なく動作することぉを確認します。
おわりに
現時点でデバッグについて考えていたことを言語化してみました。今後もデバッグ経験を積むにつれ、考え方や手段をアップデートできたらなと思います。
他にも良いアイデアや方法あれば教えて下さい!