Simon Willison《Agentic Engineering Patterns》導讀: 寫程式碼變便宜了,好程式碼沒有

Raw capture

<p>Simon Willison 從今年二月開始做一件事: 把他這幾年寫的 AI 輔助寫程式內容重新整理成一份有結構的東西,叫做 <a href="https://simonwillison.net/guides/agentic-engineering-patterns/">Agentic Engineering Patterns</a>。他自己的說法是,ai-assisted-programming 標籤下已經累積 345 篇文章,但太零散,他想要一個能一次回答「怎麼把這東西用好」的地方。</p>

形式上他做了一個新的內容型別,叫 guide: 每一章其實就是一篇 blog 文章,但日期擺得不顯眼,設計上就是要持續改版,而不是凍結在發表當下。格式參考 1994 年那本《Design Patterns》。收錄標準也講得很明白: 只收「不太會因為工具進步就過時」的 pattern。

目前累積到 6 大類 16 章,小編全部讀完,整理成這篇導讀。

1. 原則
什麼是 agentic engineering
寫程式碼變便宜了
囤積你會做的事
AI 應該幫我們寫出更好的程式碼
反面模式
2. 與 coding agent 協作
coding agent 怎麼運作
搭配 Git 使用
Subagents
3. 測試與 QA
Red/green TDD
先跑測試
讓 agent 做手動測試
4. 理解程式碼
線性導覽
互動式解說
5. 逐句拆解的 prompt
用 WebAssembly 做 GIF 壓縮工具
幫電子報工具加新的內容型別
6. 附錄
我自己在用的 prompt

1. 出發點: 寫程式碼變便宜了,好程式碼沒有

整份 guide 的核心主張就這一句,其他章節多半是它的推論。

過去程式碼一直是貴的。幾百行乾淨、有測試的程式碼,多數開發者要花上一整天。而我們現有的工程習慣,不管大小,都建立在這個前提上: 大的層面,我們花很多時間設計、估時、規劃,就是為了確保昂貴的開發時間用在刀口上,一個功能要值得做,它帶來的價值得是開發成本的好幾倍; 小的層面,每天做幾百個決定也都在算同一筆帳: 這個函式要不要多花一小時重構得漂亮一點? 文件要不要寫? 這個邊界條件值得加測試嗎? 為了 debug 專門做一個介面,划得來嗎?

Coding agent 把「把程式碼打進電腦」這件事的成本壓到趨近於零,於是上面那些直覺全部失效。而且平行跑多個 agent 之後更難算了: 一個人現在可以同時在好幾個地方實作、重構、測試、寫文件。

但 Simon 強調的下半句同樣重要: 交付程式碼幾乎免費了,交付「好的程式碼」還是明顯貴很多。他列了一份清單定義什麼叫好:

已經變便宜的
把可運作的程式碼生出來
重構、改名、拆檔案
補測試、補文件
做原型驗證技術選型
維護瀏覽器自動化測試
仍然要花錢的「好程式碼」
它能動,而且你知道它能動
它解的是對的問題
錯誤情況處理得可預期,訊息夠後人查
簡單、最小,人跟機器現在和以後都讀得懂
有測試保護,能擋未來的退步
文件跟現況一致 (行為改了文件要跟著改)
設計保留未來變更的空間,但不過度預設未來
其他該有的非功能性品質: 無障礙、可測試、可靠、安全、可維護、可觀測、可擴展、易用

Agent 對上面右欄多數項目都幫得上忙,但確保產出真的落在「這個專案需要的那個好」的範圍內,責任還是在驅動它的人身上。

那新習慣怎麼建立? Simon 說業界都還在摸索,他自己也是。目前他能給的最好建議是懷疑自己的直覺: 任何時候心裡冒出「別做了,不值得那個時間」,就還是丟一個 prompt 出去,開一個非同步的 agent session,最壞的結果就是十分鐘後回來看,發現不值得那些 token。

2. 出貨更差的程式碼,是一種選擇

很多開發者擔心把程式碼交給 AI 會讓品質下降。Simon 的回應很直接: 如果導入 coding agent 之後品質確實掉了,那就直接處理這個問題,找出流程中哪一段在傷害品質然後修掉。用 agent 出貨更差的程式碼是一種選擇,我們也可以選擇出貨更好的。

