昨天說這一年八個案子裡有兩個失敗、三個做到了,而兩邊出自同一群人。今天先拆失敗的那一個。它是整個 Part 0 的主案例,後面幾天的數字幾乎都從它身上來。
我們接了一個後台系統的技術升級案。舊系統是十幾年前的 Web Forms,要換成前後端分離的現代架構。整個案子全程使用 AI 輔助開發,而它的起點,是一份畫好版面的 Prototype。
但有一件事我必須先講,因為它會改變你對後面所有數字的理解。這個案子在我們接手之前,已經有一個廠商執行失敗了。而客戶找我們的原因很直接:時程已經嚴重不足,他們想知道能不能用 AI 快速地把它做出來。
也就是說——AI 在這個案子裡不是「我們想試試看的新方法」,是一根救命稻草。後面每一個決定的形狀,都被這件事決定了。
而我們當時走的路,其實比那個時間點的主流前面一點。那時候大部分人還在談 Vibe Coding,我們已經在試另一條:
AI 讀舊程式 → 產生規格 → 照規格改寫
而且我們知道 AI 會產生幻覺。 所以我們一開始就對客戶提了一個要求。我到現在都認為那個要求是對的:
請你們能夠明確地進行測試,把測試案例寫出來。
因為如果 AI 的產出沒有一個外部的對照基準,「它做對了嗎」就永遠只能靠人一頁一頁看。
**然後我們卡住了。而卡住的地方不是 AI。**走到最後,客戶來跟我們協商,他想要找人重做。理由是他們認為透過 AI 產生的東西有問題。專案在四個月後結束。時間軸大概是這樣:
第 1 個月 啟動。一週掃完舊系統的全部頁面,十天產出全部需求文件
第 2 個月 開始出現規範文件——API 命名規範、「絕對禁止異動 DB Schema」
第 3 個月 進入測試。三輪功能測試,累積八十幾個問題
月底:上線準備度報告——完成度 65–70%,預估還要 15–25 天
修完之後又冒出七十幾個,分 12 輪處理,然後交付客戶測試
—— 空窗約三週(客戶測試 + 農曆春節)——
第 4 個月 年後回來。主規範文件大改寫,加入「行為複製規範」
完成全部 Use Case 重做
然後雙方商議停止工作
那個「請你們寫測試案例」的要求,最後沒有被滿足。不是客戶不配合——是他們答不出來。那套系統跑了十幾年,規則散在裡面,當初知道的人早就不在了。你要他們寫測試案例,等於要他們先說出「這個系統應該怎麼運作」。而那正好是沒有人知道的事。
所以整個案子的真實形狀是這樣:
時程嚴重不足 → 找 AI 加速
AI 會產生幻覺 → 要求測試案例當外部基準
客戶答不出來 → 沒有基準
沒有基準 → 只能靠人一頁一頁看
而當我們想再變一次招的時候,客戶喊了停。這件事我後來想了很久,最後收斂成一句話:
在建造一個東西之前,你要先明白你要建造什麼。
這句話聽起來像廢話。它在 AI 進來之前也確實接近廢話,因為那個「不明白」可以靠工程師邊做邊補,補完沒有人會發現。
而現在補不了。 這一整個系列,說穿了都是在處理這句廢話變成硬約束之後的那些後果。----**重啟之後做的第一件事,很說明問題:回頭把整個系統的需求,用 149 份 Use Case 重新寫一次。**那,正是這個案子在第一個月就應該交付的東西。
然後那 149 份 Use Case,成了這個案子最後的交付物。
所以這個案子的形狀是這樣的:
我們花了四個月,最後終於把需求寫對了。
然後就沒有專案可以用它了。
那三週空窗,一半是客戶測試,一半是農曆春節。所以第 4 個月的「重啟」,其實就是年後回來。進度看起來斷了很久,但那段時間本來就不在工期裡。回來之後做的第一件事,是把整個系統的需求用 149 份 Use Case 重新寫一次。為什麼會在這個時間點,去產製大量的 Use Case 文件?
不是為了交文件。是為了讓 AI 讀得懂既有規格。有了規格,才能反過來讓 AI 對照規格,去審查和驗證前面幾個月開發出來的東西。
而會走到這一步,是因為當時卡在一個很尷尬的位置:
兩邊都沒有標準答案。 所以工程團隊試著用 AI 把規格補出來,弭平那個差距。
然後客戶喊停了。理由是:不要再使用 AI。
這裡有一個迴圈,我到現在都覺得很難消化:
用 AI 開發,因為規格不明確而出事。
於是想用 AI 把規格補起來,好讓 AI 去驗自己的產出。
而客戶正是在這一刻決定:不要再用 AI 了。
從客戶的角度,這個決定完全合理。他看到的是「用了 AI,然後測起來很痛苦」。但被停掉的那個動作,恰好是這個案子唯一在往正確方向走的動作。----
這件事要先說清楚,不然前面那些數字會被高估。**整個測試的焦點,從頭到尾都在 UI 介面。業務邏輯的部分,一直沒有被深入驗證過。**這有兩個方向相反的後果,兩個都要認:
一、「客戶要求重做」是根據 UI 層的體驗做出來的,不是對整個系統的技術評價。它很真實、也足以殺死一個專案,但它不等於「這套程式碼是壞的」。二、而「後端幾乎沒事」也要跟著打折。 後端問題單少,有一部分原因是沒有人深入測過。
第二點我必須自己認下來,因為它正是這個系列一直在講的那句話。沒有訊號,不等於沒有問題。這句話對後端一樣成立,對我自己拿來當證據的那個對照組也一樣成立。
所以那個對照我仍然相信方向,但強度要降:有驗證機制的地方沒出事,其中一部分是「真的沒事」,另一部分是「我們不知道」。----
在拆這個案子的細節之前,我想先把整個 Part 0 的骨架講一下,這樣後面在看那些數字的時候比較能聚焦。因為接下來幾天會出現很多現場的細節,如果沒有一根軸把它們串起來,讀起來就只是別人的災難紀錄而已。
通常我們在講「這個東西做對了沒有」的時候,其實隱含了三件事情要同時成立:
規格說了 → 產出做了 → 驗收驗了
這三個環節,任何一個斷掉,結果都是錯的。而我這一年遇到的失敗,剛好就是這三種斷法:
| 規格 | 產出 | 驗收 | 你會看到什麼 | |
|---|---|---|---|---|
| 一 · 漏做 | 沒說 | 沒做 | 看不到 | 什麼都沒有 |
| 二 · 多做 | 沒說 | 自己補了 | 看不到 | 一個看起來很專業的東西 |
| 三 · 錯維度 | 說了 | 做了 | 驗錯地方 | 一個綠燈 |
第一種是「漏做」。規格裡沒提到,AI 自然不會做,而你驗收的時候也不會想到要去看一個從來沒被提過的東西。所以最後的結果是:什麼都沒有,而且沒有人發現。
第二種是「多做」。規格裡一樣沒提到,但這次 AI 自己補上去了 (它從訓練資料裡學到「這種頁面通常會有這些東西」)。你打開來看,畫面很完整、甚至比你想的還專業,所以也不會覺得有問題。
第三種比較尷尬。規格說了、AI 也做了,問題出在驗收。我們檢查的不是那一項。所以你會拿到一個綠燈,然後很有信心地交出去。這三種的共同點,其實只有一句話:
它們都沒有訊號。
第一種你看不到東西,第二種你看到的東西看起來很好,第三種你看到的是綠燈。沒有一種會自己舉手告訴你「這裡有問題」。那 Part 0 剩下的日子,基本上就是把這張表的三個欄位各自展開,每一種失敗會用一到兩天來講。中間會穿插它們共同的下游:當三種失敗都沒有訊號的時候,測試階段會變成什麼樣子。

