ソフトウェアの問題を解決するデバッグ作業時の5つのヒント

文:Chip Camden  翻訳校正:アークコミュニケーションズ、坂野裕史
2008-02-29 08:00:00
  • このエントリーをはてなブックマークに追加

 ここでは、わたしが利用している一般的な問題解決手法をいくつか紹介しよう。これらの多くは、ソフトウェアのバグだけでなく、あらゆる種類の問題に適用できる。

 1.問題を小さくする。問題を再現するのに必要な最小限のコード量になるまで、問題があるコードを「精製」する。無関係の部分はすべて削除するのだが、そんな手間をかけるのはなぜだろうか。干し草の山から針を探す最も簡単な方法の1つは、ほとんどの干し草を取り除くことだ。何かを取り除くと問題が消えてしまう場合もあるが、そのことが、問題が潜んでいる場所のヒントになるはずだ。そのうえ、繰り返しのデバッグサイクルに入った場合は、より少ないコードとステップを使ってずっと早く作業を繰り返すことができる。

 2. 前提条件を疑え。先日、静的データがreturnステートメントによって変更されているようだという問題を連絡してきたクライアントがいた。これを聞いた読者が考えそうなことはわかるが、このコードに関係するオブジェクトはなかったので、デストラクタは呼び出されていなかった。クライアントの言葉を信じると、使用している言語の実行時環境にとんでもないバグがあることになるが、わたしにはとてもそうは思えなかった。そこで、データが返る前後にどうやってデータを調べたかを質問した。データはデバッグシンボルを持っていないライブラリモジュールに格納されていたので、データを照会する標準的なルーチンへの呼び出しを自分のコードに追加したそうだ。しかし、このルーチンには(それが呼び出された方法では)、データを変更してしまう不適切な副作用もあることに気付いていなかった。一瞬にして、いわゆる「ハイゼンバグ(Heisenbug)」(不確定性原理で有名なドイツの理論物理学者ハイゼンベルクにちなんで名付けられた、出現したり消えたりするバグ)のできあがりだ。デバッグ用のステートメント自体が問題を引き起こしているときに、クライアントはこれらの呼び出しの周辺を調べて、データを変更したステートメントを特定しようとしていたのだ。

 3. 誤った原因に気を付ける。「変化したのはXだけだから、問題はXに関連しているはずだ」と何度聞いたことだろう。これは、絶対、絶対、絶対に正しくない!半分以上は、別の何かが変化したのに、それを忘れているか、そうしたものが存在することさえわかっていないのだ。「明らかな」原因が実は無関係だとわかると、あるいはそれが判明する前でさえ「わしは何も知らん、知らないんだ!」というセリフをいつも繰り返す。そう、もっとソクラテスの精神に沿うべきなのだ。しかし、証明されるまで原因を決めつけてはいけない。ただし、自分の直感を最初に調べてはいけない、という意味ではない。人に直観があるのは理由があってのことだから。

 4. 結果から始めて、戻りながら作業する。デバッグセッションを開始してからルーチンを1つずつステップ実行し、その間に変数を調べて、正しく動作しなくなる場所がたまたま見つかることを願うプログラマが多いようだ。通常この方法は、まったくうまくいかない。これは、一見問題のない発端から問題が生じている場合が多いためだ。コードは逆向きに実行されるわけではないため非生産的に思えるかもしれないが、エラーが明らかになった時点(たとえばエラーメッセージ)から開始し、その時点で何が問題なのかを調査すると効率的なのだ。その後で、その場所につながるコードに戻り、問題のコードを見つけるまでルーチンごとに戻りながら、どこで問題が起きたかを確認する。後ろ向きにステップ実行できるようにデバッガが作られていれば理想的なのだが、デバッグセッションを繰り返し100回開始する必要があっても、先頭側から原因をつかもうとするより時間の節約になる。

 5. 構成要素を再検討する。状況の複雑さが問題の一部になっている場合がある。ある関数で実行することの定義が完全に首尾一貫しておらず、それがエラーにつながっていることもあるだろう。設計を簡素で明確なものにすることで、そうした一貫性のなさが自然と明らかになる場合も多い。しかしこの手法は、慎重に検討してから利用すること。この方針でいったん開始すると、非常に長い期間、作業を止められないことがある。

このサイトでは、利用状況の把握や広告配信などのために、Cookieなどを使用してアクセスデータを取得・利用しています。 これ以降ページを遷移した場合、Cookieなどの設定や使用に同意したことになります。
Cookieなどの設定や使用の詳細、オプトアウトについては詳細をご覧ください。
[ 閉じる ]