Matt Pocock 前陣子直播訪了 Robert C. Martin,也就是《Clean Code》的作者、大家口中的 Uncle Bob。73 歲的人,本來以為會是「老派工程師教訓 AI 世代」的戲碼,結果完全不是。他去年十二月開始玩 coding agent,玩到現在,整套工作方式被他自己翻掉重來了一次。
我看完覺得有一堆東西值得寫下來,所以整理成這篇。
一開始,AI 是來扯後腿的
他說他早期試 ChatGPT、Grok 那些東西,沒什麼感覺。真正的轉折是他手上剛好有個專案,就順手叫 agent 幫忙寫。agent 是寫出來了,但東西很髒,他得一直在後面收拾。
他的結論當時是:這玩意兒很快,但它讓我變慢。
然後他想通了一件事,也是整場對談最關鍵的一句:正因為它快,它可以做一些我這輩子做不到的事。
那些「當年好棒但根本跑不動」的老點子
他舉了兩個 2000 年初的東西。
一個叫 CRAP 分數。做法是把測試覆蓋率跟函式的循環複雜度丟進一個公式,算出這個函式有多爛。概念超讚,但當年他跑完之後,面對一整串爛函式,要一個一個改、測試還要重寫,光想就放棄了。
另一個是 mutation testing(突變測試)。有個程式會去你的原始碼裡亂改:把大於改成小於、等於改成不等於、正號改負號,每改一次就把整套測試跑一遍。照理說測試應該要爆掉,如果沒爆,代表這段程式根本沒被真正測到,那隻「活下來的突變體」就得被解決掉。他當年跑一次要跑整晚。
兩個工具的共同問題都一樣:不是不好,是沒有那個人力去跑。
而 agent 剛好是那種又快、又不會抱怨工作很無聊、你叫它做它就做的勞動力。所以他現在就是叫 agent 寫完 code 之後自己跑 CRAP、自己跑 mutation testing、自己把洞補起來。以前要跑一整晚的,現在半小時。
他現在的目標講得很直接:讓自己完全不用看程式碼。他改成去看 CRAP 分數、偶爾抽查、跑一堆其他的檢查。理由也很誠實——agent 處理程式碼很快,他很慢,那他就不要把自己的慢強加在上面。
等一下,那為什麼還要在乎程式碼乾不乾淨?
這是我最想聽他回答的部分。既然人都不看了,髒就髒吧?
他的答案是:agent 一樣會被爛程式碼拖垮。
他早期讓 agent 一路往前做,不清理,結果就是它開始變慢、開始鬼打牆——改好這邊、弄壞那邊,回頭修那邊、又弄壞這邊,繞圈圈繞不出來。他甚至遇過 agent 直接放棄,講出類似「我搞不定這個了」的話。
所以門檻可能跟人不一樣,但那個門檻是存在的。程式碼可以亂到連 agent 都投降。
別再往 prompt 裡塞規則了
大部分人碰到 agent 亂寫,反應是拚命加指令:claude.md 越寫越長、agents.md 塞滿規矩,看到什麼壞習慣就加一條。
Uncle Bob 一開始也是這樣,寫到五頁十頁在講什麼是 clean code、什麼是 TDD。然後他發現 agent 對這些規則的態度,用他的說法是很「神鬼奇航」——那不是規定,那比較像是參考用的建議。
背後有技術原因,叫 lost in the middle。context window 裡最前面跟最後面的東西比較有份量,中間的會被淡化。而你寫在開頭的東西,只要夠長,隨著 context 累積就會被推進中間,然後就沒了。你的第 50 句、第 80 句規則,基本上不存在。
所以他的做法是兩件事:
- 初始 prompt 砍到不能再砍,只留真正重要的,讓它留在「有份量」的位置。
- 其他全部交給確定性工具。
工具不會被淡化。工具的做法是把 agent 丟進迴圈:你改,改到這個工具說 OK 為止。於是 agent 就自己在那邊繞——補測試、拆函式、降複雜度——繞到過關。
當然這是拿速度換品質。他也承認總有一天會換過頭,慢到還不如人自己寫,但目前還沒摸到那個點。
他的 agent 流水線
他現在不是一隻 agent 做完全部,是分工:
- Specifier:把人寫的文件轉成 Gherkin(given/when/then 那種驗收測試)跟一份 QA 流程。而且他要求用「你是一個人類,你正在用 UI 操作這個系統,你要證明它能動」的角度寫。
- Coder:寫單元測試跟實作,讓 Gherkin 通過。
- Cleaner:跑 CRAP 分析、做 code review,收拾 coder 留下的爛攤子(他說到這一步一定是一團亂)。
- Hardener:跑 mutation testing,這隻最狠,每個等號每個小於號都不放過。
- QA agent:把 QA 文件變成可執行的腳本,實際操作系統跑出結果。
拆開的好處有兩個:可以平行跑,以及每隻 agent 的任務夠窄,context 就控制得住,lost in the middle 沒那麼嚴重,你也才塞得進多一點規則。而且可以讓 agent 用完即死,下一隻拿到乾淨的 context。
代價是啟動成本,每隻開起來、重新理解狀況都要時間。一個單獨 agent 五分鐘(但結果很可疑)能做完的事,這條流水線要跑一小時。不過人自己做要半天,所以還是划算四五倍,而且品質遠比人手工做的高。
「軌跡」這個概念
Matt 丟出一個我覺得很實用的說法:你在控制的不只是 context window 的內容,還有它的軌跡。
你一旦在某個 session 裡把 agent 推往某個方向,之後這個 session 裡所有的事情都會沿著那個方向走。你要它測 UI 一次,接下來它每次都會想測 UI。要清掉軌跡,只能清掉 context。
Uncle Bob 完全同意,還補了一個非工程師也懂的例子:你在跟模型聊咖啡怎麼煮,旁邊有人經過在聊昨天的八點檔,這段話進了 context。從此之後,所有咖啡的討論都會沾上八點檔的味道。模型分不出來哪句話是你說的、哪句是路人說的。
所以重點是讓 context 裡的東西保持方向一致。方向一致,那些莫名其妙的幻覺就少很多。
模組化,還是那個模組化
那如果測試很完整、但 API 設計爛、模組切得亂七八糟呢?
他說理由跟當年講 clean code 一模一樣:切得好、介面乾淨的東西,人才抓得住,因為人是靠分區塊在理解事情的。模型也一樣。模組如果塞滿了不相干的東西,agent 進去也會茫然。這就是咖啡跟八點檔的問題換個地方發生而已。
他的做法蠻硬派的:
- 叫 agent 幫他做了一個架構檢視器,會畫出類 UML 的模組圖,可以點進去看子模組、再點下去看程式碼,想看多細就多細。
- 另外寫了一個確定性工具,用一份規格檔定義哪個模組可以依賴誰、不能依賴誰、相依性往哪個方向流。最後有個檢查器在跑,違反了就得想辦法修——反轉相依、插介面、把模組拆兩半之類的。
他說他正在試著把這步也自動化,目前不太順利。誠實。
(對談中也提到 John Ousterhout 的 deep module:介面窄、內部藏很多。這對 agent 特別友善,因為它可以只讀介面就動手,不用讀實作。當然那也是風險,前提是底下的東西真的一致。)
哪些東西該改?
他被問到《Clean Code》裡有沒有東西要修正,講了兩點,我覺得都很有料。
第一,門檻要調。 agent 的短期記憶又大又精準,跟人不是同一個量級。所以他把允許的函式規模放寬了:給人看的話 CRAP 分數他會壓在 4 以下,給 agent 他調到 6,還在考慮要不要推到 8。他也說他跟 agent 辯論過這件事,然後補一句——跟 agent 辯論的結果你不能信,但他還是照辯不誤。
第二,TDD 不要硬套在 agent 身上。 他自己是 TDD 的死忠,但他說那是人類的紀律,是因為人腦就長那樣。叫 agent 寫一行測試再寫一行實作,沒有意義。他允許 agent 用比較 Ousterhout 式的做法:寫完一個函式,測那個函式,再寫下一個。反正就算你叫它嚴格 TDD,它最後也會滑回這條路。
他給了一句我很喜歡的總結:不要把人的「紀律」強加給 agent,但人的「價值觀」該加還是要加。 行為可以不一樣,門檻可以不一樣,在乎的東西不能不一樣。
關於 spec-driven development,他不看好
Matt 問他在丟進流水線之前做多少規劃。他的回答基本上是在潑冷水。
「先規格規格規格,規格完再交出去」這個誘惑很老了,70 年代就有,結果是瀑布式開發,而敏捷就是對它的反擊。現在大家又想對 agent 做同一件事。
他試過,而且說結果永遠是災難,而且災難長得都一樣:你把計畫寫得漂漂亮亮,agent 開跑之後你才發現它根本照著跑不了,因為你沒想到的事很多,而它沒有你聰明。於是它半吊子地往某個荒謬方向衝,你得喊停、倒帶、重寫計畫、重開一次。
所以他放棄了,改回敏捷那套:做一兩個 story,回頭看架構,必要時手動整理一下,再做幾個。
他有個我很愛的比喻。假設蓋房子的任何一次修改都只要一塊錢,包括打地基、蓋屋頂,全部都是一塊錢一次。你會怎麼蓋?你會先花幾千塊請建築師畫一份完美的圖,然後花一塊錢叫工人一次蓋好嗎?還是你會直接跟工人說:地基放這,形狀這樣——欸不對,改一下——廚房放這邊客廳放那邊——不行動線很爛,樓梯移開——
答案很明顯。而修改的成本已經跌到接近零了。既然如此,你為什麼要花大錢在前面規劃?直接調到對為止就好。
他也不留規格。規格是用完即丟的,會一直變。以前原始碼就是最終的規格,因為那是人寫的;現在人不寫了,很多人不習慣沒有一份「人類定義的東西」在最上游,但他覺得不用勉強。
延伸出來的做法也很有趣:他自己寫了一堆工具(CRAP for Clojure / Java / Go、mutation tester、agent harness),但他跟大家說不要下載。那些是為他自己寫的。你該做的是叫你的 agent 去看那些東西,然後幫你做一個你自己的。與其給你成品,不如給你本質,再讓你客製。
一個很好笑的不對稱
Matt 講了一句話我覺得該裱起來:你丟一份長規格給人類,命中率可能 20%,講不定 5%;丟給 agent,它真的會讀完。
Uncle Bob 接下去:反過來,agent 寫的東西,人類根本不讀。
它們期待我們讀完它們寫的所有東西,而我們就是不讀。
那新人要怎麼辦?
如果 agent 已經把「戰術層」的工作吃掉了,那沒經驗的人怎麼練出「戰略層」的判斷?
他老實說他沒有標準答案,但他的想法是這樣:
先寫程式碼,寫個一年,寫到你知道 agent 在面對什麼。然後進到一間重度使用 agent 的公司之後——你應該被當成一隻 agent 對待。帶你的人給你的任務,應該跟他給 agent 的任務一樣;你也要被同一套確定性工具檢查。你會有好幾個月極度沒生產力,但你會學到非常多。撐過那個關卡,也許你才有資格自己操作 agent。
他把這個講成一條完整的路:從二進位、組合語言,到 C 這種基本的東西,再到 Python 這類高階語言,然後才是 agent 跟確定性工具,最後在監督下做戰略性的操作。
順帶一提,他十年前就在講:如果你從沒寫過組合語言,花一個週末寫一次。不然你整天寫 Java,你活在一個幻想世界裡,底下還有你不懂的魔法。
還有一段我覺得是整場最實用的。Matt 問他當初怎麼知道 agent 寫的是垃圾。他說看 code 看出髒東西不是重點,重點是他看得出 agent 在掙扎——那個原地打轉的樣子他認得,因為他自己經歷過。新手的問題不是不會寫程式,是認不出那個掙扎。
要怎麼學?他推薦去翻那些沒人讀的老書,Tom DeMarco、Ed Yourdon、《The Pragmatic Programmer》那一類。裡面有些東西確實過時了,得自己過濾,但這些教訓就是在那個年代學會的。
結論:抽象層又爬了一階,然後呢
他最後把這件事放回歷史線上。
我們的抽象層從二進位到組合語言、到編譯器,現在到了模型這一層。每一次往上爬,站在下一階的人都會說:完了,這下什麼都毀了,工作要沒了,五歲小孩都能寫程式了。當年講這句話的人,嘴裡講的還是二進位。
然後呢?每次都一樣。規則沒變,那些基本功因為同樣的理由繼續存在。
他說軟體大概是人類嘗試過最複雜的東西,而所謂的基本功,就是我們把複雜度整理成「腦袋裝得下」的形狀的方法——不只是人的腦袋,模型也是,畢竟模型某種程度上就是照著人建出來的。
那些現在覺得基本功不重要的人,他說他們會學到教訓,而且不會花太久。他自己撞過那面牆,知道牆在哪,所以不想再撞一次。
他的原話大意是:你現在丟掉的那些規則,一年後你會從地上把它們撿起來,拍掉灰塵,然後想起你為什麼需要它們。
原始對談:Matt Pocock 訪談 Robert C. Martin,2026 年 8 月直播。
沒有留言:
張貼留言