iT邦幫忙

2026 iThome 鐵人賽

DAY 2
0

昨天說這一年八個案子裡有兩個失敗、三個做到了,而兩邊出自同一群人。今天先拆失敗的那一個。它是整個 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 個月:用 AI 把規格補回來,然後客戶說不要再用 AI

那三週空窗,一半是客戶測試,一半是農曆春節。所以第 4 個月的「重啟」,其實就是年後回來。進度看起來斷了很久,但那段時間本來就不在工期裡。回來之後做的第一件事,是把整個系統的需求用 149 份 Use Case 重新寫一次。為什麼會在這個時間點,去產製大量的 Use Case 文件?

不是為了交文件。是為了讓 AI 讀得懂既有規格。有了規格,才能反過來讓 AI 對照規格,去審查和驗證前面幾個月開發出來的東西。

而會走到這一步,是因為當時卡在一個很尷尬的位置:

  • 客戶端在測前端驗證,測得很痛苦
  • 而客戶自己也說不出系統原本的規格是什麼

兩邊都沒有標準答案。 所以工程團隊試著用 AI 把規格補出來,弭平那個差距。

然後客戶喊停了。理由是:不要再使用 AI。

這裡有一個迴圈,我到現在都覺得很難消化:

用 AI 開發,因為規格不明確而出事。
於是想用 AI 把規格補起來,好讓 AI 去驗自己的產出。
而客戶正是在這一刻決定:不要再用 AI 了。

從客戶的角度,這個決定完全合理。他看到的是「用了 AI,然後測起來很痛苦」。但被停掉的那個動作,恰好是這個案子唯一在往正確方向走的動作。----

而整場評價,是在 UI 上做出來的

這件事要先說清楚,不然前面那些數字會被高估。**整個測試的焦點,從頭到尾都在 UI 介面。業務邏輯的部分,一直沒有被深入驗證過。**這有兩個方向相反的後果,兩個都要認:

一、「客戶要求重做」是根據 UI 層的體驗做出來的,不是對整個系統的技術評價。它很真實、也足以殺死一個專案,但它不等於「這套程式碼是壞的」。二、而「後端幾乎沒事」也要跟著打折。 後端問題單少,有一部分原因是沒有人深入測過。

第二點我必須自己認下來,因為它正是這個系列一直在講的那句話。沒有訊號,不等於沒有問題。這句話對後端一樣成立,對我自己拿來當證據的那個對照組也一樣成立。

所以那個對照我仍然相信方向,但強度要降:有驗證機制的地方沒出事,其中一部分是「真的沒事」,另一部分是「我們不知道」。----

三種失敗,三種斷法

在拆這個案子的細節之前,我想先把整個 Part 0 的骨架講一下,這樣後面在看那些數字的時候比較能聚焦。因為接下來幾天會出現很多現場的細節,如果沒有一根軸把它們串起來,讀起來就只是別人的災難紀錄而已。

通常我們在講「這個東西做對了沒有」的時候,其實隱含了三件事情要同時成立:

規格說了   →   產出做了   →   驗收驗了
  • 規格說了:這件事有沒有被寫進要求裡(或者說,有沒有人講出來過)
  • 產出做了:AI 有沒有照著那個要求做
  • 驗收驗了:我們最後檢查的時候,有沒有真的檢查到那一項

這三個環節,任何一個斷掉,結果都是錯的。而我這一年遇到的失敗,剛好就是這三種斷法:

  規格 產出 驗收 你會看到什麼
一 · 漏做 沒說 沒做 看不到 什麼都沒有
二 · 多做 沒說 自己補了 看不到 一個看起來很專業的東西
三 · 錯維度 說了 做了 驗錯地方 一個綠燈

第一種是「漏做」。規格裡沒提到,AI 自然不會做,而你驗收的時候也不會想到要去看一個從來沒被提過的東西。所以最後的結果是:什麼都沒有,而且沒有人發現。

