【初心者向け】デバッグで意識するべき、基本の十ヶ条

debugging-tips

デバッグ。プログラミングに内在するバグ(不具合)を除くための作業です。

プログラムには、バグは必ず存在します。したがってデバッグ作業も、プログラマーには必須の作業となります。

このデバッグ作業、実は、人によって効率の差が顕著に表れます

  • 初心者プログラマーが、3日かかったデバッグ作業を
  • ベテランプログラマーなら、3分で解決する

こんなことも、ザラに起こります。

何が違うのでしょう?デバッグには、意識すべき基本の心得があるのです。

目次

こんなデバッグはいけない

プログラミング初心者は、バグに遭遇すると、軽くパニックになりますよね。

新人くん

あれ?なんか謎のエラーメッセージで止まる・・・
ここに出るはずの結果が表示されない・・・

そして、おもむろにコードをいじり始めます。

新人くん

ここを直せばいいのかな?
カチャカチャ・・・

でもなかなか直りません。それどころか、

新人くん

あれ?さらにおかしくなった・・・

そして、泥沼にはまっていくのです。

リーダーさん

待って待って!
デバッグは、やみくもにやっちゃダメ

デバッグには、それなりのお作法や心得が、あるのです。

デバッグにおける、基本の十ヶ条

デバッグには、心得ておくべき基本事項が、いくつもあります。最も基本は、次にあげる十ヶ条。

デバッグにおける十ヶ条

デバッグを始める前の心得

  1. 再現方法を確かめておく
  2. ログやトレースを確認しておく
  3. 仮説を立てる

デバッグ中の心得

  1. 推測ではなく事実を確認する
  2. 二分探索で原因箇所を絞り込む

デバッグが終わった後の心得

  1. 同様の修正を水平展開する
  2. リグレッションテストを行う

今後デバッグしやすくするための心得

  1. コンパイルやリントによるエラー検出を考える
  2. 契約による設計を考える
  3. リファクタリングを考える
リーダーさん

デバッグは、段取りよくやるのが大事!

順番に見ていきましょう。

デバッグを始めるまえの心得

プログラムにバグが発生!さっそくデバッグ開始・・・の前に、ちょっと待って。

バグが発生したからといって、すぐにコードをさわり始めるのはNGです。

新人くん

でも、コード直しながら確認したほうが、早いのでは?

リーダーさん

下準備をちゃんとすることが、結局は近道だよ!

なにごとも、準備が大切。それにより、後の混乱が防げます。

(1)再現方法を確かめておく

デバッグした後は、ほんとうにバグが直っているのか、確かめる必要があります。

確かめ方はこうですね。直す前とまったく同じことをして、ちゃんと動作するか

つまり、どういう手順でやったらバグが起こるのか、事前に確認しておくことが大事です。

特に、このようなときは要注意。

再現しにくいバグ
  • 環境により動きが変わるもの 自分のPCで動くけど、あなたのPCで動かない
  • 日付や時刻で動きが変わるもの 特定の日や特定の時刻でだけ起こるもの
  • 起きたり起きなかったりするもの マシンのメモリや負荷状況によるもの、並列処理によるもの

必ず、バグが再現できる手順を確認しておきましょう。

(2)ログやトレースを確認しておく

デバッグとは、バグがありそうな箇所を推理する作業、といえるでしょう。

推理に重要なのは、証拠です。

バグの状況が再現できたら、あらかじめ証拠を集めておきます。

証拠を集めよう
  • 表示内容
  • 送信内容
  • 保存結果

さらには

  • プログラムが出力するログ
  • エラー時に表示されるトレース情報(プログラムの実行履歴)

いろいろなものを証拠として集めておきましょう

特に、再現しにくいバグの場合、ログやトレースで内部状態を追跡することも重要になってきます。

忘れずに収集しておきましょう。

(3)仮説を立てる

デバッグを始めるための、証拠が揃いました。

次に重要なことは、証拠をもとに仮説を立てること

