あなたのコードレビューはおそらく機能不全だ

ほとんどのコードレビューは、本来見つけるべき欠陥の15〜30%しか捉えられない。これは憶測ではない。IBMが1970年代に測定し、AT&T、HP、Microsoftでの研究が何十年にもわたって同じ範囲を確認している。

非公式なレビューは安価で、非同期であり、社会的にも受け入れられやすい。しかし、バグを見つけるという点ではほとんど効果がない。エンジニアは読むのが速すぎ、エラーパスを飛ばし、マージを止める人になりたくないので本質的な問題を指摘しようとしない。

60〜90%の欠陥除去率を一貫して報告する代替手段がある。それは1976年にIBMのMichael Faganによって発明された。ツールもAIも予算も必要ない。必要なのは、ほとんどのエンジニアリングチームが拒否するものだ。それは「構造」である。

Fagan Inspectionとは何か

Fagan Inspectionは、特定の役割、時間制限、入力基準、チェックリストを持つ、形式的に定義された多段階レビュープロセスである。典型的なプルリクエストレビューとは異なり、著者とレビュアーとの会話ではない。モデレーター、リーダー、インスペクター、著者による構造化された会議である。

著者はほとんど黙っている。会議は厳密にタイムボックスされる。そして唯一の目的は欠陥を見つけることだ。

このプロセスは6つのステップに従う:

  1. Planning(計画)。 モデレーターが資料を選定し、入力基準を検証し、役割を割り当て、会議をスケジュールする。入力基準には理由がある。草稿は検査しない。文書は完全で、コンパイル可能で、テスト済みでなければ、4人の時間を消費する権利を得られない。

  2. Overview(概要)。 任意。インスペクターがドメインに不慣れな場合、著者が文脈を説明する。

  3. Preparation(準備)。 各インスペクターは会議前に個別に資料をレビューする。これは譲れない。準備なしで出席することはない。インスペクターは一般的な欠陥タイプに合わせたチェックリストを使用し、問題を個人的に注釈する。

  4. Inspection(検査)。 会議自体。コードを書いていないリーダーが1行ずつ読み進め、声に出して言い換える。インスペクターは不整合を発見した際に問題を提起する。著者は聞く。誰も修正案を提案しない。モデレーターは時間制限を厳守し、会議を欠陥の特定のみに集中させる。

  5. Rework(修正)。 著者が欠陥を修正する。

  6. Follow-up(フォローアップ)。 モデレーターがすべての欠陥が対処されたことを確認する。欠陥が多すぎる場合は再検査が行われる。

4つの役割がプロセスを公正に保つ。モデレーターは計画と管理を行う。著者は成果物を作成し、聞かれたときのみ質問に答える。リーダーは会議中にコードを言い換え、より遅く慎重な理解を強制する。インスペクター、通常2〜4人が欠陥を見つける。

なぜ非公式レビューが失敗し、Fagan Inspectionが成功するのか

違いは才能ではない。プロセス設計である。

典型的なプルリクエストレビューでは、レビュアーはブラウザで差分を読み、ハッピーパスをざっと眺め、数件のコメントを残し、承認する。準備時間はない。チェックリストもない。レビュアーにエラーハンドリングや境界条件を調べさせる仕組みもない。社会的ダイナミクスは、徹底性ではなく速度と配慮を報いる。

Fagan Inspectionはそのインセンティブを逆転させる。

個別準備とは、会議開始前に各インスペクターが実際にコードを読んだことを意味する。リーダーの言い換えは、グループがコードをスキミング速度ではなく理解速度で処理することを強制する。チェックリストは、目に留まったものではなく、既知の欠陥カテゴリへ注意を向ける。時間的プレッシャーは会議が設計論争に逸れないように防ぐ。そして欠陥発見と欠陥修正を分離することで、グループが最初に提示された解決策に固定されるのを防ぐ。

結果として、Fagan Inspectionはテストや本番に到達する前にほとんどの欠陥を捉える。

コストは前倒しで人時にかかる。

本当のトレードオフ:人時対欠陥の逸出

なぜほとんどのチームがFagan Inspectionを使わないのか、理由はここにある。

1回の検査には、約250行のコードをレビューするために、4〜6人が最大2時間部屋にいる必要がある。小さな変更で8〜12人時だ。1日に何度もデプロイする現代のCI/CDワークフローでは、これは馬鹿げているように見える。

このプロセスは官僚的にも感じられる。入力基準、正式な役割、印刷されたチェックリスト、フォローアップ検証。ほとんどのエンジニアは原則として嫌うだろう。そして大きな差分にはスケールしない。2000行のリファクタリングには8回の別々の検査会議が必要になる。

しかし、会議コストではなく総コストを見ると計算が変わる。

IBMの元データは、検査中に欠陥を発見・修正するコストは、テスト中に同じ欠陥を発見・修正するコストの約10分の1だったことを示した。本番に逸出した場合、比率は20〜30倍にまで膨れ上がった。

確かに、検査は高価だ。それでも本番インシデントのデバッグ、リアクティブ修正でスプリント容量を燃やすこと、顧客の信頼を失うことよりは安い。

