你的程式碼審查可能已經失效
大多數程式碼審查只能發現本應找到的缺陷的15%到30%。這不是猜測。IBM在20世紀70年代就測量過,AT&T、惠普和微軟的研究也在數十年間反覆確認了這一範圍。
非正式審查成本低廉、非同步進行、 socially acceptable。但它在發現缺陷方面基本上是無效的。工程師讀得太快,跳過錯誤路徑,而且為了避免成為阻塞合併的那個人,他們不願指出真正的問題。
有一種替代方法能夠持續報告60%到90%的缺陷移除率。它由麥可·法根於1976年在IBM發明。不需要工具,不需要AI,不需要預算。它需要的是大多數工程團隊不願給予的東西:結構。
什麼是Fagan Inspection
Fagan Inspection是一種正式定義的多步驟審查流程,具有特定角色、時間限制、准入標準和檢查清單。與典型的拉取請求審查不同,它不是作者和審查者之間的對話。而是一個有主持人、閱讀者、檢查員和作者參與的結構性會議。
作者基本保持沉默。會議有嚴格的時間限制。唯一的目標是發現缺陷。
該流程遵循六個步驟:
-
規劃。 主持人選擇材料,驗證准入標準,分配角色,並安排會議。准入標準的存在是有原因的。不審查草稿。文件必須完整、可編譯且經過測試,才有資格占用四個人的時間。
-
概述。 可選。如果檢查員不熟悉該領域,作者解釋背景。
-
準備。 每位檢查員在會議前單獨審查材料。這一點不可協商。不能毫無準備地到場。檢查員使用針對常見缺陷類型定製的檢查清單,並私下標註問題。
-
檢查。 會議本身。沒有寫過代碼的閱讀者逐行瀏覽代碼並大聲複述。檢查員發現差異時提出問題。作者傾聽。沒有人提出修復方案。主持人執行時間限制,並確保會議僅專注於缺陷識別。
-
返工。 作者修復缺陷。
-
跟進。 主持人驗證每個缺陷都已得到處理。如果發現太多缺陷,則進行重新檢查。
四個角色確保流程的公正性。主持人負責規劃和控制。作者創建了作品,僅在有人詢問時才回答問題。閱讀者在會議期間複述代碼,迫使大家以更慢、更仔細的速度理解。檢查員通常為二至四人,負責發現缺陷。
為什麼非正式審查失敗的地方,Fagan Inspection能成功
區別不在於天賦。在於流程設計。
在典型的拉取請求審查中,審查者在瀏覽器中閱讀差異,瀏覽正常路徑,留下幾條評論,然後批准。沒有準備時間。沒有檢查清單。沒有強制審查者檢查錯誤處理或邊界條件的機制。社交動態獎勵的是速度和禮貌,而不是徹底性。
Fagan Inspection反轉了這些激勵。
個人準備意味著每位檢查員在會議開始前確實已經閱讀了代碼。閱讀者的複述迫使團隊以理解速度而非瀏覽速度來處理代碼。檢查清單將注意力引向已知的缺陷類別,而不是什麼吸引了眼球。時間壓力防止會議偏離到設計辯論中。將缺陷發現與缺陷修復分開,防止團隊錨定在某人提出的第一個解決方案上。
結果是,Fagan Inspection在缺陷到達測試或生產環境之前就能發現大部分缺陷。
成本前置體現在人時上。
真正的權衡:人時與缺陷逃逸
這就是大多數團隊不使用Fagan Inspection的原因。
一次檢查需要四到六個人在房間裡待上最多兩個小時,才能審查大約250行程式碼。這是一項小變更需要8到12人時。在現代CI/CD工作流中,團隊每天部署多次,這看起來荒謬。
該流程也讓人感覺官僚化。准入標準、正式角色、列印的檢查清單、跟進驗證。大多數工程師原則上就會討厭它。而且它無法擴展到大型差異。一個兩千行的重構需要八次單獨的檢查會議。
但當你看總成本而非會議成本時,計算就變了。
IBM的原始數據顯示,在檢查期間發現和修復缺陷的成本約為在測試期間發現和修復同一缺陷成本的十分之一。當它逃逸到生產環境時,比例增長到二十或三十比一。
所以是的,檢查很昂貴。但它仍然比調試生產事故、將衝刺容量消耗在被動修復上以及失去客戶信任要便宜。
問題是節省是看不見的。你無法衡量你預防的缺陷。會議的成本是即時且明顯的。這就是為什麼非正式審查在大多數組織中獲勝。它優化的是可見速度,而非隱形品質。
在2026年執行輕量級Fagan Inspection
你不需要採納完整的儀式。大多數團隊可以通過保留核心機制、去掉文書工作,以20%的開銷獲得70%的收益。
以下是一個實用的流程:
在任何同步審查之前要求個人準備。如果你沒有讀過代碼,你就不參加。
指派一個沒有寫過代碼的閱讀者大聲講解邏輯。不要讓作者主導。複述迫使團隊處理每一個分支。
使用針對團隊最常見缺陷類型定製的檢查清單。從下面的清單開始,並從逃逸的缺陷中學習,不斷添加條目。
時間限制為九十分鐘。即使沒完成也要準時結束。與其讓疲勞破壞品質,不如安排第二次會議。
讓作者保持被動。他們只回答澄清問題。不要為設計選擇辯護。
記錄缺陷,而不是解決方案。會議後再修復缺陷。
為了具體說明,這裡有一個小型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是一種具有定義角色、准入標準和檢查清單的結構化六步審查流程。它由麥可·法根於1976年在IBM開發,用於在測試之前發現軟體工作產品中的缺陷。
Fagan Inspection與拉取請求審查有何不同?
拉取請求審查通常是非同步的、非正式的,由作者主導。Fagan Inspection是一個同步會議,具有分配的角色、強制性的個人準備、嚴格的時間限制,以及作者保持沉默而其他人發現缺陷的規則。
為什麼Fagan Inspection沒有更普及?
它們在人時上代價高昂,對現代團隊來說感覺官僚化,而且無法很好地擴展到大型、頻繁的變更。成本是可見且即時的。被預防的缺陷是不可見的。
Fagan Inspection能在敏捷或CI/CD環境中運作嗎?
可以,但需要修改。大多數團隊使用輕量級版本:強制個人準備、複述代碼的閱讀者、檢查清單和嚴格的時間限制。完整的正式流程通常僅保留給關鍵或高風險的模組。
在一個模組上嘗試
你不需要重寫你的流程。選擇一個在過去一個月中有過逃逸缺陷的模組。召集三位沒有寫過它的工程師。提前二十四小時給他們代碼和檢查清單。安排九十分鐘。指派一位閱讀者。讓作者傾聽。
測量你的發現。然後決定會議的成本是否高於缺陷可能造成的成本。
如果你想要原始數據,法根1976年的論文《Design and Code Inspections to Reduce Errors in Program Development》仍然是最佳參考。它已有五十年歷史,而大多數團隊仍未趕上。