Systematic Debugging
当てずっぽうの修正は時間を失い、新たなバグを生む。
Core principle: 修正の前に根本原因を特定する。症状の修正は修正ではない。
The Iron Law
根本原因の調査なしに修正を提案しない
Investigation を完了してから、修正を提案する。
いつ使うか
テスト失敗、本番バグ、予期しない挙動、パフォーマンス問題、ビルド失敗、統合エラー。
特にこういう時:
- 時間に追われている(焦りは当て推量を誘う)
- 「ちょっと直すだけ」に見える
- すでに複数の修正を試みた
- 問題を完全に理解していない
4 ステップ
各ステップを完了してから次に進む。ステップは名前で参照する(番号は使わない)。
Investigation(根本原因の調査)
修正を試みる前に:
エラーメッセージを丁寧に読む
- スタックトレースを最後まで読む
- 行番号、ファイルパス、エラーコードをメモ
- エラーメッセージ自体に解決策が含まれていることが多い
再現を確認する
- 確実に再現できるか? 手順は?
- 再現不可なら → データを集める。推測しない
最近の変更を確認する
git diff、最近のコミット- 依存関係の変更、設定の変更、環境差異
マルチコンポーネントの場合: 各層にログを仕込む
各コンポーネント境界で: - 入力データをログ - 出力データをログ - 環境/設定の伝播を検証 → 1回実行してどこで壊れるか証拠を集める → その特定コンポーネントを調査データフローを追跡する
- 不正な値はどこで生まれた?
- 何がその値を渡した?
- 源流まで遡り、源流で修正
Pattern Analysis(パターン分析)
- 動作する類似コードを探す - 同じコードベース内に手がかりがある
- 差分を特定する - 動くものと壊れたものの違いをすべてリストアップ
- 「関係ないはず」を疑う - 小さな差異こそ原因であることが多い
Hypothesis(仮説と検証)
科学的方法で:
- 1つの仮説を立てる: 「Xが根本原因だと思う。理由はY」
- 最小限の変更でテスト: 1変数ずつ。複数を同時に直さない
- 確認してから進む: 効かない → 新しい仮説を立てる。上から修正を積まない
Fix(修正実装)
失敗するテストケースを作る -
tddスキルに従う1つの修正を実装 - 根本原因に対処。ONE change at a time
修正を検証 - テスト通過? 他テストは壊れていない?
修正が効かない場合:
- 修正回数を数える
- 3回未満: Investigation に戻り、新情報で再分析
- 3回以上: アーキテクチャを疑う
- このパターンは根本的に正しいのか?
- 惰性で続けていないか?
- ユーザーと議論してから次の修正を試みる
Red Flags - 止まって Investigation に戻る合図
- 「とりあえず直して、後で調べる」
- 「X変えて動くか見てみよう」
- 調査前に修正案を並べている
- 2回以上失敗して「もう1回だけ」
クイックリファレンス
| Step | 主な活動 | 完了条件 |
|---|---|---|
| Investigation | エラー読解、再現、変更確認 | WHATとWHYを理解 |
| Pattern Analysis | 動作例との比較 | 差異を特定 |
| Hypothesis | 仮説立案、最小検証 | 確認または新仮説 |
| Fix | テスト作成、修正、検証 | バグ解決、テスト通過 |