他用技術債來談這件事。技術債來自取捨: 「正確做法」太花時間,所以在時間壓力下先湊合,祈禱專案活得夠久讓你以後還得起。而最好的處理方式是一開始就不要欠。

他觀察到有一類技術債特別常見: 概念上很簡單,但就是很花時間。

  • 早期 API 設計沒涵蓋到後來出現的情況,要修得改幾十個地方,於是乾脆加一個只差一點點的新 API,忍受重複
  • 早期概念命名沒取好 (例如該叫 groups 卻叫了 teams),全面改太累,最後只改了 UI 那層
  • 系統長期演化出重複但略有差異的功能,需要合併重構
  • 某個檔案已經好幾千行,理想上該拆成多個模組

這幾類正好是 coding agent 的理想任務。開一個 agent、講清楚要改什麼,讓它在背景的分支或 worktree 裡跑。Simon 自己這種工作多半交給非同步的 agent (Gemini Jules、Codex web、Claude Code on the web),這樣不會打斷他在筆電上手邊的事。結果用 PR 來評估: 好就合併,差一點就再 prompt 告訴它哪裡要改,太差就丟掉。

這類改善的成本已經低到,我們可以對小的 code smell 和不順手的地方採取零容忍態度。

另外一個角度是探索性原型。最嚴重的技術債往往來自規劃階段的選擇失誤: 錯過一個明顯更簡單的解法,或選了後來發現不合適的技術。要對技術選型有信心,最好的方法是做原型驗證。Redis 適不適合一個預期上千並行使用者的動態牆? 直接接一個模擬系統起來、跑壓力測試看哪裡先壞掉。Agent 從一個寫得好的 prompt 就能建出這種模擬,成本低到可以同時跑好幾個實驗、比較幾種方案再挑。

他也引用了 Every 的 Compound Engineering: 每個專案結束時做一次回顧,把這次學到什麼寫進給未來 agent 的指示。這裡有個順向的關係: 想要 agent 表現好,就得持續提升 codebase 品質; 而品質提升的成本已經降到沒有理由不做。

3. 囤積你已經知道怎麼做的事

小編覺得這章最實用,而且是那種讀完會想馬上改變自己習慣的內容。

Simon 說,寫軟體很大一部分能力來自於「知道什麼做得到、什麼做不到,以及大概怎麼做」。這些問題可以很廣也可以很偏: 網頁能不能只靠 JavaScript 跑 OCR? iPhone app 在沒被開啟的狀態下能不能跟藍牙裝置配對? Python 能不能處理一個 100GB 的 JSON 檔而不整份讀進記憶體?

手上有越多這種問題的答案,就越可能看到別人沒想到的解法。 而要對答案有信心,最好的方式是看過可運作的程式碼。知道理論上做得到,跟親眼看過它跑起來,是兩件事。

Simon 自己囤積的方式包括 blog、TIL blog、一千多個 GitHub repo,還有 tools.simonwillison.net 這個單頁 HTML 工具集,以及 simonw/research 這個放「叫 agent 研究問題並交出可運作程式碼加書面報告」的地方。

囤積這些東西的第二個用途,是它們變成 agent 的輸入。他最喜歡的 prompt 模式之一,就是叫 agent 把兩個以上的既有範例組合成新東西。

最早的例子是 2024 年 3 月那個瀏覽器版 OCR 工具。他想要一個能對「整份都是掃描影像、沒有文字層」的 PDF 做 OCR 的網頁工具。他先前玩過 Tesseract.js (Tesseract OCR 的 WebAssembly 版),也用過 Mozilla 的 PDF.js (可以把 PDF 每一頁算繪成影像),兩段程式碼片段都留在筆記裡。於是他把兩段程式碼貼進 prompt,最後加上這段:

Use these examples to put together a single HTML page with embedded HTML and CSS
and JavaScript that provides a big square which users can drag and drop a PDF file
onto and when they do that the PDF has every page converted to a JPEG and shown
below on the page, then OCR is run with tesseract and the results are shown in
textarea blocks below each image.