第二種是「多做」。規格裡一樣沒提到,但這次 AI 自己補上去了 (它從訓練資料裡學到「這種頁面通常會有這些東西」)。你打開來看,畫面很完整、甚至比你想的還專業,所以也不會覺得有問題。

第三種比較尷尬。規格說了、AI 也做了,問題出在驗收。我們檢查的不是那一項。所以你會拿到一個綠燈,然後很有信心地交出去。這三種的共同點,其實只有一句話:

它們都沒有訊號。

第一種你看不到東西,第二種你看到的東西看起來很好,第三種你看到的是綠燈。沒有一種會自己舉手告訴你「這裡有問題」。那 Part 0 剩下的日子,基本上就是把這張表的三個欄位各自展開,每一種失敗會用一到兩天來講。中間會穿插它們共同的下游:當三種失敗都沒有訊號的時候,測試階段會變成什麼樣子。

https://ithelp.ithome.com.tw/upload/images/20260830/20178262tMRpSPwZK0.png

同一個案子裡的對照組:後端幾乎沒事

這個案子有一個旁證,我認為是整段最值得看的一件事。同一個案子、同一群人、同一個 AI。後端幾乎沒出事。

因為後端 API 那邊,AI 產出了滿滿的測試案例,形成了回歸保護網。翻那 187 張問題單,後端核心邏輯的異常非常少。出事的全部集中在前端,而且主要是驗證。而客戶最後會崩潰,也正是崩潰在前端驗證這件事上。

有驗證機制的地方,AI 表現得很好。沒有的地方,全崩。

(前面已經扣掉一層:後端的「沒事」有一部分是沒人深入測過。以下講的是扣掉之後還剩下的部分。)這個對照的力量在於它排除了最常見的變因。不是「A 團隊比較強」,不是「這個模型比較好」。同一批人、同一個時期、同一套工具。

但我要把話收一點回來。 我原本寫的是「排除了所有變因」,那句過頭了:前後端至少還差三件事。前端的規格更不完整、前端的失效天生沒有訊號、AI 對 UI 的訓練偏好特別強。三個變因剛好都指向同一個結論,所以結論我仍然相信;但「所有」兩個字,不該出現在一份後面會承認「沒有對照組」的稿子裡。

Clean Architecture,卻被評為「不可維護」

最後一件事,我認為是整個案子最反直覺的。AI 不是亂寫的。它用了 Clean Architecture。分層清楚、相依方向朝內、該有的邊界都在。以「有沒有照著良好的設計規範做」來說,它做到了。

**而這個系統最後被評為「不可維護」。**一開始我覺得這個評價不公平。後來我認為它成立,只是「可維護」這個詞的意思,跟我原本以為的不一樣:

可維護性不是程式碼的屬性,是程式碼跟那群要維護它的人之間的關係。

Clean Architecture 是一套需要被理解才會發揮作用的東西。它並沒有消滅複雜度,是把複雜度換了位置。用更多的檔案、更多的間接層,換取邊界清楚、換取以後改得動。這筆交易划不划算,取決於接手的人有沒有那套心智模型。 沒有的話,你交出去的不是「好維護的系統」,是「更多要讀的東西」。

而這個案子裡,那套心智模型從來沒有在任何一個人的腦袋裡建立起來。**它只存在於產生它的那個 AI 的上下文裡,而那個上下文早就沒了。**用你可能更有感的講法:

好的架構要搭配得起它的工程師,好的設計要搭配維護得了它的團隊。
搭不起來的時候,它就只是一件藝術品。

這件事後面還會再遇到一次,而且是用一個更嚴肅的形式。當程式碼還在、但那套理解它的人已經散掉的時候,這個系統還算不算活著。----

那我當時到底該說什麼

寫到這裡,我心裡真正的 OS 是這一句:

不是要叫 AI 做「最好」的東西,是要叫它做「最適合」的東西。

而這兩個詞的差別,剛好就是這個系列一直在繞的那件事:

  是什麼 誰判斷得了