仮説を立てよう
  • 例えば、エラーメッセージが発生していたら?おそらく、コードでメッセージを出力している箇所から、バグが追跡できるでしょう。
  • 期待と異なるような結果が出るようなケースなら?その結果を作り出しているデータか、変換過程に、バグが潜んでいそうです。

仮説を立てることにより、調査箇所をあらかじめ絞り込みます。そうしないと、後の作業がとりとめもないものになってしまいます。

デバッグ中の心得

それでは、いよいよデバッグの開始です。

仮説に基づき、なぜバグが起こるのかを明らかにしつつ、コードを直していきます。

といっても、

新人くん

コードのどこを直せばいいのか、迷いますよね・・・

リーダーさん

大事なのは、「事実を確認しながら」「少しずつ進める」こと!

やみくもにコードに手を出してはいけません。状況を見ながら、少しずつ進めます。

(4)推測ではなく事実を確認する

デバッグのとき、一番厄介となる敵。それは一体何でしょう?

それは、「思い込み」です。

  • ここはこう動いているだろう
  • ここはこういう結果が出力されているだろう

一度そう思うと、なかなかそこから抜け出せず、泥沼にはまります。

先入観に囚われず、事実を確認しましょう。

事実を確認しよう
  • 変数やデータがどうなっているか
  • コードのどこを通っているのか

変数の中身や実行状況を確認する用に、大抵のプログラミング言語は、デバッガを提供しています。

デバッガを使うのが難しいなら、ひたすらprint文で変数を表示しまくるのもアリですよ。(俗に言う「プリントデバッグ」)

(5)二分探索で原因箇所を絞り込む

デバッグで重要なことは、バグが起こっている箇所を特定すること

そのときに大事な考え方が、二分探索です。

二分探索で絞り込む

検査すべきコードの中間あたりで、事実(変数の中身など)を確認する

  • その場所での結果がすべて期待どおりなら、バグは、その場所の「後」にある
  • その場所で既に期待と違う結果であるなら、バグは、その場所の「前」にある

これで、バグが存在しそうな場所が、前半か後半か、半分に絞られるわけです。

範囲が絞られたら、さらにその範囲で、二分探索。

こうやって、見るべき場所を絞り込んでいき、バグの箇所を特定していくわけです。

もしそれでもバグの箇所が見つからなかったら?それはおそらく、仮説が間違っていたのでしょう。あらためて仮説に立ち戻りましょう。

デバッグとはつまり、

  • 証拠を集め
  • 仮説を立て
  • 事実を確認していく

このサイクルの繰り返しなのです。

デバッグが終わったあとの心得

バグの箇所が特定でき、コードの修正が完了。期待通りに動くようになりました。

新人くん

やったー!バグが直りましたよ!

リーダーさん

おめでとう!でもまだまだ、やることあるよ

そう、バグが直ったからといっても、まだまだやるべきことがあるのです。

(6)同様の修正を水平展開する

バグの原因は、割と単純なことだったりもしますね。

基本的なバグ
  • ファイルの操作誤り
  • ライブラリ操作の誤認識

こういう単純なバグは、もしかしたら、他のところでも同じことをやっているかも?

同じようなバグが他の箇所にもあれば、同じように直しましょう。

こういった作業を、「横展開」とか「水平展開」と呼びます。水平展開すべき箇所はないか、確認しましょう。

(7)リグレッションテストを行う

デバッグでコードを修正したときに、注意しなければいけないのが、デグレードです。

デグレード
  • ここのバグは確かに直ったけど
  • そのせいで、今まで動いていたとこが動かなくなっちゃった!

バグを修正したら、そのバグの箇所はもちろん、その周辺のコードもテストします。デグレードが発生していないかを確認するのです。

デグレードがないことを確認するテストのことを、リグレッションテストといいます。

リグレッションテストを忘れずに行いましょう。

リグレッションテストに有効なのが、ユニットテストの仕掛けです。テストを自動化しておくと、リグレッションテストが格段にラクになります。可能であれば導入を検討してみましょう。

今後デバッグしやすくするための心得

横展開で修正し、リグレッションテストもパス。ひととおりデバッグの作業は終了です。

