<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


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝29   💬1  
431
🥈
我愛JS
3
🥉
NewsData
2
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登