1真的,DDD太好玩了

DDD也是牛馬

乾坤未定你我皆是牛馬,而DDD又何嘗不是牛馬呢?面試的時(shí)候,寫(xiě)博客的時(shí)候,和朋友吹牛皮的時(shí)候,作為一個(gè)技術(shù)人,你要是不把DDD搬出來(lái),你都不好意思說(shuō)你是一個(gè)開(kāi)發(fā),不僅是后端開(kāi)發(fā)在搞這個(gè),前端也在搞這個(gè)。裝完之后呢,DDD就怕被束之高閣了,landing是不可能landing的,這輩子也不可能landing。是的,博主我也是這樣的人。

什么是DDD

DDD,Domain-Driven Design,即領(lǐng)域驅(qū)動(dòng)設(shè)計(jì),用領(lǐng)域建模的思想去進(jìn)行業(yè)務(wù)設(shè)計(jì)或技術(shù)設(shè)計(jì)。

幾年前,也沒(méi)有幾年前,畢竟我才工作四年,也就18年我畢業(yè)的時(shí)候,DDD還是蠻新的東西,起碼你在找工作時(shí),大家平時(shí)交流中時(shí),是很少談?wù)撨@個(gè)東西,那時(shí)候JVM是蠻火的,面試基本都會(huì)問(wèn)JVM,現(xiàn)在很少問(wèn)了。而這兩年,我看很多崗位描述上都要求有DDD相關(guān)經(jīng)驗(yàn)。其實(shí)也蠻喜新厭舊的,畢竟在程序設(shè)計(jì)思想這塊,面向?qū)ο笤?jīng)才是老大哥,基本面試都會(huì)問(wèn)面向?qū)ο笕髾C(jī)制,或者設(shè)計(jì)原則,或者設(shè)計(jì)模式,此時(shí)單例模式表示很淦,都被你們整出了7種寫(xiě)法了。

時(shí)過(guò)境遷,技術(shù)人不迎頭趕上,遲早要被拍打在冷冷的沙灘上。

面向?qū)ο蠛蚐OLID原則

要說(shuō)DDD,我們要先聊聊面向?qū)ο蟮脑O(shè)計(jì)原則即SOLID原則,后面談到設(shè)計(jì)模式時(shí),默認(rèn)也是面向?qū)ο笤O(shè)計(jì)原則的體現(xiàn),不糾結(jié)某個(gè)設(shè)計(jì)模式體現(xiàn)了什么設(shè)計(jì)原則。SOLID原則如下所示:

S即單一職責(zé)原則(Single Responsibility Principle),答應(yīng)我,一個(gè)類(lèi)就干一件事,別多管閑事。

O即開(kāi)閉原則(Open Closed Principle),每次新需求,你都把所有類(lèi)修改一遍,你敢上線發(fā)布,測(cè)試敢嗎?到底要回歸哪些流程?能不能多開(kāi)些擴(kuò)展口子,新需求來(lái)了就擴(kuò)展一下口子。

L即里氏替換原則(Liskov Substitution Principle),爸爸都說(shuō)了,這個(gè)方法是a+b,到了你那,就變成a-b了,爸爸不要面子的嗎?

I即接口隔離原則(Interface Segregation Principle),答應(yīng)我,一個(gè)接口就約定一件事。

D即迪米特法則,依賴(lài)倒置原則(Law of Demeter,Dependence Inversion Principle)迪米特法則,不該知道的不要知道;依賴(lài)倒置原則,想做甲方爸爸,你就要學(xué)會(huì)定義接口。

SOLID原則和其他面向?qū)ο笤O(shè)計(jì)原則我先不做過(guò)多解釋?zhuān)竺嫖覀冊(cè)诹腄DD的時(shí)候也會(huì)談到這些原則,我也會(huì)進(jìn)一步做解釋。其實(shí)在這里,我已經(jīng)表達(dá)出了我這篇博客的核心觀點(diǎn),也是我要傳遞的想法,領(lǐng)域即對(duì)象,領(lǐng)域建模即對(duì)象建模,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(DDD)即面向?qū)ο笤O(shè)計(jì)(OOD,Object-Oriented Design)。就如同一個(gè)劇本,換了演員和背景,一切好像又是新的劇情,但核其實(shí)還是那個(gè)核。歷史就是個(gè)輪回,誰(shuí)說(shuō)不是呢。

