vatt'ghern jaskier's ballads

軟體工程師常說,自己 review AI 生成的程式碼時,問題都抓得住——但初步證據顯示,這份自信本身可能就是問題所在:人在審查 LLM 寫出的程式碼時更有信心找齊了缺陷,實際抓到的卻更少。

審查 AI 生成的程式碼,撐不起 AI coding 的效率神話

多工程師形容自己跟 AI coding assistant 相處的方式,是「像帶 intern」——你不會盲目信任這個新人寫的每一行,但你會 review。軟體工程師 Thomas Depierre 在部落格 softwaremaxims 那篇〈Reviewing AI Code Is Not A Viable Argument〉裡,把這個類比接下去的推論攤開來檢查:既然你反正都要 review 所有進到 codebase 的程式碼,AI 寫的東西也不例外,「you are doing that for all the code that get into your codebase anyway, you do not let code get in without a review, right」——那 review 這道關卡,是不是就已經把「AI 有時候寫錯」的風險擋掉了?

Depierre 開頭先撇清立場:他懷疑 LLM coding assistant 的效益,不是因為智慧財產權的爭議,也不是因為生態或資源消耗——這兩個常見的批評他都同意「highly problematic」,但都不是這篇文章要談的。他要談一個更技術性的問題:review 這件事本身,有沒有辦法撐起「AI 讓寫程式變便宜,但我們靠 review 守住品質」這句話。答案他早早就給了:撐不住,理由跟 code review 已經有的實證研究直接衝突。

這篇文章值得認真讀,不是因為它的結論驚世駭俗——「review 是有成本的」這句話工程師大概都同意——而是因為它把這個常識拆成可以計算的東西。大部分關於 AI coding 效率的討論,停在「生成速度變快了」這一半,很少有人把「review 這邊有沒有跟著變快」拿出來算一次。Depierre 做的事,就是把後面這一半攤開來看。

「review 一遍就好」的推論,接在哪裡

把 intern 類比接到底,推論鏈其實有三段:第一,AI 寫的程式碼跟 intern 寫的一樣不可盡信;第二,你原本就會 review 所有要進 codebase 的東西,這件事沒有變;第三,既然 review 這道關卡本來就在,AI 的產出多寫一點、寫快一點,只是把更多東西送進同一道關卡,關卡本身不用跟著變。這條推論在直覺上很順,問題出在第三段偷渡了一個假設:review 這道關卡的產能是無限的,或者至少有足夠的彈性,可以吸收任何份量的輸入。Depierre 接下來要做的,是把這個假設拿去對照 code review 已經有的實證研究。

類比

「像帶 intern」——AI 寫的程式碼跟新人寫的一樣不可盡信,你反正都要 review 所有進 codebase 的東西。

「you do not let code get in without a review, right」——review 這道關卡本來就在,AI 只是多送一點東西進來。

斷點

review 這道關卡的產能有實證上限:大約 400 LOC/小時,超過 1 小時效益就快速遞減。

從來沒有人規定,帶 intern 時「review 的量」要追上 AI 這種產出速度。

兩張卡片放在一起看,斷點很清楚:「review 一遍」這件事本身能撐多少量、撐多久,從來沒有人拿去跟 AI 的產出速度放在一起對照過。這條斷點不是 Depierre 發明的新概念——任何團隊在制定 code review 規範時,多少都隱約知道 review 有速度限制,只是很少人把它寫成一個明確的數字,拿去跟另一件事的速度做對照。intern 類比之所以好用,是因為它把「review 有極限」這件事藏在一個大家都熟悉、不會細想的比喻裡;一旦兩個速度被同時攤開,比喻能提供的安全感就消失了。

review 有自己的物理上限

Depierre 把兩個數字當成 code review 這個領域已經確立的實證發現在講。第一個是速度上限:「a maximum of 400 LOC/H is a good maximum speed acceptable for efficience」——一小時審查超過 400 行程式碼,有效性就開始打折。第二個是時間上限:「reviews that are longer than 1h quickly reach diminishing returns whatever is the size of the code being reviewed」——一場 review 只要拖過一小時,不管在審查多大的一塊程式碼,效益都會快速遞減。