(用這些範例組出一個單一 HTML 頁面,內嵌 HTML、CSS 和 JavaScript,提供一個大方框讓使用者把 PDF 拖放進去,然後把 PDF 每一頁轉成 JPEG 顯示在下方,接著用 tesseract 跑 OCR,結果顯示在每張圖下方的 textarea。)

當時的模型還是 Claude 3 Opus,一次就成功。

有了 coding agent 之後,這個做法威力更大,因為你不必再手動貼程式碼。Simon 給了三種指法:

Use curl to fetch the source of `https://tools.simonwillison.net/ocr` and
`https://tools.simonwillison.net/gemini-bbox` and build a new tool that lets you
select a page from a PDF and pass it to Gemini to return bounding boxes for
illustrations on that page.

(用 curl 抓這兩個工具的原始碼,然後建一個新工具,讓使用者選 PDF 的某一頁丟給 Gemini,回傳頁面上插圖的 bounding box。)

這裡有個細節值得抄走: 他特別指定用 curl 而不是讓 Claude Code 用預設的 WebFetch 工具,因為 WebFetch 會把頁面內容摘要過,拿不到原始 HTML。

Add mocked HTTP tests to the `~/dev/ecosystem/datasette-oauth` project inspired by
how `~/dev/ecosystem/llm-mistral` is doing it.

(參考 llm-mistral 專案的做法,幫 datasette-oauth 專案加上 mock 掉 HTTP 的測試。)

Clone `simonw/research` from GitHub to `/tmp` and find examples of compiling Rust
to WebAssembly, then use that to build a demo HTML page for this project.

(把 simonw/research clone 到 /tmp,找出把 Rust 編譯成 WebAssembly 的範例,然後用它幫這個專案做一個 demo HTML 頁面。)

clone 到 /tmp 是刻意的: 確保參考用的程式碼不會被誤加進自己的 commit。

這章的結論寫得很好: 有用的技巧只需要搞懂一次。只要那次的成果被記錄在某個地方、而且附上可運作的程式碼,之後遇到形狀類似的專案,agent 都可以回頭查那份範例。

4. 兩個四個字的 prompt

Guide 裡有兩章各自在講一句極短的 prompt,小編覺得放在一起看特別有意思。

Use red/green TDD

TDD 最有紀律的形式是測試先行: 先寫測試、確認它失敗,再改實作直到通過。這跟 coding agent 特別合,因為 agent 最常見的兩個風險是「寫出不能動的程式碼」和「寫出根本沒人用的多餘程式碼」,測試先行同時擋掉這兩個。

關鍵在中間那步不能省: 一定要先確認測試失敗。跳過的話,你可能寫了一個本來就會過的測試,它根本沒有驗到新實作。紅燈階段看著測試失敗,綠燈階段確認它們通過,這就是 red/green 的意思。

Build a Python function to extract headers from a markdown string. Use red/green TDD.

(寫一個從 markdown 字串中抽出標題的 Python 函式,用 red/green TDD。)

First run the tests

Simon 每次對既有專案開新 session 都會先下這句 (他的 Python 專案是 Run "uv run pytest")。這四個字同時做了幾件事:

  • 告訴 agent 這專案有測試套件,並逼它自己搞清楚怎麼跑。這幾乎確保了它之後改東西會再跑一次確認沒弄壞
  • 多數測試框架會回報測試數量,這可以當作專案規模與複雜度的代理指標,也暗示 agent 想更了解專案可以去讀測試
  • 讓 agent 進入測試的狀態,跑過測試之後它自然會傾向替新程式碼補測試

這兩句 prompt 有效的原因是同一個: 這些工程紀律本來就已經在模型裡了,四個字只是叫用它的關鍵字。「Use red/green TDD」在模型那邊會展開成「用測試驅動開發、先寫測試、確認測試失敗,再實作到它們通過」這整套。這比自己寫一長串規則有效率得多。

5. 測試通過不代表能動: 手動測試也交給 agent

這章的前提是一句所有寫過自動測試的人都懂的話: 測試全過不代表程式能動。伺服器啟動就掛、關鍵 UI 元素沒顯示、測試沒涵蓋到的細節出錯,都是常見情況。Simon 說他還是喜歡在上線前親眼看到功能運作,而他發現讓 agent 也做一遍手動測試,經常會抓到自動測試沒抓到的問題。

