問題の検出からバグ修正までの流れ
本記事はruiさんのnote記事に触発されて書きました。本記事を書くに至った背景となった文を引用します。
私はプログラミングは結構自信があるんですが、他の人の作業をつぶさに観察したことがあるわけでもないので、自分で当たり前だと思っているコーディングの方法が他の人にとってはそうではないこともあると思ってます。上手い人がどういうふうにしてプログラムを書いているのか知りたいんですよね。
逆に私はどういうふうに書いているかちょっとまとめてみました。自分はこうしている、というのがあったらぜひ教えてください。
...
と、こんなふうに作業しているわけですが、こういう最終結果に現れないものというのはソースコードをみても学べないので他の人がどうやって作業しているのかはいまだによくわかりません。みなさん、どうやっているんでしょうか? ぜひ教えてください。
わたしは(も)一からプログラムを書き起こすよりも人の書いたコードを改善することが多いです。大がかりな機能開発よりも、なんらかの問題が検出された後にそれを引き起こしたバグを修正するための小さめのプログラムが多いです。本記事ではこのようなプログラムを書くときに私が意識してやっていることを、バグの検出からプロダクションコードへの取り込みまで、順を追って書いていきます。トラブルシューティングの型を紹介するといってもいいでしょう。
ruiさんの記事と重なるところが多いですが、オリジナリティよりも自分が何をしているかを余すところなく書くのが主題なので、重複ご容赦。
では実際の流れを追っていきます。本記事ではおおよそ一直線に綺麗な流れで検出からバグ修正まで進みますが、実際は前のステップに戻ったり、あるいは迅速な解決のために複数人で作業を進めたりします。
問題の検出と現状の把握
まずは自分ないし他の人が問題を検出します(以後他の人が検出したと仮定して、かつ、その人を"検出者"と記載します)。「バグ」ではなく「問題」と書いたのが重要で、この時点では問題はソフトウェアのバグとは限りませんし、バグだったとしてもシステムを構成する数あるソフトウェアのうちどれに問題があったか、およびソフトウェアがわかったとしてもその中のどこにバグがあるかがわかりません。どういう問題が把握してはじめて手の打ちようが出てくるので、まずやることはなるべく詳細な事実確認です。事実確認の手段にはメトリクスを見る、ログを見る、検出者にヒアリングをしていつ(とくに問題が起きた直前)何をしたのかを詳細に尋ねる、などがあります。
仮説を立てて検証する
事実確認の結果「こういう状況が起きているのではないか」と仮説を立てます。続いてその仮説に従い以下のようなことをします。
- 再現プログラムを書く。できれば単一のソフトウェアだけで短時間で問題を発生させられる必要最小限のものにする。できれば検出者の環境を再現して同じ問題が起きるかも確認する
- 問題に関係しそうな部分のソースコードを確認する。これは際限プログラムが小さければ小さいほどやりやすい。
git bisect
によってバグを仕込んだコミットを絞り込めることもある
再現プログラムを書くのはソースコードの絞り込みにも後のステップにも非常に役立つのですが、場合によっては書けないこともあります。たとえばきわめて特殊な状況でしか起きず、その状況が手元で再現できない、などです。
自分が立てた仮説が最初から正しいとは限りませんので、このステップでは仮説を立てて検証というループを何度も繰り返すことが多いです。仮説が間違っていたらがっかりするのではなく、「一つ可能性を潰せた」と前向きに考えるとモチベーションを保ちやすいです。
コードを書く
バグがある部分が見つかれば、いよいよコードを書きます。このときは以下のようなことに気を付けます。
- 別のバグを仕込まないように、なるべく影響範囲を最小限にする。リファクタリングなどの別目的の修正は避ける
- 修正後にバグが復活するのを避けるためにテストコードを書く。再現プログラムはもちろん、ユニットテストも書ければ書く
検出者の環境で問題が修正されたことを確認する
できれば検出者の環境で修正版(できれば検出者の環境に必要最小限の修正パッチを当てただけのもの)を使って問題が発生しなくなることを確認します。問題が発生したシステムが重要であったり、あるいは再現させるのに高い負荷が必要であったりすると、やらない(できない)こともあります。
プロダクションコードに取り込んでリリース
ここまでやって、ようやくプロダクションコードに取り込んで、リリースします。あとは…検出者の環境で問題が修正されていることを祈ります。
おわりに
ソフトウェア開発者といえばコーディングをする人というイメージがあるでしょうが、本記事の内容を見ていただければ、少なくともバグ修正については全体の中でのコーディングの割合がいかに少ないかわかっていただけたかと思います。
本記事に書いたことはトラブルシューティングに慣れた人にとっては当たり前ですが、その当たり前が案外難しいのです。人がやっているのを横目で見ていて当たり前のことをしていると感じても、いざ自分でやると手間取ったり、「あれ、ここではどうすればいいんだっけ」となりがちです。ぜひ本書で紹介した型を使って自分で何度も試してみてください。
参考までに関連記事を紹介しておきます。以下の記事は型に従ったトラブルシューティングの実践例です。
問題検出者がお客様だった場合は以下の記事が役立つでしょう。
Discussion