DDD領域驅動設計-項目包結構說明-Ⅳ


 基於DDD領域驅動設計的思想,在開發具體系統時,需要先建立不同的層級包。主要是梳理不同層面(應用層,領域層,基礎設施層,展示層)包括的功能目錄,每一個層面應該包括哪些模塊。本例所講述的分層是DDD落地方案中常用的一種(參考),且本例適當做了調整和細化。詳細分層目錄參考下圖:

1. 展示層

展現層(用戶接口層)(Presentation Layer):負責以Restful的格式接受Web請求,然后將請求路由給Application層執行,並返回視圖模型(View Model),其載體通常是DTO(Data Transfer Object)。
* userinterfaces: 展示層,又稱用戶接口層
* 用戶接口層為外部用戶訪問底層系統提供交互界面和數據表示。
* 用戶接口層在底層系統之上封裝了一層可訪問外殼,為特定類型的外部用戶(人或計算機程序)訪問底層系統提供訪問入口,並將底層系統的狀態數據以該類型客戶需要的形式呈現給它們。
*
* 用戶接口層有兩個任務:
* 從用戶處接收命令操作,改變底層系統狀態;
* 從用戶處接收查詢操作,將底層系統狀態以合適的形式呈現給用戶。
*
* 本例用戶接口層包括如下子模塊:
* 命令目錄(command): 對象命名為XxxCommand,指調用方明確想讓系統操作的指令,其預期是對一個系統有影響,也就是寫操作。通常來講指令需要有一個明確的返回值(如同步的操作結果,或異步的指令已經被接受)。
* 查詢目錄(query): 對象命名為XxxQuery,指調用方明確想查詢的東西,包括查詢參數、過濾、分頁等條件,其預期是對一個系統的數據完全不影響的,也就是只讀操作。
* 事件目錄(event): 對象命名為XxxEvent,指一件已經發生過的既有事實,需要系統根據這個事實作出改變或者響應的,通常事件處理都會有一定的寫操作。事件處理器不會有返回值。這里需要注意一下的是,
* Application層的Event概念和Domain層的DomainEvent是類似的概念,但不一定是同一回事,這里的Event更多是外部一種通知機制而已。
* 返回數據對象目錄(dto): 對象命名為XxxDto,作為ApplicationService的出參 * 控制層(Controller): 提供restful接口,供外部系統調用 * * 規范: * ApplicationService的接口入參只能是一個Command、Query或Event對象,CQE對象需要能代表當前方法的語意。唯一可以的例外是根據單一ID查詢的情況,可以省略掉一個Query對象的創建 * CQE,Dto,都是Value Object,但是從語義上來看有比較大的差異,主要是從命名上區別出來。 * CQE:CQE對象是ApplicationService的輸入,是有明確的“意圖”的,所以這個對象必須保證其"正確性"。為驗證部分字段的格式,必填性,可基於Spring Validation等模式做基礎數據驗證。 * DTO:Dto對象只是數據容器,只是為了和外部交互,所以本身不包含任何邏輯,只是貧血對象。

2. 應用層

應用層(Application Layer):主要負責獲取輸入,組裝上下文,做輸入校驗,調用領域層做業務處理,如果需要的話,發送消息通知。當然,層次是開放的,若有需要,應用層也可以直接訪問基礎實施層。
* application 應用層
* 相對於領域層,應用層是很薄的一層,應用層定義了軟件要完成的任務,要盡量簡單.
* 它不包含任務業務規則或知識, 為下一層的領域對象協助任務、委托工作。這一層也很適合寫一些任務處理,消息處理
* 它沒有反映業務情況的狀態,但它可以具有反映用戶或程序的某個任務的進展狀態。
*
* 對外:為展現層提供各種應用功能(service)。
* 對內:調用領域層(領域對象或領域服務)完成各種業務邏輯任務
*
* 事件(event): 對象命名為XxxEvent,跨聚合根,或部分業務處理完成后,需要通知其他模塊的,本例采用 Spring event模式。本例是將領域事件放在應用層的。
* 應用服務(service): 對象命名為XxxService,應用層的服務
*
* 一個應用層通常包括以下三種服務:
*
* 業務處理類:XxxCommandService
* 業務查詢類:XxxQueryService
* 業務事件類:XxxEventService
特別說明:一個實體處理完成后,若存在副作用,可基於事件模式處理。關於事件模塊到底是放置在領域層還是應用層,網上存在不同的模式(參考網址: DDD-領域事件)。本例是基於Spring Event模式,放在應用層的。

