定義
????????DDD是Domain driven design(領域驅動設計)的簡稱,是一種軟件設計和開發的方法論,特別適用于復雜業務領域軟件設計和開發
核心
? ??????將所有業務邏輯內聚到業務領域(domain)層,將設計和開發的關注點聚焦到業務領域
戰略上:上下文(Bounded Context)、防腐層(Anticorruption Layer)、開放主機服務
戰術上:entity\value object\Aggregate\root entity\domain service\factory\repository\domain event
????????戰略上,通過上下文(Bounded Context)解耦各個業務系統/組件,通過防腐層(Anticorruption Layer)確保各自業務領域不受外界污染,通過開放主機服務(Open Host Service)向外界提供服務。
????????戰術上,將業務對象建模為entity和value object,entity有唯一業務標識且在其生命周期中狀態可變,value object與之相反;關聯性強的entity和value object聚合成一個Aggregate,每個Aggregate有一個root entity,確保Aggregate內容業務規則和行為的一致性;業務行為盡量建模在entity/ value object 上,當業務行為無法建模到任何業務entity/value object時,可以使用領域服務(domain service);使用factory創建復雜的業務entity,使用repository實現實體的重建和持久化操作;領域相關的通知等可以通過domain event發布出去。
概念
Bounded context:邊界上下文
劃分領域邊界,邊界內領域模型保持一致,強調內聚,并與邊界外的領域模型解耦
Entity:領域實體
有唯一標識,可變的業務實體對象,有自己的生命周期,如User等
Value Object:領域值對象
沒有唯一標識,通常依附于領域實體,值對象的內容不可變 ,要么被整體替換
Aggregate:聚合
是一組業務關聯度很強的實體/值對象的集合,每個聚合都有一個根實體(root entity),通過根實體可以路由到整個聚合
Domain Event:領域事件
領域內發生的異步處理事件、異步消息通知等,比如異步寫入的登錄日志,通常借助消息隊列實現
Domain Service:領域服務
當某一類業務行為無法歸類到實體/值對象時,可以創建領域服務來完成。比如賬戶轉賬場景,涉及兩個Account實體;再比如社區敏感詞過濾場景,帖子可以用、評論也可以用,因此可以抽離到ContentFilter完成
Repository:倉庫
嚴格意義上講,倉庫是基礎設施層的東西,但為了保持領域模型的完整性,將倉庫的接口定義放到領域中,可以在領域內約束實體/值對象的行為,還可以方便地完成倉庫的內存形式實現,使得領域模型弱依賴于持久化層。這一點在書中被稱為“依賴倒置”(參考《實現領域驅動設計》P372)。
Factory:領域對象工廠
用于復雜領域對象的創建和重建,重建是指通過repository加載持久化對象后,重新創建領域對象
圖解分層
User Interface——用戶界面層:提供與用戶/界面交互的接口,可以是restful api,也可以是view,或者二進制形式的tcp協議接口等
Application——應用服務層:組合Domain和Infrastructure,完成具體的業務邏輯
Domain——業務領域層:是DDD中的核心層,內聚所有的業務邏輯,保持領域的一致性。需要用到Infrastructure的基礎組件
Infrastructure——基礎設施層:提供公共服務組件,比如validation、登錄態校驗、日志記錄等
架構風格
針對DDD的架構設計,《實現領域驅動設計》提到了幾種架構風格:六邊形架構、REST架構、CQRS、事件驅動等。在實際使用中,落地的架構并非是純粹其中的一種,而很有可能戶將上述幾種架構風格結合起來實現
六邊形架構
端口和適配器
框架實現
User Interface層
門面層,對外以各種協議提供服務,該層需明確定義支持的服務協議、契約等,包括dto和controller
dto
包括request和response兩部分,定義出錯和入參的契約,可以調用基礎設施層的validation組件完成入參格式校驗
facade\controller——控制器
支持不同訪問協議的控制器實現,比如:http/restful協議、tcp協議、mq消息/json對象等,包括但不限于:
? 調用RequestMapping完成Servlet路由
? 調用checkLogin完成登錄態和權限認證
? 調用logging組件完成日志記錄
assembler——組裝器
負責將多個不同的領域對象組裝成dto對象,比如查詢帖子列表,需要從帖子(領域對象)中獲取帖子的詳情,還要從用戶(領域對象)中獲取用戶的基本信息
實現DTO與領域對象之間的相互轉換,數據交換,因此Assembler幾乎總是同DTO一起出現
不能有業務邏輯,主要負責格式轉換、字段映射等
Application層
包含service和assembler
service——應用服務層
對外,組合domain層的領域對象和基礎設施層的公共組件,根據業務需要包裝出多變的服務
? 訪問domain層的領域對象
? 訪問infrastructure的公共組件,比如消息組件等
task——邏輯任務
對內,調用領域層(領域對象或領域服務)完成各種業務邏輯任務(task)
Domain層
高內聚的業務領域層,所有的業務邏輯都在這里
domain entity——領域實體對象
有唯一標識,可變的業務實體對象,業務實體有自己的生命周期,比如社區這個業務領域中,“帖子”就是一個業務實體,它的內容和狀態可以不斷發生變化。
domain?value object——值對象
可以沒有唯一性的業務標識,通常是短暫的,與java中的值對象(基本類型和String類型)類似。比如帖子的置頂信息可以理解為一個值對象,不需要為它定義獨立的業務唯一性標識,只需要用帖子id,還有置頂狀態和置頂位置,一旦任何一個屬性值發生變化,重建值對象并賦值給帖子實體引用。
domain?factory——對象工廠
用于復雜領域對象的創建/重建。重建是指通過repository加載持久化對象后,重建領域對象
domain service——領域服務,區別與Application層的service,屬于業務領域服務
任何無法歸類給領域實體和值對象的行為,都可以為它創建獨立的領域服務,比如轉賬服務,需要操作借方/貸方兩個業務實體。傳統意義上的util類中static方法,涉及業務邏輯的,都可以歸入domain service
domain event——領域事件
領域中一些消息事件,通過事件通知和訂閱的方式,可以在性能和解耦方面提供非常大的好處
repository——倉庫
與domain entity緊密聯系,通過與基礎設施的持久化層交互后 ,完成領域對應的增刪改查操作
根據不同業務場景,倉庫的實現,可以是reids、數據庫、mongodb等
translator(翻譯器,一般可以沒有這一層)
將持久化的對象翻譯成統一領域對象,不應該有業務邏輯,負責格式轉換、字段映射等。
作用等同于Application層中的轉換器 assembler
Infrastructure層
公共基礎組件,供User Interface中的controller、Application層中的service、以及整個Domain層調用
repository impl?
對domain層repository接口的實現,對應每種存儲介質有其特定實現,如oracle的mapper,mongodb的dao等等。repository impl會調用mybatis、mongo client、redis client完成實際的存儲層操作。
authorization 權限認證
提供給User Interface層的Controller調用。
exception 異常處理
提供公共的異常處理邏輯
logging 日志記錄
日志模塊
transport 傳輸器
transport完成和第三方服務的交互,可以有多種協議形式的實現,如http+json、tcp+自定義協議等,配套使用的還有Resolver解析器,用于對第三方服務的請求和響應進行適配,提供一個防腐層(AnticorruptionLayer)的作用
transaction 事務管理
事務管理,一般交給Spring管理
DDD的框架實現示意圖