DDD 戰略設計#

模組化與依賴方向告訴我們「怎麼切」才內聚低耦合,但沒回答一個更前置的問題:該沿著哪條線切? 領域驅動設計(Domain-Driven Design, DDD)的**戰略設計(Strategic Design)**提供了答案——以業務領域的自然邊界作為切分依據。本章只談戰略層(宏觀邊界劃分),不涉及實體、值物件等戰術層細節。

本章開宗明義先講清楚:DDD ≠ 微服務。DDD 是一套劃分業務邊界的方法論,產出的是「限界上下文」這種邏輯邊界;要不要把每個上下文部署成一個獨立微服務,是另一個(架構風格層級的)決策。DDD 在單體裡同樣適用。微服務拆分如何借用這些邊界,見服務拆分策略

統一語言(Ubiquitous Language)#

戰略設計的地基,是統一語言:開發者、領域專家、產品在「同一個邊界內」使用完全一致的術語,且這套術語直接體現在程式碼裡(類別名、方法名)。

  • 沒有「業務說 A、程式碼叫 B、文件寫 C」的翻譯損耗。
  • 同一個詞在不同上下文可以有不同意義——這正是需要劃分邊界的訊號。

例如「商品(Product)」:在「商品目錄」上下文裡指規格、描述、分類;在「庫存」上下文裡指 SKU 與數量;在「物流」上下文裡指重量與體積。硬要全公司共用一個 Product 巨型模型,反而把不相干的概念綁死。

限界上下文(Bounded Context)#

限界上下文是統一語言成立的邊界——在這個邊界內,每個術語都有單一、明確的意義;跨出邊界,同名術語可能意義不同。它是 DDD 最核心的戰略概念。

flowchart LR
    subgraph BC1[商品目錄 Context]
        P1[Product = 規格/描述/分類]
    end
    subgraph BC2[庫存 Context]
        P2[Product = SKU/數量]
    end
    subgraph BC3[物流 Context]
        P3[Product = 重量/體積]
    end

    style BC1 fill:#e3f2fd
    style BC2 fill:#e8f5e9
    style BC3 fill:#fff3e0

限界上下文同時是模型邊界團隊/所有權邊界:一個上下文有清楚的負責團隊,內部高度內聚,對外只透過明確契約溝通。它天然滿足第 9 章的高內聚低耦合。

子域分類:把精力放在對的地方#

業務領域(Domain)可拆成多個子域(Subdomain)。依「是否是公司競爭力來源」分三類,決定投資策略:

子域類型定義投資策略例子(電商)
核心子域(Core)公司賴以致勝的差異化能力最強團隊自研,精雕細琢推薦演算法、動態定價
支撐子域(Supporting)必要但無差異化,配合核心自研但求堪用,或外包商品評論、賣家後台
通用子域(Generic)業界通用、已有成熟方案直接買 / 用現成(不要自研)金流、寄信、登入認證

子域分類最大的價值是指導取捨,呼應合適原則:把最好的人力與最複雜的架構留給核心子域;通用子域千萬別自己造輪子。判斷標準是「這塊做得比對手好,客戶會不會因此選我們?」——會,才是核心。

子域(業務的問題空間)與限界上下文(解決方案的邊界)理想上一一對應,但實務上可能多對多,需要刻意對齊。

Context Map:上下文之間的關係#

系統由多個限界上下文組成,它們必然要協作。Context Map(上下文映射)描繪這些上下文間的整合關係與權力結構——誰受誰影響、誰要遷就誰。

flowchart TD
    Catalog[商品目錄] -->|共享核心| Search[搜尋]
    Order[訂單] -->|客戶-供應商<br/>U/D| Payment[支付閘道]
    Order -->|防腐層 ACL| Legacy[舊 ERP]
    Promo[行銷活動] -->|遵奉者| Catalog
    Risk[風控] -.各行其道.- Recommend[推薦]

    style Order fill:#e3f2fd
    style Legacy fill:#ffebee
    style Payment fill:#fff3e0

常見的關係模式:

關係模式權力/方向適用情境
共享核心(Shared Kernel)雙方共管一小塊共用模型兩團隊緊密協作,願意共同維護一小段重疊
客戶-供應商(Customer-Supplier)上游(U)供應、下游(D)消費;下游有發言權上游願意配合下游需求排優先序
遵奉者(Conformist)下游完全順從上游模型,無發言權上游強勢(如大平台 API),下游只能接受
防腐層(ACL, Anti-Corruption Layer)下游建一層轉換,隔離上游模型上游是爛模型/舊系統,不想讓它污染己方
開放主機服務(OHS)+ 發布語言(PL)上游提供標準化公開協定上游要服務多個下游,定義通用整合協定
各行其道(Separate Ways)完全不整合整合成本高於收益,乾脆切開

防腐層(ACL) 是實務上最常用、也最值得投資的模式:當你必須對接一個模型混亂的舊系統或第三方時,建一層轉換,把外部概念翻譯成自己上下文的統一語言。它正是第 9 章端口-適配器在領域整合層級的應用——保護核心模型不被外部細節腐蝕。

與微服務拆分的關係#

限界上下文與微服務常被混為一談,務必分清:

概念本質邊界類型是否需獨立部署
限界上下文領域模型的語言邊界邏輯邊界不一定
微服務可獨立部署的執行單元物理邊界

合理的關係是:限界上下文是微服務拆分的「候選邊界」。一個上下文可以:

  • 先作為單體內的一個模組(依第 9 章保持內聚);
  • 待團隊規模、部署需求成長後,再依演化原則獨立成微服務;
  • 甚至一個上下文拆成多個服務、或多個小上下文合成一個服務——按需決定。

不要「一個限界上下文一定要一個微服務」地教條化。先用 DDD 把邏輯邊界劃清楚(這在單體裡就該做),再依架構風格的取捨決定物理部署。把語言邊界劃錯,拆成再多微服務也是分散式大泥球。微服務的拆分時機與粒度,詳見服務拆分策略

本章小結#

主題核心觀點
統一語言同一邊界內術語完全一致,並落到程式碼
限界上下文統一語言成立的邊界,同時是模型與團隊邊界
子域分類核心/支撐/通用,指導人力與自研/採購取捨
Context Map描繪上下文間的整合與權力關係;ACL 最常用
DDD ≠ 微服務上下文是邏輯邊界、是微服務的候選;是否獨立部署另行決策