DDD領(lǐng)域驅(qū)動設(shè)計(jì)落地實(shí)踐(十分鐘看完,半小時落地)

推薦:講給P8聽的業(yè)務(wù)設(shè)計(jì)課:DDD領(lǐng)域驅(qū)動設(shè)計(jì),架構(gòu)師必會技能(一個案例讓你透徹理解DDD)

一、引子

不知今年吹了什么風(fēng),忽然DDD領(lǐng)域驅(qū)動設(shè)計(jì)進(jìn)入大家視野。該思想源于2003年 Eric Evans編寫的“Domain-Driven Design領(lǐng)域驅(qū)動設(shè)計(jì)”簡稱DDD,Evans DDD是一套綜合軟件系統(tǒng)分析和設(shè)計(jì)的面向?qū)ο蠼7椒?。剛好公司領(lǐng)導(dǎo)強(qiáng)力推薦這個,抱著學(xué)習(xí)的心態(tài),耗時5個月,體驗(yàn)了一把:“DDD從入門到棄坑”。

二、思想

學(xué)習(xí)網(wǎng)站:https://www.jdon.com/ddd.html

2.1 服務(wù)器后端發(fā)展三個階段

服務(wù)器后端發(fā)展三個階段:

  1. 面向過程腳本:初始簡單,業(yè)務(wù)復(fù)雜后,維護(hù)難度指數(shù)上升。-->基本不為主流使用
  2. 面向數(shù)據(jù)庫表:初始難度中,業(yè)務(wù)復(fù)雜后,維護(hù)難度延遲后再指數(shù)上升。--->目前市面上主流
  3. 面向業(yè)務(wù)模型:DDD+SOA微服務(wù)的事件驅(qū)動的CQRS讀寫分離架構(gòu):應(yīng)付復(fù)雜業(yè)務(wù)邏輯,以聚合模型替代數(shù)據(jù)表模型,以并發(fā)的事件驅(qū)動替代串聯(lián)的消息驅(qū)動。真正實(shí)現(xiàn)以業(yè)務(wù)實(shí)體為核心的靈活拓展。初始難度高,業(yè)務(wù)復(fù)雜后,維護(hù)難度線性上升(已很不錯)。

2.2 DDD最大特點(diǎn)

DDD革命性在于:領(lǐng)域模型準(zhǔn)確反映了業(yè)務(wù)語言,而傳統(tǒng)微服務(wù)數(shù)據(jù)對象除了簡單setter/getter方法外,沒有任何業(yè)務(wù)方法,即失血模型,那么DDD領(lǐng)域模型就是充血模型(業(yè)務(wù)方法定義在實(shí)體對象中)。

三、落地

3.1 領(lǐng)域模型設(shè)計(jì)

以渠道中心(一個微服務(wù))作為例子來做領(lǐng)域模型設(shè)計(jì),核心就是設(shè)計(jì)2個圖,一個是戰(zhàn)略設(shè)計(jì)圖(宏觀) ,一個是戰(zhàn)術(shù)設(shè)計(jì)圖(細(xì)節(jié))。

1.領(lǐng)域戰(zhàn)略設(shè)計(jì)圖

戰(zhàn)略設(shè)計(jì)圖是從一個限界上下文的角度出發(fā)去分析業(yè)務(wù)場景。主要是宏觀上的核心域、子域、實(shí)體關(guān)系圖。demo如下圖:

2.領(lǐng)域戰(zhàn)術(shù)設(shè)計(jì)圖

戰(zhàn)術(shù)設(shè)計(jì)圖是從一個限界上下文的角度出發(fā)去分析業(yè)務(wù)場景。細(xì)化到核心業(yè)務(wù)字段、領(lǐng)域?qū)嶓w、值對象、領(lǐng)域服務(wù)、領(lǐng)域事件等等?;旧线@個圖畫完,代碼已經(jīng)知道怎么寫了。demo如下圖:

3.2 技術(shù)實(shí)現(xiàn)

整體項(xiàng)目框架分層圖如下所示:

如上圖,4層典型DDD分層結(jié)構(gòu),

1.展現(xiàn)層:controller層。無業(yè)務(wù)邏輯

