Top Of Page バグとチャンス デバッグとは 原因特定 バグ修正 Bottom

デバッグ

デバッグとは、バグの原因を調査し、特定し、それを修正することです。バグを検出することが目的の「単体テスト」と表裏一体です。
私を含めて(笑)、多くのプログラマは、この作業が最も嫌いです。
それは、この作業は、プログラミングにおける最も困難な作業だからです。
その作業を、なるべく困難にしないようなガイドラインを考えていきましょう。

ところで。
デバッグは品質を高めるために行うのでしょうか。
もちろんそういった一面もあります。しかしあくまでもデバッグは「バグの修正」を行う作業です。
高品質なプログラムを作るには、決して、デバッグすればいいというだけではありません。
しつこいようですがもう一度書きます。
高品質なプログラムを作成するには、正確な要求解析やプロトタイピング、優れた設計、高品質なコーディング技法を駆使する必要があります。 それを駆使してなお、バグは発生します。
その上で、そのバグを見つけ、捕まえ、駆除─検出、原因特定、修正─する、それがテストとデバッグの本質です。

バグだ!チャンスだ!

なんのチャンスだ何の。
─というツッコミが聞こえてきそうですが。
以下のことを調べるチャンスです。開発しながらだとなかなか時間が取れないことですが、デバッグ中なら大手を振って調査できます。やってしまいましょう(笑)
バグを出したということは、そのプログラムについての理解が十分ではなかった可能性があるということです。そんなときは、どう直そうかという方針を立てるとともに、そのプログラムについて十分に理解しましょう。もともと何をするためのプログラムなのか、全体のうちのどのあたりを担当しているのか。そういった観点でプログラムを眺めてみると、いままで気が付かなかった解決法が見つかるかもしれません。

また、自分が書いたプログラムなら自分がバグを入れたのです。つまり自分の間違いです。
毎日毎時毎分毎秒と自分の間違いに向き合っていると気が滅入ります(笑)。だから、普段はそんなことはあまり考えないものなのですが、バグがあったときくらいは、自分がどんな間違いをしたか、詳しく調べて見みましょう。
なぜバグになったのか。どうしたらもっと早く発見できたか。似た間違いをほかでしでかしていないか。
その調査を、次のコーディングに役立てましょう。

バグの原因を特定し、修正するためには、プログラムをあちこち読まなければなりません。
どうせあちこち読むのですから、その際に、自分が書いたプログラムがどの程度読みやすいのかをチェックしましょう。
読みにくかったらできれば直したいとこですが、直すことによって別のバグを入れてしまうこともありますから慎重に。今回直さなくても、次回のコーディングは読みやすくなるように心がけましょう。

バグがなかなかなくならない、という人は、自分のデバッグ方法に疑いを持つべきかもしれません。
自分のデバッグ方法はうまく機能するのか。バグの原因を早く見つけられるのか。いいかげんな仮説を立てていないか。改善の余地がないものなのか。
デバッグにかける時間を思えば、自分のデバッグ方法を検討する時間が無駄とは思えないでしょう。
デバッグ方法の洗練は、デバッグ作業を速やかなものにするための重要な要素なのです。

デバッグとは

デバッグとは、大体において以下の作業です。
  1. バグを安定させる
  2. バグの原因を見つける
  3. バグを修正する
  4. 修正が正しいか検査する
  5. 同じようなバグがないか検討する
バグを安定させ、検査条件を単純化するには、カンではいけません。
たとえば、組み合わせるとバグを引き起こす要因がいくつあるかを調べ、どの要因がバグの発生と無関係かを調べていきます。
そして、無関係と判断した要因の値を変えてテストします。バグがまだ起こればその要因ははずすことができますから、バグ発生の条件を単純にできます。一般に、これらの条件が単純であるほど、バグの原因の特定もしやすいのです。

バグの原因を特定するためには、ただバグを探すのではなく、こういうバグだ、という仮定をたてて、それを検査します。例えば境界の問題か、とか不正なデータか、とか、そういった仮定に対して、確かめていきます。

デバッグは大きく分けて、原因特定のフェーズと、バグ修正のフェーズがあります。
次の節で、それぞれについて分析してみましょう。

