TDD / DDD / BDD 開發方法論完全指南

釐清最常被混淆的三種 *DD 開發方法論,比較它們的層次與關係,並概覽其他常見方法論


目錄


概覽:三個 *DD 不是同一層的東西

名字都叫「X-Driven」,但它們回答的問題不同、作用層次不同,這是最常被誤解的地方:

方法論 全名 驅動的是 關注層次
TDD Test-Driven Development 用「測試」驅動寫程式 程式碼 / 實作
BDD Behavior-Driven Development 用「行為描述」驅動開發 需求 / 溝通
DDD Domain-Driven Design 用「業務領域」驅動設計 架構 / 模型
DDD:怎麼「設計」軟體(領域模型、邊界、架構)       ← 戰略/架構層
BDD:怎麼「描述需求與行為」(讓三方溝通一致)       ← 需求/協作層
TDD:怎麼「寫程式」(測試先行、紅綠重構)           ← 實作/程式碼層

三者不互斥,可同時使用:用 DDD 設計領域模型、用 BDD 釐清行為、用 TDD 實作細節。


TDD:測試驅動開發

TDD(Test-Driven Development) 的核心:先寫測試,再寫實作。測試定義「程式該做什麼」,實作只為通過測試而存在。

紅-綠-重構循環(Red-Green-Refactor)

🔴 Red    :先寫一個會失敗的測試(功能還不存在)
🟢 Green  :寫最少的程式碼讓測試通過(不求漂亮)
🔵 Refactor:在測試保護下重構,改善設計,保持測試綠燈
↺ 重複

範例(虛擬碼)

# 1. Red:先寫測試
test "add(2, 3) 應回傳 5":
    assert add(2, 3) == 5      # add 還不存在 → 失敗

# 2. Green:最小實作
def add(a, b):
    return a + b               # 測試通過

# 3. Refactor:在測試保護下整理程式碼

Kent Beck 的三條規則

  1. 在寫出失敗測試前,不寫任何產品程式碼
  2. 只寫剛好能失敗的測試(編譯失敗也算失敗)
  3. 只寫剛好能讓當前失敗測試通過的產品程式碼

優缺點

優點 缺點 / 限制
測試覆蓋率高、迴歸有保障 前期較慢、學習曲線
逼出可測試、低耦合的設計 不適合需求探索期 / 拋棄式原型
重構有信心、文件即測試 測試本身也要維護
快速回饋、縮短除錯時間 UI / 整合 / 難測元件不易套用

TDD 是實作層的紀律,產出的測試多為單元測試(unit test)。


BDD:行為驅動開發

BDD(Behavior-Driven Development) 是 TDD 的延伸與「外移」:把焦點從「測試程式單元」提升到「描述系統行為」,並用自然語言業務、開發、測試三方對需求達成共識。

Given-When-Then 結構

行為以「情境」描述,常用 Gherkin 語法:

Feature: 購物車結帳

  Scenario: 套用折扣碼
    Given 購物車有一件 1000 元的商品
    When 我套用折扣碼 "SAVE10"
    Then 應付金額應為 900 元
  • Given:前置條件(情境)
  • When:觸發的動作 / 事件
  • Then:預期的結果

工具

這些情境可被工具解析、對應到測試步驟並自動執行:

  • Cucumber(多語言)、SpecFlow(.NET)、Behave(Python)、JBehave(Java)

BDD vs TDD

面向 TDD BDD
焦點 程式單元正確 系統行為符合需求
語言 程式語言 / 測試框架 自然語言(Gherkin)
讀者 開發者 開發 + 測試 + 業務
問題 「這段程式對不對」 「我們是否做對的東西」

BDD 不是取代 TDD,而是在更外層補上「需求溝通」。很多團隊「外層 BDD 描述行為、內層 TDD 實作細節」。


DDD:領域驅動設計

DDD(Domain-Driven Design) 由 Eric Evans 提出,核心:讓軟體模型忠實反映業務領域,把複雜度管理在領域本身。它是設計 / 架構方法,與 TDD/BDD 的層次不同。

戰略設計(Strategic Design)— 巨觀

概念 說明
通用語言(Ubiquitous Language) 業務與開發共用同一套術語,反映在程式碼中
限界上下文(Bounded Context) 把大系統切成有明確邊界的子領域,各自有獨立模型
上下文映射(Context Map) 描述各 Bounded Context 之間的關係與整合方式
核心域 / 支撐域 / 通用域 區分業務的核心價值與周邊,集中資源在核心域

戰術設計(Tactical Design)— 微觀

領域模型的建構元件:

元件 說明
Entity(實體) 有唯一識別、生命週期的物件(如 訂單 Order)
Value Object(值物件) 無識別、以值相等、不可變(如 金額 Money、地址)
Aggregate(聚合) 一組相關物件的一致性邊界,由 Aggregate Root 統一存取
Repository(儲存庫) 封裝聚合的取存,隔離持久化細節
Domain Service(領域服務) 不屬於單一實體的領域邏輯
Domain Event(領域事件) 領域中發生的有意義事件,用於解耦
Factory(工廠) 封裝複雜聚合的建立邏輯

範例(聚合概念)

Order(聚合根 Aggregate Root)
 ├─ OrderItem(實體,只能透過 Order 操作)
 ├─ Money(值物件,不可變)
 └─ 不變條件:訂單總額 = 所有明細金額加總
   → 外部不能直接改 OrderItem,必須經由 Order 維持一致性

適用與成本

  • 適合:業務複雜、規則多變、長期演進的核心系統
  • 不適合:簡單 CRUD、業務邏輯薄的應用(會過度設計)
  • 成本:學習曲線陡、需要與領域專家密切協作