這里我要表明我對(duì)DDD的看法,DDD是一種業(yè)務(wù)設(shè)計(jì)思想(不僅僅是開(kāi)發(fā),對(duì),說(shuō)的就是產(chǎn)品,你們也要懂點(diǎn)DDD),是一種業(yè)務(wù)認(rèn)知的方法論,它給出了一種認(rèn)識(shí)業(yè)務(wù),并剝離開(kāi)技術(shù)實(shí)現(xiàn)的可能性(對(duì),可能性,因?yàn)橹懒艘矡o(wú)法landing),即DDD是一種將核心業(yè)務(wù)規(guī)則與具體技術(shù)實(shí)現(xiàn)解耦的設(shè)計(jì)思想。這里提到的解耦也是一種程序設(shè)計(jì)方法,當(dāng)然也是面向?qū)ο蟮脑O(shè)計(jì)方法。

DDD三駕馬車(chē)

DDD主要分為三大塊,分別為架構(gòu)設(shè)計(jì),戰(zhàn)略設(shè)計(jì)和戰(zhàn)術(shù)設(shè)計(jì)。

架構(gòu)設(shè)計(jì)主要涉及到的核心思想是分層,當(dāng)然分層基本是所有架構(gòu)設(shè)計(jì)采用的思想,比如計(jì)算機(jī)網(wǎng)絡(luò)中的七層架構(gòu),MVC三層架構(gòu),公司組織架構(gòu)等等。

戰(zhàn)略設(shè)計(jì)主要涉及到通用語(yǔ)言,領(lǐng)域劃分(domain,核心域,通用子域,支撐子域),限界上下文(bounded contex),上下文映射圖(context map)。

戰(zhàn)術(shù)設(shè)計(jì)主要涉及的概念有實(shí)體(entity),值對(duì)象(value object),領(lǐng)域事件(domain event),領(lǐng)域服務(wù)(domain service),應(yīng)用服務(wù),倉(cāng)儲(chǔ)/資源庫(kù)(repository),聚合(aggregate),聚合根(aggregate root),工廠(factory)。

具體的含義我不做過(guò)多解釋?zhuān)竺娌┛臀覀儠?huì)繼續(xù)聊如何進(jìn)行DDD設(shè)計(jì),今天我們只聊DDD和面向?qū)ο笤O(shè)計(jì)之間的關(guān)系,如何從面向?qū)ο蟮慕嵌瓤碊DD,讓DDD不再高大上,不再神神秘秘,讓DDD成為一種顯學(xué),人人都會(huì)DDD,人人都是DDDer。

DDD與面向?qū)ο?/h1>

DDD本質(zhì)是面向?qū)ο?,只是換了更高一層的說(shuō)辭去包裝了一遍。

我們?cè)诩軜?gòu)設(shè)計(jì)中談?wù)摳鞣N架構(gòu)范式,但始終脫離不了依賴(lài)倒置原則,這是DDD架構(gòu)設(shè)計(jì)的核心。依賴(lài)倒置原則就是面向接口編程,什么是接口,接口即規(guī)范。誰(shuí)定義了接口,誰(shuí)就是游戲規(guī)則的制定者,其他實(shí)現(xiàn)接口的開(kāi)發(fā)者都是純純牛馬,純純打工人。我們把核心接口都定義在領(lǐng)域?qū)?,讓領(lǐng)域?qū)映蔀楹诵膶?,控制流從各個(gè)方向指向了領(lǐng)域?qū)?。端口適配器模式即六邊形架構(gòu),直接在命名中就點(diǎn)出了面向接口原則,什么是端口,其實(shí)就是接口,適配器模式是做什么用的,就是轉(zhuǎn)換接口,將老接口換成新接口。


四層架構(gòu)