這兩個數字是這篇文章論證的地基,但地基本身沒有附上任何一篇論文、研究或部落格文章的連結——整篇文章能找到的連結,只有 Depierre 自己的 Mastodon、GitHub、信箱跟 Atom feed。他講「400 LOC/H」這種精確度講得很篤定,卻沒有留給讀者可以自己回頭核對的路徑。這不代表 400 LOC/H 或一小時上限是錯的——code review 領域確實累積了不少關於審查速度與缺陷密度的研究——但單看這篇文章,讀者只能選擇相不相信作者的轉述,沒辦法直接查證。

合理的推測是,400 LOC/H 這個數字算的多半是「讀懂並判斷正確與否」的速度,不包含來回討論、等 CI 跑完、或重新測試這些前置與後續動作——真正把一個 pull request 從送出到 merge 的總時間,通常比單純的閱讀速度還要長。這一層推算文章本身沒有明說,但如果連閱讀本身都卡在 400 LOC/H,加上其他流程只會讓實際產能更低,不會更高。

把這兩個數字換算成「一天到底能安全生出多少行程式碼」,可以自己拖拖看下面三個滑桿——AI 一天生成多少、你 review 的速度有多快、你願意花多少時間在 review 上。

拖曳三個滑桿,看 review 產能追不追得上 AI 的生成速度 · 3 個變數

3,000
400
2
今天生成的量,跟今天真正審得完的量,是兩件事 AI 生成 可安全 review 完 <1,000 0 2000 4000 6000 8000 LOC/天
淡綠區間:作者稱的「最佳情境」——幾千行/天(原文未給精確數字,這裡抓 2,000 到 4,000 當示意區間) 虛線:作者稱的「更真實情境」——<1,000 LOC/天(原文給的精確數字)
今天生成3,000 LOC
今天可安全 review 完600 LOC
缺口(backlog)2,400 LOC/天
五個工作日後累積12,000 LOC

「可安全 review 完」的演算法:前 1 小時照設定的速度算,超過 1 小時的部分打對折——這是本圖為了畫出「超過 1 小時效益快速遞減」這句話而用的示意模型,原文只說 quickly reach diminishing returns,沒有給精確的衰減公式,此處的對折假設是作者本站自己的推算,不是原文的數字。

預設值已經很說明問題:一天生出 3,000 行,以 400 LOC/小時的速度 review 兩小時,扣掉超過一小時後打對折的效益,一天真正審得完的只有 600 行——缺口 2,400 行,五個工作天下來就是 12,000 行沒被真正看過的程式碼堆在那裡。把生成速度拉到更快、把 review 時數壓得更低,缺口只會更難看,這正是 Depierre 想讓讀者自己動手算一次的東西。

合理的推測是,這個缺口不會只發生在單一工程師身上。一個團隊裡如果多個人同時用 AI coding assistant,每個人的生成量都在往上疊,但 review 資源——不管是同儕互審還是資深工程師把關——並沒有跟著等比例增加。缺口不是加總,是乘上團隊人數之後的結果,backlog 累積的速度只會更快。

換算下來,一天到底能生出多少「安全」的程式碼

Depierre 自己給的答案分兩個版本:「a developer using a LLM Coding Assistant can write, review and commit, at best, a few thousands LOC per day to a codebase. And that is the best case scenario, a more realistic one is less than 1k LOC per day」——樂觀情境一天幾千行,更真實的情境一天不到 1,000 行。這兩個數字包含了所有種類的程式碼:樣板、測試、遷移腳本、設定檔,不是只挑最容易寫的那一種來算。跟「AI 一天能生成幾千甚至上萬行」這種常見說法擺在一起,落差就出來了:生成速度從來不是瓶頸,review 產能才是。

這個結論本身不需要多花俏的統計——它只是兩個速度上限相乘的結果。真正值得留意的,是這個結論跟「review 一遍就好」那個直覺說法之間的距離:後者假設 review 是一道可以無限拉伸的關卡,前者說它其實是整條生產線裡最硬的天花板。業界對 AI coding 效率的討論,大多停留在「生成速度提升幾倍」這個框架裡——這個框架本身沒有錯,錯的是把它直接等同於「工程團隊整體產出提升幾倍」。中間那道 review 關卡的產能,從來沒有被拉進同一個公式裡一起算,Depierre 這篇文章做的,就是把這道關卡放回公式裡。

這也是為什麼「review 一遍就好」這句話容易讓人安心,卻經不起計算:它把 review 講成一個開關——「有做」或「沒做」,而不是一個有速度、有上限、會累積 backlog 的流程。一旦把它當成流程來看,跟排程或佇列沒有本質差別:進來的速度超過處理的速度,排隊的東西只會越堆越多,不會自己消失。

