<em>AI 生成程式碼的速度比以往任何時候都快,但這不代表我們交付正確軟體的速度也更快。</em>
最近,我請一個程式代理打造一個密碼重設流程。它大約在五分鐘內產生了路由、權杖處理、電子郵件整合以及介面。
但這個實作有一個 bug。重設連結可以重複使用。用它設定新密碼後,再打開同一個連結一次,它仍然有效。
需求文件並沒有明確寫出重設連結必須只能使用一次。之所以沒寫,是因為這種事在出問題之前,大家都默認它理所當然。人工逐步點過的每條路徑都運作完美。程式碼審查也許能抓到,但 Demo 不會。
我想談的,就是這個落差。
<h2>程式碼生成不再是最昂貴的部分</h2>
傳統軟體開發有一個明顯的限制:人類必須親手寫出軟體。我們思考需求、設計實作、寫程式、執行、發現不能用、除錯,然後重複直到足夠有把握。
AI 程式代理大幅壓縮了這個迴圈中的某些部分。代理通常能比我徹底審查它產生的內容更快完成實作,於是出現了一種反轉。很長一段時間以來,寫程式是昂貴的,而檢查它相對便宜。當寫程式變得便宜時,會發生什麼事?
驗證就變得相對更有價值。
假設代理在五分鐘內實作了一個功能,但要確認這個實作是否正確,還需要另外 45 分鐘的人工測試與程式碼審查。我們並沒有創造出一個五分鐘的開發流程,而是創造出一個 50 分鐘的開發流程,只是其中的實作階段非常快。
而且驗證的那一半比以前更難,因為你現在是在審核不是自己寫的程式碼。
多生成程式碼無法解決這件事。我們需要更好的回饋迴圈。
<h2>規格正在成為持久的產物</h2>
我認為最重要的轉變在這裡,而且遠遠超過測試本身。
如果代理可以廉價地重寫某個元件,我們就不會那麼依附任何特定實作。實作正在變成可丟棄的東西。六個月後,路由會變、框架會變、DOM 會變、內部架構也會變。
但使用者需求不會變:
<blockquote>
重設密碼的使用者之後必須能用新密碼驗證成功、不能再用舊密碼驗證成功,且不能再次使用重設連結。
</blockquote>
在程式碼生成成本低廉的時代,值得維護的東西越來越是規格,而不是實作。這表示我們值得先寫規格,刻意把它當成一個獨立產物,而不是已完成系統的文件說明。
<h2>從行為開始,不是從實作開始</h2>
我用一個<a href="https://github.com/kenwalger/spec-first-verification">小型 Web 應用程式</a>、<a href="https://claude.com/product/claude-code">Claude Code</a> 和 <a href="https://testrigor.com/">testRigor</a> 做了測試。
這個應用刻意做得很普通:身分驗證、使用者帳號、登入行為,這類在無數商業應用中都看得到的功能。我不是想知道代理能不能做出視覺上很驚豔的東西,我想回答另一個問題:我們能不能先定義預期行為,讓代理去實作,然後用獨立的端到端驗證來判斷代理是否真的成功?
以密碼重設功能為例。實作包含路由、表單處理、權杖產生、驗證、密碼雜湊、資料庫更新、工作階段行為、錯誤處理與 UI 變更。代理可以很快把這些全部生出來。
但使用者在意的不是那些實作細節。使用者在意的是:能不能提出重設、收到信件、設定新密碼、用新密碼登入,以及舊密碼和已用過的連結是不是都不能再用了。
這些都是可觀察的結果。這讓它們成為一個很好的邊界,用來區分我們要求代理建造的東西,以及代理實際建造出的東西。
<h2>可執行規格</h2>
這就是 testRigor 讓我覺得有意思的地方。
testRigor 以接近英文的行為指令來表達測試,而不是要求測試作者主要處理選擇器和自動化程式碼。測試描述的是使用者做了什麼,以及他們期待看到什麼。
搭配 AI 輔助開發時,這就產生了一個機會,因為行為測試可以充當可執行規格。
與其告訴代理「新增密碼重設」,不如提供一份行為契約。應用程式必須寄出重設連結;連結必須導向表單;新密碼之後必須可用;同一條連結不能第二次再用。
這樣就有兩個產物、兩種責任。程式碼代理負責想辦法把行為實作出來。行為測試負責判斷這個行為是否存在。
這種分離,才是重點。
<h2>不要讓學生替考試打分</h2>
AI 程式工具越來越能自己生成測試,這很有用,我也會用。但如果同一個系統去解讀需求、建立實作、替這份實作建立測試,最後再宣告一切都通過,那就會有問題。
同一個系統可能在多個地方犯下同樣的錯誤。如果代理誤解了需求,它會產生符合這種誤解的程式碼,以及驗證同樣誤解的測試。
全部都綠燈,但全部也都錯了。
這正是重設連結那次發生的事。若叫一個代理替它剛做好的功能寫自己的測試,它會測試 happy path,因為它理解中的需求就是 happy path。測試會通過。
只有因為一份在寫程式前就先寫好的規格,才會提出需求文件從未提過的問題,所以才會有「只能使用一次」這個檢查。這正是它的價值:重點不是測試用英文寫,而是它是由思考需求的人,而不是思考實作的人所寫。
獨立的行為驗證問的是另一個問題:
<strong>不管你怎麼實作,這個軟體是否展現出我們指定的行為?</strong>
這更接近使用者真正關心的問題。
<h2>把迴圈接起來</h2>
我最感興趣的部分不是測試工具,而是這個回饋迴圈。
一旦端到端測試產生確定性的通過或失敗,結果就能成為程式代理的輸入。代理實作功能,行為測試執行;如果測試失敗,失敗結果就回傳給代理。代理檢視實作,再做一次修改,接著再次進行驗證。
<img src="https://www.kenwalger.com/blog/wp-content/uploads/2026/09/mermaid-diagram-2026-09-08-140833.png" alt="流程圖,展示 AI 輔助軟體開發迴圈:將行為契約交給 AI 程式代理,代理產生實作。行為端到端驗證檢查預期行為是否存在。通過的行為會成為已驗證行為,而失敗證據則回傳給程式代理以進行下一次實作嘗試。
" />
在我的案例中,整個流程跑了三次。第一次對基準版本是紅燈,因為功能還不存在。生成後再跑一次,因為重複使用連結而再次紅燈。把失敗訊息作為上下文回傳給代理後,第三次變成綠燈。實際耗時約二十分鐘,大部分時間都不需要我盯著。
失敗訊息比我預期的更重要。它不是堆疊追蹤,而是一個行為步驟,用很白話的英文描述了「應該發生卻沒有發生」的事。人看得懂,代理也看得懂,這就是讓迴圈能夠閉合、而不需要我在兩者之間轉譯的原因。
代理現在擁有的,不只是「再試一次」,而是某個特定預期行為沒有被觀察到的證據。
https://www.youtube.com/watch?v=QCAUyFKlhhQ
<a href="https://youtu.be/QCAUyFKlhhQ">AI 生成程式碼的 Spec-First 驗證</a>
這支影片的完成度不高,或許正適合作為一個實驗。真正有意思的不是製作精良,而是看這個迴圈如何運作。
<h2>生成和權威是兩種不同的工作</h2>
這也強化了我最近在 AI 系統設計上一直在思考的一件事。機率式系統非常適合用來提出建議:生成這個實作、解讀這個需求、建議一個修正、解釋這個失敗、判斷哪些檔案可能需要改。
但有些地方,我希望由別的東西來擁有權威。建置是否成功?API 是否回傳預期回應?資料庫是否包含預期狀態?使用者能否完成指定流程?測試是否通過?
這些問題都可以用確定性的方式回答,這帶來一個很有用的架構分工:
<strong>AI 提議,確定性系統驗證。</strong>
這不會消除錯誤。寫得不好的測試會驗證錯的東西。不完整的規格會漏掉重要行為。測試環境可能和正式環境不同。驗證本身也需要工程設計。
但把生成和驗證分開,代表我們不再把模型的自信當成實作正確的證據。
<h2>行為測試不是魔法</h2>
使用這種接近英文的測試系統,也讓我再次體會到另一件事:自然語言不代表不需要學習成本。
工具仍然有語意。你還是得理解系統如何辨識元素、如何解讀指令、如何管理狀態、如何處理驗證,以及當應用程式沒有如預期運作時它會怎麼反應。我有好幾次都得先學會 testRigor 特有的語彙,某個看似理所當然的指令才會照我預期執行。我的規格原本假設重設成功後應用程式會進到登入表單,但它沒有。那是我規格的缺口,不是應用程式的 bug,而我花了一次原本沒預留的執行才找出來。
這不是 testRigor 獨有的缺陷。抽象化不會消除複雜度,它只是把複雜度移到別處。
SQL 並沒有消除理解資料庫的需要;高階語言並沒有消除理解軟體的需要;自然語言測試也沒有消除理解測試的需要。
改變的是,誰可以表達行為,以及這個行為和實作細節之間綁得有多緊。那一點確實很有意思。
<h2>我們應該優化的是什麼</h2>
AI 輔助開發的熱潮,很大一部分都聚焦在生產力上。開發者寫程式能快多少?代理能完成多少任務?用了多少 token?
這些指標不是沒用,但它們不是結果。軟體存在的目的,是要以足夠正確的方式運作,解決問題。
如果代理十分鐘內生成了一萬行程式碼,而我們接下來花了一整天確認其中有沒有任何一段能用,那些程式碼就不是生產力的證據,而是等待檢查的庫存。
真正值得追蹤的指標,是單位時間內交付的正確功能。這包含生成,也包含驗證。當生成的邊際成本趨近於零時,剩下的成本主要就在第二半段。
程式代理一定會變得更強。它們會產生更大的變更、在更少監督下運作更久、理解更複雜的儲存庫,並更自主地處理更多實作流程。這只會讓驗證更重要,而不是更不重要。沒有獨立評估就提高自主性,不會帶來更好的開發系統,只會帶來更快產出未驗證內容的來源。
機會在於,把驗證納入架構本身,而不是事後才補上。規格定義目的地,程式代理提出路線,驗證告訴我們是否真的到達。
不是更快生成程式碼,而是更快交付可正常運作的軟體。
原文出處:https://dev.to/kenwalger/the-verification-bottleneck-in-ai-generated-software-3p7l