原因特定フェーズ

デバッグにおいて時間がかかるのは、バグを安定させ、原因を見つけ、それを理解することです。デバッグの時間の90%はこれに費やされるといっても過言ではないでしょう。
原因を見つけるためのヒントとして、以下のものがあります:
コードの妖しい範囲を絞る方法として、たとえばあるルーチンを呼ばないようにしてみます。それでも同じバグが出るのでしたら、そのルーチンが原因でバグがおきているわけではありません。
でたらめに絞るのではなく、効率的に分割していくことが重要です。(ここでも、適切にルーチン化されているかどうかがデバッグのしやすさに直結します)
たとえば、ある大きなルーチンの半分を処理しなくしてみる。そしてその次の半分を…というように絞りながら、バグを突き止めていきます。

誰かと問題を議論することを私は「告白デバッグ」と呼んでいます。他の人に、どんなバグかを話すことで、そのバグの原因に気が付くことがあります。
先輩:
「あのさ、ちょっといいかな
売上リストって売上額の大きい順にソートされてなきゃいけないんだけどさ、ソートされてないことがあるんだよ。
2回目に印刷するときはきちんとソートされているんだけど、1回目にはまずいんだわ。
新しく名前を入れるときにだめなのかなあと思って調べたけど、そうじゃないらしい。
最初の印刷だってソートされているはずなんだ。
ちゃんと入力時にすぐソートしてるし.....と、まてよ。違う、入力したときにはちゃんとソートされてない。
ああそうか。完全にはソートされないじゃん。なるほどなるほど。
サンキュー、助かったよ」
これ実話です。私はなんにもしてません(笑)
他人様というのは、非常に強力なデバッグツールで、私もしばしばお世話になります(^^;

どうしても行き詰まったら。
コーヒーでも飲んで、一休みしましょう(笑)
そうしているうちに、ひらめくかもしれませんし。

バグ修正フェーズ

前の節でも書いたとおり、大変なのは原因を究明することです。修正はそれほど難しくはなりません。
しかし、油断は禁物です。他の簡単な作業がそうであるように、この作業もまた誤りを発生しやすい作業です。つまり「デバッグでバグる」ってやつです。
それを少なくするためガイドラインとしては、以下のものがあります。

理解する、というのがいくつかありますね。「プログラムを理解する」なんていやな言葉でしょう。しかし、何万行もあるプログラムをすべてを理解し直す必要はありません。問題が発生する状況を理解したら、そこだけでなく近くで何をしているか調べるということです。ここで近く、というのは数百行程度ということです。

原因特定終了、あとは修正だけ、よっし楽勝!ささっと直すぞ!─いやそれもOKです。でも、直し間違えたらばかばかしいですよね。落ち着いていきましょう。

そのバグの修正がある程度高くつく(直し個所が多いとか、時間がかかるとか)場合、プロジェクトマネージャは、「そのエラーは致命的じゃない。とりあえずいいから、そのままいく」と言うかもしれません。だから、修正前のソースを保存する事は重要です。

修正するときは、問題の本質を捉え、その問題そのものを直すようにしましょう。その問題が引き起こす表面的な兆候にとらわれて、その兆候だけを直してはいけません。問題の本質を修正しない限り、そのバグは息を潜めて、再発の時を待ちつづけます。

ある程度のベテランになれば、いくつものバグを一度に修正することもできますし、そのほうが効果的であることもあります。
でも、たとえば、いくつも変更して、それがすべてデバッグOKならいいのですが、いくつも変更したが、いくつかのバグが直らなかった場合…原因の特定が困難になります。まずは、一つずつ修正し、再テストし確認、という手順でいきましょう。

修正したら必ずテスト。思い通りに修正されているか必ず確認しましょう。特に時間に追われて余裕がないときは、デバッグでバグってることも多くあります。

そしてバグはまとまって発生する傾向があります。同じようなバグがないかどうか、探しましょう。
探し方がわからないときは、プログラムを理解していないことが多いです。


はじめに ルーチン モジュール 変数名の力 変数使用法 制御構造 レイアウト コメント テスト デバッグ 謝辞 Top of Site

Copyright (c) 2000 Takao Tamura