接下來(lái),我們?cè)儆懻搼?zhàn)略設(shè)計(jì)部分,什么是領(lǐng)域劃分?如何進(jìn)行領(lǐng)域劃分?劃分原則是什么?不就是單一職責(zé)原則嗎?每個(gè)業(yè)務(wù)域負(fù)責(zé)一個(gè)核心業(yè)務(wù)能力,讓每個(gè)模塊以及模塊與模塊之間形成高內(nèi)聚,低耦合的一種關(guān)系,每個(gè)子域內(nèi)聚在一起形成一種業(yè)務(wù)能力,子域與子域之間是低耦合的,子域提供的能力通過(guò)RPC或者HTTP進(jìn)行交互。也就是說(shuō),領(lǐng)域劃分的原則是單一職責(zé)原則,領(lǐng)域之間的關(guān)系是高內(nèi)聚低耦合的。以上也就是戰(zhàn)略設(shè)計(jì)的核心內(nèi)容。

最后我們?cè)倭囊涣氖裁词菓?zhàn)術(shù)設(shè)計(jì),這一層更接近代碼編寫(xiě)了。我們?cè)陬I(lǐng)域建模過(guò)程中強(qiáng)調(diào)的實(shí)體值對(duì)象,其本質(zhì)就是充血模型,讓每個(gè)實(shí)體具備業(yè)務(wù)規(guī)則,而不僅僅像MVC時(shí)那樣,變成了數(shù)據(jù)庫(kù)記錄承載者,即對(duì)象關(guān)系映射(ORM),這違背了面向?qū)ο笤O(shè)計(jì)的原則。對(duì)象是屬性和方法的封裝,其中屬性是數(shù)據(jù)字段映射,而方法是該對(duì)象所代表的業(yè)務(wù)規(guī)則,而不僅僅是數(shù)據(jù)承載容器。至于領(lǐng)域事件,我就不提了,核心是解耦的思想,其實(shí)現(xiàn)方式可以是觀察者模式,也可以是消息隊(duì)列。聚合則是將幾個(gè)緊密相關(guān)的實(shí)體組合在一起,形成了一種同生共死(you die i die,you live i live)的關(guān)系。幾個(gè)相關(guān)的對(duì)象組合在一起,就像一家人,那么這時(shí)創(chuàng)造對(duì)象就會(huì)比較繁雜,需要同時(shí)構(gòu)建幾個(gè)對(duì)象,這時(shí)候工廠設(shè)計(jì)模式就發(fā)揮作用,繁雜重復(fù)的構(gòu)造邏輯由工廠(factory)整合起來(lái)了,你要?jiǎng)?chuàng)建對(duì)象的話,就調(diào)用一下工廠提供的接口吧,一家人在一起就要整整齊齊。

還剩下repository(倉(cāng)儲(chǔ)/資源庫(kù)),其實(shí)對(duì)多數(shù)據(jù)源開(kāi)發(fā)來(lái)說(shuō),repository蠻重要的,它是一種接口即面向接口編程,當(dāng)我們?cè)陬I(lǐng)域?qū)佣x好了數(shù)據(jù)的接口時(shí),那么不管基礎(chǔ)設(shè)施層采用什么技術(shù)手段進(jìn)行數(shù)據(jù)儲(chǔ)存,如redis,mysql,oracle,hbase等等,我都不再關(guān)心,你只要按照我的接口進(jìn)行實(shí)現(xiàn)就好。而傳統(tǒng)實(shí)現(xiàn)中,如MVC,傳統(tǒng)DDD四層架構(gòu),MVC是service層依賴(lài)dao層,也就是說(shuō),核心服務(wù)層依賴(lài)了底層數(shù)據(jù)層,底層數(shù)據(jù)的實(shí)現(xiàn)技術(shù)發(fā)生變化,那么service就要變,此時(shí)在service定義接口的話,就可以實(shí)現(xiàn)依賴(lài)反轉(zhuǎn)(倒置),service就不要再做任何改變了。當(dāng)然這也是Spring IOC的核心思想,實(shí)現(xiàn)方式不同罷了。

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

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

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