前一篇談 API 契約時,我們把前端和後端想成兩個部門。雙方先約好 API 路徑、資料格式與狀態碼,才不會一邊送出 taskId,另一邊卻在等 id。
但一套系統不只有 API 契約。ProjectManagementWeb 還要處理角色權限、Task 狀態轉換、資料版本和交易規則。假設我只對 AI 說:「幫我做批次更新 Task 狀態。」它可能幾分鐘後就交出一份看起來很完整的程式碼,卻漏掉一條重要規則:其中一筆失敗時,其他資料也不能偷偷更新成功。
問題往往不是 AI 不會寫,而是我沒有把「完成」說清楚。規格驅動開發(Specification-Driven Development,SDD)便是從這裡開始:寫 Code 之前,先讓彼此對成果有相同理解。
可以把 AI 想成一位動作很快的新同事。交代工作時,我們不會只說一句「把批次更新做完」就轉身離開,至少會告訴他哪些人能操作、資料要怎麼檢查、失敗時要不要全部取消,以及最後如何驗收。
AI 很會根據常見寫法補齊缺少的部分,可是它不會讀心。沒有寫清楚的地方,它只能猜。偏偏專案最麻煩的規則,常常就藏在這些「大家應該都知道吧」的空白裡。
規格可以把空白補起來。它讓人和 AI 在寫 Code 之前,先對下面幾件事有共同理解:
把這些答案整理成可以閱讀和審查的內容,就是一份規格的起點。接下來的設計、實作與驗證,都要回頭對照它。
「先釐清需求,再實作」早就存在。到了 AI Coding 的工作流程中,規格除了給產品、開發與測試人員閱讀,也成為 AI 調查專案、提出計畫和修改程式時的參考。
SDD 目前沒有一套所有工具都遵守的標準流程。Martin Fowler 對 SDD 的整理將常見做法分成三種程度:
| 程度 | 白話說法 |
|---|---|
| Spec-first | 這次先寫規格,再依規格完成程式 |
| Spec-anchored | 規格完成後繼續留在專案裡,功能修改時也一起更新 |
| Spec-as-source | 人主要修改規格,程式則由工具依規格產生 |
三種做法都先寫規格,差別在於規格要不要長期保留,以及人是否仍會直接修改程式。剛開始接觸時,先做到 Spec-first 就夠了。至少在動手前留下一份共同依據,可以減少「寫完才發現理解錯了」的來回修改。
完整的 SDD 工具會把這套想法拆成幾個明確的階段。以 Kiro 為例,一個功能通常會整理成三份可以修改、也可以審查的 Markdown 文件:
| 階段 | 文件 | 要回答的問題 | 常見內容 |
|---|---|---|---|
| Requirements | requirements.md |
使用者需要什麼?怎樣才算完成? | User Story、驗收條件與例外情況 |
| Design | design.md |
系統準備怎麼完成需求? | 架構、元件分工、資料流與測試策略 |
| Tasks | tasks.md |
要先做什麼?每一步如何確認? | 可以追蹤、可以個別驗證的小任務 |
可以把它想成請新同事接下一項工作。requirements.md 是工作說明,先把目標和規則講清楚;design.md 是他提出的處理方式;tasks.md 則是雙方確認後排出的待辦清單。
每一份文件都提供一次停下來檢查的機會。需求有沒有漏掉權限?設計有沒有繞過現有架構?任務是不是大到做完後才有辦法測?AI 可以先整理草稿,這些判斷仍要由人負責。
GitHub Spec Kit 使用不同的檔案和指令,目前的主要流程是 Constitution、Specify、Plan、Tasks、Implement 與 Converge。它先記錄專案長期遵守的原則,接著定義需求、規劃做法、拆出任務並實作,最後回頭檢查成果與規格之間還有哪些差距。名稱雖然多,順序其實很直白:先談清楚,再動手,做完還要核對。
Codex 的 /plan 是多步驟任務使用的規劃模式。當需求牽涉多個檔案或元件時,可以先讓 Codex 讀取專案、調查現況並提出做法,暫時不要動手修改。我們可以繼續追問或調整計畫,等範圍、順序、風險與測試方式都確認後,再進入實作。
它和 SDD 的精神很接近,但不是同一件事。/plan 是 Codex 的工作模式,不是一套完整的規格管理框架。開啟它之後,不會自動替每個功能建立 requirements.md、design.md 和 tasks.md,也不會保證規格永遠跟程式同步。
| 比較項目 | Kiro、Spec Kit 這類 SDD 工具 | Codex 規劃模式 |
|---|---|---|
| 主要用途 | 用固定流程管理規格、設計、任務與實作 | 編輯前先調查專案並提出計畫 |
| 規格來源 | 依工具流程建立或整理規格文件 | 可以直接讀取現有的 User Story、架構圖與 API 契約 |
| 產出形式 | 有固定階段、範本或檔案結構 | 以這次任務需要的計畫為主 |
| 後續保存 | 通常把規格放進 repository 持續追蹤 | 由團隊決定哪些計畫或文件要保留 |
| 適合情境 | 需要完整追溯或多人共同維護規格 | 已有規格,想先確認 Codex 的實作方向 |
如果專案已經有 User Story、架構圖或 API 契約,/plan 可以先讀取這些資料,再把「要做什麼」整理成「這次準備怎麼做」。它能接住既有規格,不必為了使用某套工具而重寫一份相同的文件。
回到一開始的批次更新。假如只寫:
請幫我完成批次更新 Task 狀態。
AI 得自己猜很多事:誰能更新?可以選幾筆?遇到沒有權限的 Task 怎麼辦?資料衝突時,已經更新的部分要不要留下?
對照 Day3 的 User Story 後,我們可以把需求整理得更具體:
目標:讓有權限的使用者一次更新多筆 Task 狀態。
規則:
1. 後端必須逐筆檢查專案權限、指派關係與狀態轉換。
2. 所有更新必須放在同一個交易中。
3. 只要其中一筆失敗,全部資料都不更新。
4. 成功後,前端要清除這次勾選的 checkbox,並顯示最新狀態。
驗證:
- 全部資料合法時,所有指定 Task 都更新成功。
- 任一筆權限不足、狀態不合法或版本衝突時,所有 Task 維持原狀。
這還不是完整的技術設計,但最容易誤解的邊界已經寫出來了。開發者可以用它檢查設計,測試人員也能直接看出要準備哪些情境。
本系列採用比較輕量的 SDD。ProjectManagementWeb 已經有 User Story、架構圖、流程圖與資料庫設計,這些文件就是人與 AI 討論功能時共同查看的地圖,不需要再抄成另一套規格。
我想保留的是規格先行的習慣。動手寫 Code 前,先讓 AI 理解這次要解決的問題、不能碰的邊界,以及怎樣才算完成。遇到說不清楚或彼此衝突的地方,就停下來討論,不讓 AI 自己猜一個看似合理的答案。
方向確認後才開始實作,做完再用測試與驗收逐項核對。規格像地圖,可以幫我們少走冤枉路,但最後還是要由人確認有沒有抵達目的地。這就是本系列使用 SDD 的方式。
剛開始看到這些縮寫,很容易以為要選一個門派加入。其實它們關心的是不同問題,可以在同一個專案裡合作。
| 方法 | 關心的問題 | 在本系列中的用法 |
|---|---|---|
| SDD | 要做什麼?有哪些限制? | 用規格引導規劃、實作與驗收 |
| BDD | 某個情境發生時,使用者應看到什麼行為? | 把驗收條件整理成 Given-When-Then 情境 |
| DDD | 業務裡有哪些概念、規則與邊界? | 釐清 Project、Task Item、角色與狀態 |
| TDD | 一小段程式應該如何運作? | 先寫會失敗的測試,再實作並重構 |
簡單來說,SDD 先確認整件事要做成什麼樣子,DDD、BDD 與 TDD 再從業務模型、使用行為和程式測試等角度,把不同問題處理清楚。它們可以同時出現在一個專案裡,不必選邊站。
SDD 也有成本。小修改如果硬要走完一大套流程,可能產生比程式碼還長的文件。AI 讀取既有專案時,也可能漏掉藏在程式裡的規則;功能持續修改後,規格和程式甚至會慢慢走散。
所以規格要跟著任務大小調整。一個按鈕改字,不需要三份設計文件;牽涉角色、交易與多個 API 的功能,先寫清楚通常比較划算。判斷方式很實際:如果做錯的代價高,或同一句需求可能有好幾種解讀,就值得多花一點時間整理規格。
規格寫完,不等於功能完成。實作後還是要執行自動化測試、檢查 Git diff、審查程式碼,並逐項對照驗收條件。AI 說「完成了」只能算工作回報,測試結果才是可以檢查的證據。
對本系列來說,SDD 的價值不在於產生多少份 Markdown,而是把人腦裡的期待變成團隊和 AI 都看得到的規則。
有了共同理解,Codex 才知道該往哪裡走,人也知道要檢查什麼。下一篇會接著看單元測試,並使用 Fluent Assertions 把「程式結果應該是什麼」寫得更接近自然語言。規格先把答案說清楚,測試再確認程式有沒有真的答對。
/plan 指令)