DDD 常與微服務搭配:Bounded Context 是切分微服務邊界的自然依據。


三者比較與關係

        需求/溝通           設計/架構            實作/程式碼
          BDD                 DDD                  TDD
   「做對的東西嗎?」     「如何建模領域?」      「程式對不對?」
   Given-When-Then      Bounded Context        Red-Green-Refactor
   自然語言情境          Entity/Aggregate       測試先行
          │                   │                    │
          └─────── 可同時使用、互補,非互斥 ───────────┘
維度 TDD BDD DDD
類型 開發實踐 開發實踐 / 協作 設計方法論
解決問題 程式正確性 需求一致性 複雜度管理
主要產物 單元測試 行為規格(可執行) 領域模型 / 架構
核心關係人 開發者 開發 + 業務 + 測試 開發 + 領域專家
是否需要測試 是(核心) 是(行為層) 否(與測試正交)

關鍵認知:DDD 回答「軟體怎麼設計」,TDD/BDD 回答「怎麼把它正確做出來並驗證」。三者解決不同問題,搭配使用最常見。


其他開發方法論

除了這三個,*Driven 家族與相關方法論還有不少:

*DD 家族

縮寫 全名 核心
ATDD Acceptance Test-Driven Development 以「驗收測試」驅動,與 BDD 高度重疊,更強調驗收標準
FDD Feature-Driven Development 以「功能清單」為單位迭代開發
MDD Model-Driven Development 以模型(UML 等)為核心,部分程式由模型生成
EDD Event-Driven Development 以事件流為核心的架構風格(與 event-driven architecture 相關)
TypeDD Type-Driven Development 以型別系統引導設計(Haskell / Idris 等強型別語言)
CDD Contract-Driven / Component-Driven 以介面契約 / 元件為驅動單位

ATDD 與 BDD 常被混用:兩者都以「期望行為 / 驗收條件」先行,差別主要在用語與側重(ATDD 偏驗收標準,BDD 偏行為描述與三方溝通)。

相關工程實踐 / 流程

  • XP(eXtreme Programming,極限編程):TDD、配對編程、持續整合等實踐的集合
  • Scrum / Kanban:敏捷專案管理框架(流程層,非編碼方法論)
  • CI/CD:持續整合 / 持續交付(自動化流程)
  • DevOps:開發與維運整合的文化與實踐

設計原則(不是方法論,但常一起談)

  • SOLID:物件導向五大原則
  • DRY / KISS / YAGNI:避免重複 / 保持簡單 / 不過度設計
  • Clean Architecture / Hexagonal(六角架構):與 DDD 常搭配的分層架構

怎麼選 / 怎麼搭配

沒有「選一個」這回事

它們大多是互補的。常見的組合:

DDD(設計領域模型、切 Bounded Context)
  └─ BDD(用 Given-When-Then 描述每個行為 / 驗收條件)
       └─ TDD(實作時測試先行,紅綠重構)
            └─ CI/CD(自動跑測試、自動部署)

依情境取捨

情境 建議
簡單 CRUD、邏輯薄 不必上 DDD;TDD 視團隊習慣
業務複雜、長期演進 DDD 管理複雜度,搭 TDD/BDD
需求模糊、跨部門溝通成本高 BDD 拉齊三方理解
重視品質、頻繁重構 TDD 提供安全網
探索性原型 / 拋棄式程式 先別套 TDD,避免拖慢探索

常見問題

問題 1:TDD、BDD、DDD 要三選一嗎?

不用。它們作用在不同層次(實作 / 需求 / 設計),可同時使用、互相補強。

問題 2:BDD 是不是只是「換句話說的 TDD」?

不是。BDD 把焦點從「測程式單元」提升到「描述系統行為」,用自然語言讓業務也看得懂,重點在需求一致性與溝通,而不只是測試。

問題 3:DDD 為什麼跟 TDD/BDD 不太一樣?

因為 DDD 是設計 / 架構方法論(怎麼建模領域、切邊界),而 TDD/BDD 是開發實踐(怎麼把它正確做出來)。DDD 不規定你怎麼測試。

問題 4:小專案需要 DDD 嗎?

通常不需要。業務邏輯薄的 CRUD 套 DDD 會過度設計。DDD 的價值在於管理複雜業務,簡單系統用不到那層抽象。

問題 5:ATDD 和 BDD 差在哪?

高度重疊,都以期望行為 / 驗收條件先行。差別主要在側重:ATDD 強調「驗收標準」,BDD 強調「行為描述與三方共同語言」,實務上常被當成同一回事。


總結

核心要點

  • 三個 *DD 不同層次:TDD(實作)、BDD(需求溝通)、DDD(設計架構),不互斥
  • TDD:先寫測試 → 紅綠重構,逼出可測試的低耦合設計
  • BDD:Given-When-Then 自然語言描述行為,拉齊業務 / 開發 / 測試三方
  • DDD:用通用語言與限界上下文建模複雜業務,戰略 + 戰術設計
  • 還有 ATDD / FDD / MDD / EDD / TypeDD 等家族,以及 XP、SOLID 等實踐與原則
  • 實務常疊加使用:DDD 設計 → BDD 描述 → TDD 實作 → CI/CD 自動化

快速參考

方法論 一句話 招牌
TDD 測試先行 紅-綠-重構
BDD 行為先行 Given-When-Then
DDD 領域先行 Bounded Context / Aggregate
ATDD 驗收先行 驗收測試
FDD 功能先行 功能清單迭代

建立日期:2026-06-18

🔗相關文章