DDD在解決什么問題
當(dāng)我們在談?wù)擃I(lǐng)域驅(qū)動設(shè)計的時候实撒,我們到底在談?wù)撌裁矗款I(lǐng)域驅(qū)動設(shè)計是在解決什么問題仍侥?
領(lǐng)域本質(zhì)是一種認(rèn)知,是我們對業(yè)務(wù)問題域的認(rèn)知鸳君,與其說我們是在用技術(shù)解決業(yè)務(wù)問題农渊,更不如說,我們是在不斷地提升對業(yè)務(wù)的認(rèn)知或颊,不斷地優(yōu)化業(yè)務(wù)領(lǐng)域模型砸紊,從而不斷地接近業(yè)務(wù)問題的本質(zhì)。代碼壞味道的背后反映的是對業(yè)務(wù)問題不清晰的認(rèn)知囱挑,最終落地了不優(yōu)雅的代碼實現(xiàn)醉顽。回歸到生活中平挑,工作中游添,我們會經(jīng)常遇到各種問題,大多數(shù)時候不是我們沒有習(xí)得解決問題的技能通熄,而是我們對問題的認(rèn)知不夠唆涝。
在上一篇文章《真的,DDD太好玩了》中我們說棠隐,DDD是一種業(yè)務(wù)設(shè)計思想石抡,用以將業(yè)務(wù)邏輯和技術(shù)實現(xiàn)分離,今天我們就是要討論一下DDD三駕馬車之中的架構(gòu)設(shè)計(三架馬車指的是架構(gòu)設(shè)計助泽,戰(zhàn)略設(shè)計和戰(zhàn)術(shù)設(shè)計),即如何將業(yè)務(wù)邏輯和技術(shù)實現(xiàn)分離嚎京。DDD中常見的架構(gòu)設(shè)計有:MVC三層架構(gòu)嗡贺,傳統(tǒng)四層架構(gòu),依賴倒置的四層架構(gòu)鞍帝,六邊形架構(gòu)(又稱端口適配器架構(gòu)诫睬,我更喜歡這個名字),洋蔥架構(gòu)帕涌,事件驅(qū)動架構(gòu)(EDA摄凡,Event-Driven Architecture?),命令與查詢分離(CQRS蚓曼,Command Query Responsibility Segregation)亲澡。
四個分層
首先我要介紹一下四層架構(gòu)的各個分層是做什么事情的,這對于理解后面各種架構(gòu)設(shè)計是有幫助的纫版,不管上述幾種架構(gòu)是如何命名的床绪,是如何定義和認(rèn)識業(yè)務(wù)邏輯和技術(shù)實現(xiàn)分離這個命題的,其內(nèi)核都是一樣的。四層架構(gòu)的四層分別指的是用戶接口層癞己、應(yīng)用層膀斋、領(lǐng)域?qū)雍突A(chǔ)設(shè)施層,其定義如下:
用戶接口層(User Interface):主要負(fù)責(zé)處理用戶請求痹雅,并將請求轉(zhuǎn)發(fā)給應(yīng)用層處理仰担。
應(yīng)用層(Application):主要負(fù)責(zé)協(xié)調(diào)上游的用戶接口層以及下游的領(lǐng)域?qū)樱⒁獾氖羌ㄉ纾搶舆壿嬕M可能簡單惰匙,否則會導(dǎo)致領(lǐng)域?qū)拥呢氀?/p>
領(lǐng)域?qū)樱―omain):主要包含了核心業(yè)務(wù)邏輯,包含實體铃将,值對象项鬼,領(lǐng)域服務(wù),領(lǐng)域事件等劲阎。
基礎(chǔ)設(shè)施層(Infrastructure):主要提供各種技術(shù)中間件绘盟,數(shù)據(jù)庫(MySQL,NoSql)和應(yīng)用配置等技術(shù)實現(xiàn)方面的能力悯仙。
架構(gòu)設(shè)計分析
在DDD架構(gòu)設(shè)計中龄毡,核心的目標(biāo)就是將業(yè)務(wù)邏輯和技術(shù)實現(xiàn)分離,這也正是MVC三層架構(gòu)留下來的問題锡垄。
我們在MVC三層架構(gòu)中將業(yè)務(wù)邏輯和技術(shù)實現(xiàn)一股腦寫在了Service層沦零,技術(shù)實現(xiàn)中參雜了業(yè)務(wù)邏輯,業(yè)務(wù)邏輯中也揉合了技術(shù)實現(xiàn)货岭,從而將本來就復(fù)雜的業(yè)務(wù)邏輯變得更加復(fù)雜了路操。端口適配器架構(gòu)則簡化了這個問題,很直白地將架構(gòu)設(shè)計成了兩部分千贯,即內(nèi)部的業(yè)務(wù)邏輯和外部的基礎(chǔ)設(shè)施和用戶界面屯仗,當(dāng)然這也是一種分層架構(gòu),即內(nèi)部和外部兩層搔谴。如果將內(nèi)部業(yè)務(wù)邏輯對外部的依賴定義成接口魁袜,那么基礎(chǔ)設(shè)施表示的技術(shù)實現(xiàn)部分,用戶界面表示的是用戶請求就都算是適配器實現(xiàn)敦第。
這種實現(xiàn)業(yè)務(wù)邏輯和技術(shù)實現(xiàn)分離的架構(gòu)真的是太優(yōu)雅了峰弹,很符合奧卡姆剃刀原理(“如無必要,勿增實體”芜果,即“簡單有效原理”)鞠呈,簡單就是美。但其實也會帶來另一個問題师幕,即如何去認(rèn)識業(yè)務(wù)邏輯粟按?難道業(yè)務(wù)邏輯就是一個大塊頭嗎诬滩?該如何下手設(shè)計這個大塊頭呢?
洋蔥架構(gòu)既在端口適配器架構(gòu)之上灭将,提出了一種劃分業(yè)務(wù)邏輯的方法疼鸟,將業(yè)務(wù)邏輯劃分為應(yīng)用服務(wù),領(lǐng)域服務(wù)和領(lǐng)域模型庙曙,并且依賴方向也是從外向內(nèi)空镜。這里其實也有了依賴倒置四層架構(gòu)的味道了。
那么我們就順理成章地介紹一下四層架構(gòu)捌朴,在傳統(tǒng)的四層架構(gòu)中吴攒,我們可以發(fā)現(xiàn),所有的依賴都指向了基礎(chǔ)設(shè)施層砂蔽,這帶來了一個很大的問題洼怔,業(yè)務(wù)邏輯依賴了技術(shù)實現(xiàn),技術(shù)實現(xiàn)的變動會導(dǎo)致業(yè)務(wù)邏輯發(fā)生變化左驾,這不符合我們的認(rèn)知镣隶。在理想的架構(gòu)實現(xiàn)中,不管你技術(shù)如何變化诡右,我的業(yè)務(wù)邏輯是不應(yīng)該受到技術(shù)變化影響的安岂。這時候依賴倒置原則就可以發(fā)揮作用了,將技術(shù)實現(xiàn)的契約或者規(guī)范定義在領(lǐng)域?qū)臃牵A(chǔ)實施層只管實現(xiàn)就好了域那,從而實現(xiàn)了依賴方向的反轉(zhuǎn)。這種架構(gòu)設(shè)計維護(hù)了業(yè)務(wù)邏輯的穩(wěn)定猜煮,也更近一步地將技術(shù)實現(xiàn)對業(yè)務(wù)邏輯的影響降到了最低次员,從而實現(xiàn)了業(yè)務(wù)邏輯和技術(shù)實現(xiàn)的解耦,也使得領(lǐng)域?qū)犹幱诩軜?gòu)模型中的核心地位友瘤。
在上面的分析中翠肘,我們可以發(fā)現(xiàn),其實DDD的四層架構(gòu)是一種相對而言更便于理解和落地的架構(gòu)辫秧,它可以讓我們更輕松地從MVC三層架構(gòu)的認(rèn)知中遷移至DDD四層架構(gòu)。
至此被丧,四層架構(gòu)模型似乎已經(jīng)解決了業(yè)務(wù)邏輯和技術(shù)實現(xiàn)分離的問題盟戏,事實上也確實如此。CQRS架構(gòu)模型和EDA架構(gòu)模型在我眼中更像是對四層架構(gòu)的優(yōu)化甥桂。其中CQRS模型類似于讀寫分離柿究,其中命令是客戶端讓服務(wù)器做事情,是從客戶端向服務(wù)器后端發(fā)出寫入操作命令黄选,通常會改變后端模型的狀態(tài)蝇摸;而查詢是服務(wù)器后端向客戶端返回結(jié)果婶肩。在前面幾種架構(gòu)模型中,查詢和變更操作都是經(jīng)過完整的四層處理貌夕,并且實現(xiàn)邏輯都耦合在一起了律歼,即實現(xiàn)在相同的類中。其實對于查詢操作來說啡专,這是一種很輕量級的業(yè)務(wù)邏輯险毁,核心就是獲取數(shù)據(jù)并進(jìn)行轉(zhuǎn)化,最終展示給用戶们童,將其與命令分離開使得讀寫邏輯可以獨立建模畔况,邏輯更清晰,也可以專門優(yōu)化查詢操作慧库。
而EDA架構(gòu)的核心目的是提供一個業(yè)務(wù)認(rèn)知和業(yè)務(wù)解耦的方法跷跪,通過事件的流轉(zhuǎn)來認(rèn)識業(yè)務(wù)邏輯,并且也可以通過業(yè)務(wù)事件來解耦業(yè)務(wù)齐板。因為不斷是什么業(yè)務(wù)場景吵瞻,其本質(zhì)都是事件導(dǎo)致結(jié)果發(fā)生,每個結(jié)果也有可能是一個事件覆积,從而通過事件來串聯(lián)整個業(yè)務(wù)流程听皿,但也會帶來事務(wù)問題。
最后
上面分析了這么多架構(gòu)模式宽档,但仿佛是個屠龍之術(shù)尉姨,學(xué)了很多又似乎無用武之地。但回過頭看吗冤,正是因為領(lǐng)域設(shè)計的目標(biāo)又厉,才有了形形色色的架構(gòu)模式,每個架構(gòu)架構(gòu)模式都在提出自己對問題的認(rèn)知和解決方案椎瘟,即如何將業(yè)務(wù)邏輯和技術(shù)實現(xiàn)分離覆致,從而使得領(lǐng)域設(shè)計回歸本質(zhì),關(guān)注于業(yè)務(wù)認(rèn)知肺蔚,而不是技術(shù)實現(xiàn)煌妈。
注:本文圖片均來源于網(wǎng)絡(luò)。