誰も使わない、最も効果的な品質プロセス

1976年、Michael FaganはIBM Systems Journalに論文を発表した。そこに記されたレビュー・プロセスは、ソフトウェア品質のゴールドスタンダードとなるほど効果的だった。Fagan Inspectionsは、1つのテストも実行される前に、全欠陥の60〜90%を捉えていた。2002年のNASAの調査では、インスペクションに1時間費やすごとに、後の保守作業を平均33時間防いでいたことがわかった。

あらゆる測定基準から見て、これはソフトウェア工学史上、最高のレビュー・プロセスだった。

今日、ほとんど誰もこれを使っていない。

問われるべきは、Fagan Inspectionsが機能したかどうかではない。あまりにも機能しすぎたのだ。問われるべきは、そこまで実績を積んだプロセスがなぜ主流の開発現場から消えたのか、そして我々がそれを置き換えたとき、重要な何かを失わなかったのかということである。

Fagan Inspectionsの実際の姿

Faganはcode reviewそのものを発明したわけではない。欠陥を見つけるための、特定の、高度に構造化された儀式を発明したのだ。

このプロセスは6つの厳格なフェーズから成る。

  1. Planning: モデレーターが参加者を選び、資料がエントリー基準を満たしているか検証する。
  2. Overview: 著者が背景を説明する。これは文脈設定であり、レビューそのものではない。
  3. Preparation: 各参加者が資料を個別に精査する。速度はおおむね1時間あたり150行。疑わしい欠陥の個人リストを作成する。
  4. Inspection Meeting: チームは2時間以内に集まる。Readerが論理を声に出して読み上げる。Recorderが欠陥を記録する。モデレーターは、欠陥を解決することではなく、欠陥を発見することに会議の焦点を合わせる。
  5. Rework: 著者が記録されたすべての欠陥を修正する。
  6. Follow-up: モデレーターが修正が行われ、新たな欠陥が混入していないか検証する。

役割は明確で重複しない。モデレーターはプロセスを運営するが、技術的権限者ではない。Readerはコードを読み上げるが、擁護はしない。著者は出席するが、会議中に意図を説明することを禁じられている。目的は協力ではない。冷徹で体系的な欠陥検出なのだ。

これこそが機能した所以である。通常のエンジニアリング会議の社会力学は、意図的に排除されている。

なぜ数値があれほど優秀だったのか

欠陥検出率が偶然ではなかった。いくつかの意図的な設計上の選択から生じていた。

Independent preparationによって、6人がグループ討論によって影響を受ける前に、同じコードを隔離して精査した。リストの重なり部分は、欠陥がどれほど明らかだったかを示す。1人だけが見つけた項目が、しばしば最も価値が高かった。

2時間という厳格な上限は、疲労が判断を損なうのを防いだ。Faganは、2時間を過ぎるとインスペクションの効果が急激に落ちることを知っていた。1時間あたり150行という速度も意図的だった。それ以上速くなると、人は実際にあるものではなく、自分が期待するものを見始める。

No-solutionsルールは会議の焦点を保った。メンバー全員が、まだ十分に特徴づけもされていない欠陥の修正案を設計し始める会議ほど、インスペクションを破壊するものはない。

これらの制約は官僚的なオーバーヘッドではなく、仕組みそのものだった。これらを取り除けば、より親しみやすいが、効果的でないものができあがる。

Fagan Inspectionsを殺したもの

これほど効果的なプロセスが、なぜ消えたのか。

短く答えれば、それは現代のソフトウェア開発が容認しようとしない方法で、コストがかかっていたのだ。

1回のFagan Inspectionは、レビュー対象コードの作成に費やされた工数の15〜20%を消費した。記録された事例では、348行のコードに27.3人時のインスペクションが必要だった。この比率は、1日に何度もリリースするチームにとって想像を絶する。

スケジュール調整だけでも常勤の仕事だった。5〜6人を2時間拘束し、preparationとfollow-upを加える。大規模組織では、モデレーター、Reader、2名のReviewer、Recorder、著者が全員参加できる2時間の枠を見つけるのに数日を要することもあった。

