最近我們用 AI Coding Agent 寫了一個完整的後端 + 前端功能模組。Agent 跑完之後,dotnet build 過了,pnpm build 也過了,單元測試也沒紅燈。
看起來一切完美,對吧?
Build Pass 的假象
事情是這樣的。我們有一個新功能需求:一個庫存轉換模組,包含後端 API(.NET Core)和前端介面(React)。我把需求拆成 11 個 unit,交給 AI Agent pipeline 去跑——後端 7 個、前端 4 個,依序執行。
大概跑了一個多小時,11 個 unit 有 10 個成功(1 個因為 session lock timeout 失敗,清掉重跑就好了)。最後我手動確認:
1 | dotnet build # ✅ Build succeeded |
好,建 PR,準備 review。
然後災難就開始了。
第一輪:命名全歪
Review 的第一件事就發現,AI 產生的 DTO 命名跟我們的 codebase 慣例完全對不上。
我們的慣例是這樣的:
- API 層:Request 用
XxxReq、Response 用XxxRes、查詢用XxxSearchParams - BLL 層:輸入用
XxxInfo、輸出用XxxResult、查詢用XxxSearchInfo - 資料夾:
Dtos/Params/(放 Req)、Dtos/ViewModel/(放 Res)
AI 寫出來的呢?XxxParams、XxxViewModel、XxxResModel——每一個都「幾乎對」但「就是不對」。更慘的是,它在 API 層和 BLL 層之間的命名混在一起,改 A 的時候不小心動到 B。
這不是 AI 笨。這是 AI 沒有讀過我們內部的 convention document,它只能從 prompt 裡的描述去「推測」命名規則。推測的結果就是——看起來合理,但跟實際 codebase 不一致。
第二輪:業務邏輯的「合理但錯誤」
命名改完,開始看邏輯。AI 寫了一個 Save 方法,做了這些事:
- 判斷
info.Id == null來決定新增或更新 - 新增和更新分成兩個 private method
- 用 transaction 包起來,失敗 rollback
每一項都「聽起來合理」。但我們的 codebase 慣例是:
- 用
query.FirstOrDefault()判斷資料存不存在(不看 Id) - 單一
Savemethod,不拆分 - 草稿存檔不需要 transaction
這就是 AI 程式碼最危險的地方:它寫出來的東西在技術上完全正確,但不符合你的團隊慣例。如果你不熟悉自己的 codebase,你甚至不會發現有問題。
第三輪:Controller Return 的鬼打牆
這一輪讓我印象最深刻,因為我自己也搞混了。
AI 的 Controller 這樣寫:
1 | [] |
看起來沒問題?但我們的慣例是:
- POST 新增 →
StatusCode(201, id) - PUT 更新 →
StatusCode(201) - DELETE →
StatusCode(204) - GET →
Ok(data)
我先改成 Created(),發現不對。改成 Ok(),還是不對。改成 StatusCode(201),差一點。最後才確認是 StatusCode(201, id) ——因為前端需要拿回 id 做導航。
這來回改了四次。四次。
第四輪:前端的過度工程
前端也沒好到哪去。AI 為了一個「掃碼 → 新增明細」的功能,寫了 500 多行的 Form component,包含:
materialLockstateqtyLockstateMaterialSelectormodalensureMaterialInfo驗證函式useRef做 material cache
實際上需要什麼?一個掃碼輸入框 + 一個 append 按鈕。掃完碼,填入 mini form,按 append 寫進主表單。大概 100 行。
AI 傾向於「防禦性過度設計」——它會想像各種邊界情況然後全部處理,結果是把一個簡單的功能變成一個複雜的系統。
第五輪:細節魔鬼
到了第五輪,剩下的都是小東西,但加起來很要命:
- 編輯模式的按鈕文字用了
save而不是update - Form 嵌套問題(
<Form>裡面不能再放<Form>) initialValues應該改用useEffect+setFieldsValue- 路由用 query string(
/form?id=xxx)而不是 path params(/:id/edit)
每一個都不難改,但 如果你信任 build pass 就直接 merge,這些問題全部會進 production。
問題出在哪?
回頭看這整件事,核心問題很清楚:
AI 能理解「通用最佳實踐」,但不能理解「你的團隊慣例」。
dotnet build 檢查的是語法和型別。它不會檢查你的 DTO 叫 Req 還是 Params,不會檢查你的 Controller 回 Ok() 還是 StatusCode(201),不會檢查你的 Save method 是不是 follow 團隊的固定 pattern。
這些「慣例」存在於:
- 團隊成員的腦中
- 散落在各處的 convention document
- Codebase 裡已有 module 的「既有寫法」
AI Agent 能接收 prompt,但 prompt 不可能把所有慣例都塞進去。結果就是——AI 寫出來的 code「技術正確、慣例錯誤」,而且錯得很隱蔽。
我們後來怎麼做
踩完這次坑之後,我們做了幾件事:
1. 把 convention document 原子化
原本我們有兩份大文件:backend.md(300+ 行)和 frontend.md(200+ 行)。問題是太長了,AI 不一定會把每條規則都記住。
我們拆成小檔案,每個檔案 < 200 行,開頭寫「什麼時候要讀這個檔案」:
bll-save.md— 寫 Save 方法時讀controller.md— 寫 API endpoint 時讀frontend-form.md— 寫表單時讀
這樣 AI Agent 在執行特定任務時,只需要載入相關的小檔案,而不是一次消化 500 行規範。
2. Prompt 裡加 CRITICAL WARNINGS
在每個 unit 的 prompt 裡,我們開始加上醒目的警告:
1 | ⚠️ CRITICAL: BLL Save 必須用單一 Save method, |
不是期待 AI 自己推論,而是直接告訴它「你最可能犯的錯」。
3. Build Pass ≠ Review Pass
這是最重要的心態調整。我們現在的 pipeline 是:
- AI Agent 跑完 → 確認 build pass
- 人工 review(至少看 DTO 命名、BLL pattern、Controller return)
- 修正 → 再 review
- 確認 merge
Build pass 只是第一關,不是最後一關。
4. 先 grep 再寫
這條規則現在寫死在我們的 agent prompt 裡:
寫任何 BLL 方法前,先 grep 同類方法看現有 pattern,一模一樣照抄。
不要讓 AI「發明」寫法。讓它先看你的 codebase 怎麼寫,然後照抄。
結語
AI Coding Agent 是真的很強。一個小時跑完 11 個 unit,涵蓋 DDL、DTO、BLL、Controller、前端頁面——如果全部手寫,至少要兩三天。
但「能跑」和「能用」之間,還是有一道很深的溝。
這道溝不是 AI 的問題,是「團隊知識」的問題。你的命名慣例、你的 Save pattern、你的 return convention——這些東西沒有寫在任何 RFC 或 best practice guide 裡面,它們只存在於你的團隊文化中。
AI 不會自動學會你的文化。你得教它。而且得教得很具體、很原子化、很不留餘地。
如果你也在用 AI 寫 production code,我的建議是:永遠不要相信 build pass。Review 每一行。不是因為 AI 寫得爛,而是因為「正確」有兩個層次——技術正確和慣例正確。AI 能做到前者,後者目前還是需要人。
至少目前是這樣。