SDD 規格驅動開發
當我們對 AI 說:「幫我做一個登入功能」,AI 花了幾分鐘產出一堆程式碼,最後很有信心地說:「完成了!這個功能已經可以使用。」
看了一下,好像有登入表單、有驗證邏輯、有錯誤處理。看起來很專業。結果實際試一下,發現登入成功後沒有跳轉頁面。怎麼辦?接著我們可能再跟 AI 說:「登入成功後要跳到首頁。」AI 又再次修好了,但這次忘記處理密碼錯誤的情況。再修,它又改壞了另一個地方。就這樣來來回回,原本以為十分鐘能搞定的功能,搞了兩個小時。
更慘的是,最後拿到的程式碼跟我們想像的架構完全不同。AI 用了我們從來沒看過的套件,寫了一堆看不懂的抽象層。最後可能確實能動,但你完全不知道它在幹嘛,也不知道以後怎麼維護。
這不是你的問題,也不是 AI 的問題,這是方法論的問題。
Vibe Coding 的甜蜜與危險
2025 年初,Andrej Karpathy 提出 Vibe Coding 的概念,就是「憑感覺寫程式」,我們好像不用真的懂程式在幹嘛,只要跟 AI 聊天、許願,它就會幫你把東西生出來。做出來的東西不喜歡?沒關係,再繼續跟 AI 聊天、許願,它就會調整,整個過程就像在跟一個很厲害又超級有耐心的同事聊天,聊著聊著程式就寫完了。
Vibe Coding 在某些場景下非常有效,例如想快速做個 POC 驗證想法?沒問題。想寫個小工具自己用?完全可以。在探索一個新技術,不確定要怎麼用?Vibe Coding 能讓我們很快地摸到感覺。但當專案變大、需求變複雜或是團隊成員變多的時候,Vibe Coding 的問題就會浮現。這也是 Vibe Coding 這個詞好像已經變成一種嘲諷或是反面教材的原因之一。
所以,Vibe Coding 可能會遇到的第一個問題是 AI 產出的程式碼風格不一致。我們今天早上請它寫會員登入功能,下午讓它寫購物車,明天再來一個訂單管理功能,它可能會用三種完全不同的方法跟架構。整個專案看起來像是三個不同的人寫的,因為它確實是三次不同的對話產出的結果。
第二個問題是 AI 可能不會主動告訴你它漏掉了什麼。我們跟它說要登入功能,它就做登入功能,但它不一定會問「登入失敗要怎麼處理?」、「密碼有什麼格式限制?」、「要不要實作『勿忘我』的功能?」(啊,抱歉用了超老派的死語)。這些細節沒跟 AI 講,AI 可能就不會做,或是反之沒講但做了你目前可能還不想要或不需要的功能。等你發現的時候,已經寫了一堆程式碼,要回頭改就很痛苦,說不定整個砍掉再重來一次還比較快。
第三個問題是最致命的,就是 AI 很會說「我完成了」。Amazon Kiro 的首席工程師 Al Harris 在 2025 年的演講中講得很直白,他說 AI 很擅長說「我做完了,我很滿意,你應該也很滿意」之類的話。但實際上測試沒過、邏輯有漏洞、邊界條件沒處理,它都會輕描淡寫地帶過。「喔對,測試沒過,但那個測試很煩,我試了三次都不行,就先跳過了。」
這不是 AI 在騙你,這是 LLM 本質上的問題。LLM 擅長模式識別和文字生成,但不擅長理解我們心裡真正想要什麼。給它一個模糊的指令,它就會用「最常見」的模式來填補那些模糊的空間。問題是,我們的需求往往不是最常見的那種。
於是有人開始想有沒有什麼方法可以讓 AI 更可靠一點?大家最近常聽到的 Spec-Driven Development(SDD)就是其中一個答案。
SDD 是什麼?
大家別誤會,以為 SDD 是什麼新的發明。「先寫規格再寫程式」這個概念早就存在了,瀑布式開發時代就已經在做這件事。TDD、BDD 這些方法論也都強調「先定義預期結果,再寫實作」的精神。這些做法在 AI Coding 興起之後經歷了一次復興,加上一些 KOL 的推廣或炒作,變成現在大家在講的 SDD。
它的核心想法其實不複雜,就是在寫程式之前,先把規格寫清楚。這不是要我們寫一份落落長的規格文件然後丟給 AI,而是把規格變成 AI 和人類之間的共同語言,一個可以持續演進的共識基礎。根據 Amazon Kiro 團隊的定義,SDD 的工作流程分成三個階段,每個階段都有對應的文件。
第一個是 Requirements,把需求寫成「使用者故事(User Story)」的格式,附上明確的「驗收標準(Acceptance Criteria)」,存在 requirements.md 裡。第二個是 Design,產出技術設計文件,包含架構圖、資料模型等,存在 design.md 裡。第三個是 Tasks,把工作拆成一個一個可追蹤的小任務,存在 tasks.md 裡。這三份文件會隨著專案演進而更新,而且規格跟程式碼要保持同步。
換句話說,SDD 試圖解決的問題是當我們跟 AI 許願「做一個登入功能」的時候,要怎麼保證我們跟 AI 對於「登入功能」的理解是一致的,或是如何確保最後產出的程式碼真的做到了我們想要的事情。來細看 SDD 的這三個階段...
SDD 的三個階段
第一階段 Requirements
需求階段。這個階段的目標是把你腦袋裡模糊的想法變成清晰的、可被驗證的需求。這不只是簡單寫一句「要有登入功能」就好了,而是要寫成使用者故事的格式,然後附上具體的驗收標準。例如:
作為一個使用者,我希望能夠用 Email 和密碼登入,這樣我就能存取我的個人資料。
這是使用者故事,遵循「作為《角色》,我希望《功能》,這樣我就能《好處》」的格式。
然後驗收標準可能會寫成:
- 「當使用者輸入正確的 Email 和密碼的時候,系統應該將使用者導向首頁。」
- 「當密碼錯誤超過三次的時候,系統應該鎖定帳號三十分鐘。」
這種「當...的時候,系統應該...」的寫法其實就是待會介紹的 EARS 格式。如果各位有寫過 BDD 測試,可能會覺得這跟 Given、When、Then 的寫法很像。兩者的概念確實相近,只是 EARS 省略了 Given(前提條件),直接從觸發條件開始描述。在這個階段結束的時候,我們和 AI 對於「什麼叫做完成」應該有一致的理解。
第二階段是 Design
設計階段。有了清晰且一致的需求之後,接著由 AI 幫忙產出一份技術設計文件。這份文件會包括系統架構圖、資料流程、資料模型、錯誤處理策略、測試策略等等。
設計階段的重點是讓我們有機會在寫程式之前就發現問題。比如說,你可能會發現某兩個需求是衝突的,或是某個技術選擇會讓後續的擴展變得困難。這些問題在設計階段發現,修改成本很低。如果這等到程式都寫完了才發現,那就有點痛苦了。在這個階段,我們可以要求 AI 加入 wireframe mock,不是要用 Photoshop 或 Figma 畫,光是用 ASCII 畫出大概的介面就行了。這樣你就能在寫程式之前就確認介面的設計是你要的。如果不是,現在改規格很簡單,比等程式寫完再改容易太多了。
第三階段 Tasks
到了這個階段,AI 會根據需求和設計,把工作拆成一個一個小任務。每個任務都有明確的目標和驗收標準,而且會追溯到最初的需求編號。
任務的「顆粒度(granularity)」很重要,但這沒有一定要切多大或多小的標準答案。一般來說每個任務應該要夠小,小到「你」可以在一個合理的時間內完成並驗證。為什麼我特別標記「你」?因為每個人的經驗和能力不同,對任務大小的感受也會不同。你可以根據自己的經驗來調整任務的大小,確保每個任務都是你能夠掌握的範圍。
這樣做的好處是,如果某個任務出了問題,你很快就能發現,而且修復的範圍是有限的。不會像 Vibe Coding 那樣,做到一半才發現整個架構都錯了,要全部重來。
EARS 讓需求變得可執行
剛才提到 EARS 格式,這是 SDD 裡面一個很重要的概念。EARS 的全名是 Easy Approach to Requirements Syntax,翻成中文大概是「需求語法的簡易方法」。這個格式是 Alistair Mavin 和 Rolls-Royce 團隊在 2009 年提出的,最初是為了分析噴射引擎控制系統的適航法規。他們發現需求最容易閱讀的方式,是讓各個子句永遠按照固定順序出現,然後逐漸精煉成這套格式。後來被 Airbus、NASA、Siemens 等公司採用,也被很多大學納入教材。
EARS 的核心是用 shall 搭配固定順序的條款(例如 When…shall…),必要時用 Then 拆出結果,以結果來說它是人類可以讀懂的文字,又有足夠的結構讓機器可以解析。
舉個例子:
WHEN the user enters correct email and password
THEN the system SHALL redirect the user to the home page
這個需求很清楚地說明了觸發條件(輸入正確的帳密)和預期行為(跳轉到首頁)。沒有模糊空間,沒有需要猜測的地方。
EARS 格式的好處有幾個:
首先它強迫我們把需求想清楚。我們不能再寫「登入要順暢」這種模糊的東西,必須明確定義什麼情況下應該發生什麼事。
其次它讓需求更容易被測試。因為需求被寫成明確的觸發條件與預期結果,我們更容易把它們整理成測試案例,進而驗證行為是否符合規格。
最後它減少了 AI 的猜測空間。當使用結構化的語言描述需求,AI 就不需要去猜到底想要什麼。它可以直接根據需求來生成程式碼,而且生成的結果更可預測。
SDD 的三個層級
如果你去看目前市面上的幾種 SDD 工具,你會發現它們對「Spec」的使用方式不太一樣。在 Martin Fowler 團隊的文章裡有提到把 SDD 分成三個層級:
第一層是 Spec-first,規格優先。這是最基本的 SDD 做法,就是在寫程式之前先寫好規格,然後用規格來引導 AI 生成程式碼。當這個任務完成之後,規格可能就被丟掉了,下次有新任務再寫新的規格。大部分的 SDD 工具都至少支援 Spec-first,這已經比 Vibe Coding 好很多了,因為你至少有一份文件記錄你當初想要什麼。
第二層是 Spec-anchored,規格錨定。這個層級的做法是把規格保留下來而且還加進版本控制裡,讓它隨著專案演進而更新,而且團隊成員手上都有一份。當你要修改功能的時候,你不是直接去改程式碼,而是先改規格,然後讓程式碼跟著規格走。Spec-anchored 的好處是你永遠有一份文件知道系統應該做什麼。這對團隊協作特別有幫助,因為新來的人可以先看規格,就能理解系統的設計意圖,而不是只能從程式碼去猜。
第三層是 Spec-as-source,規格即原始碼。這是最激進的做法,你根本不直接編輯程式碼,你只編輯規格。程式碼完全由規格自動生成,甚至會在檔案開頭加上「GENERATED FROM SPEC - DO NOT EDIT」這樣的警告。
對原本就會寫程式碼的工程師來說,Spec-as-source 聽起來有點夢幻,但它的邏輯其實很清楚。如果我們相信「規格是真相的來源」,那為什麼還要讓人去碰程式碼呢?讓程式碼完全由規格生成,就能確保兩者永遠一致。
目前大部分的工具還是停留在 Spec-first 或 Spec-anchored 的階段。Spec-as-source 還在實驗階段,這對規格的撰寫能力要求很高,因為我們得要把規格寫得非常非常精確,才能確保生成的程式碼是正確的。
工具比較
市面上已經有幾個工具在做 SDD 相關的事情。讓我們來看看幾個比較有代表性的工具。
Kiro
Amazon Kiro 是從 VS Code 專案 fork 出來的,由 Amazon 團隊開發。它的工作流程是 Requirements → Design → Tasks,三個階段都有對應的 Markdown 文件。Kiro 的特色是它使用 EARS 格式來撰寫需求,而且支援 property-based testing,可以自動驗證程式碼是否符合需求。
Kiro 還有一個叫做 Hooks 的功能,可以在檔案變更的時候自動觸發某些動作。比如說,你可以設定一個 Hook,讓每次 CSS 檔案變更的時候,自動檢查它是否符合 Figma 設計稿。這對維護設計一致性很有幫助。
Spec Kit
Spec Kit 是 GitHub 推出的開源工具,可以搭配 GitHub Copilot、Claude Code、Gemini CLI 等各種 AI Coding 工具一起使用。它的工作流程是 Constitution → Specify → Plan → Tasks,多了一個 Constitution 的概念,用來定義團隊的基本原則和約束。
Spec Kit 的特色是高度可客製化。因為所有的東西都是放在你的專案目錄裡的,你可以自己修改模板、調整流程、加入額外的檢查點。這對有特殊需求的團隊來說很有彈性。不過根據 Martin Fowler 團隊的觀察,Spec Kit 目前還是比較偏向 Spec-first 層級,對於 Spec-anchored 的支援還不是很明確。每次建立規格都會開一個新的 branch,這暗示他們把規格視為某次變更的產物,而不是功能的長期文件。
Tessl Framework
Tessl Framework 目前還在封閉測試階段,但它的願景很有趣。Tessl 明確追求 Spec-as-source 的層級,希望讓規格變成唯一需要維護的東西,程式碼完全由規格生成。
Tessl 的 Framework 會幫你建立三種東西:Plans(行動計畫)、Specs(意圖描述)、Tests(驗證測試)。除了 Framework 之外,他們還提供一個免費的 Spec Registry,裡面有超過一萬個 OSS 函式庫的 usage specs。這些 usage specs 的用途是幫助 AI agent 正確使用函式庫的 API,避免產生不存在的方法或版本混淆的問題。
Martin Fowler 團隊在試用 Tessl 的時候發現,因為 LLM 的非確定性,同樣的規格多次生成可能會產出不同的程式碼。這意味著你需要把規格寫得非常精確,才能確保每次生成的結果是一致的。這是一個有趣的挑戰,也讓我們重新思考「什麼是足夠好的規格」。
OpenSpec
最後要介紹的是 OpenSpec,這是一個開源的輕量級工具。如果你覺得 Spec Kit 的流程太重,為了修一顆螺絲要寫十幾頁文件,OpenSpec 可能更適合你。
OpenSpec 的設計理念是 brownfield-first,也就是說它不只適合從零開始的新專案,更適合在現有系統上做修改。它把「真相的來源」和「變更提案」分開管理:openspec/specs/ 存放目前系統應該長什麼樣子,openspec/changes/ 存放你想要做的變更。這樣的分離讓你可以清楚看到每次變更的範圍,也讓多人協作的時候不會互相踩到。
工作流程很簡單:先寫一個 proposal 說明你想做什麼,跟 AI 討論到雙方都同意,然後實作,最後 archive 把變更合併回 specs。整個過程不需要 API key,所有東西都是 Markdown 檔案,放在你的專案目錄裡。
OpenSpec 支援的工具很廣,Claude Code、Cursor、GitHub Copilot、Windsurf、Gemini CLI 等主流的 AI coding 工具都有原生整合。如果你的工具不在支援清單裡,它也提供 AGENTS.md 的方式讓任何 AI 工具都能讀取工作流程指示。我目前主要的開發都是用 Claude Code 搭配 OpenSpec,用起來滿開心的,我再來寫一篇專文分享心得。
SDD 不是萬靈丹
講了這麼多 SDD 的好處,我們也要誠實面對它的問題...
第一個問題是 SDD 會讓開發速度變慢。有開發者在 Hacker News 上分享他用 Kiro 的經驗。他想做一個很簡單的工具,顯示 macOS 的全域鍵盤快捷鍵。他給 Kiro 一份簡短的規格和一些 TypeScript 的 schema,結果 Kiro 寫了大概 5000 行程式碼,包含測試。程式碼可以跑,測試也過了,但 5000 行對這麼簡單的任務來說太誇張了。他後來手動把它縮減到 800 行,功能都沒少。
這說明 SDD 適合有一定複雜度的專案。如果你只是要做一個小工具,直接 Vibe Coding 可能更有效率。
第二個問題是 SDD 會改變工程師的角色。有開發者說,用 SDD 開發流程的感覺不像在寫程式,反而比較像在當 PM。會變成花很多時間在定義需求、審核設計、驗收結果,真正寫程式的時間反而變少了,甚至沒有什麼程式碼是自己寫的,感覺像是在監工 AI 的工作。
這對有些人來說是好事,對有些人來說是壞事。像我原本是很享受寫程式的過程,SDD 就讓我覺得少了什麼。但如果各位更在意的是把事情做好,SDD 確實能幫我們更可靠地達成目標。
第三個問題是要做好 SDD 需要學習新的技能。寫好規格不是一件容易的事,這跟寫程式一樣需要訓練。我們可能得學會用像是 EARS 格式之類的寫法、學會怎麼把模糊的需求變成清晰的驗收標準、學會怎麼設計可測試的系統。這些技能跟寫程式不太一樣,但都需要時間訓練。
第四個問題是工具還在快速演進中。Kiro、Spec Kit、Tessl 以及 OpenSpec 這幾套工具對 SDD 的實現方式都不太一樣,也許下個月又會冒出新的工具、新的方法論。如果現在投入大量時間學習某個特定工具,不能保證這個投資會有長期回報。不過我倒是不太在意這點,因為 SDD 的核心概念是「先寫規格再寫程式」,這個概念不會變。工具只是幫助我們實踐這個概念的手段,學會了 SDD 的思維方式,換工具也不會太困難。
什麼情況適合用 SDD?
根據 Spec Kit 的文件,SDD 適合三種開發階段:
第一種是全新專案(0-to-1 Development),從零開始建立一個系統。這時候花時間寫規格是值得的,因為你有機會在最一開始就把事情想清楚,避免後面付出更大的代價去修正錯誤的設計決策。
第二種是探索性開發(Creative Exploration),嘗試不同的實作方式。當你不確定要用什麼技術、什麼架構的時候,可以用 SDD 的方法同時探索多種可能性。因為規格是跟實作分開的,你可以用同一份規格去嘗試不同的技術組合,看哪個最適合。
第三種是漸進式改進(Iterative Enhancement),在現有的程式碼上工作。這包括新增功能和舊系統現代化,可能也是 SDD 最能發揮價值的場景。現有系統通常有很多隱藏的約束和假設,如果你直接讓 AI 去改程式碼,很容易改壞其他地方。先寫規格、釐清新功能如何與現有系統互動,能大幅降低出錯的機率。
軟體圈常用 Greenfield 和 Brownfield 來區分「全新專案」和「既有系統」這兩種情境,這個比喻來自土地開發或環境工程。Greenfield 指的是未開發的綠地,可以從零開始蓋;而 Brownfield 是已開發過的棕地,可能有舊工廠要拆、土地被污染過,得先處理既有的東西才能動工。
再以 OpenSpec 為例,specs 和 changes 的分離設計就是針對既有系統這個痛點。specs 資料夾告訴 AI「這些是已經存在的規格,你不能亂動」,changes 資料夾則是「這次想做的變更」。更關鍵的是 proposal 階段強迫你先想清楚「這次變更會影響什麼」,列出 Affected specs 和 Affected code。這個動作本身就是在釐清邊界,如果你自己都列不出來,AI 更不可能知道。
不過既有系統有個前提,就是你得先有 specs 可以錨定。如果現有系統本來就沒有規格文件,你得先花時間把現有行為記錄下來,這是導入成本。很多專案的現況是「程式碼就是文件」,要回頭補 specs 需要意志力。所以比較務實的做法是漸進式導入,先從新功能開始建立 specs,慢慢累積,而不是一開始就想把整個系統的規格都補齊。
小結
回到文章一開始的那個問題,當 AI 說「完成了」,你怎麼知道它真的完成了?我想答案應該是:
在開始之前,先定義什麼叫「完成」。
這聽起來很簡單,但做起來不容易。它需要你改變工作方式,從「邊做邊想」變成「想清楚再做」。它需要你學習新的技能,把模糊的想法變成清晰的規格。它需要你接受一個事實,就是前期多花的時間,會在後期省回來。
如果你現在主要是用 AI 來做小專案、寫 POC、或是探索新技術,Vibe Coding 可能還是最有效率的方法。享受那個快速迭代、即時回饋的感覺。但如果你開始做更大的專案、跟團隊協作、或是需要長期維護的系統,我會建議試試看 SDD。不一定要用特定的工具,光是養成「先寫規格再寫程式」的習慣,就能讓你跟 AI 的協作品質提升很多。
SDD 的目標並不是少用 AI,而是讓 AI 的產出變得更可控,也就是說與其完全相信 AI 說「我做完了」,不如用更明確的規格和自動化測試來把關。SDD 不是要取代 AI,而是要讓 AI 更可靠。透過結構化的需求、明確的驗收標準、以及自動化的驗證,我們可以把 AI 變成一個可以信任的協作夥伴。
下次 AI 再跟你說「完成了」的時候,也許可以反問它一句「完成了什麼?」 :)