Domain-Driven Design (DDD)

閱讀DDD相關文章重點整理。

Domain-Driven Design

價值: 把將商業領域的知識映照到程式碼中,解放「程式歸程式,業務歸業務」的傳統思維

模型中有以下概念

  • 上下文(Context): 詞或句子出現的位置。
  • 領域(Domain): 知識,影響,或活動。客戶使用軟體要處理旳問題種類即為軟體的領域。
  • 模型(Model): 一類描述域的不同方面並可用於解決相關問題的系統化的抽象。
  • 統一術語(Ubiquitous Language): 一種團隊成員使用,為了描述域模型而構造的語言。 用於如下:
    • User story 或RFC
    • 任意的會議
    • 書信往來
    • 技術文件
    • 流程或是行程
    • 程式碼

Building blocks

在領域驅動設計一書中[2]闡述了一些高層次的概念和實踐,比如通用語言,這意味著領域模型應該形成領域專家為描述系統需求而提供的共同語言,同樣的,這些語言也需要能夠被商業使用者或贊助商和軟體開發商使用。本書專注於將領域層描述為具有多層體系結構的物件導向系統中的常見層次之一。在 DDD 中,有表示,建立和檢索域模型的工件:

  • Entity: 一個不由自身屬性定義而是由標識線和它的身分定義的物件。
    例如:大多數航空公司在每次航班上都獨特地區分每個座位。每個席位都是在這種情況下的一個實體。不過,西南航空,EasyJet 和瑞安航空並沒有區分每個座位;所有的座位都是一樣的。在這種情況下,一個席位實際上是一個Value Object
  • Value Object: 只包含元素屬性的不可變物件。
    例如:當人們交換名片時,他們一般不會區分每張獨特的名片;他們只關心印在卡片上的資訊。在這種情況下,名片是 Value Object
  • Service: 強調與其他物件的關係,只定義了可以為客戶做什麼,不應該替代 Entity 和 Value Object 的所有行為。
  • Module: 一種表達機制,劃分代碼和概念。
  • Factory: 對於那些需要建立特定域物件的方法應該委派給工廠物件,因為這樣可以更容易的替換實現。
  • Repository: 對於檢索特定域物件的方法應該委派給 Repository 物件,因為這樣可以很容易地互換替代儲存的實現。
  • Aggregate: 由 ROOT ENTITY 繫結在一起的物件的集合,也稱為聚合根。聚合根通過禁止外部物件保持對其成員的參照來保證在聚合內進行的更改的一致性。
    例如:駕駛汽車時,不必擔心向前移動車輪,使發動機燃燒火花和燃料等。你只是在開車。在這種情況下,汽車是其他幾個物件的集合,並作為所有其他系統的聚合根
  • Domain Event: 一個域物件定義了一個事件。域事件是域專家所關心的事件。

貧血模型 (Anemic Model)

特徵:
其中包含物件,許多物件會以領域空間中的名詞來命名,而且這些物件會透過真實領域模型所具有的豐富關聯性和結構來連接。
從行為上會看出端倪,並了解這些物件上幾乎沒有任何行為,比較像是一組 getter 和 setter。
使用 Anemic 領域模型時,會從一組擷取所有領域或商務邏輯的服務物件 (service,傳統上稱為「商務層」**) 來使用這些資料模型。 商務層位於資料模型最上層,其使用資料模型的方式就像是資料一樣。

重點節錄(來自微軟)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Anemic 領域模型只是程序樣式設計。 Anemic 實體物件不是真正的物件,因為它們缺少行為 (方法)。
它們只會保存資料屬性,因此不是物件導向設計。

藉由將所有的行為放入服務物件(商務層)中,您基本上會得到spaghetti 程式碼或交易腳本,
因此您會失去領域模型所提供的優點。

即便如此,如果您的微服務或限定內容很簡單 (CRUD 服務),只有資料屬性之實體物件形式的 Anemic 領域模型便已足夠,
而且可能不值得實作更複雜的 DDD 模式。 在此情況下,它只是持續性模型,因為您刻意建立只有 CRUD 用途資料的實體。

這就是為什麼微服務架構對於根據每個限定內容之多架構方法很理想的原因。
例如,在 eShopOnContainers 中,
訂購微服務會實作 DDD 模式,但目錄微服務是簡易 CRUD 服務,因此不會實作此模式。
它其實取決於您實作的內容。 如果您要建立的微服務夠簡單 (例如 CRUD 服務),遵循 Anemic 領域模型就不是反模式。

不過,如果您需要處理微服務網域的複雜性,
而此領域有許多不斷改變的商務規則,則 anemic 領域模型可能是該微服務或限定內容的反模式。
在此情況下,將它設計為具有實體的豐富模型可能會相當有利於這類微服務的長期成功,
因為這些實體包含資料加上行為,並實作額外的 DDD 模式 (彙總、值物件等)。

Anemic Model

豐富領域模型(Rich Domain Model)

Rich Domain Model

架構參考:

傳統架構

架構轉成DDD

DDD 之後

閱讀參考

程式架構:
阿里技术专家详解 DDD 系列- Domain Primitive
阿里技术专家详解DDD系列 第二弹 - 应用架构
阿里技术专家详解DDD系列 第三讲 - Repository模式
DDD系列第四讲:领域层设计规范

其他:
什么是领域模型(domain model)?贫血模型(anaemic domain model)和充血模型(rich domain model)有什么区别?
领域模型驱动设计(Domain Driven Design)入门概述
领域驱动设计(Domain Driven Design)参考架构详解
微服務 - 架構電子書 (微軟) - 設計微服務領域模型
關於 Domain-Driven Design 以及他的魅力 (這個上面寫的程式範例不太好,看其他文章範例)
My vision, as a Software Engineer, about DDD (Domain Driven Design) — Part 2 (Java 為範例)
Domain Driven Design
【DDD】领域驱动设计实践 —— Domain层实现
DDD 程式設計範例討論