如何快速入門領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(DDD)漠烧,DDD 架構(gòu)及使用詳解

一、背景與問題

無論是企業(yè)內(nèi)部系統(tǒng)還是互聯(lián)網(wǎng)產(chǎn)品靡砌,多年來開發(fā)這種基于業(yè)務(wù)與數(shù)據(jù)庫的系統(tǒng)都是 IT 領(lǐng)域一個(gè)重要的內(nèi)容已脓。作為一個(gè) IT 開發(fā)團(tuán)隊(duì),無論是做外包還是自己的產(chǎn)品通殃,都面臨從產(chǎn)品經(jīng)理拿到需求度液,然后需要進(jìn)行兩方面重要的工作:一是把需求轉(zhuǎn)換為設(shè)計(jì)、二是從設(shè)計(jì)開始編寫代碼画舌。

以前我們開發(fā)這種基于業(yè)務(wù)的軟件產(chǎn)品堕担,通常都是基于開發(fā)人員自己的經(jīng)驗(yàn)和編寫代碼的習(xí)慣開始系統(tǒng)的設(shè)計(jì)與代碼的編寫。常見的方式是項(xiàng)目經(jīng)理或架構(gòu)師分析需求后曲聂,開始進(jìn)行數(shù)據(jù)庫表結(jié)構(gòu)的設(shè)計(jì)照宝,然后按照自己熟悉的分層架構(gòu),比如四層架構(gòu)(數(shù)據(jù)訪問層-業(yè)務(wù)邏輯層-WebApi-前端)進(jìn)行代碼組織句葵。從上述的實(shí)現(xiàn)可以看出幾個(gè)問題:

  1. 沒有描述需求的設(shè)計(jì)模型;而是直接通過數(shù)據(jù)庫表的方式體現(xiàn)兢仰,也就是需求與設(shè)計(jì)是脫節(jié)的乍丈。
  2. 編碼的架構(gòu)也沒有與設(shè)計(jì)和需求對(duì)應(yīng)起來。
  3. 業(yè)務(wù)邏輯與技術(shù)混在一起把将;業(yè)務(wù)邏輯可能直接調(diào)用的數(shù)據(jù)訪問轻专,這樣把業(yè)務(wù)邏輯與數(shù)據(jù)訪問的技術(shù)混在一起。
  4. 開發(fā)沒有層次感和節(jié)奏感察蹲;系統(tǒng)沒有一個(gè)統(tǒng)一的約束请垛,開發(fā)人員沒有一個(gè)統(tǒng)一的節(jié)奏,這主要體現(xiàn)在隨意的編碼洽议。
  5. Bug 定位困難:當(dāng)系統(tǒng)出現(xiàn)業(yè)務(wù)異常行為時(shí)宗收,無法快速準(zhǔn)確的定位出現(xiàn)問題的位置,因?yàn)橄到y(tǒng)不同開發(fā)人員的代碼放置隨意性亚兄。
  6. 需求變更響應(yīng)緩慢:在大型的系統(tǒng)或產(chǎn)品中混稽,當(dāng)需要增加功能或修改現(xiàn)有功能時(shí),因?yàn)榇a架構(gòu)的隨意性,可能會(huì)出現(xiàn)改了功能可能會(huì)影響到其他的功能匈勋,造成系統(tǒng)極不穩(wěn)定礼旅。 大家知道,萬事萬物都有其內(nèi)在規(guī)律洽洁,這就是套路痘系,軟件設(shè)計(jì)與開發(fā)也是如此。軟件設(shè)計(jì)與開發(fā)的套路就是領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(簡稱 DDD)饿自。DDD 這個(gè)套路能夠靈活解決以上的問題汰翠,為我們提供一個(gè)好的設(shè)計(jì)、架構(gòu)以及高質(zhì)量的代碼璃俗。

二奴璃、為什么要學(xué)習(xí) DDD

DDD 是軟件行業(yè)的一種成熟的方法論和模式。通過應(yīng)用 DDD城豁,我們能夠很好的將需求應(yīng)對(duì)到設(shè)計(jì)苟穆,能夠讓開發(fā)聚焦業(yè)務(wù)本身而不是技術(shù),能夠讓代碼體現(xiàn)我們?cè)O(shè)計(jì)唱星,能夠讓團(tuán)隊(duì)在一個(gè)框架內(nèi)有節(jié)奏的開發(fā)雳旅。

1. DDD 核心概念

