name: systematic-debugging description: "バグや障害を体系的に調査し、エビデンスに基づいて根本原因を特定する。Use when: 「動かない」「エラーが出る」「なぜか失敗する」「原因がわからない」「デバッグしたい」「テストが落ちる」「本番で問題が起きている」「再現できない」。一般的なコードレビューにはfind-bugsを使用。"
Systematic Debugging
推測ではなくエビデンスに基づいて根本原因を特定する体系的デバッグプロセス。
Iron Law
NO FIXES WITHOUT ROOT CAUSE INVESTIGATION FIRST
原因を特定せずに修正を試みることを禁止する。3回修正に失敗したらアーキテクチャの問題として人間にエスカレーションする。
Common Rationalizations
| こう思ったら | 現実 |
|---|---|
| 「原因は多分これだから先に直す」 | 推測で修正するな。まず再現・証拠を取れ |
| 「3回直しても失敗したがもう1回試す」 | 3回失敗はアーキテクチャの問題。人間にエスカレーション |
| 「ログを見れば分かる」 | ログは症状。根本原因は別のレイヤーにある可能性を疑え |
核心原則: 仮説を立てる前に事実を集める。修正する前に原因を理解する。
5ステップ プロセス
Step 1: 症状の正確な記録
まず事実を集める。推測しない。
記録する項目:
□ 何が起きているか(エラーメッセージ、スタックトレース)
□ 何が期待されていたか
□ いつから発生しているか(直近の変更との関連)
□ 再現条件(常に再現?特定条件?間欠的?)
□ 影響範囲(1ファイル?複数?全体?)
調査コマンド例:
# 直近の変更を確認
git log --oneline -10
git diff HEAD~5
# テスト失敗の詳細
# プロジェクト固有のテストコマンドを使用
Step 2: 仮説の列挙(まだ検証しない)
症状から考えられる原因を列挙する。この時点では検証しない。
| # | 仮説 | 確信度 | 検証コスト |
|---|------|--------|----------|
| 1 | {仮説A} | 高/中/低 | 小/中/大 |
| 2 | {仮説B} | 高/中/低 | 小/中/大 |
| 3 | {仮説C} | 高/中/低 | 小/中/大 |
優先順位: 確信度が高く検証コストが低い仮説から検証する。
Step 3: 仮説の検証(1つずつ)
各仮説を1つずつ検証する。複数同時に検証しない。
検証の記録:
□ 検証した仮説: {仮説名}
□ 検証方法: {何をしたか}
□ 結果: 支持 / 棄却 / 不確定
□ 根拠: {具体的なエビデンス}
検証テクニック:
- 二分探索: 問題を半分に分けて切り分ける
- 最小再現: 問題を再現する最小のコードを作る
- 差分分析: 動く状態と動かない状態の差分を特定する
- ログ挿入: 一時的なログでデータフローを追跡する
- git bisect: いつから壊れたかを特定する
Step 4: 根本原因の特定と修正
根本原因が判明したら:
- 原因を文書化: なぜこのバグが発生したかを記録
- 修正案を提示: 複数のアプローチがあれば比較
- 修正の影響範囲を評価: この修正で他が壊れないか
- テストを先に書く: 修正前にバグを再現するテストを作成(Red)
- 修正を実装: テストが通ることを確認(Green)
Step 5: 再発防止
修正だけでなく、同種のバグの再発を防ぐ:
□ テストが追加されたか(同じバグが再発したら検出できるか)
□ 根本原因は構造的か(他の箇所にも同じ問題が潜んでいないか)
□ ドキュメントの更新が必要か
デバッグのアンチパターン
- 推測で修正: 原因を特定せずに「これかも」で修正する
- 複数同時変更: 一度に複数の修正を入れて何が効いたか分からなくなる
- ログの消し忘れ: デバッグ用ログを本番に残す
- 症状の修正: 根本原因ではなく表面的な症状だけを修正する
- テストなし修正: 修正後のテストを書かずにクローズする
重要ルール
- 推測で修正しない: エビデンスに基づいて原因を特定してから修正する
- 1つずつ検証: 複数の仮説を同時に検証しない
- 修正前にテスト: バグを再現するテストを先に書く
- 記録を残す: 調査過程を
status.mdに記録する
関連スキル
- find-bugs: コードレビュー観点でのバグ発見に使用