56 分鐘對談 | 29 個我按下截圖的瞬間 | 每頁可直接跳到影片時間點
為什麼規範寫得越長越沒用,以及 Bob 的五段式 agent 流水線
影片 13:18 / 56:39 · 本段共 2 張截圖 · ▶ 從這裡開始看
規範寫得越長,被遵守的機率越低。
「我早期的 prompt 是:這是 TDD 的做法、這是 Clean Code 的做法……最後變成一份五到十頁的文件。我甚至想過把整本書都餵給它。」
「但 agents 看待這些規則的方式,很像《神鬼奇航》裡的說法:比較像指引。就是「可能」會遵守。」
影片 13:55 / 56:39 · ▶ 從這裡開始看
位置是稀缺資源:頭尾是精華地段,中間是垃圾掩埋場。
「有個現象叫做 lost in the middle。context window 越堆越長,最開頭和最後面的內容會比中間更受重視。」
「你一開始說得太長,前面的話就會被擠到中間。開頭那三句可能還有優先權,但第 50 句和第 80 句就沒了。」
影片 15:16 / 56:39 · ▶ 從這裡開始看
該追求的不是更大的 context window,是更小的進場 prompt。
「我把 context window 分成智慧區和笨區(Dex Hardy 的說法)。前段、像前 15 萬 token 還滿聰明的,越往後 attention 就越吃力,被稀釋得很嚴重。」
「就像每個 token 都在越來越擁擠的房間裡大喊。雜訊太多,根本聽不見訊號。」
影片 20:37 / 56:39 · ▶ 從這裡開始看
agent 之間要交接,就得有一份可執行的規格當契約。
「我會先跑一個 specifier,把人寫的文件轉成 Gherkin 和 QA 流程。」
「Gherkin 就是 Given、When、Then 那套,是高階驗收測試;QA 流程是系統測試,從使用者角度透過 UI 操作整個系統,證明系統能正常運作。」
影片 21:45 / 56:39 · ▶ 從這裡開始看
不要用一個萬能 agent。把寫、清、逼、驗拆成有明確交接物的角色。
「程式設計師寫單元測試和實作 → 交給清理者跑 crap analysis 和 code review,清掉爛攤子(做到那時肯定已經亂成一團)→ 交給強化者。」
「強化者負責跑突變測試,而且絕不留情。做到 100% 覆蓋率,每個等號、每個小於號都會測。最後交給 QA agent,把 QA 文件轉成可執行腳本。」
深層模組為何對模型特別有利,以及 TDD 該不該套在 agent 上
影片 29:57 / 56:39 · ▶ 從這裡開始看
好架構的回報變高了 —— 介面窄,agent 讀得懂,也不需要讀太多。
「(Ousterhout 的)淺層模組:介面很大、裡面藏的東西不多。深層模組:介面很小、裡面藏了大量資訊。這對模型很有利,因為它們只要看介面,不用理解實作細節。」
「模型會看結構,這讓它們不必讀底下的程式碼 —— 這既是風險也是優勢。它們也會看測試,透過測試了解系統在做什麼。」
影片 34:03 / 56:39 · ▶ 從這裡開始看
Clean Code 之父說:我的招牌紀律,不要套在 agent 上。
「我很支持測試驅動開發。但那是因為人類天生需要這種紀律。要 agent 一行測試、一行正式碼、再一行測試,我覺得毫無意義。但對人類有意義,至少對我來說。」
「我讓 agent 更像 Ousterhout 那樣:先寫一個函式,再替它寫測試。就算我要求嚴格 TDD,它們最後也總是回到那種做法。」
影片 35:04 / 56:39 · ▶ 從這裡開始看
規範結果,不要規範動作。
「把人類的紀律強加給 agent,可能是個錯誤。但把人類價值觀加諸 agent,並不是錯誤。只是有些門檻可能得調整。至於那些行為本身,我覺得不該強加給它們。」
70 年代的老誘惑在 agent 時代重演,以及「規格是耗材」
影片 36:00 / 56:39 · ▶ 從這裡開始看
執行成本降低後,做錯方向反而變成主要成本。
Matt:「在進入這個 gauntlet 迴圈前,你會做多少規劃?畢竟把錯的工作丟進 gauntlet 非常浪費。」
影片 36:10 / 56:39 · ▶ 從這裡開始看
AI 沒有讓瀑布變可行,只是讓它重演得更快。
「人很容易想先把規格寫好,寫了又寫、寫了又寫,再交給 agent。這是很老的誘惑,我們 70 年代就經歷過,這導致了瀑布式流程。」
「敏捷革命就是對此的回應:『前期規劃搞得這麼重,只會把一切弄得一團糟,因為最後產出的東西根本不像原本的計畫 —— 而且從來都是如此。』」
影片 37:42 / 56:39 · ▶ 從這裡開始看
大計畫 × 高速執行 = 大規模返工。切小、交付、看、再切。
「我試過先規劃再交給 agent,這週還在試。結果總是災難,而且每次都一樣。」
「『好,等一下,現在來試試敏捷方法。』先讓它們做一兩個 story,最後再看架構。或許我得親自介入處理幾件事,然後再做幾個 story。」
「我們可能永遠都無法省掉最後手動整理的步驟。」
影片 40:59 / 56:39 · ▶ 從這裡開始看
規劃之所以值錢,是因為改動很貴。改動變便宜了,規劃的相對價值就跌了。
(用蓋房子比喻)「先做一點。廚房放這邊、客廳放那邊,這才 2 美元。不行?那就調整一下,讓小孩走過去看看 —— 喔,動線很爛,就把樓梯移走。」
「變更成本已經暴跌到我覺得幾乎是最低點了。既然低到這種程度,何必一開始就先規劃?那很花錢。為什麼不直接一直調、一直調,直到看起來對了?」
影片 41:45 / 56:39 · ▶ 從這裡開始看
判斷是不是 SDD,不看你寫得多詳細,看你事後會不會回去看。
「我對『規格驅動開發』這標籤有個很大的問題。規格驅動開發到底是什麼?可以有十種不同解讀。以前你會跟同事說『你去修一下 header 的載入問題』—— 這算規格驅動開發嗎?」
「我覺得差別在於:你有沒有把規格保存下來?你會不會回頭參考那些規格?」
影片 42:38 / 56:39 · ▶ 從這裡開始看
規格是耗材,不是資產。
Matt:「那你怎麼看規格?會把所有規格列在 repo 裡嗎?」
Bob:「不會。規格是暫時的,之後會消失,也常常改。我會一直調整,然後它就沒了。」
影片 42:49 / 56:39 · 本段共 2 張截圖 · ▶ 從這裡開始看
規格的位置從事前的文字,移到事後的成果 + 驗收工具。
「它不像原始碼有對應的東西。以前是人寫原始碼,所以原始碼就是最終規格。但現在不是了。現在還是有原始碼,但不是人類在寫。」
「我最近在做的是:不再寫規格來定義我想要什麼,我會看最終成果,然後說:這就是規格。」
影片 44:05 / 56:39 · ▶ 從這裡開始看
AI 會讀完你寫的每個字;你不會讀完它寫的每個字。
「agent 最奇怪的一點就是,你丟東西給它,它會讀。這跟人類差很多 —— 你丟一大份規格給人,能有 20% 的命中率就不錯了,20% 可能還太樂觀,5% 吧。」
「但你把規格交給 agent,它們大概真的會讀。反過來,agent 寫的東西,人類根本不看。」Matt:「它們以為我們會讀完它們寫的每個字,但我們就是不會。」
AI 吃掉的正是過去用來練功的那一層
影片 45:46 / 56:39 · ▶ 從這裡開始看
AI 吃掉的,正是過去用來練功的那一層。
「戰術型就像地面的士官,負責打仗的人;策略型則是像指揮戰局的將軍。agents 很擅長戰術,戰略卻很差。」
Matt:「那剛入門的人該怎麼辦?現在 AI 已經吃掉所有戰術工作,他們要怎麼學戰略程式設計?」
影片 47:41 / 56:39 · ▶ 從這裡開始看
學不到策略,就先把戰術做到底 —— 而且用跟 agent 一樣的規則做。
「剛受訓完的年輕人,應該被當成 agent 對待。帶領的人可能是資深工程師,或其他帶著一堆 agents、負責策略的人。」
「他們應該把你當成 Agent,交給你跟 Agent 一樣的任務,也讓你用同樣的確定性工具。」Matt 接:「你當 agent 的 sub-agent。」
影片 47:49 / 56:39 · 本段共 2 張截圖 · ▶ 從這裡開始看
養成期本來就該是低效率的。
「你得維持這種狀態好幾個月,效率慘不忍睹,卻學到一大堆。等你熬過這段考驗,也許就能信任你自己操作 Agent。」
「我是吃過苦才學到的。挫折中學習。」
影片 48:02 / 56:39 · ▶ 從這裡開始看
抽象層之上的人,仍然要下去看過一次底層。
「你不能完全丟掉程式碼。我以前常跟人說,十年前也這樣說:如果你沒寫過組合語言,就該花個週末寫寫看,才知道底層到底在幹嘛。」
「因為如果你整天只寫 Java,你就活在幻想世界裡。還有很多你不懂的魔法。」
影片 48:17 / 56:39 · ▶ 從這裡開始看
操作 agent 是最後一階,不是第一階。
「你得從最基礎的二進位開始,一路學到組合語言、C 這類基礎程式,再到 Python 之類的高階程式,然後處理 Agent 相關工作,以及確定性工具,最後才能在監督下、有策略地操作 Agent。」
影片 50:17 / 56:39 · ▶ 從這裡開始看
整場唯一對新人有利的結構性改變:爛設計的報應來得更快了。
Matt:「策略性程式設計的回饋週期很長。做了六個月就離職的人可能永遠學不會,因為他們犯的錯要九個月後才會出現,根本看不到自己的錯。」
「但有了 agents,我想就可以了 —— 因為速度快了很多,你可以更早得到更多犯錯的回饋。」
第四階抽象化,以及每一次都會出現的那句「這會毀了一切」
影片 53:06 / 56:39 · ▶ 從這裡開始看
基本功 = 把複雜性整理成可理解的形式。這件事沒被取代,只是換了讀者。
「軟體是人類至今嘗試過最複雜的東西(我記得是 Dijkstra 說的)。所以基本功,就是把這份複雜性整理成可理解的形式 —— 不只人類能理解,模型也能理解,畢竟模型也是仿照人類打造的。」
「現在有人覺得基本功不重要。他們會學到的,而且會吃盡苦頭。」
影片 54:36 / 56:39 · ▶ 從這裡開始看
把 AI 放回歷史的位置 —— 它是第四階,不是第一次。
「現在我們已經到了編譯器之上的層級。以前,我們的抽象層是編譯器;在那之前是組合語言;在那之前是二進位。現在則到了模型這個層級。」
影片 55:07 / 56:39 · ▶ 從這裡開始看
恐慌會重演,原則會回來。
「底下一層的人抱怨說:『喔,這會毀了一切。我們連工作都沒了。事情變得太簡單,連五歲小孩都會寫程式。』你知道嗎,當時他們講的還是二進位。」
「不會。規則還是一樣。所有基本原則依然存在,理由也一樣。你丟掉的規則,一年後又會從地上撿回來,拍拍灰,想起為什麼需要它們。」
影片 55:52 / 56:39 · ▶ 從這裡開始看
每次恐慌都對事實判斷正確,對價值判斷錯誤。
Matt:「我記得有句很棒的話,好像是柏拉圖說的:文字會讓人變笨,對吧?從希臘時代起,大家就在爭論同樣的抽象化問題。很荒謬。」
導讀現場容易卡住的典故,抽出來單獨解釋,不打斷主線
《神鬼奇航:鬼盜船魔咒》(2003)。伊莉莎白被抓上黑珍珠號,搬出「海盜法典」(the Pirate's Code)要求談判 —— 法典在海盜世界裡,被講得像神聖不可違逆的鐵律。
結果巴博沙船長一臉輕鬆地回她:
—— Captain Barbossa,《神鬼奇航:鬼盜船魔咒》(2003)
Matt 笑完馬上接一句:「我可以稱讚你一下嗎?我腦中也立刻想到這個比喻,很高興我們想法一致。」所以那陣笑聲,一半是梗好笑,一半是兩個人想到同一個梗的默契。
笑點三層
莊嚴的法典,在不方便的那一瞬間降格成「參考用」—— 而且說的人毫無愧色。
海盜引用這句,就是為了不履行剛剛答應的事。agent 的行為一模一樣:它讀了你的規範,然後在關鍵時刻自行決定那只是建議。
Uncle Bob 是《Clean Code》的作者 —— 那本書大概是這行最接近「法典」的東西。他在說:連我自己寫的法典,AI 也只當成 guidelines。
一句話:它不是拿來測程式的,是拿來測你的測試的。
工具把原始碼偷改一小處產生「突變體」,再跑一次你全套測試:測試掛了=突變體被殺掉;測試全綠=它存活,那裡就是測試的破洞。最後算 mutation score = 殺掉數 ÷ 總突變數。
常見突變運算子
| a < b | → | a <= b |
| a + b | → | a − b |
| if (x) | → | if (!x) |
| return total | → | return 0 |
| 某一行程式 | → | 整行刪掉 |
常見工具:PIT(Java)、Stryker(JS/TS/C#)、mutmut 或 cosmic-ray(Python)、go-mutesting(Go)。
為什麼 Bob 這麼重視它
Bob 這句不是比喻,是字面意思 —— 他描述的就是突變運算子本身。
測試可以完全沒有 assert,照樣衝到 100% coverage。突變測試會把這種假測試打回原形。
agent 很擅長寫「一定會過」的測試。突變測試是它沒辦法用話術繞過的確定性檢查。
代價:N 隻突變體 × 跑一次完整測試,成本是平方級的 —— 通常只在 CI 夜間跑,或只掃核心模組。
run the gauntlet:古代軍中刑罰 —— 犯錯的人要從兩排士兵中間跑過去,兩側一路輪流打他,撐過去才算完事(中文常譯「夾道鞭刑」)。引申為一連串接連不斷的嚴酷考驗。
Matt 用這個字替 Bob 的五段流水線取綽號:程式碼丟進去,一路被五個 agent 輪流毒打。
Matt 口中的 gauntlet = Bob 的五段流水線
| specifier | 人話 → Gherkin 驗收條件 |
| programmer | 寫實作與單元測試 |
| cleaner | crap analysis + code review |
| hardener | 突變測試,100% 覆蓋 |
| QA agent | QA 文件 → 可執行腳本 |
冷知識:gauntlet 原指鐵手套(throw down the gauntlet = 下戰帖);刑罰那個源自瑞典文 gatlopp,本來拼 gantlet。
為什麼這個字取得好
沒有任何一關在幫忙或背書,全部是攻擊。活著走出來的才算合格。
呼應 Bob 那句「做到那時肯定已經亂成一團」—— 這是設計,不是抱怨。
所以 Matt 的問題才成立:重點是入口丟什麼進去,不是流水線跑多快。
CRAP=Change Risk Anti-Patterns(變更風險反模式)。名字是故意的雙關 —— 跑完直接告訴你「這段是 crap」。它把循環複雜度與測試覆蓋率合成一個風險分數:
同一個複雜度 10 的方法,覆蓋率一拉高,分數就崩塌
| 覆蓋率 0% | 110 |
| 覆蓋率 50% | 22.5 |
| 覆蓋率 80% | 10.8 |
| 覆蓋率 100% | 10 = 純複雜度 |
常用門檻 30 —— 反推:完全沒測試的方法,複雜度必須 ≤ 5 才過得了關(5²+5=30)。
為什麼清理者用它
覆蓋率滿了第一項歸零,CRAP 就等於複雜度本身 —— 風險還在,但已被測試看住。
它不挑風格,只指出「又複雜、又沒人測」的地方,而且數字沒辦法用話術爭辯。
CRAP 看覆蓋率(便宜、可騙);突變測試驗那些覆蓋是不是真的(貴)。清理者粗篩,強化者複驗 —— 順序沒排反。
2007 年由 Alberto Savoia 與 Bob Evans 在 Google Testing Blog 提出。