領域驅動設計 (DDD) 精華整理
DDD 不是資料夾改名或套用技術模板(如 UserService),而 是一套設計哲學:讓軟體架構精準反映業務邏輯,並讓開發者與業務專家使用同一套語言。
一、核心觀念:軟體即業務的鏡像
- DDD 是方法,不是技術規範——用來讓開發者與業務專家(Domain Experts)達成共識。
- 關鍵目標: 程式碼反映業務領域,且團隊與業務使用同一套語言。
- 常見誤區: 把 DDD 當成「資料夾結構」「微服務專用」或「萬靈丹」。
二、兩大組成:戰略 vs 戰術
多數團隊只做「戰術」,卻忽略更重要的「戰略」。
戰略設計 (Strategic Design) —— 大局觀
決定系統邊界與架構,是最關鍵的一步。
| 概念 | 說明 |
|---|---|
| 界限上下文 (Bounded Contexts) | 定義模型邊界。同一詞(如「客戶」)在銷售與售後系統中意義不同,應 拆成不同上下文。 |
| 上下文地圖 (Context Maps) | 描述各邊界之間如何溝通與協作。 |
戰術設計 (Tactical Design) —— 實作細節
程式碼層級的模式,用來具體建立模型。
| 模式 | 說明 |
|---|---|
| 實體 (Entities) | 有唯一 ID 的物件(如:訂單)。 |
| 值物件 (Value Objects) | 由屬性定義、不可變、無 ID(如:金額、地址)。 |
| 聚合 (Aggregates) | 一組相關物件,由「聚合根」控制存取,確保資料一致性。 |
| 領域事件 (Domain Events) | 描述已發生的事實(如:OrderPlaced),用來解耦不同上下文。 |
三、共通語言 (Ubiquitous Language)
共通語言是 DDD 的靈魂。
- 定義: 開發、PM、QA 與業務專家在溝通與程式碼中,使用完全相同的詞彙。
- 對比:
- 非 DDD:
processRecord(status = 1)—— 業務聽不懂。 - DDD:
approveLoanApplication()—— 業務與程式碼一致。
- 非 DDD:
四、常見四大錯誤
-
貧血領域模型 (Anemic Domain Models)
實體只有 Getter/Setter,邏輯全塞在 Service,違反物件導向與 DDD。 -
單一萬能模型 (One Model to Rule Them All)
用一個「客戶」類別滿足全公司需求,導致物件臃腫難維護。 -
直接跳入戰術模式
邊界還沒釐清,就開始爭論「是實體還是值物件」。 -
忽視共通語言
程式碼名詞與業務名詞脫鉤,增加翻譯與溝通成本。
五、實踐路徑建議
- 先學語言: 建立術語表,讓程式碼與業務專家說同一套話。
- 鎖定一個界限上下文: 從核心業務(最有價值的商業邏輯)開始。
- 紙上模擬: 用 Event Storming(事件風暴) 工作坊,以便利貼對齊業務流程。
- 保持聚合精簡: 聚合越小,越容易維護與擴充。
總結
DDD = 正確的邊界 (Strategic) + 統一的語言 (Language) + 豐富的模型 (Tactical)
它是一場「理解業務」的長期修煉,而不是一次性的技術套用。