新人くん

いやーデバッグって大変ですね・・・

でも、まだ考えることがあります。それは今後のこと。

プログラムにバグがある以上、デバッグという作業はなくなりません。

でも、デバッグをラクにするために、事前にできること、はあるのです。

リーダーさん

そもそも、デバッグしやすいコードを書くことが大切だよ!

(8)コンパイルやリントによるエラー検出を考える

デバッグをラクにする方法のひとつは、バグを早く見つけること

できれば、プログラムを動かす前に見つけらるなら、それにこしたことはありません。

今のプログラミング言語では、動作する前に問題点を見つけてくれる仕掛けが、いろいろあります。

エラーを事前に検出しよう
  • コンパイル型言語なら、コンパイル時の警告で、問題の起こりそうな箇所を教えてくれます
  • リンターと呼ばれる、コードをチェックするツールも、積極的に使いましょう。

コンパイル時点で、バグの芽を早めに摘んでおく。これが深刻な不具合の防止に役立ちます。

(9)契約による設計を考える

あるところで発生した小さなバグが、いろいろな箇所に派生し、深刻な不具合になる場合もあります。

バグは、できるだけ早い段階で検出できるほうがよいのです。

その検出方法のひとつが「契約による設計」です。

契約による設計
  • プログラムが、動作中に守るべき事項(=契約)を定める
  • その契約内容をコードに埋め込む
  • 契約が破られた場合、プログラムを停止する

不適切なデータなど、契約違反が起これば、プログラムは直ちに停止。そこから先に不具合が波及することを防止できるのです。

(10)リファクタリングを考える

バグが発生しやすいコード、デバッグがしにくいコード。

それは経験則として、こんなコードでしょう。

バグが出やすいコード
  • 分かりにくいコード
  • 複雑なコード

プログラムは、書き方によって簡単になったり複雑になったりします。

なので、同じことをするなら、簡単で単純なコードであるほうが、デバッグがしやすくなります。

読みやすいコードを書きましょう。読みやすければ、間違いも発見しやすくなります。

さらには、ちゃんと内部構造を改善し、分かりやすいコードに改善できるとベストです。

そういう修正のことを、リファクタリングといいます。

可能であれば、リファクタリングにも挑戦する価値があります。今後のデバッグ作業を格段にラクにしてくれるはずです。

デバッグにAIを活用しよう

デバッグ作業は、ある意味、職人技とも言えるもの。

ですが近年では、AIの登場により、デバッグ作業は格段にラクになってきています

例えば、このようなことができます。

AIの活用

バグが発生したとき

  • 対象のソースコード
  • 発生したエラーメッセージ
  • 期待する結果
  • 実際に起こる結果

といった情報をChatGPTなどのAIに入力

「バグの原因を教えて」と聞く

これでけっこう、コードの内容やバグの原因を教えてくれたりします。

新人くん

デバッグにAIを使うときの、コツって何かあります?

リーダーさん

「事実をありのままに伝える」のがポイントだね!

AIに聞くとき、良かれと思い「ここがおかしいと思うんだけど」みたいな情報を加えてしまいがち。

しかしそれが、思い込みの解釈であった場合、AIをミスリードしてしまいます。

対象のコード、発生したメッセージなど、事実をありのまま伝えましょう。そのほうが正確な回答を得やすくなります。

デバッグにおけるAIの活用は、まだまだ発展途上です。今後さまざまな研究がなされ、進化していくでしょう

活用しない手はないですね。

AIに入力したソースコードなどは、AIの学習に使われる可能性があります。秘匿性の高いコードなどの扱いには注意しましょう。

まとめ

実はプログラマーは、コーディングする時間と同じくらい(いやそれ以上に)デバッグに時間を費やします

そしてデバッグ作業は、技量により、効率に圧倒的な差が出やすい作業です。

でも大丈夫、基本をおさえて経験を積めば、デバッグ技術はどんどん向上します。

リーダーさん

基本の心得を身につけ、AIも活用して、デバッグ経験を積んでいこう!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次