問題は、節約が見えないことだ。防止したバグを測定することはできない。会議のコストは即座に明白だ。そのため、ほとんどの組織で非公式レビューが勝つ。可視な速度を不可視な品質よりも最適化する。

2026年に軽量Fagan Inspectionを実行する

完全な儀式を採用する必要はない。ほとんどのチームは、コアメカニクスを維持し書類仕事を削ることで、オーバーヘッドの20%で70%の利益を得られる。

実践的な手順は以下の通り:

同期レビューの前に個別準備を必須とする。コードを読んでいない場合は出席しない。

コードを書いていないリーダーを割り当て、論理を声に出して説明させる。著者に主導させない。言い換えはグループにすべての分岐を処理させる。

チームで最も一般的な欠陥タイプに合わせたチェックリストを使用する。以下のリストから始め、逸出した欠陥から学びながら項目を追加する。

90分にタイムボックスする。終わっていなくても時間通りに終了する。疲労が品質を損なわせるよりは、2回目のセッションをスケジュールする。

著者を受動的に保つ。彼らは明確化の質問のみに答える。設計判断を擁護しない。

解決策ではなく欠陥を記録する。会議後に欠陥を修正する。

具体化するために、検査を計画し、時間を見積もり、役割別チェックリストを出力する小さなPythonスクリプトを以下に示す:

#!/usr/bin/env python3
"""
Plan a Fagan-style inspection: estimate time and emit checklists.
"""

import argparse


def count_lines(filepath):
    """Count non-blank lines."""
    try:
        with open(filepath, "r") as f:
            return sum(1 for line in f if line.strip())
    except Exception:
        return 0


def plan_inspection(files, rate=125):
    """
    rate: reviewable lines per hour. Fagan recommended 100-125 for code.
    """
    total = sum(count_lines(f) for f in files)
    hours = total / rate
    minutes = hours * 60

    print(f"Total reviewable lines: {total}")
    print(f"At {rate} lines/hour, schedule: {hours:.1f} hours ({minutes:.0f} min)")

    if hours > 2:
        sessions = int(hours / 2) + 1
        print(f"WARNING: exceeds 2-hour limit. Split into {sessions} sessions.")

    print("\n--- ROLE: Reader ---")
    print("Paraphrase each block aloud. Do not just read variable names.")
    print("Pause at every conditional, loop boundary, and API call.")

    print("\n--- ROLE: Inspector ---")
    checklist = [
        "Off-by-one in loops and array or slice access",
        "Null, None, or undefined dereferences",
        "Resource leaks: files, connections, locks, contexts",
        "Error paths: are they handled, returned, and tested?",
        "Return values: are they checked before use?",
        "Shared mutable state and thread safety",
        "Boundary conditions and input validation",
        "Invariant violations: what should stay true, and does it?",
    ]
    for item in checklist:
        print(f"  [ ] {item}")

    print("\n--- ROLE: Moderator ---")
    print("Start on time. End on time.")
    print("No design debates. No solution proposals.")
    print("Record each defect with: file, line, severity, type.")


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Plan a Fagan inspection")
    parser.add_argument("files", nargs="+", help="Source files to inspect")
    parser.add_argument("--rate", type=int, default=125, help="Lines per hour")
    args = parser.parse_args()

    plan_inspection(args.files, args.rate)

これを inspect.py として保存し、python inspect.py src/auth.py src/orders.py を実行すれば、時間見積もりとチェックリストが得られる。

よくある質問

Fagan Inspectionとは何ですか?

Fagan Inspectionは、定義された役割、入力基準、チェックリストを持つ構造化された6ステップのレビュープロセスである。1976年にIBMのMichael Faganによって開発され、テスト前にソフトウェア成果物の欠陥を見つけるために作られた。

Fagan Inspectionとプルリクエストレビューの違いは何ですか?

プルリクエストレビューは通常非同期で、非公式であり、著者主導である。Fagan Inspectionは、割り当てられた役割、必須の個別準備、厳格な時間制限、そして他の人が欠陥を見つける間著者が沈黙を保つルールを持つ同期会議である。

なぜFagan Inspectionはもっと普及していないのですか?

人時において高価であり、現代のチームにとって官僚的に感じられ、大規模で頻繁な変更にはうまくスケールしない。コストは可視で即座である。防止された欠陥は不可視である。

Fagan InspectionはアジャイルやCI/CD環境で機能しますか?

はい、ただし変更を加える必要がある。ほとんどのチームは軽量版を使用する:必須の個別準備、言い換えるリーダー、チェックリスト、厳格なタイムボックス。完全な正式プロセスは通常、重要または高リスクなモジュール用に予約される。

1つのモジュールで試してみる

プロセスを書き換える必要はない。先月に逸出欠陥があったモジュールを1つ選ぶ。それを書いていない3人のエンジニアを集める。24時間前にコードとチェックリストを渡す。90分をスケジュールする。リーダーを割り当てる。著者に聞かせる。

何が見つかったかを測定する。そして会議のコストがバグのコストより高かったかどうかを判断する。

元データが必要な場合、Faganの1976年の論文「Design and Code Inspections to Reduce Errors in Program Development」が依然として最良の参考文献である。50年前のものだが、ほとんどのチームはまだ追いついていない。