3. 領域層

領域層(Domain Layer):主要是封裝了核心業務邏輯,並通過領域服務(Domain Service)和領域對象(Entities)的函數對外部提供業務邏輯的計算和處理。
* domain 領域層
* 領域層主要負責表達業務概念,業務狀態信息和業務規則。是一個純內存化的操作。
* Domain層是整個系統的核心層,幾乎全部的業務邏輯會在該層實現。領域層不關注數據是如何落地存儲的,領域層也不直接調用底層倉庫接口保存數據。
* 領域模型層主要包含以下的內容:
*
* 實體(Entities): 對象命名為XxxE,具有唯一標識的對象,所有實體統一用E作為后綴,如PersonE
* 工廠(factory): 接口命名規則為XxxFactory,創建復雜的實體,聚合根,只做創建處理
* 值對象(vo): 對象命名為XxxV,無需唯一標識的對象,所有值對像統一同V作為后綴 ,如PersonV,實體的主鍵編碼以Id結尾
* 領域服務(Domain Services): 接口命名規則為XxxDomainService,一些行為無法歸類到實體對象或值對象上,本質是一些操作,而非事物(與本例中domain/service包下的含義不同)
* 倉儲(Repository): 接口命名規則為XxxRepository,創建復雜對象,隱藏創建細節,提供查找和持久化對象的方法。本層僅編寫倉庫的接口。具體實現再基礎層
* 聚合/聚合根(Aggregates,Aggregate Roots): 對象命名為XxxA,聚合是指一組具有內聚關系的相關對象的集合,每個聚合都有一個root和boundary,所有聚合統一用A作為后綴,如PersonA
*

4. 基礎實施層

基礎實施層(Infrastructure Layer)主要包含Tunnel(數據通道)、防腐層,Config和Common。這里我們使用Tunnel這個概念來對所有的數據來源進行抽象,這些數據來源可以是數據庫(MySQL,NoSql)、搜索引擎、文件系統、也可以是SOA服務等;Config負責應用的配置;Common是通用的工具類。
* infrastructure 基礎實施層
* 向其他層提供 通用的 技術能力(比如工具類,第三方庫類支持,常用基本配置,數據訪問底層實現)
* 基礎實施層主要包含以下的內容:
* 為應用層 傳遞消息(比如通知)
* 為應用層 提供持久化機制(最底層的實現)
*
* 防腐層(acl): 實體對接外部系統,實體與外部系統之間,不同領域之間,不同的參數轉換,語義轉換等
* 轉換層(assembler): 數據轉換工具類,如Dto轉換為實體,實體轉換為數據表pojo對象,基於org.mapstruct.Mapper實現
* 倉庫層(repository): 倉庫實現層,實體與DB之間存儲的功能層
* 異常管理(exception): 封裝具體業務的異常處理信息
* 配置模塊(config): 封裝配置信息,包括一些基礎靜態字段,基於阿波羅等獲取的配置信息
* 枚舉模塊(enum): 封裝該模塊的枚舉信息
* 數據庫映射的基礎數據對象(database): 命名規則為:XxxDo,數據表翻譯為java基礎的pojo對象

5.項目分層

一個微服務里,通常包括多個不同的領域業務。一個領域業務基於DDD的模式,通常都包括上述的分層模塊,為了區分不同的領域業務,有兩種方案建立包的層級。
  1. DDD層級分類:基於分層包,在每一個包下面,新建具體業務的名稱,如在application.service包下面建立退款,售后補償業務。建立兩個分別為application.service.refund(退款包),application.service.compensate(售后包)。
  2. 業務分類:基於業務分層,在四層包的前提下,每一個業務均包括DDD的分層包。如下圖所示:
本例選用的方案2,便於歸類業務在各個層的模塊代碼。最后層級結構確定下來后,每個層只負責該層應該負責的功能,不可混用,濫用。好的設計需要開發人員遵守一定的規則,關於層級划分,沒有絕對的標准,可參考開源COLA 4.0或其他架構學習。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM