AI 協作系列|第 4 篇:AI 協作開發的複雜度問題

承接 第 0 篇 的脈絡。系列的最後一篇。

一個我越來越在意的擔心

我有一個擔心,說出來之前我自己也不確定有多真實:AI 協作開發,會不會讓 codebase 越來越複雜?

不是因為需求複雜,而是因為 Agent 在設計上傾向往複雜的方向走。

說「傾向」是因為這不是必然的,而是一個我觀察到的模式。Agent 看到一個問題,容易想到的解法常常包含:加一個抽象層、抽一個 utility、新增一個 config option、引入一個 pattern。這些做法本身不是錯的,問題是:它做這些的觸發條件,比人低很多。


人有摩擦成本,Agent 沒有

一個工程師在寫 code 的時候,「多加一層抽象」是有摩擦成本的。要新建一個檔案、想命名、寫 interface、更新引用、補測試。這個摩擦成本不是壞事——它會讓人在抽象之前先問:「這個真的值得抽嗎?以後真的會重用嗎?」

Agent 沒有這個成本。對它來說,抽一個 utility 和不抽,工作量差不多。所以它傾向做得更多——因為「多做」在它的視角裡,等於「做得更完整」。

問題是,很多時候「多做」等於「引入了不需要的複雜度」。


複雜度是怎麼悄悄累積的

幾個常見的模式:

為未來預備。「這個功能以後可能要支援多種格式,所以先把 parser 做成可插拔的。」但那個「以後」不一定會來,而「先做可插拔」的代價是現在的代碼多了一層間接。

同功能多個實作。每次改動,Agent 可能用稍微不一樣的方式解同樣的問題。一段時間後,codebase 裡有三種日期格式化的方法、兩種 API error 處理的方式,各自都沒錯,但它們不一致,維護的人要記三件事而不是一件事。

有 native 解法但選了外部套件。原生的 fetch 其實就夠,但 Agent 提議用某個 HTTP library,因為它有更多功能。多了一個依賴,為了一個用不到的功能。

抽象了只用一次的邏輯。一個 function 只在一個地方被呼叫,但 Agent 把它獨立出來,因為「這樣可讀性更好」或「日後可以複用」。結果是多了一個 function,但閱讀的時候需要多跳一層。

每一個單獨看都有它的道理,累積起來,就是一個比需求複雜得多的系統。


「簡單性」是要刻意設計的

這個問題讓我意識到一件事:在 AI 協作開發的脈絡裡,「簡單」不是預設值,是要主動選擇的。

對人來說,摩擦成本自然會推向簡單。對 Agent 來說,需要明確的規則才會推向簡單。

於是我定了一個原則,現在寫在規則系統的 Spec 先行那條規則裡:

在所有能完整滿足驗收條件的方案中,選擇複雜度最低的那個,並說明為何需要這個複雜度。

這個原則的重點在「完整滿足驗收條件」——這不是讓 Agent 做少一點,而是在「同樣可以做到正確」的前提下,選最簡單的那條路。


最重要的一個邊界

定這個原則的時候,我擔心一件事:Agent 會不會用「保持簡單」當藉口,跳過錯誤處理或省略邊界條件?

這個擔心是真實的。如果原則沒有寫清楚,「保持簡單」很容易被誤解成「少做事」。

所以原則裡有一條明確的邊界:簡單性適用於設計選擇,不適用於正確性要求。

設計選擇:用 useState 還是 Zustand、要不要獨立出一個 service、用哪個 library——這些有簡單和複雜之分。

正確性要求:完整的 error handling、所有 non-happy path 都有對應邏輯、邊界條件有處理——這些不受簡單性原則影響,該做就要做。

用一個具體的例子說:

「付款 API 只處理了成功的回應,沒有處理 timeout 和 duplicate charge 的情況」——這不是「複雜」,這是正確性問題,簡單性原則管不到這裡。

「為了應對未來可能有的多貨幣支援,現在先把金額計算抽成一個可插拔的 Calculator class」——這是設計選擇,現在沒有多貨幣需求的情況下,這個選擇增加了不必要的複雜度。


review 框架的對應

有了這個原則,review 的時候也需要對應的 checklist。

在 delivery-review 框架裡,over-abstraction 的定義除了「wrapper 套 wrapper」、「為假設需求預先抽象」這些常見型態,今天新增了兩個更具體的情況:

  • 有更簡單的 native / built-in 方案存在,卻選用了外部 library 或自訂抽象
  • 實作複雜度明顯超出需求實際規模(一個 checkbox 的狀態用了 state machine;一個靜態清單上了分頁和虛擬化)

後者的「明顯超出」這個表述是刻意的。不是「有複雜度就報」,而是「複雜度和需求規模不成比例」才報。這需要判斷,不是核對 pattern。


複雜度是在哪裡決定的

想清楚這些之後,我意識到一件事:複雜度其實不是 review 階段的問題。

Review 是事後的動作。但「這個方案是不是比需求複雜太多」這個問題,只有在計畫還沒有落地之前,你才有辦法問到。等 Agent 已經寫完,才去找「哪裡抽象過頭」,等於是在問事後有沒辦法修——不是在問「一開始要不要這樣設計」。

簡單性偏好原則的真正意義在這裡:它不只是 review 時的一條 checklist,它是計畫審查時應該問的問題——「這樣設計是因為需求需要,還是因為 Agent 覺得這樣比較完整?」把這個問題帶進計畫的評估,比在事後 review 找多餘的抽象層有效得多。

規則能做的是讓這個標準明確,讓這個問題有辦法被問出來。複雜度在哪裡被決定,這個問題是在計畫還可以改的時候。


系列結尾

這個系列記錄的是一整天的反省。從想大掃除、到發現問題比清垃圾更根本、到試著把幾件事想清楚、寫進規則。

有些事現在更清楚了:我想要的協作方式是什麼、規則系統要怎麼設計、review 要做什麼和不做什麼、複雜度的邊界在哪裡。

有些事還沒有答案:這些規則真的會改變 Agent 的行為嗎?複雜度問題靠規則能解多少?「參與決策」這個目標,執行起來會是什麼樣子?

我打算繼續觀察。

本文是系列的第 4 篇,也是最後一篇。從 第 0 篇 開始閱讀。