厳格な役割構造もスケールしなかった。Fagan Inspectionsは、全役割を埋められる十分な人員を持つ安定したチームを前提としていた。スタートアップの5人チームでは、velocityを損なわずに専任モデレーターを置くのは難しい。

最大の要因は文化的なものだった。Fagan Inspectionsは意図的に不快感を伴うものだった。著者は黙って座り、同僚が自分のコードを読み上げ、その欠陥を記録する。これは「まだ初稿だから」という言い訳の余地がない。欠陥は高価で、社会的摩擦は安価だという前提に立っている。現代のエンジニアリングは、正反対の前提で動いている。

我々が置き換えたもの

業界は構造化レビューを放棄したわけではない。pull requestに置き換えたのだ。

Pull request reviewは非同期で、儀式を最小限に抑え、開発workflowに直接組み込まれている。Reviewerは会議の合間に、スマートフォンで、あるいはCIの終了を待ちながらdiffを見ることができる。割り当てられた役割はない。著者とReviewerは、mergeのためにあと1つapprovalが必要な同じ人間であることも多い。

これはアクセシビリティ、速度、developer experienceにおいて飛躍的な改善だ。同時に、欠陥検出において飛躍的な後退でもある。

複数の調査で、非公式レビューは構造化インスペクションが捉える欠陥のおおむね半分しか捉えられないことが判明している。2009年にBasiliらが行った実験では、Fagan式インスペクションとlightweight reviewを比較し、軽量プロセスが同じ資料から著しく少ない欠陥を検出した。

問題はReviewerが怠けているからではない。プロセスは欠陥を見つけるよう設計されていない。コードを出荷する際に「もう1組の目」が通っていることを保証するよう設計されており、それは別の話だ。

我々が実際に失ったもの

Pull request reviewはスループットを最適化する。Fagan Inspectionは徹底性を最適化した。これらは本質的に異なる目標であり、どちらが間違いというわけではない。間違いは、軽量プロセスが重量プロセスの厳密な上位集合だと仮定することだ。

ここに消えたものがある。

Independent preparation。 Pull requestでは、Reviewerはdiffを白紙状態で見る。周辺文脈を読み、データフローを追跡し、メンタルモデルを構築するための1時間を費やしていない。通知に反応しているだけだ。精査の深さは比較にならない。

Readerの役割。 誰かにコードを声に出して読ませると、グループは最も遅い人間でもついていけるペースで進まなければならない。黙読では隠れてしまう仮定が浮き彫りになる。画面のdiffでは目が退屈な部分を飛ばす。Readerは飛ばさない。

Defect-only focus。 Pull requestのコメントは、スタイルやアーキテクチャの意見に流れがちだ。それらにも価値はあるが、欠陥検出ではない。インデントを議論する1分間は、null dereferenceを見つけるために費やされなかった1分間だ。

測定可能なプロセスデータ。 Fagan Inspectionsは硬い数値を生み出した。欠陥数/時間、preparation時間、rework時間、モジュールあたりのdefect density。現代のレビューツールはコメント数とapproval数を数えるだけで、レビュー品質についてほとんど何も語らない。

実用的な中間点

現代のcontinuous deployment環境で完全なFagan Inspectionsを実施するのは現実的ではない。しかし、重要な部分は借りることができる。

最も重要な移植可能なアイデアは、構造化されたindependent preparationだ。深い非同期レビューの前に、Reviewerが資料と単独で時間を過ごすことを義務付ける。ざっと目を通すのではない。本物のpreparationだ。

「LGTM」のような定型文に頼るのではなく、Faganが役割とルールに組み込んだ規律を模倣する軽量checklistを課す。

from dataclasses import dataclass, field
from typing import List, Optional
from enum import Enum

class DefectSeverity(Enum):
    MINOR = "minor"
    MAJOR = "major"
    CRITICAL = "critical"

@dataclass
class ReviewEntry:
    line_number: Optional[int]
    category: str
    severity: DefectSeverity
    description: str

@dataclass
class InspectionReport:
    reviewer: str
    prep_time_minutes: int
    entries: List[ReviewEntry] = field(default_factory=list)

    def defect_count(self) -> int:
        return len(self.entries)