更弔詭的一條——review AI 寫的碼時,人更有信心,抓得更少

Depierre 舉的另一個發現比前兩個數字更關鍵,也更沒有把握。他寫的是「humans that review code generated by LLM Coding Assistants are more confident that they found all the defects, while finding less defects」——人在審查 LLM 生成的程式碼時,更有信心自己抓齊了所有缺陷,但實際找到的缺陷卻更少。他自己給這個發現的定性是「tentative evidence」,後面又補了一句「so far there is tentative burgeoning evidence that reviewing LLM generated content is, indeed, different」——初步、剛冒出頭的證據,說明審查 LLM 生成的內容,確實跟審查人寫的內容不一樣。

Depierre 講的落差可以拆成兩半:review AI 生成的程式碼時,人的審查信心原文:more confident that they found all the defects——作者自稱這是 tentative evidence,沒有附上研究連結。會提高,但實際抓到的缺陷原文:while finding less defects——信心上升、缺陷偵測下降,是同一句話的前後兩半,同時發生。反而變少。

「humans that review code generated by LLM Coding Assistants are more confident that they found all the defects, while finding less defects.」
「so far there is tentative burgeoning evidence that reviewing LLM generated content is, indeed, different.」

這條發現如果站得住,後果比前兩個數字更嚴重——因為它動搖的不是「review 能撐多少量」,而是「review 這個動作本身,對 AI 生成的程式碼還有沒有效」。但 Depierre 自己也沒有把它講死,用的字是 tentative,不是 established 或 proven。這篇文章對這條發現誠實的地方,剛好也是它最沒有分量的地方:一個連作者自己都還在觀察的訊號,沒辦法拿來當成論證的地基,只能當成一個值得留意的方向。

合理的推測是,這種過度自信的來源,可能跟 AI 生成的程式碼「看起來很完整」有關——變數命名工整、註解齊全、格式一致,這些表面特徵容易讓審查者的警覺下降,即使程式邏輯本身有問題。人審查同事寫的、風格參差的程式碼時,反而更容易停下來多想一步。這個機制文章沒有明說,只是一個合理的猜測,不是 Depierre 給出的解釋。

如果這個落差真的存在,它對 review 流程設計的意義,可能比「花更多時間 review」更值得想:與其假設同一套 review 習慣可以無差別套用在人寫的碼跟 AI 生成的碼上,不如承認兩者需要不同的檢查方式——比方說對 AI 生成的內容多問一句「這段邏輯我自己會不會寫成一樣的?」,而不是只確認格式跟語法有沒有問題。這是一個延伸的建議,文章本身沒有具體展開。

最該小心 review 的 shell script,大家反而最常丟給 AI

Depierre 挑出一個具體場景收尾:shell script。他形容這類程式碼「the code that is the easiest to get wrong, the harder to review, the harder to understand you made a fatal mistake that will blow up everything be written by the machine」——最容易寫錯、最難 review,也最難在出錯的當下就看出「這會把整個系統炸掉」。他補了一句更直白的:「a simple typo in a ponctuation could be utterly harmless or literally make you delete a whole computer」——一個標點符號打錯,結果可能毫無影響,也可能把整台電腦刪掉。

shell script 裡打錯一個標點 a simple typo in a ponctuation outcome A 「utterly harmless」 幾乎看不出差別 程式照常跑 outcome B 「delete a whole computer」 把整台電腦 的資料清空
Depierre 形容這類程式碼「the easiest to get wrong, the harder to review」——同一種打錯標點的錯誤,落在 outcome A 還是 outcome B,事前很難分辨。

諷刺的地方在這裡:shell script 恰好是最常被人推薦「乾脆讓 AI 寫」的一種程式碼——重複性高、樣板感重,看起來最適合交給 assistant 代勞。但如果 review 本身的產能有上限,AI 生成的內容又讓人「更有信心、抓得更少」,把這兩個弱點同時疊在 shell script 這種容錯率最低的場景上,等於把 review 最脆弱的地方,擺在後果最重的地方。

shell script 之所以特別脆弱,某種程度上也跟它的語言設計本身有關:沒有強型別系統可以在編譯期擋下明顯的錯誤,字串跟指令之間的界線又常常靠空白字元跟引號撐著,一個字元的差異就可能改變整條指令的語意。這些是 shell 這個語言長期以來就有的已知特性,不是這篇文章的論點,但正好解釋了為什麼「打錯一個標點」這種描述不是誇張的說法。

