iT邦幫忙

2025 iThome 鐵人賽

DAY 12
0
Software Development

微服務導入:從觀念到落地的架構實戰地圖系列 第 12

微服務導入 - D12 微服務與 DDD 的交織

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20250919/2017826247MiClg8FW.png

當我們討論「微服務」時,很容易把焦點放在技術層面,例如 Spring Boot、Kubernetes、Service Mesh 或 API Gateway。然而,若僅以技術去思考,往往容易落入「從框架開始切割」的陷阱,最後產出的服務不僅不獨立,還可能形成比單體架構更複雜的「分散式大泥球」。

這也是為什麼許多專家會強調:微服務設計應以領域為核心。領域驅動設計(Domain-Driven Design, DDD)不僅是一種建模方法,更提供了一套思維工具,引導我們從業務語言、組織結構與上下文邊界出發,逐步切分出合理的微服務。

換句話說,微服務架構並不是純粹的技術議題,而是一個結合業務策略、組織協作與技術實踐的系統工程。DDD 的「戰略設計」恰好提供了這個橋樑。


DDD 的戰略設計基礎

DDD 可分為「戰略設計」與「戰術設計」兩個層面:

    • 戰略設計:關注整體系統的劃分與協作,核心概念包括 Bounded Context(界限上下文)、Context Map(上下文關係圖)、通用語言(Ubiquitous Language)等。
    • 戰術設計:關注單一上下文內部的建模與實作,例如 Entity、Value Object、Aggregate、Repository、Service 等設計元素。

在微服務設計的階段,我們應優先從戰略設計切入。因為若沒有清楚的上下文邊界,服務之間的責任就容易模糊,進而導致高耦合、重複功能,甚至團隊溝通成本的增加。

舉例來說,假設我們正在設計一個銀行的數位金融平台,若沒有 DDD 的視角,可能會直接切出「客戶服務」、「交易服務」、「報表服務」等技術導向的服務。但若從 DDD 出發,我們會先觀察「零售銀行」、「企業銀行」、「風控」等業務領域,並識別其中的核心子領域,再基於這些子領域切割服務。這樣做的好處是,服務邊界天然地與業務語言對應,能降低跨領域的耦合度。


Bounded Context:服務邊界的根本單位

Bounded Context(界限上下文) 是 DDD 中最重要的戰略設計元素,也是微服務設計的核心。它的定義是:在某一個邊界內,特定的模型擁有明確、一致的語義與規則。

這意味著:

  1. 不同的上下文可以使用相同的詞彙,但語義可能完全不同。
  • 例如「客戶」在 CRM 系統中指的是「潛在客戶與聯絡資訊」,但在交易系統中則指「擁有帳號、具備交易資格的使用者」。
  1. 不同的上下文內部可以有獨立的資料結構與業務規則。
  • 例如「產品」在行銷上下文中可能只需要名稱、價格與促銷資訊,但在庫存上下文中則必須管理數量、倉儲位置與批號。

當我們在做微服務設計時,其實就是在尋找並劃定這些 Bounded Context,讓每個服務專注於自己的責任範圍,並透過清楚的 API 與其他上下文互動。


Context Map:情境脈絡之間的關係