這個案子有一個旁證,我認為是整段最值得看的一件事。同一個案子、同一群人、同一個 AI。後端幾乎沒出事。
因為後端 API 那邊,AI 產出了滿滿的測試案例,形成了回歸保護網。翻那 187 張問題單,後端核心邏輯的異常非常少。出事的全部集中在前端,而且主要是驗證。而客戶最後會崩潰,也正是崩潰在前端驗證這件事上。
有驗證機制的地方,AI 表現得很好。沒有的地方,全崩。
(前面已經扣掉一層:後端的「沒事」有一部分是沒人深入測過。以下講的是扣掉之後還剩下的部分。)這個對照的力量在於它排除了最常見的變因。不是「A 團隊比較強」,不是「這個模型比較好」。同一批人、同一個時期、同一套工具。
但我要把話收一點回來。 我原本寫的是「排除了所有變因」,那句過頭了:前後端至少還差三件事。前端的規格更不完整、前端的失效天生沒有訊號、AI 對 UI 的訓練偏好特別強。三個變因剛好都指向同一個結論,所以結論我仍然相信;但「所有」兩個字,不該出現在一份後面會承認「沒有對照組」的稿子裡。
最後一件事,我認為是整個案子最反直覺的。AI 不是亂寫的。它用了 Clean Architecture。分層清楚、相依方向朝內、該有的邊界都在。以「有沒有照著良好的設計規範做」來說,它做到了。
**而這個系統最後被評為「不可維護」。**一開始我覺得這個評價不公平。後來我認為它成立,只是「可維護」這個詞的意思,跟我原本以為的不一樣:
可維護性不是程式碼的屬性,是程式碼跟那群要維護它的人之間的關係。
Clean Architecture 是一套需要被理解才會發揮作用的東西。它並沒有消滅複雜度,是把複雜度換了位置。用更多的檔案、更多的間接層,換取邊界清楚、換取以後改得動。這筆交易划不划算,取決於接手的人有沒有那套心智模型。 沒有的話,你交出去的不是「好維護的系統」,是「更多要讀的東西」。
而這個案子裡,那套心智模型從來沒有在任何一個人的腦袋裡建立起來。**它只存在於產生它的那個 AI 的上下文裡,而那個上下文早就沒了。**用你可能更有感的講法:
好的架構要搭配得起它的工程師,好的設計要搭配維護得了它的團隊。
搭不起來的時候,它就只是一件藝術品。
這件事後面還會再遇到一次,而且是用一個更嚴肅的形式。當程式碼還在、但那套理解它的人已經散掉的時候,這個系統還算不算活著。----
寫到這裡,我心裡真正的 OS 是這一句:
不是要叫 AI 做「最好」的東西,是要叫它做「最適合」的東西。
而這兩個詞的差別,剛好就是這個系列一直在繞的那件事:
| 是什麼 | 誰判斷得了 | |
|---|---|---|
| 最好 | 產出自己的屬性 | AI 判斷得了。 它讀過的最佳實踐比我們任何人都多,你不講它也會往那邊走 |
| 最適合 | 產出跟環境之間的關係 | AI 判斷不了。 環境不在它的上下文裡 |
所謂環境,是這些東西:**接手的人有幾個、他們熟不熟這套分層、這個系統三年後還有沒有人養、客戶願不願意為了「邊界清楚」多付一條學習曲線。**沒有一項寫在需求裡。而沒有人告訴它「適合」是什麼,它就只好做「最好」。
然後它做得很好——好到被評為不可維護。
但這裡我要先把「最好」這個詞收一點回來。
說「AI 會做最好的東西」其實是抬舉它了。它做的是「手邊最近的那個 prior」。在架構這件事上,最近的 prior 剛好是 Clean Architecture(訓練資料裡到處都是);但換一個場景,最近的 prior 可能是這個 repo 裡某人三年前註解掉、沒清乾淨的爛主意。
所以更準的講法是:
不是「AI 會做最好的,而你要告訴它什麼是適合的」。
是「AI 會拿手邊最近的東西填空,而只有你知道那個空該填什麼」。
回頭看,這正是那張表的第二種失敗:規格沒說,AI 自己補了。只是這一次它補的不是一段驗證邏輯,是一整套架構決策。而架構決策沒有紅字提示,也不會在測試裡跳出來。它要等到有人接手的那一天才會結算。
這個案子結束之後,我們做了一輪完整的回顧。六個群組,將近三千行。然後在下一個案子上換了一種做法。那個案子的紀錄是這樣的:
43 次執行 橫跨約兩個半月
一次通過率 36 / 37
人工修正量 42 / 43 次是 0
測試成長 101 → 350 條全綠
同一群人、隔了幾個月、跑的是真實的錢。
所以這個系列真正要處理的問題,不是「AI 產出的品質好不好」。是那兩件事之間,到底差了什麼。
我先把話說在前面:我沒有完全答出來。 我有一套解釋,它在後面幾個案子上也用了,但它沒有對照組。我從來沒做過「同樣的功能人工寫一遍,比較品質和時間」的實驗。所以那套解釋能不能被稱為「有效」,我在最後會逐條算帳。
這個系列是那個追問的過程,不是結論。----
今天講的是這個案子的形狀。從上面看下去:三個環節、三種斷法、一個照著規範做卻被評為不可維護的架構。
而在現場,沒有人看得到形狀。
現場看到的是一張一張的問題單。這個欄位沒擋、那個頁面跳錯、這個訊息沒出來。一輪修完,下一輪又冒出來。沒有人會在第 37 張單的時候說「啊,這是第一種失敗」。大家只會覺得「怎麼修不完」。
而這正是「三種失敗都沒有訊號」的下游:
沒有訊號的東西不會消失,它們只是全部延後,堆到同一個地方才出現。
那個地方是人工測試,而它們出現的形式,是一張一張的單。
所以明天要從形狀下到地板上,看那個測試階段實際長什麼樣。先給你一個數字當預告:那 187 張問題單累積了四個月。而我拿其中一輪去拆,35 張單,其實只有 18 個 bug。
本系列所有案例均經去識別處理,不指涉任何特定客戶、系統或產業。