デバッグ方法について
詳細設計、実装、単体テストといったいわゆる開発工程においてコードを書いている時間というのは少ないものです。
それよりもコードを読んでいる時間やデバッグしている時間のほうが圧倒的に長い。
その割にはコードの読み方やデバッグ方法に関する情報は少ない。コードの読み方に関しては近年情報も出始め書籍としてもCode Reading―オープンソースから学ぶソフトウェア開発技法があります(僕はちゃんと読んでませんが)。また雑誌ではJava World (ジャバ・ワールド) 2005年 9月号でEclipseを使ってJUnit3.8のコードリーディングを解説しており参考になります。僕はこの記事を読んでEclipseによるコードリーディング方法を学ぶことができました。
一方デバッグに関してはあまり情報が無く、まだまだ開発者個人の暗黙知になっている部分が多いと思います。
ただ僕がいままで明示的にであれ非明示的にであれ優秀な方々から教わった(盗んだ)ことやCODE COMPLETE 第2版 下 完全なプログラミングを目指しての第23章「デバッグ」やビューティフルコード (THEORY/IN/PRACTICE)の第28章「美しいデバッグ」に書かれていることがおおむね同じであると思いました。やはり優秀な人間の考えることは似てくるんだと思います。「愚かしさの様態には限りがないが、賢さはどれも似ている」 from 現代思想のパフォーマンス (光文社新書) 「幸せな家族はどれもみな同じにみえるが、不幸な家族にはそれぞれの不幸の形がある。」 from アンナ・カレーニナ〈1〉 (光文社古典新訳文庫) ということだと思います(どんなだw)。
ま、僕なりに良いと思われるデバッグ方法について簡単にまとめると以下のようになります。書いててあまり実践できてないことに気付いたのは内緒だw
- 1.まず現象を再現させる
- 基本ですね。再現手順をちゃんと整理することが問題解決の第一歩ですね。再現できないものについてはここでは論じません。現象を再現させる(できれば)最小のテストデータ、手順を作ります。ここはポイントですね。もしミドルウエアのバグだったりしたら対処しようがないので、この情報をベンダーに送ります。
- 2.失敗する(現象を再現させる)ような(自動化された)テストケースを書く
- これは難しいかも。ま、できなければ次のステップへ進む。
- 3.失敗の原因について仮説を立てる
- 例えば問題はこの変数xの値が不正だからかもしれないとか。
- 4.仮説にもとづいて予測する
- 例えばxの値が不正なのはメソッドfが原因だろうとか
- 5.その予測を実際にプログラムを動作させて確認する
- 例えば確かにfでxに不正な値をセットしているとか
- 6.予測が正しければコード修正に取りかかる。正しくなければ3にもどる。
- 修正前と後の差分もきっちり確認してコミットする。差分重要。スペースとかタブとかバグ修正に直接関係無い差分は無いようにしてコミットね。フォーマットしたい場合は別コミットで。
- 7.動作確認
- ちゃんとデグッて無いことも確認する。
- 8.類似ケースが無いか探す
- ま、なかなかできなかったりするけどw
- 9.テストケースの追加
- ま、なかなか(ry
またSubversionのような構成管理ツールの力も必要です。場合によってはEclipseのローカルヒストリーも。
たとえばver1.0(r1000)時点では作りこまれていないバグがver2.0(r2000)ではあるとします。
その場合バグを作りこんだリビジョン番号を特定できれば問題の大半は解決したも同然です。
当然r1000〜r2000まで1個ずつ確認なんてやってられないですよね。そこで2分探索です。
r1500でバグが見つかるならr1250へ、見つからないならr1750へってな感じで絞り込んでいきます。r1100とr1800の修正を両方適用した場合にのみバグが再現とかってなるとこの手法だとだめなわけですが、たいていは大丈夫なんじゃないかな。
あとデバッグとは直接関係ない話ですけど、バグ1個修正するのに5回ぐらい連続してコミットする人がいるけど1回にしたほうがいいでしょう。そのほうがあとで追いやすいし。ファイル1個に対して1度コミットしなきゃいけないと思ってるのかなあ。