【DDD】領域驅動設計實踐

轉載:https://www.cnblogs.com/daoqidelv

一、框架實現圖

框架實現圖
該框架實現基本和DDD的指導思想契合,主要分爲四層,且將關注點放在了domain層。下面將逐層介紹各個組件的職責。

二、框架詳述

User Interface層

門面層,對外以各種協議提供服務,該層需要明確定義支持的服務協議、契約等。包含:

dto
包括request和response兩部分,通過它定義入參和出參的契約,在dto層可以使用基礎設施層的validation組件完成入參格式校驗;

controller
支持不同訪問協議的控制器實現,比如:http/restful風格、tcp/二進制流協議、mq消息/json對象等等。

controller使用基礎設施層公共組件完成許多通用的工作:

  • 調用RequestMapping(SpringMVC公共組件)完成servlet路由;
  • 調用checklogin完成登錄態/權限校驗;
  • 調用logging組件完成日誌記錄;
  • 調用message-resource組件完成錯誤信息轉義,支持I18N;

application層

service
應用服務層,組合domain層的領域對象和基礎設施層的公共組件,根據業務需要包裝出多變的服務,以適應多變的業務服務需求。

應用服務層主要訪問domain領域對象,完成服務邏輯的包裝。

應用服務層也會訪問基礎設施層的公共組件,如rabbitmq,完成領域消息的生產等。

assembler
組裝器,負責將多個domain領域對象組裝爲需要的dto對象,比如查詢帖子列表,需要從Post(帖子)領域對象中獲取帖子的詳情,還需要從User(用戶)領域對象中獲取用戶的基本信息。

組裝器中不應當有業務邏輯在裏面,主要負責格式轉換、字段映射等職責。

domain層

業務領域層,是我們最應當關心的一層,也是最多變的一層,需要保證這一層是高內聚的。確保所有的業務邏輯都留在這一層,而不會遺漏到其他層。按照ddd(domain driven design)理論,主要有如下概念構成:

domain entity
領域實體。有唯一標識,可變的業務實體對象,它有着自己的生命週期。比如社區這一業務領域中,‘帖子’就是一個業務實體,它需要有一個唯一性業務標識表徵,同時他的狀態和內容可以不斷髮生變化。

domain value object
領域值對象。可以沒有唯一性業務標識,且一旦定義,他是不可變的,它通常是短暫的。這和java中的值對象(基本類型和String類型)類似。比如社區業務領域中,‘帖子的置頂信息’可以理解爲是一個值對象,不需要爲這一值對象定義獨立的業務唯一性標識,直接使用‘帖子id‘便可表徵,同時,它只有’置頂狀態‘和’置頂位置‘,一旦其中一個屬性需要發生變化,則重建值對象並賦值給’帖子‘實體的引用,不會對領域帶來任何負面影響。

domain factory
領域對象工廠。用於複雜領域對象的創建/重建。重建是指通過respostory加載持久化對象後,重建領域對象。

domain service
領域服務。區別於應用服務,他屬於業務領域層。

可以認爲,如果某種行爲無法歸類給任何實體/值對象,則就爲這些行爲建立相應的領域服務即可。比如:轉賬服務(transferService),需要操作借方/貸方兩個賬戶實體。

傳統意義上的util static方法中,涉及到業務邏輯的部分,都可以考慮歸入domain service。

domain event
領域事件。領域中產生的一些消息事件,通過事件通知/訂閱的方式,可以在性能和解耦層面得到好處。

repository
倉庫。我們將倉庫的接口定義歸類在domain層,因爲他和domain entity聯繫緊密。倉庫用戶和基礎實施的持久化層交互,完成領域對應的增刪改查操作。

倉庫的實際實現根據不同的存儲介質而不同,可以是redis、oracle、mongodb等。

鑑於現在社區服務的存儲介質有三套:oracle、redis、mongodb,且各個存儲介質的字段屬性名不一致,因此需要使用translator來做翻譯,將持久化層的對象翻譯爲統一的領域對象。

translator
翻譯器。將持久化層的對象翻譯爲統一的領域對象。

翻譯器中不應當有業務邏輯在裏面,主要負責格式轉換、字段映射等職責。

infrastructure層

基礎設施層提供公共功能組件,供controller、service、domain層調用。