最好 產出自己的屬性 AI 判斷得了。 它讀過的最佳實踐比我們任何人都多,你不講它也會往那邊走
最適合 產出跟環境之間的關係 AI 判斷不了。 環境不在它的上下文裡

所謂環境,是這些東西:**接手的人有幾個、他們熟不熟這套分層、這個系統三年後還有沒有人養、客戶願不願意為了「邊界清楚」多付一條學習曲線。**沒有一項寫在需求裡。而沒有人告訴它「適合」是什麼,它就只好做「最好」。

然後它做得很好——好到被評為不可維護。

但這裡我要先把「最好」這個詞收一點回來。

說「AI 會做最好的東西」其實是抬舉它了。它做的是「手邊最近的那個 prior」。在架構這件事上,最近的 prior 剛好是 Clean Architecture(訓練資料裡到處都是);但換一個場景,最近的 prior 可能是這個 repo 裡某人三年前註解掉、沒清乾淨的爛主意。

所以更準的講法是:

不是「AI 會做最好的,而你要告訴它什麼是適合的」。
是「AI 會拿手邊最近的東西填空,而只有你知道那個空該填什麼」。

回頭看,這正是那張表的第二種失敗:規格沒說,AI 自己補了。只是這一次它補的不是一段驗證邏輯,是一整套架構決策。而架構決策沒有紅字提示,也不會在測試裡跳出來。它要等到有人接手的那一天才會結算。

但同一群人,後來做出了 36/37

這個案子結束之後,我們做了一輪完整的回顧。六個群組,將近三千行。然後在下一個案子上換了一種做法。那個案子的紀錄是這樣的:

43 次執行          橫跨約兩個半月
一次通過率         36 / 37
人工修正量         42 / 43 次是 0
測試成長           101 → 350 條全綠

同一群人、隔了幾個月、跑的是真實的錢。

所以這個系列真正要處理的問題,不是「AI 產出的品質好不好」。是那兩件事之間,到底差了什麼。

我先把話說在前面:我沒有完全答出來。 我有一套解釋,它在後面幾個案子上也用了,但它沒有對照組。我從來沒做過「同樣的功能人工寫一遍,比較品質和時間」的實驗。所以那套解釋能不能被稱為「有效」,我在最後會逐條算帳。

這個系列是那個追問的過程,不是結論。----

現場看不到形狀,只看得到問題單

今天講的是這個案子的形狀。從上面看下去:三個環節、三種斷法、一個照著規範做卻被評為不可維護的架構。

而在現場,沒有人看得到形狀。

現場看到的是一張一張的問題單。這個欄位沒擋、那個頁面跳錯、這個訊息沒出來。一輪修完,下一輪又冒出來。沒有人會在第 37 張單的時候說「啊,這是第一種失敗」。大家只會覺得「怎麼修不完」。

而這正是「三種失敗都沒有訊號」的下游:

沒有訊號的東西不會消失,它們只是全部延後,堆到同一個地方才出現。
那個地方是人工測試,而它們出現的形式,是一張一張的單。

所以明天要從形狀下到地板上,看那個測試階段實際長什麼樣。先給你一個數字當預告:那 187 張問題單累積了四個月。而我拿其中一輪去拆,35 張單,其實只有 18 個 bug。

參考文獻

  1. Martin, R. C.(2017)。Clean Architecture: A Craftsman's Guide to Software Structure and Design。Prentice Hall。
    核心約束是相依性法則(The Dependency Rule):原始碼的相依方向只能由外層指向內層,內層不得知道外層的存在(第 22 章〈The Clean Architecture〉)。

本系列所有案例均經去識別處理,不指涉任何特定客戶、系統或產業。


上一篇
Day 1 - 為什麼我要寫這個系列
下一篇
Day 3 - 同一個原因,修了 20 次
系列文
綠燈不等於做對:AI 開發的驗收工程 ——從兩個失敗的案子,到驗收交付13
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言