光有 Bounded Context 還不夠,因為在真實世界中,這些上下文並不是孤立存在,而是彼此交織、互相依賴。因此,DDD 提供了 Context Map(上下文關係圖),幫助我們明確描繪上下文之間的互動模式。
以下整理常見的九種模式:

  1. Partnership(合作夥伴)
    兩個團隊有共同目標,必須同步演進。例如支付服務與交易清算服務,若其中一方改變資料結構,另一方也必須即時調整。

  2. Shared Kernel(共享核心)
    雙方共用部分模型,並共同維護。例如「客戶基本資料」由 CRM 與交易系統共享,雙方必須遵守相同的規範。

  3. Customer/Supplier(顧客/供應商)
    上游提供 API,下游依賴它。典型案例是「報表系統」依賴「交易系統」提供交易流水。

  4. Conformist(順從者)
    下游沒有談判空間,必須完全接受上游的模型。例如「稅務申報服務」必須遵守政府的資料交換格式。

  5. Anti-Corruption Layer(防腐層)
    下游透過轉換層避免直接依賴上游的模型。例如新系統導入時,建立 ACL 避免受到舊系統複雜資料結構的污染。

  6. Open Host Service(開放主機服務)
    上游提供一組標準化 API,允許不同下游接入。例如「支付閘道」提供標準化 API 讓各個電商平台接入。

  7. Published Language(公開語言)
    雙方使用公開協議進行交換。例如使用 ISO20022 作為金融報文標準。

  8. Separate Ways(各走各路)
    上下文之間沒有直接依賴,各自獨立演進。例如「人力資源系統」與「行銷平台」。

  9. Big Ball of Mud(大泥球)
    上下文之間沒有清楚的邊界,耦合混亂,這往往是我們要避免的最差情境。


通用語言(Ubiquitous Language)的力量

在 DDD 中有一句核心原則:模型就是語言,語言就是模型。這就是所謂的通用語言。它強調開發人員與業務人員應使用相同的詞彙來溝通,並將這些詞彙反映在程式碼與 API 設計中。

例如,在保險業務中,「核保」、「理賠」、「保單」都是核心語彙。若系統設計中使用這些詞彙,業務人員就能清楚理解 API 與資料結構的意義,避免「專業詞彙」與「技術詞彙」的落差,降低溝通成本。

這一點對微服務尤其重要,因為微服務的邊界往往就是以這些語言為界。若語言不統一,邊界自然會模糊。


領域驅動設計常見的設計陷阱

  1. 資料庫導向切割:直接以資料表為基準切服務,導致跨服務 join 頻繁,耦合度極高。
  2. 技術導向切割:以前端、後端或框架來切割,忽略業務語義。
  3. 共用大模型:多個服務共用一個「客戶物件」,修改時牽一髮動全身。

比較踏實一點就是,忘掉這些已經存在的「資料表格」或是「使用者介面」的限制,回歸到業務流程的本質,以領域為核心,尋找業務驅動的邊界 (以業務能力、以子領域、自治服務與 Service per team)。


康威定律與微服務邊界

康威定律(Conway’s Law) 指出:系統設計會反映出組織的溝通結構。換句話說,如果組織是「產品部門」與「營運部門」各自孤立,那麼系統也很可能被切分為兩大塊,各自管理自己的資料。

在微服務設計中,康威定律的啟示是:

  • 若想要更合理的服務邊界,就必須調整團隊結構。
  • 服務邊界與團隊邊界應保持一致(Service per team)。

這也是為什麼像亞馬遜提出「Two Pizza Team(兩片披薩團隊)」的概念,強調每個團隊應足夠小,能獨立負責自己的服務。

我有遇過服務切割後,組織卻沒有任何異動的情況,造成多團隊之間責任歸屬不清,互推責任,最終招致整個轉型不順暢的案例。所以,就我自己的經驗,有了好的團隊這件事情才會比較容易進入狀況。


結語

當我們談「微服務設計」時,最終都會回到一個問題:服務邊界應如何定義?

DDD 的 Bounded Context 提供了語言與模型的邊界,Context Map 提供了上下文之間的互動模式,康威定律則提醒我們組織結構與系統設計必須一致。這三者共同構成了微服務設計的基石。

因此,若要避免落入「分散式大泥球」的陷阱,我們必須時刻檢視:

  • 是否以業務語言為中心?
  • 是否隱藏了變動的細節?
  • 是否降低了跨服務的耦合?

唯有如此,我們才能建立真正具有彈性、可演進、且能支撐業務長期發展的微服務架構。


上一篇
微服務導入 – Day 11 微服務架構的設計核心 - 耦合與解耦
下一篇
微服務導入 – Day 13 從模型驅動到微服務落地的核心實踐
系列文
微服務導入:從觀念到落地的架構實戰地圖15
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言