首先給大家描述一下 DDD 的概念:DDD 是一種開發(fā)理念,核心是維護(hù)一個(gè)反應(yīng)領(lǐng)域概念的模型(領(lǐng)域模型是軟件最核心的部分间聊,反應(yīng)了軟件的業(yè)務(wù)本質(zhì))攒盈,然后通過大量模式來指導(dǎo)模型設(shè)計(jì)與開發(fā)。

從上述定義可以看出哎榴,DDD 方法首先是需要將需求分析后型豁,形成一個(gè)反應(yīng)需求的領(lǐng)域模型。領(lǐng)域模型就是大家平常理解的類尚蝌、類的屬性迎变、類之間的關(guān)系等。當(dāng)然在 DDD 中飘言,為了更好的將領(lǐng)域模型反應(yīng)需求衣形,對(duì)類、類的屬性姿鸿、類之間的關(guān)系等有一些模式的指導(dǎo)谆吴。比如類的屬性可能是一般屬性,也可能是值對(duì)象苛预;比如有關(guān)系的類之間是否是代表一個(gè)整體概念句狼、有相同生命周期、需要統(tǒng)一持久化等热某。所以我們的領(lǐng)域模型除了能夠跑通需求外鲜锚,還要考慮聚合根突诬、實(shí)體、值對(duì)象芜繁、聚合等概念的應(yīng)用旺隙,這樣領(lǐng)域模型的設(shè)計(jì)才能更好的反應(yīng)需求,也能夠更好的將設(shè)計(jì)對(duì)應(yīng)成有約束力的代碼骏令。

另外 DDD 也提供了大量模式蔬捷,告訴我們應(yīng)該如何編寫對(duì)應(yīng)設(shè)計(jì)的代碼,能夠?qū)⑽覀兊拇a真正映射到設(shè)計(jì)榔袋;如何進(jìn)行業(yè)務(wù)邏輯與持久化機(jī)制的剝離周拐;如何進(jìn)行更好的架構(gòu)設(shè)計(jì)等。

2. DDD 能應(yīng)對(duì)復(fù)雜性

在軟件設(shè)計(jì)與開發(fā)過程中凰兑,復(fù)雜性主要體現(xiàn)在三個(gè)方面妥粟。一是技術(shù)維度,有業(yè)務(wù)代碼的實(shí)現(xiàn)吏够、有與數(shù)據(jù)庫或其他持久化存儲(chǔ)交互的實(shí)現(xiàn)勾给、有消息隊(duì)列的實(shí)現(xiàn)、有身份驗(yàn)證與授權(quán)的實(shí)現(xiàn)锅知、有 WebAPI 暴露的實(shí)現(xiàn)等播急;二是業(yè)務(wù)維度,有太多的模塊和功能需要去做售睹;三是時(shí)間維度桩警,需要快速的開發(fā),快速的響應(yīng)需求的變更昌妹,快速的修正 Bug捶枢。那么 DDD 是如何解決上述三個(gè)維度的復(fù)雜性呢?

  • a. 技術(shù)維度:通過合理的架構(gòu)分層飞崖,能夠讓每層關(guān)注自己的事情烂叔,比如領(lǐng)域?qū)又魂P(guān)注業(yè)務(wù)邏輯的事情,倉儲(chǔ)實(shí)現(xiàn)層只關(guān)注持久化數(shù)據(jù)與查詢的事情蚜厉,應(yīng)用服務(wù)層只關(guān)注協(xié)調(diào)領(lǐng)域?qū)优c倉儲(chǔ)實(shí)現(xiàn)層完成用例的事情,接口層只關(guān)注暴露給前端的事情畜眨。
  • b. 業(yè)務(wù)維度:通過將大系統(tǒng)劃分成多個(gè)界限上下文昼牛,可以讓不同團(tuán)隊(duì)和不同人只關(guān)注當(dāng)前上下文的開發(fā)。在當(dāng)前界限上下文中的領(lǐng)域?qū)涌的簟}儲(chǔ)實(shí)現(xiàn)層贰健、應(yīng)用服務(wù)層、接口層都與其他界限上下文獨(dú)立開來恬汁,這樣可以專注開發(fā)伶椿,并且在修改代碼與發(fā)布產(chǎn)品時(shí),影響面較小。
  • c. 時(shí)間維度:通過敏捷式迭代快速驗(yàn)證脊另,快速修正导狡。

三、什么人適合學(xué)習(xí) DDD

