散亂堆疊的文件與程式碼,經由箭頭整理成分層的金字塔

AI 開發時,是否有注意到這些事?

在現在的軟體開發裡,AI 已經是基本起手式了。

AI 怎麼一步步看懂專案

一開始(像早期的 GitHub Copilot),AI 只看得到眼前這幾個檔案。它懂語言,也懂主流框架,但知識停在訓練截止那天,遇到新版 API、冷門套件或專案自己的慣例就不熟,常寫出過時的寫法,或乾脆繞過框架自己刻。

2024 年底 Anthropic 推出 MCP(Model Context Protocol),讓 AI 能透過統一的介面接上外部工具與資料,框架團隊和社群也開始做自己的 MCP server 來補上更完整的知識。像 Context7 就是專門處理這個問題的服務:它把最新、對應版本的套件文件直接餵給 AI。

後來大家發現,AI 還是沒辦法知道功能的全貌:它可能只改了某個 function 或某個 API endpoint,卻不知道整個功能還牽動哪些地方,或者誤解了商業邏輯。於是開始有了 SDD(Spec-Driven Development)的開發方式,以 2025 年推出的 Kiro 為例,會先建立 Requirements、Design、Tasks 三份文件,再讓 AI 照著做。

同一年 Anthropic 又推出 Agent Skills,大家開始寫自己的 skill,把專案的 Domain(領域)、Docs(文件)、ADR(決策紀錄)、Issue(待辦議題)整理成 AI 讀得懂的形式。

AI 越來越理解專案,知道做什麼事時該看哪個 skill,也知道有哪些歷史決策。一開始這是個甜蜜點:大量的開發飛快地加速,從測試到落地,速度完全超越以前。

但進行一陣子後,會發現一些問題。

文件飄移

文件飄移(Documentation Drift)是以前寫文件時就有的老議題。當功能有了屬於它的文件,寫著為什麼要這樣做、絕對不要怎麼做,就代表必須同時維護「程式碼」跟「文件」。這也是 SDD 裡有人主張「規格即原始碼」(spec-as-source)的原因之一:規格是唯一的來源,人只改規格、不直接碰程式碼,像 Tessl 就是走這條路。

每次 AI 調整或修正某個功能時,只要沒改到文件,就會造成飄移;文件飄移之後,下一次動到這個功能,就可能再踩一次當時的坑。

程式碼文件飄移
程式碼一次次往前改,文件還停在第一版,兩者的距離越拉越大

雖然測試本身就是一份不會飄移的文件(行為一變,測試就會失敗),但大多時候,我們還是希望 AI 跟工程師看同一份文件來理解每項功能。

解法

可以參考社群裡多人推薦的 skill,它們已經把流程想得比較完整。流程類的像 obra/superpowers,把發想 → 計畫 → TDD → review 串成一套;管文件的像 mattpocock/skills 的 domain-modeling,會在討論時同步更新詞彙表與 ADR。流程可以參考社群的,專案知識則還是要自己寫。

除此之外:

  • 寫 hook:hook 是事件觸發的,可以在 AI 改完程式碼時(例如 Claude Code 的 PostToolUse 或 Stop hook)提醒或檢查對應的文件有沒有一起改
  • 定期 review 文件
  • 把文件整理成 domain(領域詞彙),或寫成更行為導向的描述

歷史軌跡

為了避免決策時出問題,很多時候在請 AI 改功能或做決策時,我們會順手、或 AI 會主動把決策日期寫進某段程式碼的註解。剛開始看時能快速理解,上線後出問題也能快速聚焦;但隨著時間過去,上面可能會累積很多像這樣的註解:

# 2026-01-01 因為第三方異動,所以改成傳 id
# 此次異動透過 commit 4728775e
# 該功能於 tag: 1.0.123 版上線

解法

限制註解的內容,只留一個檔案位置,指到統一管理的地方(ADR 或 issue),避免資訊分散:

# 2026-01-01 因為第三方異動,所以改成傳 id
# 此次異動透過 commit 4728775e
# 該功能於 tag: 1.0.123 版上線
# 為什麼改成傳 id:見 docs/adr/0012-partner-api-use-id.md

日期、commit、tag 都能用 git blame、git log、git tag --contains 查到,本來就不必寫進註解;「為什麼這樣改」則寫在 commit message 或 ADR。

大量測試

建立起整個 workflow 之後,即使只是小異動,AI 可能也會走 TDD、自動補上測試,或問你要不要寫測試。整個專案的測試碼就會大量產出,但不一定是照測試金字塔(Test Pyramid)設計過的。每次跑 CI/CD 時,可能花了很多時間驗證其實可以更快的東西,例如可以寫成單元測試的,卻寫成了整合測試。

解法

先定好覆蓋率的護欄(例如下降不超過 1%),再把只驗單一元件邏輯的測試下推到單元層級,並刪掉上層重複的測試;元件之間的銜接點(資料庫、API 契約、第三方串接)則至少保留一個整合測試。也可以定期調整程式碼結構,讓邏輯更容易在單元層級測試。

E2E整合單元銜接點
只驗單一元件邏輯的測試從整合層下推到單元層,元件銜接點留一個整合測試

不過金字塔也不是放諸四海皆準。Kent C. Dodds 提出的測試獎盃(Testing Trophy)就主張以整合測試為主。像前端 UI 這類價值大多在元件組合上的程式,整合測試的比例本來就會比較高,要看專案性質決定。

結語

在這個開發飛快的時代,也需要注意這些問題。它們不一定會讓東西壞掉,但會慢慢拖慢 AI 跟開發者讀懂專案的速度。

以前可能要互相提醒有沒有寫文件、有沒有寫測試、測試完不完整;但現在很多事都交給 AI 在 auto mode 下進行,反而關注的點跟以前都不太一樣了。

還有很多開發行為,以前跟現在可能完全不同,如果你也有想分享的,歡迎留言交流。

留言