repository impl
對domain層repository接口的實現,對應每種存儲介質有其特定實現,如oracle的mapper,mongodb的dao等等。repository impl會調用mybatis、mongo client、redis client完成實際的存儲層操作。

checkLogin
權限校驗器,判定客戶端是否有訪問該資源的權限。提供給User Interface層的Controller調用。

exception
異常分類及定義,同時提供公共的異常處理邏輯,具體由ExceptionHandler實現。

transport
transport完成和第三方服務的交互,可以有多種協議形式的實現,如http+json、tcp+自定義協議等,配套使用的還有Resolver解析器,用於對第三方服務的請求和響應進行適配,提供一個防腐層(AnticorruptionLayer,DDD原書P255)的作用。

transcation
提供事務管理,交給Spring管理。

logging
日誌模塊,記錄trace日誌,使用log4j完成。

message resource
消息資源管理,交給Spring統一管理。

三、模塊結構

本節介紹COMMUNITY系統的模塊結構,由於是使用java語言實現,也就是java工程中的包結構,可以直觀地看出框架的落地實現效果。
在這裏插入圖片描述

各個package的詳細解釋參考上節框架詳述,着重注意如下幾點:

  • factory是專職爲model服務的,因此放入對應的entity的modle package中;
  • domain.repository包裏面只有倉庫的接口定義,實際的實現交給了infrastrcture中的repository module,該做法被稱作"依賴倒置",好處在於確保domoain層語義完整,同時對確保業務領域的一致性也有幫助,再者可以在domain實現內存形式的repository啞實現,從而讓domain可以真正脫離掉infrastructure;
  • translator module正常情況下不需要,但在重構老系統時,往往需要隔離掉存儲模型對業務模型的影響,使用translator來講存儲模型翻譯爲業務模型;
  • infrastructure.repository作爲倉庫層,會將實體的增刪改查操作委託給具體的存儲層服務,如oracle對應的mapper實現,mongodb對應dao實現,還有redis的實現;
  • COMMUNITY中domain event的生產者和消費者實現均交給infrastructure.rabbitmq package實現。

四、引發思考

  • DDD vs MVC 異同之處?
  • DDD vs CRUD 的區別是什麼? 可參考:CRUD中沒有U
  • DDD 能帶來什麼好處?有什麼不好的地方?
  • DDD 適用的場景?
  • 你爲什麼選擇使用DDD?

DDD帶來的好處:
業務邏輯內聚到業務領域層,可以更好的保證業務規則的一致性;
軟件的可維護性和可擴展性增強,工程師可以聚焦在業務領域層,並致力於業務領域模型的迭代和維護,適應新業務的發展;
軟件的可測試性增強,領域層代碼不需要藉助用戶接口層的入口便可以獨立測試業務邏輯,通過repository的啞實現可以擺脫對數據持久層的依賴;
軟件工程師和業務領域專家(產品經理)使用同一種語言交流,溝通成本降低,提升效率;【這一點在現實中或多或少在使用,但是比較模糊,很多時候大家會用到‘領域’這個詞語,但是並不會刻意地坐下來討論各自領域應當包含哪些實體…這也是大家可以進步的地方。】
業務領域層代碼可以獨立出來,共享到其他地方,可以輕鬆將服務產品化,雲化;【這一點是yy出來的,可忽略。】

DDD不好的地方:
對工程師有較高的業務建模技能要求,期望他們能從複雜的業務上下文中識別出正確的業務模型,並將各個業務行爲歸入合適的entity/value object/domain service中;
項目前期需要投入更多的時間進行業務建模,不能快速進入開發階段;
需要資深的業務領域專家參與進來,否則業務模型的頻繁重構(重大改動)會帶來額外成本;
DDD適用場景
業務邏輯複雜的系統;不太複雜的業務系統沒有必要使用DDD,比如內容管理系統,只是對內容進行簡單的增刪改查;再比如渠道接入層系統,只是做請求的轉發和翻譯,沒有核心業務邏輯,就沒有必要使用DDD。
有資深的業務領域專家支持,需要有一個很懂業務的人,在業務上提供指導性的意見;
工程師都認可DDD設計思路,並積極主動地探討和迭代,將業務模型日趨完善;
項目工期壓力可以接受。
你爲什麼選擇使用DDD
因爲可以使用到DDD提供的好處,並且可以克服其帶來的不變~

五、附源碼

https://github.com/daoqidelv/community-ddd-demo/tree/master

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章