怎麼「手動」測試要看程式碼是什麼:

  • Python 函式: python -c "..." 直接跑。Prompt: Try that new function on some edge cases using python -c
  • 其他語言沒有這種機制的話,就叫它寫個 demo 檔編譯執行,並指定寫在 /tmp 避免不小心被 commit 進去
  • JSON API: Run a dev server and explore that new JSON API using curl。他特別提到用 explore 這個詞很有效,agent 會自己去試各種面向,覆蓋範圍拉得很快
  • Web UI: Playwright 是目前最完整的選擇,也有專為 agent 設計的 CLI 包裝像 Vercel 的 agent-browser。Simon 自己做了 Rodney,走 Chrome DevTools Protocol

他示範的 Rodney prompt 裡藏了三個設計:

Start a dev server and then use `uvx rodney --help` to test the new homepage,
look at screenshots to confirm the menu is in the right place

(啟動 dev server,然後用 uvx rodney --help 測試新的首頁,看螢幕截圖確認選單位置正確。)

一是用 uvx 執行,第一次呼叫時會自動安裝; 二是 rodney --help 的說明文字是刻意為 agent 設計的,看完就知道整個工具怎麼用; 三是「look at screenshots」這句在提示 agent 該用 rodney screenshot,同時提醒它可以用自己的視覺能力去評估產出的圖片。

如果手動測試抓到問題,Simon 會叫它用 red/green TDD 修,這樣新發現的情況就會進到永久的自動測試裡。

最後是 Showboat,他做的一個小工具,讓 agent 把手動測試過程寫成 markdown 文件。三個指令: note 加註解、exec 執行指令並記錄指令本身與輸出、image 插入截圖。

exec 是關鍵,而它的設計理由很值得注意: 因為它同時記錄指令和真實輸出,agent 就沒辦法把「它希望發生的事」寫進文件裡。這是一個防止 agent 自我宣稱的機制,小編覺得這個思路可以套用到很多 agent 產出的驗證場景。

6. 認知債: 讓 agent 反過來解釋程式碼

Simon 提出一個對應技術債的概念: 認知債 (cognitive debt)。當我們搞不清楚 agent 寫的程式碼怎麼運作,我們就在欠這筆債。

有些情況無所謂: 從資料庫撈資料輸出成 JSON,掃一眼就好。但如果應用的核心變成一個你不完全理解的黑箱,你就沒辦法有信心地推理它,規劃新功能會變難,最後拖慢進度的方式跟技術債一樣。

還債的方式是提升理解,他給了兩種做法。

線性導覽 (linear walkthrough)。他先前 vibe code 了一個 SwiftUI 簡報 app,整個 prompt 出來完全沒看程式碼,開源之後才發現自己根本不知道它怎麼運作。於是開一個新的 Claude Code session:

Read the source and then plan a linear walkthrough of the code that explains how
it all works in detail

Then run “uvx showboat —help” to learn showboat - use showboat to create a walkthrough.md file in the repo and build the walkthrough in there, using showboat note for commentary and showboat exec plus sed or grep or cat or whatever you need to include snippets of code you are talking about

(讀原始碼,然後規劃一份線性導覽,詳細解釋它整體怎麼運作。接著執行 uvx showboat --help 學會 showboat,用它在 repo 裡建一份 walkthrough.md,用 showboat note 寫說明、用 showboat exec 搭配 sed 或 grep 或 cat 之類的指令,把你在講的程式碼片段包含進來。)

最後那句是關鍵設計: 叫它用 sed / grep / cat 把程式碼抓進文件,而不是自己手打,這樣就不會有幻覺或手誤的風險。這跟上面 Showboat exec 是同一個思路。

Simon 說讀完這份文件,他不只搞懂了自己的 app,還順帶學到 SwiftUI app 怎麼組織、以及一些 Swift 語言細節。他的評語蠻好的: 如果你擔心 LLM 會拖慢你學新技能的速度,這種做法反過來讓一個 40 分鐘的 vibe code 玩具專案變成探索新生態系的機會。

