今回は、デバッグ方法を挙げてみます。
様々な環境別に、デバッグ方法は存在しますが、抽象的に捉えれば基本は同じです。
今回は抽象的なデバッグ方法をご紹介します。
早く結論を知りたい人用
対策
- ログを仕込んで情報を得よう
- 仕様を読もう
- 根拠の無い思い込みを排除しよう
- 同じ文字を打ち込む場合は、コピー&ペーストを使おう
- スペルチェックを使おう
- エラーメッセージを直接検索エンジンへ使いません
- 他の人に頼りません
崩す必要があります。
しかし、自分のレベルアップや、上記前提条件を崩せないような状況を考えると、
今回のデバッグ方法は役に立つはずです。
今回の足がかり
デバッグ時の留意点
それは、
「エラーメッセージと、エラーの原因は必ずしも一致しない」
という事実です。
ソフトウェアも人の体と同じようなもので、
「肩こりの原因が、実は遠くの血管が詰まっているせいだった」
という事があります。
いわゆる遠因というものです。
「あれ~、これスイッチ入れても動かないよ~?」
「よし、調べてみよう。う~んこの部品も壊れてないし、この部品も壊れてない・・・
なんでだろう」
→電源プラグが抜けている
エラーの発生原因が一つとは限らない
結果というのは、原因に対応するidではありません。
人の体で例えると、風邪症状の原因が、様々なウィルスが起こすものだという事です。
原因から結果は導けますが、結果から原因が導けない例です。
という上記の前提を元に、今起きている現象を事実として進める
バグの原因調査は、事実を理解する事から始まります。
事実を理解したのち、今ある事実から、原因を仮定します。
仮定した原因が正しいかどうかを調べるための情報を集め、
仮定が誤っていたら、再度事実を見つめなおします。
エラーメッセージの内容
エラーメッセージが具体的にどこのコードに問題があるか示している
原因が分かれば、その場で修正します。
良くある原因の種類
- typo(打ち間違い)
- コピー&ペースト後の変更漏れ
- 仕様を分かってない
typo(打ち間違い)
typoを引き起こす要因の一つが、一度打ち込んだ単語を、再度打ち込む事です。
予防策
同じ単語を二度以上使う場合、二度目はコピー&ペーストにすると良いです。
Vimを使ってる方であれば、`yiw`を使えば楽です。(`yiw`→`ciw`→`Ctrl+r, 0`)
置換したい場合であれば、一括置換するのも良い手だと思います。
対策
typoがある事を疑う場合は、単語のチェックを行う機能があるテキストエディタを
使うと良いでしょう。
不審な単語には、下波線を付けてくれるでしょう。
文書作成ソフト等でも単語のチェックをやってくれます。
gVimでの「スペリングチェック」
コピー&ペースト後の変更漏れ
良くある要因
変更箇所が二箇所以上ある場合に、起き易い現象です。
予防策
コピー&ペーストした対象部分を1行、1文字ずつ読みます。
また、入念にやりたい場合は、コピー&ペーストした対象以外の部分も、
同様に1行、1文字ずつ読みます。
ここで大事な事は、「見る」ではなく「読む」です。
特に声に出して読む事で、何がおかしいかについて気付けます。
人の脳は、間違っている事でも、頭が勝手に補正して、誤りに気付かないように
してしまうからです。
(個人的に特に厄介に感じる事は、「間違っていないはずだ」という「根拠の無い
思い込み」に囚われる事です。
また、「根拠があっても、証拠が足りていなかったり、前提が誤っていたりする
場合も厄介です)
「わしたははれるでしょう」
→「あしたははれるでしょう」の言い間違いだと気付きますが、
「わした」を「あした」へ直そう、とは思いません。
(なぜなら、頭の中では既に「わした」は「あした」に修正済みだからです)
対策
予防策も対策として使えます。
他には、最初から「何を変更すべきだったのか?」を整理すれば大丈夫です。
仕様を分かっていない
資料が見つからなかったり、聞ける人がいなかったりする場合が要因として
あるでしょう。
他には、「仕様は分からないけどとりあえずやってみよう」とやってみた場合も
要因としてあるでしょう。
予防策
仕様を読みましょう。「仕様がどこにあるか分からない」?探しましょう。
探し方は、その仕様次第です。オープンな仕様であれば、ググれば見つかりますし、
オープンでなければ、オープンでないなりの仕様入手方法が必要です。
(ドキュメントが存在しない事もありますから、その場合はソースコードの入手が
必要ですね)
特に、ソフトウェアで重要なのは、「バージョン」です。
メジャーバージョンアップがあった場合(番号の一番大きいものが増えた場合)、
「今までの常識が全て変わった」と思うぐらいに、仕様変更があったと思いましょう。
上司が変わったり、自分の役職が変わったりするのと同じぐらいの違いです。
慣れ親しんだ環境は、既に魔の巣窟と化しています。
RPGをレベル1から始めるぐらいの気持ちで、仕様書から読みましょう。
対策
仕様を読みましょう。
原因が分からない場合
あらゆるコードの間にログを仕込む
実際にどこで何が起きているかを把握する事が何よりも先決です。
- どういう経路を通っているのか
- どういうデータの変化があるのか
「あらゆるコード」とは、自分が追加や変更したコード以外の事も指します。
使っているライブラリであっても、もし編集してコンパイル出来るならば、ログを
仕込む価値があります。
「正しい"はず"だ」を「~という根拠があるから、正しい」と言えるようにする
もし根拠を集めた後に、まだ原因が分からなくて解決していないなら、その根拠自体も疑いましょう。
世の中、例外だらけです。前提条件は容易く覆ります。
もし使えるなら、デバッガを使ってブレークポイントを設定する事も良い方法です。
エラーメッセージが具体的にどこのコードに問題があるか示していない
また、「今何が分かっていて、今何が分からないか」を書き出してみましょう。
「分からない事が分からない」という状況であるならば、「事実」を書き出しましょう。
見たり、聞いたりして、自分の中に湧き上がる言葉を書き出せばいいだけです。
今目に見えている事は、嘘ではありませんから。
「事実」から出発し、自分の意思を少し加えれば、迷いつつも方向性が定まるはずです。
以上、今回は抽象的なお話でした。
今はプログラムの世界も、非常に広範な世界になってきて、
抽象的な理解だけでは苦しい場面も増えてきました。
しかし、抽象的な事は物事の骨組みですので、骨組みさえ分かっていれば、後は
肉付けをがんばればいいのです。
(その肉付けが大変な世界になってきている、、というのは、多様性こそが
本質であろう、という事でもあります)