從文章前面的部分大家可能有這樣的初步感覺:DDD 是一套設(shè)計(jì)偎痛、架構(gòu)和編碼指導(dǎo)的方法旱捧,通過靈活運(yùn)用 DDD,能夠設(shè)計(jì)出很好反應(yīng)產(chǎn)品需求的領(lǐng)域模型踩麦,另外通過更好的分層指導(dǎo)能夠讓我們的代碼很好的反映設(shè)計(jì)枚赡,其實(shí)最終解決的問題就是我們第一個(gè)部分提出的 6 大問題。所以只要具有業(yè)務(wù)屬性的產(chǎn)品或項(xiàng)目谓谦,在這個(gè)團(tuán)隊(duì)中的架構(gòu)師贫橙、主要后端開發(fā)人員都是比較適合去學(xué)習(xí) DDD 的。DDD 與語言無關(guān)反粥,無論是 C#卢肃、Java 還是其他的語言,只要我們是遵循 DDD 套路的設(shè)計(jì)與編碼架構(gòu)星压,那就代表我們很好的實(shí)踐了 DDD践剂。當(dāng)然為了你更好的入門 DDD,本文第五部分會(huì)有代碼的演示娜膘。在代碼演示部分使用了 C# 語言和 .net Core逊脯、EF Core、Unity竣贪、Asp.net Core WebAPI 等語言或基礎(chǔ)框架军洼,如果你是 Java 體系,也能夠找到對(duì)應(yīng)的框架實(shí)現(xiàn)的演怎。再次強(qiáng)調(diào)匕争,DDD 與語言和技術(shù)無關(guān)。

四爷耀、如何高效學(xué)習(xí) DDD

其實(shí)要學(xué)習(xí)一種方法論和架構(gòu)模式,就兩個(gè)步驟:一是了解它核心的概念和組件歹叮,二是將這些概念和組件靈活的運(yùn)用到產(chǎn)品開發(fā)中跑杭。

要高效的學(xué)習(xí) DDD咆耿,首先我們要搞清楚兩個(gè)方面的內(nèi)容:一是核心的組件和概念,二是 DDD 分層架構(gòu)萨螺。

核心組件和概念

  1. 界限上下文:首先要將大系統(tǒng)劃分為多個(gè)界限上下文窄做,比如一個(gè)經(jīng)銷商電商系統(tǒng)可以劃分為產(chǎn)品、經(jīng)銷商椭盏、訂單等幾個(gè)界限上下文组砚,每個(gè)界限上下文有自己的領(lǐng)域邏輯庸汗、數(shù)據(jù)持久化、用例蚯舱、接口等改化。每個(gè)界限上下文根據(jù)特點(diǎn)枉昏,具體實(shí)現(xiàn)方式又不同,比如有些界限上下文基本沒有業(yè)務(wù)邏輯兄裂,就是增刪改查,則可以使用 CRUD 最簡單的模式晰奖;有些界限上線文有一定的業(yè)務(wù)邏輯谈撒,但對(duì)高并發(fā)匾南、高性能沒要求,則可以使用經(jīng)典 DDD 模式蛆楞;有些界限上下文有一定的業(yè)務(wù)邏輯溯乒,而且有高性能要求豹爹,則可以使 CQRS 模式裆悄。 劃分界限上下文并且在每個(gè)上下文實(shí)現(xiàn)自己的業(yè)務(wù)邏輯、持久化臂聋、用例和接口作用是巨大大光稼,一是可以讓不同開發(fā)小組專注與此界限上下文的開發(fā),二是可以分別部署孩等,三是如果一個(gè)界限上下文出現(xiàn)問題艾君,并不影響其他界限上下文功能的使用。
  2. 實(shí)體:有業(yè)務(wù)生命周期的對(duì)象瞎访,采用業(yè)務(wù)標(biāo)識(shí)符進(jìn)行跟蹤腻贰。比如一個(gè)訂單就是實(shí)體吁恍,訂單有生命周期的扒秸,而且有一個(gè)訂單號(hào)唯一的標(biāo)識(shí)它自己播演,如果兩個(gè)訂單所有屬性值全部相同,但訂單號(hào)不同伴奥,也是不同的實(shí)體写烤。
  3. 值對(duì)象:無業(yè)務(wù)生命周期,無業(yè)務(wù)標(biāo)識(shí)符拾徙,通常用于描述實(shí)體洲炊。比如訂單的收貨地址、訂單支付的金額等就是值對(duì)象尼啡。值對(duì)象在數(shù)據(jù)庫中表的表現(xiàn)形式可以是兩種暂衡,一種是作為一個(gè)列或多個(gè)列與所屬的實(shí)體對(duì)象所對(duì)應(yīng)的表放在一起,另一種是單獨(dú)一個(gè)表崖瞭,通過ID與所屬的實(shí)體對(duì)象關(guān)聯(lián)狂巢。
  4. 領(lǐng)域服務(wù):無狀態(tài),有行為书聚,通常就是一個(gè)用例來協(xié)調(diào)多個(gè)領(lǐng)域邏輯完成功能唧领。
  5. 聚合:通常將多個(gè)實(shí)體和值對(duì)象組合到一個(gè)聚合中來表達(dá)一個(gè)完整的概念,比如訂單實(shí)體雌续、訂單明細(xì)實(shí)體斩个、訂單金額值對(duì)象就代表一個(gè)完整的訂單概念,而且生命周期是相同的驯杜,并且需要統(tǒng)一持久化到數(shù)據(jù)庫中受啥。
  6. 聚合根:將聚合中表達(dá)總概念的實(shí)體做成聚合根,比如訂單實(shí)體就是聚合根艇肴,對(duì)聚合中所有實(shí)體的狀態(tài)變更必須經(jīng)過聚合根腔呜,因?yàn)榫酆细鶇f(xié)調(diào)了整個(gè)聚合的邏輯,保證一致性再悼。當(dāng)然其他實(shí)體可以被外部直接臨時(shí)查詢調(diào)用核畴。
  7. 服務(wù):協(xié)調(diào)聚合之間的業(yè)務(wù)邏輯,并且完成用例谤草。
  8. 倉儲(chǔ):用于對(duì)聚合進(jìn)行持久化莺奸,通常為每個(gè)聚合根配備一個(gè)倉儲(chǔ)即可丑孩。倉儲(chǔ)能夠很好的解耦領(lǐng)域邏輯與數(shù)據(jù)庫温学。