互動式解說。有時候導覽還是不夠。他讓 agent 用 Rust 做了一個文字雲工具,報告說演算法是「Archimedean spiral placement with per-word random angular offset」,他看不懂; 讀了線性導覽,懂了程式碼結構,但還是對那個螺旋擺放沒有直覺。於是他請 Claude 把那份 walkthrough.md 讀進去,做一個動畫版的網頁: 每一個字嘗試擺放時顯示一個方框、檢查是否跟既有的字重疊、重疊就沿著螺旋往外繼續找位置,還附上可暫停、可調速、可逐格前進的滑桿。

看完動畫他就懂了。這章的重點是: 好的 coding agent 可以隨需求做出解說用的動畫和互動介面,用來解釋它自己寫的、或別人寫的程式碼。

7. Git history 是刻意編寫的故事

這章最值得記下來的是一句觀念:

不要把 Git 歷史當成「實際發生了什麼」的永久紀錄,把它當成一個刻意編寫的、描述專案演進的故事。

歷史是給未來開發用的工具。永久記錄錯誤和取消的方向有時候有用,但 repo 的作者可以做編輯決定: 留什麼、怎麼呈現最好。而所有 coding agent 都對 Git 的進階歷史改寫功能很熟。

幾個實用 prompt:

  • Review changes made today: 拿來當新 session 的開場很好用。它會去跑 git log,瞬間把你最近在做什麼 (改了哪些程式碼、commit 訊息怎麼寫) 載進 context,接下來就可以直接討論那些程式碼
  • Sort out this git mess for me: Simon 說他用這句的頻率高到驚人。以前 merge conflict、rebase 出事、staging 加錯東西,是 Git 最難最花時間的部分。現在 agent 可以推理新程式碼的意圖、判斷該留什麼怎麼合併,有自動測試的話還能確保合併前測試是通過的
  • Use git bisect to find when this bug was introduced: ...: bisect 是 Git 最強的除錯工具之一,但學習曲線陡,唯一的麻煩是要把「這個 bug」表達成 bisect 能執行的測試條件。Agent 可以幫你處理這些樣板,於是 bisect 從偶爾才用的工具,變成任何時候好奇歷史行為都能用
  • Undo last commit、Remove uv.lock from that last commit、Combine last three commits with a better commit message: 那些你永遠記不起來的指令 (例如 git reset --soft HEAD~1) 現在不用記了

Simon 還提到一個他常用的做法: 從大 repo 中抽出一部分程式碼做成新 repo,同時保留那段程式碼的關鍵歷史。以前這件事麻煩到多數人乾脆開一個全新的 repo,切斷歷史,現在不必將就了。

他也承認自己在 commit 訊息上讓步了: 「以前我堅持自己寫,現在我接受前沿模型寫的品質通常夠好,甚至常常比我自己寫的還好。」

8. subagent 的價值在保護頂層 context

Simon 對現況的描述蠻清楚的: context 上限這兩年沒怎麼成長,即使模型能力大幅進步。目前大概在 100 萬 token 封頂,而 benchmark 常顯示 20 萬以下品質比較好。所以管理 context 讓它待在限制內,是拿到好結果的關鍵。

Subagent 就是處理這件事的簡單方法: 派一個自己的副本去達成特定目標,用一份全新的 context 開始。

他秀了一段 Claude Code 的 Explore subagent 實例。他丟一張截圖和一句需求進去,Claude Code 第一件事是自己寫了這樣一段 prompt 派給 Explore:

Find the code that implements the diff view for "chapters" in this Django blog.
I need to find:
- Templates that render diffs (look for diff-related HTML/CSS with red/green backgrounds)
- Python code that generates diffs (look for difflib usage or similar)
- Any JavaScript related to diff rendering
- CSS styles for the diff view (red/green line backgrounds)
Search thoroughly - check templates/, static/, blog/ directories. Look for keywords
like "diff", "chapter", "revision", "history", "compare".

Simon 的觀察: 「看模型這樣對自己下 prompt 蠻有意思的,它們的 prompt 策略品味通常不錯。」

Subagent 也可以平行跑,而且可以用比較快比較便宜的模型 (例如 Haiku) 來加速。對於要改好幾個彼此不相依的檔案這種任務,速度提升很明顯:

Use subagents to find and update all of the templates that are affected by this change.

(用 subagent 找出並更新所有受這個變更影響的樣板。)

不過這章的結尾是一個節制的提醒,小編覺得比前面更重要:

