iT邦幫忙

2025 iThome 鐵人賽

DAY 13
0
Software Development

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

微服務導入 – Day 13 從模型驅動到微服務落地的核心實踐

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20250920/20178262vuGpgPvUhB.png

在領域驅動設計(Domain-Driven Design, DDD)中,我們常常將「戰略設計」與「戰術設計」並列思考。戰略設計幫助我們界定邊界、拆分業務範疇與微服務的界線;而戰術設計則進一步深入到具體的程式設計與架構實踐,讓領域模型能夠落實到程式碼之中。本文將從 Model-Driven Design 的核心理念出發,逐一介紹戰術設計中的重要構件與設計模式,並說明它們如何支撐我們打造高內聚、低耦合、具備演進性的微服務系統。


Model-Driven Design 的核心理念

戰術設計最重要的基石,是 Model-Driven Design(模型驅動設計)。這是一種以《領域模型》為核心的設計方法論,它強調軟體設計必須從業務出發,並透過不斷演進的模型,連結業務專家與技術人員,最終形成既符合業務需求、又具備技術可行性的系統。

https://ithelp.ithome.com.tw/upload/images/20250917/20178262120wp7BU60.jpg

統一語言(Ubiquitous Language)

  • 領域模型的語言必須由 業務專家與技術團隊 共同創造並使用。
  • 在程式碼、文件、甚至會議討論中,所有人應該使用相同的術語,避免出現語義不一致導致溝通斷層。
  • 例如,在保險系統中,「核保」、「理賠」、「要保人」這些詞應該出現在程式類別名稱與測試案例中,而非只是業務文件裡的專有名詞。

統一語言其實就是團隊之間在尋求「共識」的一種過程。

模型即設計

  • 模型不只是業務分析工具,更是技術設計的基礎。
  • 在程式結構中,我們應該能直接看到 Entity(實體)、Value Object(值物件)、Aggregate(聚合) 等結構,這樣才能確保程式碼與業務知識保持一致。

Most developers have never seen a domain model. They've only seen data models.

在 2017 年歐洲的 DDD 年會中,Cyrille Martraire 提到大部分的開發人員並沒有看過「領域模型」,經過我自己的經驗調查看起來好像也是這樣。

https://ithelp.ithome.com.tw/upload/images/20250917/201782629EVzSlKDXS.png

Doamin Model 是一群「名詞」的連結!

持續反饋與演進

  • 領域模型不是一次設計完成的靜態產物,而是一個 動態演進的成果。
  • 在與業務專家的持續對話中,模型會被不斷修正、細化,才能保持與現實需求的同步。

分層架構

  • 戰術設計通常與 Layered Architecture(分層架構) 搭配,將領域模型封裝於「Domain Layer」,並與 Application、Infrastructure、Presentation 解耦。
  • 這種方式能避免基礎設施的變動(例如資料庫或第三方 API)直接影響領域模型。

戰術設計的核心組件

Entity(實體)

Entity 是戰術設計中最直觀的建構。它的核心特徵是 具備唯一識別(Identity),並且隨著時間演進,內部狀態可能會發生變化。

  • 特性:
    具有唯一識別(如會員 ID、身分證字號)。
    內部屬性可變,但其身份不變。
  • 案例:
    在電商系統中,訂單(Order)是一個實體。即使訂單狀態從「待付款」變成「已出貨」,它的訂單編號依然不變。

實體設計的挑戰:過度依賴資料庫 ID,而忽略了業務層面的識別。DDD 強調的是 業務身份,而非技術層面的自增主鍵。 (放下 DB 立地成 ....)

Value Oject (值物件)

Value Object 是用來表達一個概念的值或特性,沒有唯一身份,而是由其屬性決定。

  • 特性:
    無唯一識別。
    不可變更(Immutable)。
    行為與數據緊密結合。
  • 案例:
    「金額(Money)」是典型的值物件,通常包含金額數字與幣別,並附帶運算行為(如加總、比較)。
    「地址(Address)」也是值物件,它本身沒有 ID,唯一性取決於街道、城市、郵遞區號等欄位。

反模式提醒:如果值物件僅剩下資料而沒有行為,就會淪為所謂的「貧血模型」。這會破壞 DDD 的核心精神。 (我們經常看到人們寫一個類別,然後只有 Getter and Setter 沒有核心業務邏輯)

Aggregate(聚合)