DDD 經(jīng)典分層架構(gòu)

只有了解了經(jīng)典 DDD 的架構(gòu),你才能知道具體在哪層要實(shí)現(xiàn)哪些功能仗岖,編寫哪些代碼逃延,具體在開發(fā)支撐 DDD 的輕量級(jí)框架與具體模塊代碼實(shí)現(xiàn)時(shí)揽祥,才能做到有的放矢。

傳統(tǒng)三層架構(gòu)以及問題:
傳統(tǒng)三層架構(gòu)

問題:

  1. 過分注重?cái)?shù)據(jù)訪問層拄丰,而不重視領(lǐng)域俐末。
  2. 業(yè)務(wù)邏輯直接與數(shù)據(jù)訪問層耦合,與領(lǐng)域?yàn)楹诵牡?DDD 思想背道而馳卓箫。
  3. 沒有一系列的模式與方法論指導(dǎo)這種分層架構(gòu)的開發(fā)約束。

經(jīng)典 DDD 架構(gòu):
經(jīng)典DDD架構(gòu)
還有 70% 的精彩內(nèi)容
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
支付 ¥9.99 繼續(xù)閱讀
  • 序言:七十年代末恢准,一起剝皮案震驚了整個(gè)濱河市甫题,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌坠非,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件炎码,死亡現(xiàn)場離奇詭異,居然都是意外死亡潦闲,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門辖众,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人凹炸,你說我怎么就攤上這事∑∷” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵变骡,是天一觀的道長。 經(jīng)常有香客問我锣光,道長铝耻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任频丘,我火速辦了婚禮,結(jié)果婚禮上搂漠,老公的妹妹穿的比我還像新娘。我一直安慰自己某弦,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布怔毛。 她就那樣靜靜地躺著,像睡著了一般拣度。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上螃壤,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音冤馏,去河邊找鬼。 笑死宿接,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的睦霎。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼副女,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了碑幅?” 一聲冷哼從身側(cè)響起戴陡,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤沟涨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后裹赴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡延都,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了晰房。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡殊者,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出幽污,到底是詐尸還是另有隱情,我是刑警寧澤簿姨,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站扁位,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏域仇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一暇务、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧垦细,春花似錦择镇、人聲如沸腻豌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽虱疏。三九已至,卻和暖如春做瞪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背右冻。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留国旷,地道東北人茫死。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像屡久,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子爱榔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容