雖然把任務拆給幾十個不同的專家 subagent 很誘人,但要記得 subagent 的主要價值在於保護寶貴的根層 context、以及處理消耗大量 token 的操作。你的根 coding agent 只要 token 夠,完全有能力自己 debug 或 review 自己的產出。

9. 唯一的反面模式: 不要把沒審過的程式碼丟給別人

整份 guide 目前只列了一個 anti-pattern,可見 Simon 對它的在意程度:

如果你開了一個幾百甚至幾千行、agent 產生的 PR,而你自己沒做過確認它能運作的工作,你等於是把真正的工作轉嫁給別人。他們自己也可以下 prompt 啊,那你到底提供了什麼價值?

他列了好的 agentic engineering PR 該長什麼樣:

  • 程式碼能動,而且你有信心它能動
  • 變更小到能被有效率地審查。幾個小 PR 好過一個大的,而且有 agent 幫你處理 Git 操作,拆 commit 已經很容易
  • PR 裡附上額外脈絡: 這個變更服務的更高層目標是什麼,連到相關的 issue 或規格
  • agent 寫的 PR 描述你也要讀過。期待別人去讀你自己沒讀過沒驗證過的文字,是不禮貌的

他建議附上你確實多花了功夫的證據: 手動測試的筆記、對特定實作選擇的說明,甚至功能運作的截圖或影片。這些能讓審查者知道自己的時間不會被浪費。

10. 附錄: Simon 自己在用的 prompt

最後一章是他日常在用的幾個 prompt,其中 proofreader 那個小編覺得可以直接抄:

You are a proofreader for posts about to be published.
  1. Identify spelling mistakes and typos
  2. Identify grammar mistakes
  3. Watch out for repeated terms like “It was interesting that X, and it was interesting that Y”
  4. Spot any logical errors or factual mistakes
  5. Highlight weak arguments that could be strengthened
  6. Make sure there are no empty or placeholder links

(你是一位校對者,負責即將發表的文章。1. 找出拼字錯誤與 typo。2. 找出文法錯誤。3. 注意重複用語,例如「有趣的是 X,而有趣的是 Y」。4. 指出任何邏輯錯誤或事實錯誤。5. 標出可以再加強的薄弱論點。6. 確認沒有空的或還是 placeholder 的連結。)

比起一般的「幫我校對」,第 3、5、6 條特別有用,這三條是他從自己的寫作習慣裡歸納出來的常犯錯誤。

另外還有寫 alt text 的 prompt (要求輸出成單行的 fenced code block 方便複製、圖上的文字必須完整包含、開頭先簡短說明圖的性質)、以及訪談逐字稿挑金句的 prompt。他也提到自己在 Claude Artifacts 的專案指示裡明確禁止 React,因為 React 需要額外的建置步驟,讓他沒辦法把程式碼直接複製出去丟到靜態託管。

值得一提的是這章開頭 Simon 講的一條界線:

我不讓 LLM 寫我 blog 的文字。我的紅線是: 任何表達意見、任何用「我」這個人稱的內容,都必須是我自己寫的。程式碼文件我可以讓 LLM 改,但只要掛著我的名字、帶著我的性格,就是我自己寫。

他在 guide 的開篇公告裡也重申過同一件事: 他會用 LLM 校對、補範例程式碼和各種雜務,但你讀到的文字是他自己的。

11. 補充: 三月的爐邊訪談,講了 guide 裡沒寫的東西

Simon 三月在舊金山 Pragmatic Summit 有一場關於 agentic engineering 的爐邊訪談 (Statsig 的 Eric Lui 主持,影片在 YouTube),他自己整理了逐字稿重點。內容跟 guide 高度重疊,但有幾段是 guide 裡沒有的,小編挑幾個:

一致性測試驅動開發。這是整場訪談最有料的一段,也是 guide 裡完全沒寫的做法。他要幫自己的 web 框架 Datasette 加 multipart 檔案上傳,做法是先叫 Claude 建一套「在 Go、Node.js、Django、Starlette 上都能通過」的測試套件,等於從六個既有實作反推出一份規格,然後再說「照這套測試幫我寫一個 Datasette 的實作」。他自己的形容是「幾乎像是逆向工程六個實作來得到一份標準,然後再去實作那份標準」。測試套件在這。

