← 全部文章
應用搭建 IT / CIO 已釋出 · · 作者 ObjectStack Team

Vibe Coding 技術債:為什麼 AI 生成的應用後來難改

AI 生成程式碼能讓原型很快上線,但長期系統的問題在半年後出現:沒人完整讀過那一萬多行實現,也沒人能解釋當初的業務取捨。企業應用需要生成可審查的定義,而不是難維護的黑箱程式碼。

Vibe Coding 技術債:為什麼 AI 生成的應用後來難改
  • Vibe Coding
  • 技術債
  • 程式碼生成
  • 後設資料
  • AI 治理
  • 趨勢觀點

先給結論:AI 生成程式碼的瓶頸不是寫得快不快,而是半年後沒人讀得懂、也沒人可問——讓 AI 生成後設資料而不是程式碼,這種還不掉的債才不會累積。

故事從第七個月開始。

明享是一家連鎖零售公司,門店幾百家。去年,它的財務團隊(五十多人)受夠了等 IT 排期,用 AI”一句話”搭了套報銷系統。表單、審批、對接總賬,兩天就跑起來了,全員叫好。接下來大半年,它一直好好的。

第七個月,稅務規則變了:某類發票的抵扣比例調整,報銷邏輯得跟著改。一件小事。

然後團隊發現,沒人敢動它。當初那”一句話”背後,是 AI 生成的一萬兩千多行程式碼,沒有一個人完整讀過。抵扣邏輯散在哪幾個檔案?改了會不會連帶影響審批和月末對賬?沒人說得清。更尷尬的是——連寫出這套程式碼的 AI 也幫不上忙:它是無狀態的,那次生成時腦子裡的判斷、權衡、為什麼這麼寫,一點沒留下。你只能把一萬兩千行重新餵給一個新會話,讓它”猜”一遍當初的自己。

這件小事最後排了三週。而真正的代價不止三週:上線前的評審裡,有人發現 AI 順手改動了一處和抵扣無關的對賬邏輯——差一點就讓一批報銷算錯金額流進總賬。這次僥倖被攔住了,但它說明了一件事:這套系統已經沒人能保證”改 A 不會動到 B”。

這就是 AI 程式碼技術債落到一個普通團隊身上的樣子。

這是一種特殊的債:欠了,但找不到債主

技術債不是新詞。但 AI 生成的程式碼,欠的是一種以前沒有的債。

人寫的程式碼也會爛、也會沒文件。但至少作者還在——你能把寫它的人拉來問一句”這裡當初為什麼這麼處理”。程式碼再差,背後總有一個能解釋它的人腦。

AI 生成的程式碼把這個最後的兜底也抽走了。它的”作者”是一個無狀態的模型,生成完那一刻就不存在了。它沒有把可追溯的設計判斷留下來,於是你手上是一坨能跑、但誰都無法解釋、也無人可問的實現。明享那一萬兩千行,就是這種債——它不欠在程式碼質量上,欠在”再也沒人真正理解它”上。

把它叫作**理解債(comprehension debt)**更準確:系統能跑,但組織沒有真正理解它。速度是真的,債也是真的——只是債不在交付那天結賬,而是在第七個月、第一條業務規則改變時找上門。

可程式碼生成不是在飛速變好嗎?

這裡得認真接一個反駁,否則不公道:模型一直在變強,能讀的程式碼越來越長,還有 AI 程式碼評審、“自愈”流水線——會不會再過一年,這些債就被更強的工具自動還掉了?

這個期待有它的道理,但它賭錯了瓶頸在哪。

程式碼生成進步解決的是”寫得更快”。而明享的問題從來不是寫得不夠快——恰恰相反,是寫得太快了:兩天一套系統,改動源源不斷地湧出來。瓶頸在”讀得懂、擔得起”這一側,而它不隨生成能力線性改善。更強的模型生成更多程式碼、更快,可能也會更快地累積沒人讀過的實現。AI 評審能幫著掃一遍,但”這段業務邏輯應該是什麼”這種判斷,它給不了確定答案,因為對錯只存在於業務語境裡,不在程式碼裡。

換句話說:把希望寄託在”模型再強一點”,是在用加速踏板治剎車失靈。

複利:每改一次,就更看不懂一點

為什麼是第七個月,而不是第一個月?因為這種債是複利的。

第一次改,AI 在沒讀懂舊程式碼的情況下”在旁邊再加一段”;第二次改,它面對的是”舊程式碼 + 上次沒讀懂的新程式碼”,於是再加一段。每一層都疊在沒人理解的上一層之上,理解成本指數上漲。所以風險曲線不是緩緩上升的直線,是一條前期平靜、中段陡起的指數曲線——平靜得讓你以為沒事,直到某次再普通不過的改動點燃它。

改動系統的難度隨時間變化:生成程式碼指數級上升,生成後設資料保持平穩

有個簡單的自查,能讓你提前看見自己在曲線的哪一段。下面五條,中三條,你已經在欠 AI 技術債:

  1. 系統裡有某段程式碼,團隊沒人能解釋它”為什麼這麼寫”。
  2. 要改一處,第一反應是”會不會碰壞別的地方”,而不是直接改。
  3. 安全 / 告警數量每個月都在漲,且大多來自新增程式碼。
  4. 每次要改,都得把整塊程式碼重新餵給 AI 讓它”重新讀一遍”。
  5. PR 越來越大,大到沒人真的逐行審,只能看”測試過了嗎”。