def run_inspection_checklist(
    code: str,
    reviewer: str,
    prep_time_minutes: int
) -> InspectionReport:
    """Structured prep produces structured output.

    Mimics the Fagan prep phase: reviewer spends focused
    time with the material, then logs findings against a
    consistent taxonomy instead of ad hoc comments.
    """
    report = InspectionReport(
        reviewer=reviewer,
        prep_time_minutes=prep_time_minutes
    )

    # Example: check for missing null handling
    if "->" in code and "null" not in code.lower():
        report.entries.append(ReviewEntry(
            line_number=None,
            category="null-safety",
            severity=DefectSeverity.MAJOR,
            description="No explicit null handling in pointer function"
        ))

    return report

これはFagan Inspectionではない。だが、その最も重要な特性の1つを取り戻す方法だ。レビュー成果は構造化され、測定可能であり、意見ではなくdefect categoryに焦点を合わせるべきだということだ。

もう1つの移植可能なアイデアは、time-boxed deep reviewだ。スプリントごとに1つのクリティカルなモジュールを選ぶ。Independent preparationを伴う90分間の集中レビューを計画する。欠陥のみを記録する。解決策なし、スタイル論争なし、設計議論なし。

コストは現実のものだ。しかし、NASAの比率がおおむね成り立つなら、今ここで1時間集中することで、後になって数十時間のデバッグを節約できる。

居心地の悪い真実

Fagan Inspectionsは失敗しなかった。それが要求する厳密さが、業界が優先していた速度と両立しなかったために拒絶されたのだ。

このトレードオフは多くのソフトウェアにとって理にかなっていた。landing pageのボタンのタイプミスに、5人による正式なインスペクションは必要ない。だが、Fagan Inspectionsを置き換えた文化は、すべてのコードを等しく扱い、そこにコストが潜んでいる。

最も高価な欠陥は、見た目が正しく、テストも通り、本番で実際の金銭的損失をもたらす形で失敗するコードの中にある。まさにそのコードこそが、diffをapproveするよう設計されたプロセスではなく、欠陥を見つけるよう設計されたプロセスから最大の利益を得る。

Pull request reviewは今後も続くだろうし、それ自体は構わない。しかし、それが構造化インスペクションの代替だと見なすのは構わない。それは別の仕事のための別の道具であり、どちらか一方しか持たないチームは、出荷前に優れたプロセスで捉えられたはずの高価なバグを、今後も見つけ続けることになる。

FAQ

Fagan Inspectionとは何か。

1970年代にIBMのMichael Faganが開発した、ソフトウェア成果物の欠陥を発見するための構造化された多段階レビュー・プロセス。6つのフェーズ(Planning、Overview、Preparation、Inspection Meeting、Rework、Follow-up)を持ち、参加者には特定の役割が割り当てられる。会議は欠陥の解決ではなく、欠陥の記録のみに焦点を当てる。

Fagan Inspectionsはどれほど効果的だったか。

IBMは90%を超えるdefect removal率を報告した。2002年のNASA調査では、1時間のインスペクションが平均33時間の保守作業を防いでいた。独立した調査では一貫して、構造化インスペクションが非公式レビューの約2倍の欠陥を捉えることが判明している。

なぜチームはFagan Inspectionsの使用をやめたのか。

このプロセスは総プロジェクト工数の15〜20%を消費し、複数参加者の困難なスケジュール調整を必要とし、文化的に厳格だった。ソフトウェアチームがより高速なリリースサイクルへ移行するにつれ、オーバーヘッドが持続不可能になった。Pull request reviewは、より少ない欠陥を捉えても、通常のworkflowへの統合が速くて簡単なため、デフォルトとしてそれを置き換えた。

現代のチームはまだFagan Inspectionsから利益を得られるか。

元の形ではない。割り当てられた役割を持つ完全な6フェーズ・プロセスはcontinuous deploymentには合わない。しかし、中核的なアイデアであるindependent preparation、time-boxed focused review、structured defect logging、そして欠陥発見とsolution designの分離は適応可能だ。これらをクリティカルなコードに選択的に適用するチームは、オーバーヘッドなしに多くの利益を得る。