Aggregate 是一種更高層次的建構,用來管理相關實體和值物件的整體。

  • 核心理念:
    聚合內部的所有操作,必須保持 一致性邊界。
    聚合根(Aggregate Root)負責統一對外的存取,外部不得直接操作聚合內部的子實體。
  • 案例:
    在銀行領域中,「帳戶(Account)」可以是一個聚合,其內部可能包含交易紀錄、餘額計算等子實體。所有交易都必須透過「帳戶」這個聚合根完成,確保一致性。
  • 與微服務的關係:
    一個聚合常常是 微服務劃分的最小單位。
    當系統切割微服務時,Aggregate 提供了一個天然的邊界。

Service(領域服務)

Service 負責封裝那些不屬於任何單一實體或值物件的業務邏輯。

  • 特性:
    無狀態。
    專注於協調多個實體或值物件的邏輯。
  • 案例:
    「轉帳服務(TransferService)」負責將金額從帳戶 A 轉移到帳戶 B。這個邏輯不自然屬於單一帳戶,因此需要透過 Service 來實現。

最佳實踐:Service 不應該淪為「大雜燴」,而應保持高內聚,僅承擔必要的協調角色。

Factory(工廠)

Factory 模式負責複雜物件的創建,將初始化邏輯與業務使用分離。

  • 價值:
    封裝複雜建構過程。
    確保建立物件時遵循領域規則。
  • 案例:
    在建立「保單(Policy)」時,可能需要根據多個輸入(要保人資訊、險種設定、附加條款)來決定最終的保單對象。這種情況下,Factory 能避免建構過程過度散落在應用層中。

Repository(儲存庫)

Repository 是領域層與資料持久化之間的抽象橋樑。

  • 特性:
    對領域層提供集合操作介面。
    隱藏底層資料存取細節(SQL、NoSQL)。
  • 案例:
    OrderRepository 可以提供 findById(orderId) 或 save(order) 這樣的方法,而不讓領域層關心這背後是透過 SQL 還是 API 存取。

好處:讓領域模型專注於業務邏輯,而非資料存取。

Domain Events(領域事件)

  • 特性:
    過去式命名(如 OrderShipped、PaymentCompleted)。
    具備業務意義。

  • 案例:
    當訂單完成付款後,系統會觸發 PaymentCompleted 事件,其他子系統(例如物流或通知系統)可以訂閱並執行後續處理。

  • 價值:
    領域事件能夠 解耦 Bounded Context 之間的通訊。
    在微服務架構中,領域事件更能支撐獨立部署與高擴展性。

Layered Architecture(分層架構)

典型的 DDD 分層架構包含:

  1. Presentation Layer(表現層):處理使用者介面與請求輸入。
  2. Application Layer(應用層):協調業務流程,但不包含業務規則。
  3. Domain Layer(領域層):核心業務邏輯所在。
  4. Infrastructure Layer(基礎設施層):資料庫、訊息中介軟體等技術細節。

價值:透過分層,我們能讓領域邏輯與外部技術細節解耦,提升系統的可維護性。


戰術設計與微服務的關聯

戰略設計幫助我們劃分 Bounded Context,而戰術設計則是將這些界線具體落實到程式碼中。二者的關聯可以歸納為:
• 戰略設計決定邊界:哪些功能屬於哪個服務。
• 戰術設計落實細節:如何在該服務內部以 Entity、Value Object、Aggregate 等方式實現。
• 領域事件:成為不同微服務之間的溝通橋樑。

這也是為什麼 DDD 成為微服務設計的主要方法論之一。

實務建議與常見反模式

  1. 避免貧血模型:
    若實體或值物件只有資料欄位而沒有行為,就失去了 DDD 的意義。
  2. 避免過度設計:
    戰術設計的模式不是每個專案都要用到全部,要依據業務複雜度與需求裁剪。
  3. 保持語言一致:
    程式碼命名必須對應到統一語言,否則容易回到傳統「技術導向」的設計。

結語

戰術設計是 DDD 的落地實踐,透過 Entity、Value Object、Aggregate、Service、Factory、Repository、Domain Events 與分層架構,我們能將抽象的業務需求轉化為具體的程式結構。更重要的是,這些模式讓系統具備高內聚、低耦合、持續演進的能力,支撐微服務的長期發展。

在今天快速變動的數位環境中,業務需求不斷演進。唯有透過 DDD 戰術設計,我們才能打造真正與業務緊密貼合的軟體,並且在技術上保持彈性與可持續性。這正是 DDD 能在微服務浪潮中成為核心方法論的原因。


上一篇
微服務導入 - D12 微服務與 DDD 的交織
下一篇
微服務導入 – Day 14 微服務架構下的資料庫設計
系列文
微服務導入:從觀念到落地的架構實戰地圖15
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言