1. 程式人生 > >【DDD】領域驅動設計實踐 —— 架構風格及架構實例

【DDD】領域驅動設計實踐 —— 架構風格及架構實例

讀取 bili 邏輯 stat orcal ransac 應用服務 業務場景 解讀

概述

DDD為復雜軟件的設計提供了指導思想,其將易發生變化的業務核心域放置在限定上下文中,在確保核心域一致性和內聚性的基礎上,DDD可以被多種語言和多種技術框架實現,具體的框架實現需要根據實際的業務場景和需求來制定。

核心的指導思路歸納為:

  • 關註點放在domain上,將業務領域限定在同一上下文中
  • 降低上下文之間的依賴,通過‘開發主機服務’(REST服務是其中的一種)、‘消息模式’、‘事件驅動’等架構風格實現
  • 遵循分層架構模式

架構風格

針對DDD的架構設計,《實現領域驅動設計》提到了幾種架構風格:六邊形架構、REST架構、CQRS、事件驅動等。在實際使用中,落地的架構並非是純粹其中的一種,而很有可能戶將上述幾種架構風格結合起來實現。

此部分內容主要來源於《實現領域驅動設計》的第4章,加上了自己的一些理解。

六邊形架構(端口和適配器)

所謂的六邊形架構,其實是分層架構的擴展,原來的分層架構通常是上下分層的,比如常見的MVC模式,上層是對外的服務接口,下層是對接存儲層或者是集成第三方服務,中層是業務邏輯層。我們跳出分層的概念,會發現上面層和下面層其實都是端口+適配器的實現,上面層開放http/tcp端口,采用rest/soap/mq協議等對外提供服務,同時提供對應協議的適配器;下層也是端口+適配器,只不過應用程序這時候變成了調用者,第三方服務或者存儲層提供端口和服務,應用程序本身實現適配功能。

基於上述思考,將分層接口中的上層和下層統一起來就變成了六邊形架構,基於端口和適配器的實現,示意圖如下:

技術分享

上圖來源於《實現領域驅動設計》的P111

我認為六邊形架構並非創造一種新的架構風格,只是將原來的分層架構風格重新解讀,使得架構更加簡潔通用。同時,在DDD的設計思想下,六邊形架構風格,讓領域模型處於架構的核心區域,讓開發人員將焦點聚集到領域。DDD和六邊形架構是天然契合的,是DDD的首選架構。

REST

REST——即Representational State Transfer的縮寫,翻譯過來是"表現層狀態轉化"。參考至:理解RESTful架構。

RESTful風格的架構將‘資源’放在第一位,每個‘資源’都有一個URI與之對應,可以將‘資源’看著是ddd中的實體;RESTful采用具有自描述功能的消息實現無狀態通信,提高系統的可用性;至於‘資源’的哪些屬性可以公開出去,針對‘資源’的操作,RESTful使用HTTP協議的已有方法來實現:GET、PUT、POST和DELETE。

在DDD的實現中,我們可以將對外的服務設計為RESTful風格的服務,將實體/值對象/領域服務作為‘資源‘對外提供增刪改查服務。但是並不建議直接將實體暴露在外,一來實體的某些隱私屬性並不能對外暴露,二來某些資源獲取場景並不是一個實體就能滿足的,因此我們在實際實踐過程中,在領域模型上增加了dto這樣一個角色,dto可以組合多個實體/值對象的資源對外暴露。

CQRS

CQRS——Cammand-Query Responsibility Segregation的縮寫。翻譯過來就是命令與查詢職責分離

簡而言之,CQRS就是平常大家在講的讀寫分離,通常讀寫分離的目的是為了提高查詢性能,同時達到讀/寫的解耦。讓DDD和CQRS結合,我們可以分別對讀和寫建模,查詢模型通常是一種非規範化數據模型,它並不反映領域行為,只是用於數據顯示;命令模型執行領域行為,且在領域行為執行完成後,想辦法通知到查詢模型。

那麽命令模型如何通知到查詢模型呢? 如果查詢模型和領域模型共享數據源,則可以省卻這一步;如果沒有共用數據源,則可以借助於‘消息模式’(Messaging Patterns)通知到查詢模型,從而達到最終一致性(Eventual Consistency)。

Martin在blog中指出:CQRS適用於極少數復雜的業務領域,如果不是很適合反而會增加復雜度;另一個適用場景為獲取高性能的服務。

技術分享

    圖片來源於Martin Fowler的blog,圖中表述的查詢模型和命令模型共用數據源。

關於CQRS的討論可以參考Martin大叔的blog:CQRS,以及:CQRS, Task Based UIs, Event Sourcing agh!

事件驅動

這一架構風格在實際項目中並未使用,不做過多闡述,感興趣的同學自行研究。

架構實例

結合最近在重構的社區服務系統(ECO),嘗試使用上述的指導思想和架構風格,完成一次架構設計嘗試,並詳述如下:

架構圖

技術分享

架構詳述

ECO系統架構整合了六邊形架構、RESTful架構風格、CQRS架構風格三種架構風格,並遵循經典的分層架構思想。

1、在遵循分層架構思想的基礎上,引入了六邊形架構風格,對內對外均通過適配器+端口的方式呈現:

  • 面向用戶側,提供http端口,並使用SpringMVC框架的RequestMapping、Controller等組件實現對http 請求的解析,轉化為Application層可識別的業務dto對象,這裏的Controller+RequestMapping便起著適配器的作用;
  • 面向第三方服務,通過httpclient和tcpclient的適配,可以對接多種協議的第三方服務端口;
  • 面向存儲層,通過mongoclient的適配,訪問mongodb;通過mybatis的適配,訪問oracle;通過redisclient的適配,訪問redis;
  • 面向消息中間件,通過mqclient的適配,方為rabbitMQ;

2、實現了RESTful架構風格,通過RESTful風格的接口契約對外提供主機開放服務。借助SpringMVC實現。

3、實現了CQRS架構風格:

  • orcale作為命令模型存儲存在,並配以Transaction事務管理。主要存儲帖子、評論、話題、圈子、關註等實體信息;
  • Mongodb作為查詢模型存儲存在,存儲個人動態、社區動態等非結構化數據;
  • redis同樣作為查詢模型存儲存在,存儲用戶個人信息、熱門評論、熱門帖子、熱門話題、用戶點贊信息等;
  • Application層分為QueryService和CommandService兩大類應用服務,分別組合查詢模型和命令模型;
  • 使用rabbitMQ作為消息中間件,CommandService在完成命令模型的維護後,生產事件消息寫入rabbitMQ,QueryService作為消費者從rabbitMQ讀取事件消息,更新查詢模型;
  • 查詢模型和命令模型極其對應的application service可以獨立部署,獨立擴展。

4、遵循基本的分層架構風格。

  • User Interface —— 用戶接口層。對外提供各種協議形式的服務,並提供Validation參數校驗,authenticate權限認證,業務實體組裝器Assembler等。圖中標綠組件。
  • Application —— 應用服務層。組合多個業務實體、基礎設施層的各種組件完成業務服務。圖中標黃部分。
  • Domain —— 業務領域層。DDD概念中的核心業務層,封裝所有業務邏輯,包含entity、value object、domain service、domain event等。圖中標藍部分。
  • Infrastructure —— 基礎設施層。提供公共組件,如:Logging、Trascation、HttpClient等。圖中標灰部分。

【DDD】領域驅動設計實踐 —— 架構風格及架構實例