目前團隊大多數(shù)項目都是基于DDD分層架構開發(fā)的,而不是傳統(tǒng)的MVC模式,這就讓很多之前沒有接觸過DDD思想的同學在剛開始接觸項目的時候有點懵喜每。那么什么DDD?這種DDD項目結構和之前的有哪些不同雳攘,我該如何開發(fā)我的代碼带兜,開發(fā)不同職責的代碼該放在哪里?下面就我的理解吨灭,說一說DDD的分層架構刚照。
傳統(tǒng)開發(fā)分層
傳統(tǒng)的數(shù)據(jù)驅動開發(fā)模式,View喧兄、Service无畔、dao這種三層分層模式,我們會很自然的寫出過程式代碼吠冤,這種開發(fā)方式中的對象只是數(shù)據(jù)載體浑彰,而沒有行為,是一種貧血對象模型拯辙。以數(shù)據(jù)為中心郭变,以數(shù)據(jù)庫ER圖為設計驅動,分層架構在這種開發(fā)模式下可以認為是數(shù)據(jù)處理和實現(xiàn)的過程涯保。
什么是DDD诉濒?
DDD 全稱是 Domain-Driven Design,中文叫領域驅動設計夕春,是一套應對復雜軟件系統(tǒng)分析和設計的面向對象建模方法論未荒。
以前的系統(tǒng)分析和設計是分開的,導致需求和成品非常容易出現(xiàn)偏差及志,兩者相對獨立茄猫,還會導致溝通困難狈蚤,DDD 則打破了這種隔閡,提出了領域模型概念划纽,統(tǒng)一了分析和設計編程脆侮,使得軟件能夠更靈活快速跟隨需求變化。
DDD的術語與基本概念
- 領域:
領域就是范圍勇劣。范圍的重點是邊界靖避。領域的核心思想是將問題逐級細分來減低業(yè)務和系統(tǒng)的復雜度,這也是 DDD 的核心比默。
2.子域:
領域可以進一步劃分成子領域幻捏,即子域。這是處理高度復雜領域的設計思想命咐,它試圖分離技術實現(xiàn)的復雜性篡九。
3.核心域:
在領域劃分過程中,會不斷劃分子域醋奠,子域按重要程度會被劃分成三類:核心域榛臼、通用域、支撐域窜司。
4.通用域:
中間件服務或第三方服務沛善。
5.支撐域:
企業(yè)公共服務。
6.統(tǒng)一語言:
映射概念:統(tǒng)一概念塞祈。
定義上下文的含義金刁。它的價值是可以解決交流障礙,不管是 RD议薪、PM尤蛮、QA 等什么角色,讓每個團隊使用統(tǒng)一的語言(概念)來交流斯议,甚至可讀性更好的代碼产捞。
7.限界上下文:
定義上下文的邊界。領域模型存在邊界之內(nèi)捅位。對于同一個概念
8.聚合:
聚合概念類似于包的概念轧葛,每個包里包含一類實體或者行為,它有助于分散系統(tǒng)復雜性艇搀,也是一種高層次的抽象尿扯,可以簡化對領域模型的理解。
在定義聚合的時候焰雕,應該遵守不變形約束法則:
聚合邊界內(nèi)必須具有哪些信息衷笋,如果沒有這些信息就不能稱為一個有效的聚合;
聚合內(nèi)的某些對象的狀態(tài)必須滿足某個業(yè)務規(guī)則:
一個聚合只有一個聚合根矩屁,聚合根是可以獨立存在的辟宗,聚合中其他實體或值對象依賴與聚合根爵赵。
只有聚合根才能被外部訪問到,聚合根維護聚合的內(nèi)部一致性泊脐。
9. 聚合根:
一個上下文內(nèi)可能包含多個聚合空幻,每個聚合都有一個根實體,叫做聚合根容客,一個聚合只有一個聚合根秕铛。
10. 實體:
Domain 或 entity。(有唯一ID)
11. 值對象:
Domain 或 entity缩挑。(沒有唯一ID)
常見的兩種領域模型
- 貧血型
簡單來說但两,就是 Domain Object 包含了不依賴于持久化的領域邏輯,而那些依賴持久化的領域邏輯被分離到 Service 層供置。
這種模式不在 Domain 層里依賴 DAO谨湘。持久化的工作還需要在 DAO 或者 Service 中進行。
缺點:
- Domain Object 的部分比較緊密依賴的持久化 Domain Logic 被分離到 Service 層芥丧。
- Service 過于厚重紧阔。
2. 充血模型
充血模型和第二種模型差不多,區(qū)別在于業(yè)務邏輯劃分娄柳,將絕大多數(shù)業(yè)務邏輯放到 Domain 中寓辱,Service 是很薄的一層艘绍,封裝少量業(yè)務邏輯赤拒,并且不和 DAO 打交道。即:Service (事務封裝) —> Domain Object <—> DAO
DDD分層架構
目前我們團隊項目分層主要是按照入下圖DDD分層進行诱鞠。
交互層:Web項目挎挖、Task項目、其它項目航夺,為最頂層蕉朵。
應用層:Service API項目和Service Provider項目,API項目不能對其它項目進行依賴阳掐,是整個領域的邊界始衅,向第三方提供接口。API項目包含了DTO對象和服務接口缭保。
領域層:Domain項目汛闸,純粹的領域模型,不包含任何數(shù)據(jù)訪問艺骂,純OO實現(xiàn)诸老。
基礎設施層:拆分為Component項目和Repository項目,Component項目提供公共組件钳恕,Repository項目提供領域存儲别伏,但是Domain項目不依賴于Repository項目蹄衷,相反是Repository項目依賴于Domain項目,Repository項目以依賴注入的方式厘肮,注入到領域層和應用層愧口。該設計與DDD的架構設計是存在差異的。
整個應用系統(tǒng)與Spring高度集成类茂。Factory基于Spring創(chuàng)建prototype的聚合根调卑、實體、VO大咱。聚合根使用依賴注入動態(tài)注入Repository實現(xiàn)恬涧。因此,整個系統(tǒng)的依賴關系與高層架構設計吻合碴巾。
DDD好處
最大好處就是所有參與者圍繞一個統(tǒng)一一致的領域模型工作溯捆,傳統(tǒng)的分析模型和設計模型不再割裂,不管是做設計厦瓢、做分析還是寫代碼提揍、寫文檔,腦海中所構建的畫面都是一致的煮仇。
DDD 是一個軟件開發(fā)過程劳跃,它顯式地把領域和設計放到了軟件開發(fā)的核心,軟件人員和業(yè)務人員被受到同樣的重視浙垫,他們合作來構建領域模型刨仑,使得軟件的交付質量更高且維護成本更低。
DDD 提出的分層架構夹姥,有效分離了業(yè)務復雜度和技術復雜度杉武,凸顯了領域模型,使得領域層的代碼和領域模型保持高度一致辙售。
統(tǒng)一語言非常重要轻抱,每個概念在各自的上下文中是清晰的無歧義的,同時要控制領域模型的復雜度旦部,于是 DDD 在戰(zhàn)略上提出了分離子域(問題域空間)和拆分 BC(解決方案空間)的模式祈搜,BC 間通過 Context Mapping 來集成。
DDD 在戰(zhàn)術層面提出了很多模式(聚合士八,實體容燕,值對象,服務曹铃,工廠缰趋,倉儲),對領域模型中的元素進行了分類,并給出了每類元素在領域模型中的職責和特征秘血,降低了領域模型的構建成本