DDD在項目中能落地嗎?在CQRS和Event Sourcing之外還有什么設計方法?InMemory和 InDatabase架構風格是什么?
InMemory架構風格
DDD領域驅動開發是一種In Memory架構風格,Memory架構風格的意思就是以計算機“內存”作為主要資源進行軟件設計的方式,與之對應的就是Database數據庫架構風格,典型的是以ER圖(實體關系圖)作為主要設計方式的設計方法。
|
架構風格 |
特點 |
|
Memory架構風格 |
以面向對象設計為基礎,針對業務對象、數據實體或業務行為等進行業務建模,主要采用設計模式、DDD等設計方法 |
|
Database架構風格 |
以數據關系設計為基礎,針對業務過程中的數據結構和表關系等進行數據建模,主要采用ER圖、關系數據庫表等設計方法 |
DDD中的CQRS和Event Sourcing就是兩種Memory架構風格的設計方法。
貧血模型VS富血模型
Memory架構設計風格中,最典型的沖突點就是貧血模型與富血模型,
|
模型 |
描述 |
|
貧血模型 |
強調符合JAVABean規范,Java數據對象符合JavaBean規范,業務行為放到Service類中實現,導致模型類只包含setter/getter無業務行為 |
|
富血模型 |
強調面向對象設計方法,拿人作為類比,人是具有屬性和行為的復合體,所以模型類應該既包含數據又包含業務行為 |
絕大多數的項目采用的都是“貧血模型”,在這個爭論點提出來后,我們也懷疑過貧血模型是否是個問題,但是在項目實踐中將數據與行為同時放到一個對象(類)中,會導致非常難于維護的代碼和壞味道。甚至為了解決這個沖突點出現過動態Mix類屬性和行為的方法,不過難以使用。
在經過長期實踐后發現貧血或富血并不是一個問題,而是隨著軟件業務的復雜性提升和計算機硬件的成本降低,架構設計的長期趨勢已經從數據庫為中心轉換為以內存業務模型為中心的設計。
MEES架構設計方法
MEES: Model Enhance Event Service。模型增強事件服務架構。
MEES是一種類似CQRS和EventSourcing并且基于InMemory架構風格的架構模式,該架構模式的設計視圖如下。
MEES架構設計過程:
- 基于業務中抽象領域模型,定義為Model模型
- 每個Model模型對應單獨ModelDecorator,裝飾器類承載模型對象的業務邏輯行為
- 領域Gateway通過Model模型調用Decorator進行業務處理
- Event事件處理后通過發布訂閱Pub/Sub方式通知相關Model模型進行狀態State更新
- 通過Service實現技術功能邏輯,實現業務邏輯和技術邏輯的簡單解耦,比如Service可以調用Database實現數據的持久化管理
基于DSL的MEES設計過程
MEES設計方法特別適用于使用DSL領域特定語言的開發場景,Dockerfile可以認為是一種DSL,下面用Dockerfile舉例MEES架構設計過程。
任何業務如果可以使用一種DSL語言描述,都適用于此架構設計方法。
DSL業務定義語言
FROM centos
ENV NODE_VERSION 7.2.0
RUN yum -y install wget
RUN wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz"
RUN tar -xvf redis.tar.gz
RUN echo 'hello world'
模型Model設計
|
模型 |
類 |
職責 |
|
領域Gateway |
Dockerfile |
領域聚合根,命令執行入口 |
|
實體模型 |
From |
模型定義 |
|
實體模型 |
Run |
模型定義 |
|
實體模型 |
Env |
定義 |
增強模型Decorator設計
|
類 |
裝飾器 |
主要業務行為 |
|
From |
FromDecorator |
獲取中央倉庫鏡像 |
|
Run |
RunDecorator |
執行參數本地命令 |
|
Env |
EnvDecorator |
設置全局參數 |
事件Event設計
依據Dockerfile的業務執行過程,排除模型Build過程外,可以抽象如下幾個事件用于觸發模型運行。
|
事件 |
業務行為 |
|
RunEvent |
模擬docker命令運行dockerfile |
|
StateEvent |
獲取容器運行狀態 |
服務Service設計
|
服務 |
類 |
技術行為 |
|
命令服務 |
ShellService |
用于執行OS命令 |
|
倉庫服務 |
RepoService |
用于HTTP加載遠程鏡像 |
|
消息服務 |
MsgService |
用于消息的發布訂閱Pub/Sub |
架構設計視圖View
基于以上的設計過程,MEES開發架構定義如下
示例代碼
MEES架構設計產生的代碼樣例如下,通過Builder模式加載DSL實例后,首先通過將Event傳遞給領域Gateway觸發模型運行,然后Model模型通過注冊表Registry查詢對應Decorator,再次通過Decorator實現業務層面邏輯,最后調用Service實現技術功能層面邏輯。
var docker = DockerfileBuilder.builder(file).build(){
from:Model
env:List<Model>
run:List<Model>
registry:List<ModelDecorator>
init(){
from.subscribe(DownloadedMessage){
for(r: run){
var deco = registry.findDeco(r)
deco.execute(this){
shellService.execute(cmd)
}
}
}
}
}
docker.handle(e:StateEvent){
return this.run
}
docker.handle(e:RunEvent){
var deco = registry.findDeco(this.from)
deco.download(){
repoService.download(from)
if(downloaded){
message.publish(DownloadedMessage())
}
}
}
總結
|
DDD方案 |
技術方案特點 |
|
MEES |
基于結構模式,基于Model定義Decorator增強模型方案 |
|
CQRS |
基于行為模式,一般采用管道過濾器技術架構 |
|
EventSourcing |
基于數據模式,一般是定義事件數據鏈結構 |
原文出處:
https://juejin.cn/post/7082374006073983007