這筆債的賬單,最後誰來付

複利曲線最後會變成一張具體的賬單,由四個人分著付:

  • 業務付的是速度:明享那個”小改動”排了三週。當每次改都怕碰壞別處,迭代速度會肉眼可見地塌下來——你以為 AI 讓你更快了,半年後反而更慢。
  • 風控付的是事故:那次差點流進總賬的錯算被攔住了,但下一次未必。告警、例外和安全 review 越積越多,遲早會有一個沒被攔住。
  • 團隊付的是人:沒人願意長期維護一坨自己讀不懂、改了就抖的系統。最瞭解它的人一走,這套系統就徹底變成黑箱——而 AI 程式碼本來就沒有”最瞭解它的人”。
  • 公司付的是重寫:理解債攢到某個點,“改”已經比”重寫”更貴、更險,於是專案被推倒重來。第一版省下的那點時間,連本帶利還了回去。

這四筆,沒有一筆出現在”兩天搭好一套系統”的那份驚喜裡。它們都記在第七個月之後的賬上。

先說清楚:換成後設資料,不是沒有代價

到這裡得誠實停一下,否則又成了賣靈藥。

讓 AI 生成定義而不是程式碼,有取捨。宣告式的後設資料,覆蓋的是企業應用裡反覆出現的結構——物件、欄位、關係、檢視、許可權、流程、審批。它換來的可控性,代價是你放棄了一部分”想怎麼寫就怎麼寫”的自由度。如果你要做的是一個全新的即時協作引擎、一套獨特的圖形演算法,那確實需要真正的程式碼,後設資料幫不了你,硬套反而壞事——ObjectStack 解決的是企業裡一遍遍重建的業務系統,不是下一個 Figma。

還有一層誠實:選後設資料執行時,等於把一部分實現託付給了這個執行時,你押的是它的質量和長期可用性。這是個真實的依賴——只不過,相比”押在一萬兩千行沒人讀的程式碼”上,押在一個被反覆審計、版本化、可遷移的執行時上,是好得多的賭注。

把生成的東西換掉:不是實現,是定義

回到明享那套報銷系統。同樣的需求,如果當初 AI 生成的不是一萬兩千行實現,而是這樣一份定義:

export const ExpenseReport = ObjectSchema.create({
  name: 'fin_expense_report',
  label: '報銷單',
  fields: {
    amount: Field.currency({ label: '金額', min: 0 }),
    invoice_type: Field.select({ label: '發票型別', options: ['普票', '專票'] }),
    deductible_rate: Field.percent({ label: '抵扣比例' }),
  },
});

這幾十行不是”還要去實現的介面”,它本身就是系統。執行時(ObjectOS)讀取它,自動派生資料表、API、介面,以及 agent 可呼叫的受治理工具;許可權、審批流同樣是掛在它上面的宣告,而不是手寫的判斷。

那麼第七個月那次稅務規則變更,長什麼樣?不再是一場考古,而是一行能看懂的改動:

- deductible_rate: Field.percent({ label: '抵扣比例' }),
+ deductible_rate: Field.percent({ label: '抵扣比例', defaultValue: 70 }),
+ // 專票按新規抵扣 70%,規則下沉到定義,審批與對賬自動跟隨

這是一個能在五分鐘內評審、能一鍵回滾的 diff,而不是一個沒人敢點”合併”的四百行 PR;也不會出現”順手改壞對賬”那種事,因為對賬邏輯不在這份定義裡、它根本碰不到。差別不在哪種更”高階”,而在半年後,誰還看得懂、改得動、出了錯查得到

複利機制為什麼被掐斷了

換成定義之後,那條曲線為什麼能壓平?三點,都直指明享那個故事:

  1. 沒有”沒人讀過的實現”。 實現屬於被反覆審計、所有應用共用的同一套執行時,不是每個應用各生成一份。你的應用裡只剩定義,而定義是給人讀的。
  2. 沒有”無人可問”。 定義是宣告式的,它把意圖寫在臉上——deductible_rate 是什麼、歸誰管、改它影響哪些流程,一目瞭然,不需要去問那個早已消失的生成會話。
  3. 漏洞面收窄。 許多常見風險來自手寫的認證、查詢拼接和輸入處理。這些由統一執行時承擔後,應用層能引入的漏洞類別會少很多。

結語

問題不在於 AI 寫程式碼這件事本身,而在於太多團隊把”快速生成原型”的工具,直接當成了”建設長期系統”的方式。原型可以是一堆沒人讀的程式碼,用三年的系統不該是。

下次要用 AI 搭一套真要長期用的業務系統,先別問”它生成得多快”,問明享第七個月才被迫面對的那個問題:半年後規則一變,我還敢不敢改它、查不查得到。 讓 AI 生成定義而不是程式碼,是更可靠地讓這個答案變成”敢”的路徑。

npm i -g @objectstack/cli && os start

定義一個物件,改一次欄位,看看那次改動在 git diff 裡有多幹淨——那就是一筆不會複利的債。