2.6 Spec-Driven Development:可執行的規格#
一個關鍵問題:精確規格要如何產生#
第 2.1 節提到,需求的最底層是「可執行的規格(Spec)」。而 2.5 節的結論說,人類要「產出精確的規格」。這裡浮現了 AI 時代最核心的一個命題:
過去的程式設計是「把需求翻譯成程式碼(Code)」;未來的程式設計,則是「把模糊想法翻譯成精確規格(Spec)」。
很多人會問:「可是規格要怎麼寫得精確?」這正是本節要解開的問題。我們稱這個方法為 Spec-Driven Development(規格驅動開發)——一種讓「規格即程式碼(Spec is Code)」成為可能的新開發方式。
從「人讀」到「人和機器都能讀」的規格#
傳統的需求規格是給人讀的自然語言文件(Word、PDF、UML 圖)。這種文件的最大問題是:模糊、會過期、無法直接被執行。
AI 時代的規格,是一份結構化、可執行、人和 AI 都能讀的文件。它有幾種典型的形式,每一種都「精確到可以直接拿來生成程式碼和測試」:
1. 可執行的資料/介面規格(Schema)#
以結構化方式精確定義資料結構、欄位型別、驗證規則與 API 介面。AI 可以直接讀取 Schema 來自動建立資料庫模型、產生資料驗證邏輯與 API 伺服器。
以 TypeScript 的 Zod 為例——
import { z } from 'zod';
// 定義商品項目規格
export const CartItemSchema = z.object({
productId: z.string().uuid(),
quantity: z.number().int().positive(),
price: z.number().positive(),
});
// 定義結帳請求的精確規格
export const CheckoutRequestSchema = z.object({
userId: z.string().uuid(),
items: z.array(CartItemSchema).min(1),
paymentMethod: z.enum(['CREDIT_CARD', 'LINE_PAY', 'APPLE_PAY']),
couponCode: z.string().optional(),
});
// AI 可直接利用此 Schema 進行資料驗證,免寫額外 if/else
export type CheckoutRequest = z.infer<typeof CheckoutRequestSchema>;
這份 Schema 同時是人類可讀的規格、程式會執行的驗證邏輯、以及 AI 生成程式碼的輸入。一個規格多重用途,這就是「可執行」的意義。
2. 行為規格(BDD / Gherkin)#
用 Given-When-Then 結構定義行為與邊界情境,AI 讀取後可直接轉化成自動化端到端測試。
Feature: 線上購物結帳邏輯
身為一個已登入的購物者
我希望能使用折扣碼完成付款
Scenario: 成功使用有效折扣碼結帳
Given 使用者 "User_123" 已經登入
And 購物車內包含商品,單價 100 元、數量 2 件
When 使用者輸入折扣碼 "SAVE20"
Then 系統應計算總金額為 160 元
And 系統應呼叫付款 API,金額為 160 元
Scenario: 購物車為空時結帳失敗
Given 使用者清空了購物車
When 使用者嘗試結帳
Then 系統應拒絕並回傳錯誤碼 "EMPTY_CART"
And 不應進行任何扣款
3. 架構介面規格(TypeScript Interfaces)#
定義模組邊界、服務合約,確保 AI 產出的程式碼嚴格符合架構,不出現型別不匹配。
export interface CheckoutResult {
orderId: string;
status: 'SUCCESS' | 'FAILED' | 'PENDING';
totalAmount: number;
transactionTime: Date;
errorMessage?: string;
}
export interface ICheckoutService {
executeCheckout(request: CheckoutRequest): Promise<CheckoutResult>;
}
Spec-Driven 開發的三重核心#
把上面的例子總結起來,Spec-Driven Development 有三大核心:
1. 契約優先(Contract-First)#
在生成業務邏輯程式碼之前,先定義好介面契約與資料結構。 因為介面是「契約」,定了參數與傳回型別,前端、後端、各模組才能獨立開發。契約靠 Schema / Interface 鎖定,AI 依契約生成實作,就不會跑偏。
2. 測試先行(Test-First 的延伸)#
先根據 Spec 寫出測試案例,再讓 AI 去填實作讓測試通過。 這其實是「測試驅動開發」在 AI 時代的自然延伸——只是現在「寫測試讓人類通過」變成了「寫測試讓 AI 通過」。好的驗收條件就是可驗證的規格。
3. 規格模組化(Modular Spec)#
不要試圖用一份巨大的 Spec 描述整個系統。 把系統拆成獨立的小模組(認證、支付、通知),每個模組有自己的 Spec。這有兩個好處:一是符合「高內聚、低耦合」(見第 3 章),二是避免一次給 AI 太多上下文(Context 過大時 AI 容易出錯,這是第 7 章的主題)。
人機分工:誰來寫 Spec?#
一個自然的問題是:這三份 Spec 由人寫還是 AI 寫?
答案沿用 2.5 節的框架:「人類主導概念與目標,AI 負責寫出規格,最後由人類審核確認。」人類不需要從零逐字寫 Schema 或 TS Interface,而是提供高階意圖,讓 AI 生成草稿,人類再把關微調。
| 規格類型 | 人類負責的部分 | AI 負責的部分 |
|---|---|---|
| BDD(Gherkin) | 商業目標與核心邊界:「我要結帳流程,有折價券,購物車空的要擋掉」 | 自動轉為 Given-When-Then,並反問:「折價券過期?金額為負?」補齊邊界 |
| TS Interface | 架構決策:「用單體還是微服務?要抽象化金流嗎?」 | 依架構決策產生 Interface、Enum、Service Contract |
| 可執行 Schema | 資料驗證規則:「密碼至少 8 碼」「數量不能小於 0」 | 把自然語言規則轉成正確的 Zod / OpenAPI 語法 |
完整流程#
一個完整的 Spec-Driven 開發循環是:
flowchart TD
A[人類:提供高階意圖<br/>敘述商業目標] --> B[AI:生成第一版 Spec 草稿<br/>Schema + BDD + Interface]
B --> C[人類:審核與微調<br/>補邏輯死角、修正規則]
C --> D{Spec 確認?}
D -- 否 --> B
D -- 是 --> E[AI:根據 Spec 生成程式碼<br/>Controller / Service / 資料模型]
E --> F[AI:根據 Spec 生成測試<br/>Unit Test / E2E]
F --> G[人類:審查品質與安全<br/>承擔最終責任]值得注意的是,這個流程把人從「寫實作」解放出來,集中到「前端定義問題、後端把關品質」(呼應 1.5 節)。而 Spec 是整個循環的「單一真實來源(Single Source of Truth)」——程式碼改了,Spec 應該同步更新;Spec 改了,AI 重新生成對應實作。
傳統 Spec vs AI 時代 Spec#
| 面向 | 傳統 Spec | AI 時代 Spec |
|---|---|---|
| 撰寫者 | 完全由 PM / 架構師手寫 | 人類引導 + AI 自動補全與對齊 |
| 表達形式 | 繁複的自然語言 PDF / Word / UML | 可執行的 Schema、BDD、TS Interfaces |
| 維護成本 | 極高(Code 改了,Spec 就過期) | 極低(AI 雙向同步) |
| 精確度要求 | 容忍某種模糊 | 需嚴格邏輯一致(作為 AI 生成程式碼的 Prompt) |
一句話總結:在 AI 時代,「寫精確 Spec」就是新時代的「寫程式」(Specification is Code)。 人類工程師的核心功力,不再是記得多少語法或函式庫,而是能否清晰地定義問題邊界、輸入輸出規格,以及判斷 AI 補全的邏輯是否有死角。
本章小結#
- Spec-Driven Development:規格即程式碼
- 三種可執行規格:可執行 Schema、BDD/Gherkin、TS Interface
- 三大核心:契約優先、測試先行、規格模組化
- 人機分工:人類主導概念與目標,AI 寫規格草稿,人類審核
- Spec 是單一真實來源,驅動程式碼與測試的生成
- 「寫精確 Spec」就是 AI 時代的「寫程式」
想一想#
- 用「訂位系統」為例,嘗試寫一份小的 Zod Schema(或你熟悉語言的對應)定義訂位請求。
- 為什麼規格要模組化,不能一份大文件包整個系統?
- 你覺得「Spec 是單一真實來源」這句話,在多人 + AI 協作時為什麼特別重要?(提示:見第 12 章)