AI 產出的程式碼,最危險的不是它寫錯,而是它寫得「看起來幾乎對」。
過去一年,越來越多團隊把 Copilot、Cursor、Claude Code 這類工具放進日常開發流程。問題不在 AI 寫不寫得出來,而在於它寫到八成、剩下兩成沒人想接。這兩成裡藏著錯誤的抽象、過度設計的目錄結構、看似合理但其實沒處理 edge case 的邏輯。工程師如果直接接手,常常比從零寫還慢。
接手 AI 半成品的審視順序
面對一份 AI 產出的程式碼或專案骨架,建議按以下順序檢查,而不是一打開就改:
第一步是邊界檢查。AI 很擅長把 happy path 寫得漂亮,但對輸入驗證、錯誤回傳、權限邊界往往一筆帶過。先列出這段程式碼會接收哪些外部輸入(API 參數、資料庫欄位、第三方回傳),逐一確認有沒有處理 null、超長字串、非預期型別。
第二步是抽象合理性。AI 容易過度抽象,例如為了一個只會被呼叫一次的功能,生出 interface、factory、abstract class 一整套。這在小專案是負擔,在維護期更是。判斷原則很簡單:這個抽象目前只有一個實作嗎?如果是,先打平,等真的有第二個需求再抽。
第三步是依賴與版本。AI 會引用它訓練資料裡熟悉的套件版本,可能跟你目前專案的 lock file 衝突,或引入已經不維護的函式庫。每一個 import 都要回頭問:這個依賴必要嗎?專案裡是否已有等價工具?
第四步才是邏輯正確性。前三步沒過,討論邏輯正確性意義不大。
重構策略:不要全改,也不要全留
常見的兩種極端都不好。一種是把 AI 產出整段刪掉重寫,浪費了 AI 已經處理掉的樣板工作;另一種是只改 bug 不動結構,把 AI 的怪味道整包帶進產品線。
比較務實的做法是分層處理:
# 示意:接手 AI 產出的服務層程式碼
# 1. 保留:純函式、資料轉換、樣板程式碼
def normalize_phone(raw: str) -> str:
# AI 寫的字串處理通常可信,補測試即可
...
# 2. 重寫:跨邊界的整合邏輯
class OrderService:
# AI 產出的協調邏輯往往漏掉交易、重試、冪等
# 這層建議照團隊既有 pattern 重寫
...
# 3. 刪除:過度設計的抽象層
# 例如只有一個實作的 AbstractRepository、無用的 Strategy
舉個例子,假設你請 AI 幫你生成一個訂單匯入的批次工具。它可能會給你一個包含 reader、parser、validator、writer 的完整 pipeline。對一次性的匯入腳本來說,這套結構是浪費;但其中 CSV 解析、欄位 mapping、錯誤累積這些片段是可以直接留下的。重點是判斷「哪一層適合 AI、哪一層需要人」。
另一個經驗法則是:測試一律自己寫。AI 生成的測試常常只是把實作反過來描述一次,無法捕捉真實的回歸風險。把 AI 當成寫初稿的同事,但驗收標準握在自己手上。
我們的觀察
在報價與排程時,我們通常會建議客戶不要把「AI 加速」直接折抵在開發時數上。AI 確實能砍掉部分樣板工作,但接手、審視、重構的成本是真實的,而且越是要進產品線、要長期維護的系統,這部分成本越高。把 AI 當成提升下限的工具,而不是壓縮上限的籌碼,導入過程會順很多。