把這件事跟前面兩個章節的數字放在一起看,shell script 幾乎是這篇文章論證的最壞情境:review 產能有上限、AI 生成的內容讓人更容易掉以輕心,兩者疊加後果最重的地方,剛好又是業界最常見的「反正讓 AI 寫」的場景。三件事各自看都只是提醒,疊在一起看就是一個值得認真對待的警訊。

連作者自己都沒附上引用

整篇文章讀完,最誠實的一段反而是收尾。Depierre 沒有拿出更多數字說服讀者,寫的是:「If you want to convince me, please stop calling me nuts or bringing anecdotal information about 'hey this time it worked for me'. Start looking at how we got all this empirical evidence around code review in the first place and go do some studies.」——如果你想說服我,別再說我瘋了,也別再拿「這次對我有效」這種軼事當證據,回頭看看 code review 這些實證證據當初是怎麼來的,自己去做研究。

點任一張卡看它有沒有附上研究出處 · 4 條主張

四條主張,誰標了保留、誰沒有

審查速度上限 無 hedge 無連結 一小時上限 無 hedge 無連結 信心與缺陷的落差 tentative 無連結 shell script 最難 review 無 hedge 無連結

「a maximum of 400 LOC/H is a good maximum speed acceptable for efficience」——文中沒有附上研究連結,全文能找到的連結只有作者的 Mastodon、GitHub、信箱跟 Atom feed。

「reviews that are longer than 1h quickly reach diminishing returns whatever is the size of the code being reviewed」——同樣當成既定發現在講,同樣沒有連結。

「humans that review code generated by LLM Coding Assistants are more confident that they found all the defects, while finding less defects」——作者自己標成「tentative evidence」,是四條裡唯一一條有明說保留態度的。

「the code that is the easiest to get wrong, the harder to review」——作者自己的觀察,沒有連結,也沒有引用其他人的分析。

把四條主張攤開放在一起看,只有一條被作者自己標成「tentative」,其餘三條都當成已經確立的事實在講——但四條都沒有附上連結。這不是說 400 LOC/H 或一小時上限是編造的:code review 研究這個領域確實存在,Depierre 顯然讀過一些。問題是這篇文章本身沒有留下讀者可以核對的路徑,連他自己在收尾都承認,說服他要靠「go do some studies」,而不是他已經做過的研究。

這不是特別針對 Depierre 的個人缺點——工程部落格普遍存在這個問題:作者讀過的論文、聽過的分享、自己團隊內部的觀察,混在一起變成一段語氣篤定的段落,讀者很難分辨哪一句話背後有紮實的研究,哪一句只是作者的個人經驗值。對讀者來說,比較安全的做法是把「這句話講得多篤定」跟「這句話有多少證據支撐」分開判斷,不要讓語氣本身變成說服力的來源。

這也是為什麼「AI 讓寫程式變便宜、review 把品質守住」這句話,遠比聽起來脆弱。生成端確實變便宜了——寫一個函式、拼一段 shell script,AI 幾秒鐘就能給出東西。但 review 端的成本結構幾乎沒變:一個人一小時大概還是只能有效看幾百行,一場 review 拖過一小時效益還是會掉。把便宜的生成跟昂貴不變的審查擺在一起,省下來的時間並沒有消失,只是從「寫程式」搬到了「積壓在 review queue 裡沒人看的程式碼」。

對讀者來說,這篇文章比較有用的部分,不是它給的兩個具體數字,而是它示範的計算方式:把「生成速度」跟「審查速度」拆成兩個獨立的變數,分別追問各自的上限在哪裡,再看兩者疊在一起會發生什麼事。這個計算方式,不管 400 LOC/H 這個確切數字準不準,都是值得每個團隊自己跑一次的練習。

怎麼看這篇文章:Depierre 的核心觀察經得起檢驗——review 是有產能上限的動作,AI 只加快了生成端,沒有加快 review 端,這個結構性落差是真的。但支撐它的兩個關鍵數字,跟那條「更有信心、抓得更少」的發現,文中都沒有給出可以核對的出處。讀這篇文章比較安全的方式,是把它當成一套值得認真對待的假說,而不是一份已經被驗證過的結論——這句話,某種程度上也是作者自己在收尾時的立場。