維持 codebase 品質的實際理由。他說模型有一個特性是「極度一致」: 如果你的 codebase 裡有一組慣例,它們幾乎會一模一樣地照做。所以他多數新專案都從 cookiecutter template 開始,測試放在對的位置、README 寫好、CI 設好,「光是有一兩個你喜歡的風格的測試,它就會照那個風格寫測試」。他補了一句蠻好的對照: 這跟人類團隊完全一樣,如果你是公司裡第一個用 Redis 的人,你得做到完美,因為下一個人會複製貼上你的做法。

他其實一直討厭測試先行。這段很誠實: 「我整個職涯都討厭測試先行的 TDD。以前試過,覺得很煩、拖慢我的速度,就是不喜歡。讓 agent 做就沒差了,我不在乎 agent 花幾分鐘在一個不會過的測試上繞。」他對「測試現在幾乎免費,所以完全不寫測試是很糟的做法」的立場也講得比 guide 裡更重。

信任的分界在哪。他說讓自己比較能接受的思考方式是: 在大公司工作時,其他團隊做的服務,我們讀文件、用服務,不會去看他們的程式碼,壞了才進去查。信任 AI 也是同一回事,只是感覺很不舒服。他說 Opus 4.5 是第一個贏得他信任的模型: 對他看過它處理的那類問題,他現在有信心它不會做出蠢事。至於更激進的「完全不讀程式碼」,他提到資安公司 StrongDM 那套他們自稱 software factory 的做法 (兩條原則是「沒有人寫程式碼,沒有人讀程式碼」),直說那是不負責任的做法,但因為做的是資安產品,反而值得密切觀察它為什麼還能運作。

沙盒與他自己的誠實告白。他說最重要的是沙盒隔離,這也是他喜歡 Claude Code for web 的原因: 跑在 Anthropic 的容器裡,prompt injection 最壞的結果是私有原始碼被偷,而他的東西多半開源。然後是這句: 「我在自己的 Mac 上大多直接開 dangerously-skip-permissions 跑 Claude,儘管我大概是全世界最懂為什麼不該這樣做的人。因為它太好用了。」他能做的就是在那個模式下盡量不把不信任的 repo 裡的指令丟進去。

這件事非常累人。訪談最後這段小編最有感: 「我常常同時進行三個專案,因為某件事要跑十分鐘我就切到另一個,這樣兩小時後我這天就報廢了,腦力耗盡。大家擔心技能退化和變懶,我覺得剛好相反,你得全力運轉才能讓三四個 agent 都有事做。」接著他說「這可能就是救我們的地方: 你沒辦法讓一個工程師做一千個專案,因為三小時後他會直接倒在角落。」

他給的職涯建議也在同一條線上: 因為現在可以更有野心,如果你一直因為學習成本只用兩種程式語言,現在就去學第三種,而且不要「學」,直接開始用它寫。他說自己過去兩週發布了三個 Go 專案,而他並不是流利的 Go 開發者,但他讀得懂到足以掃過去判斷「嗯,這看起來是對的」。

小結

讀完 16 章加這場訪談,小編覺得最一致的一條線索是: 每一章其實都在回答同一個問題,你怎麼知道這段程式碼真的能動?

Red/green TDD 是在測試層面回答; first run the tests 是把驗證機制先擺上桌; 手動測試是承認測試套件涵蓋不了全部; Showboat 的 exec 記錄真實輸出,是為了讓 agent 沒辦法把希望發生的事寫成已發生; 線性導覽要求用 grep 抓程式碼而不是手打,出於同樣的考量; PR 要附上手動測試筆記和截圖,是把這個舉證責任延伸到協作層面; 一致性測試套件則是連「規格」本身都先用可執行的形式確立下來。

換句話說,當寫程式碼的成本趨近於零,工程師的價值就整個移到「建立可信的驗證機制」上,而且是不依賴 agent 自我宣稱的那種。Simon 那句「出貨更差的程式碼是一種選擇」之所以成立,前提就是你有辦法知道差別在哪。

Guide 還在增長中,Simon 說他預計每週補一到兩章,也還沒決定什麼時候停。想追的話可以收 RSS。