2.應(yīng)用服務(wù)層:此層可以包含查詢邏輯,但核心業(yè)務(wù)邏輯必須下沉到領(lǐng)域?qū)印?/p>

3.領(lǐng)域服務(wù)層:業(yè)務(wù)在這里組裝。倉儲(資源庫)接口在此層定義。

4.基礎(chǔ)設(shè)施層:倉儲(資源庫)實(shí)現(xiàn)層+PO持久化層。

注:

1.簡單查詢不涉及業(yè)務(wù),是可以直接從應(yīng)用層直接穿透到PO查詢,不需要經(jīng)過domain層。如下圖所示,DDD本身是不限制非業(yè)務(wù)類操作跨層調(diào)用的。

2.DTO是不能存在于domain層的,DDD設(shè)計(jì)不認(rèn)為DTO是業(yè)務(wù)對象,entity才是。或者傳值簡單數(shù)據(jù)類型也是可以的。

3.2.1 服務(wù)調(diào)用問題

1.域內(nèi)調(diào)用

領(lǐng)域內(nèi)調(diào)用,隨便調(diào)用,絲般順滑。至于實(shí)現(xiàn),可以由一個核心域的倉儲實(shí)現(xiàn)層(第四層)去實(shí)現(xiàn)多個Repository接口。(比如這里A是核心域的實(shí)體名,B是支撐域、通用域等)

2.跨域調(diào)用

跨域分為

  • 1.同上下文跨域:ACL層->Adapter適配器層→調(diào)用其它域的repository。--->不得已才使用,不推薦使用。

  • 推薦:1.使用領(lǐng)域事件 eventbus來做解耦(nest-eventbus使用

           2.考慮是否有可能合并為一個領(lǐng)域.
    
  • 2.跨上下文(肯定跨域):ACL層->Adapter適配器層->feign調(diào)用

3.2.2 包結(jié)構(gòu)

包結(jié)構(gòu)如下:

展開包結(jié)構(gòu)如下:

展現(xiàn)層:Controller,僅做接口的入口定義和編排轉(zhuǎn)發(fā),不做任何的業(yè)務(wù)處理;

應(yīng)用服務(wù)層:application,負(fù)責(zé)接口參數(shù)DTO的簡單校驗(yàn),以及DTO和實(shí)體值對象的數(shù)據(jù)轉(zhuǎn)換,對于簡單的業(yè)務(wù),也可以在應(yīng)用層加載實(shí)體直接執(zhí)行實(shí)體行為方法;

領(lǐng)域?qū)樱?/strong>

  • 模型:根據(jù)領(lǐng)域模型分析領(lǐng)域內(nèi)各實(shí)體、聚合、聚合根、值對象等,這些對象在*.domain.model定義,實(shí)體內(nèi)的行為方法只負(fù)責(zé)維護(hù)實(shí)體自身的生命周期和狀態(tài);
  • 行為:領(lǐng)域內(nèi)各實(shí)體、聚合、聚合根等,會有相應(yīng)的行為,在*.domain.model包下定義行為方法;
  • 領(lǐng)域服務(wù):領(lǐng)域提供的接口服務(wù),需要定義在*.domain.service包下,業(yè)務(wù)相關(guān)的前置業(yè)務(wù)判斷、多個實(shí)體或值對象的行為邏輯處理等,都在領(lǐng)域服務(wù)中實(shí)現(xiàn),需要注意的是并不是每個實(shí)體都有一個對應(yīng)的領(lǐng)域服務(wù),但是依賴多個實(shí)體的行為方法,最好根據(jù)這個業(yè)務(wù)模塊是建立一個領(lǐng)域服務(wù);
  • 倉儲:領(lǐng)域服務(wù)或上層應(yīng)用服務(wù)需要使用到的基礎(chǔ)設(shè)施層,包括DB、Feign調(diào)用等,定義在.domain.repository下,在.infrastructure.repository下實(shí)現(xiàn);

適配層:在acl包下的feign定義依賴外部的接口,并在acl的adapter包編寫轉(zhuǎn)換,由倉儲層操作實(shí)體時調(diào)用;

持久層:與常用DAO定義一致,由倉儲層操作實(shí)體時調(diào)用。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容