【210730】基于領(lǐng)域驅(qū)動設(shè)計理論(DDD)設(shè)計

DDD的意義

  1. 關(guān)注精簡的業(yè)務(wù)模型及實現(xiàn)的匹配浮入,模型是對現(xiàn)實的有選著性的抽象和精簡抓于。

  2. 通過模型噩凹、通用語言,來跟領(lǐng)域?qū)<遥I(yè)務(wù)人員)毡咏、開發(fā)人員等進(jìn)行信息溝通驮宴。

  3. 通過將一個復(fù)雜的系統(tǒng)抽象建模和拆分成一個個子系統(tǒng)(模塊、子域)呕缭,以達(dá)到減少系統(tǒng)復(fù)雜度的目的堵泽,一個簡單的系統(tǒng)、或者一個初創(chuàng)的系統(tǒng)暫時沒必要恢总,也沒有意義使用DDD進(jìn)行設(shè)計及構(gòu)建迎罗,同時考慮人員因素。

  4. 軟件是將現(xiàn)實世界中的事務(wù)映射為計算機(jī)可執(zhí)行的代碼片仿,以期待提高我們的生產(chǎn)效率纹安,DDD告訴我們?nèi)绾屋^好的完成這樣的轉(zhuǎn)化,以實現(xiàn)較好的高內(nèi)聚低耦合的原則。

名詞解釋

1. 領(lǐng)域

即業(yè)務(wù)厢岂、是相關(guān)業(yè)務(wù)所涉及到的業(yè)務(wù)知識光督,如飛行系統(tǒng)、廣告行業(yè)塔粒,消費(fèi)金融行業(yè)结借、打車行業(yè)等。

2. 模型

將現(xiàn)實事物進(jìn)行抽象卒茬,保留所涉及系統(tǒng)業(yè)務(wù)關(guān)注的屬性船老、行為,去除多余的屬性和行為后的結(jié)果圃酵,比如金融行業(yè)中的用戶柳畔,我們關(guān)注用戶年齡、身份證信息等郭赐,不關(guān)注用戶有多高荸镊,多重。

3. 通用語言(UL)

在由軟件架構(gòu)師堪置、開發(fā)人員、領(lǐng)域?qū)<医M成的設(shè)計團(tuán)隊张惹,需要有一種語言來統(tǒng)一它們的行為舀锨。以幫助它們創(chuàng)建一個模型,并使用代碼來表達(dá)模型宛逗。有點類似java的中間字節(jié)碼坎匿,串聯(lián)起開發(fā)文本代碼與可執(zhí)行二進(jìn)制文件。

 (a). 以業(yè)務(wù)(領(lǐng)域)名詞為基準(zhǔn)雷激,開發(fā)使用相同概念替蔬。 

 (b). 對業(yè)務(wù)名詞添加限制和約束,定義子域和上下文(邊界)屎暇。

 (c). 隨著業(yè)務(wù)的發(fā)展承桥,創(chuàng)建名詞庫,便于后續(xù)同學(xué)理解根悼。

 (d). 通用語言凶异,可以以圖、表挤巡、UML剩彬、草圖等形式呈現(xiàn)出來。最重要的是讓業(yè)務(wù)人員(不懂技術(shù))矿卑、系統(tǒng)設(shè)計人員喉恋、開發(fā)人員(可能不懂業(yè)務(wù))對系統(tǒng)(模塊)劃分,上下文邊界達(dá)成共識。

4. 模型驅(qū)動設(shè)計

通常以面向?qū)ο蟮姆绞絹韺崿F(xiàn)轻黑。在領(lǐng)域抽象設(shè)計通用語言中糊肤,用于指導(dǎo)開發(fā)人員具體實現(xiàn)的思想。介紹如何來劃分子領(lǐng)域苔悦,讓子領(lǐng)域能夠落地實現(xiàn)轩褐。

模型驅(qū)動設(shè)計

image

1. 系統(tǒng)分層(Layered Architecture)

任何一個復(fù)雜系統(tǒng),都不可能不進(jìn)行分層設(shè)計。因為人的思維習(xí)慣一次性記住不了這么多東西病瞳,需要分層簡化處理整份。分層設(shè)計比較典型的場景應(yīng)該屬于TCP/IP的分層設(shè)計。

image

對到業(yè)務(wù)開發(fā)來說拗踢,通常我們的系統(tǒng)設(shè)計如下:

image

(a).用戶界面層:負(fù)責(zé)用戶側(cè)展示與交互,絕大部分場景下向臀,系統(tǒng)設(shè)計都是前后端分離巢墅,該模塊交由前端處理。

(b).應(yīng)用層:很薄的一層券膀,用來完成系統(tǒng)流程組合(聚合)君纫,不涉及具體領(lǐng)域內(nèi)容(邏輯)。通常是跟前端交互的最直接一層芹彬。

(c).領(lǐng)域?qū)?/strong>:用來完成具體領(lǐng)域(業(yè)務(wù))邏輯蓄髓、信息、對象處理舒帮,也是業(yè)務(wù)系統(tǒng)的核心所在会喝。在該層,重業(yè)務(wù)邏輯玩郊,輕存儲肢执。隨著業(yè)務(wù)的復(fù)雜度提升,該層也許進(jìn)一步進(jìn)行模塊化拆分译红。

(d).基礎(chǔ)設(shè)施層:作為基礎(chǔ)層预茄,輕業(yè)務(wù)邏輯,重存儲侦厚,完成模型的存儲(db/緩存)反璃、外部系統(tǒng)調(diào)用(rpc)等。

對到我以前做的金融系統(tǒng)分層如下:

image

網(wǎng)關(guān)層:對應(yīng)用戶界面層假夺,完成跟前端或rpc 消費(fèi)者交互淮蜈。

調(diào)度層:對應(yīng)應(yīng)用層,完成接口流程聚合已卷、處理MQ事件梧田、以及部分定時腳本觸發(fā)流程。

邏輯層:對應(yīng)具體業(yè)務(wù)邏輯處理。

數(shù)據(jù)層:完成數(shù)據(jù)的持久化裁眯、以及rpc訪問封裝鹉梨。

了解到廣告創(chuàng)編服務(wù)化相關(guān)系統(tǒng)分層如下:

image

2. 實體(Entities)

模型分實體或值對象。實體是整個系統(tǒng)設(shè)計中重要的對象穿稳,該對象通常具有唯一標(biāo)識符存皂,通常也是該領(lǐng)域設(shè)計總的重要模型。

比如銀行系統(tǒng)中客戶(具有客戶id逢艘,身份證號)旦袋、廣告系統(tǒng)中的廣告(具有廣告ID)、交易系統(tǒng)中的訂單(具有訂單號)等它改。

3. 值對象(Value Objects)

我們不可能將所有的對象都定義成實體(每個都分配唯一標(biāo)識符疤孕,成本過高),因此有些不是那么重要的央拖,也不需要關(guān)注狀態(tài)的對象祭阀,可以定義成值對象。

如一個坐標(biāo)定義Point(x1,x2)鲜戒、一個地址定義Address(國家专控、城市、街道)遏餐。

4. 服務(wù)(Service)

服務(wù)是模型設(shè)計對外暴露行為或調(diào)用的單元伦腐,服務(wù)不同于對象,通常包含一系列行為(操作)境输。它具備如下特點:

(a). 服務(wù)的操作包含領(lǐng)域概念,無法映射成一個對象颖系。

(b). 操作無狀態(tài)嗅剖。

5. 模塊(Module)

對于一個大型的復(fù)雜項目,模型(業(yè)務(wù))會越來越大嘁扼,每個人理解起來都會相對比較困難信粮,根據(jù)人的思維習(xí)慣,通常需要進(jìn)行系統(tǒng)拆分趁啸,分開理解降低系統(tǒng)復(fù)雜度强缘,拆分過程中,將具有公共屬性的對象不傅、行為組裝在一個模塊中旅掂。模塊名稱需要成為通用語言理解的一部分。

如金融支付系統(tǒng)中的模塊劃分:將大的模塊劃分為通道接入访娶、核心交由商虐、資金接入。

image

廣告創(chuàng)編服務(wù)化相關(guān)模塊劃分如下:

image

6. 聚合(Aggregates)

聚合,可以簡單理解為對象關(guān)聯(lián)秘车,將相關(guān)聯(lián)的對象聚合在一個實體(聚合根)下面典勇,外界對該組對象的訪問,都只能通過聚合根訪問叮趴。下圖例子比較形象:

image

消費(fèi)者對象(實體割笙、聚合根),關(guān)聯(lián)了聯(lián)系簿對象眯亦,和地址對象伤溉,外界訪問通過消費(fèi)者對象訪問。

7. 工廠(Factories)

工廠被用來封裝對象創(chuàng)建所必需的知識搔驼,創(chuàng)建對象可以由對象自己來封裝谈火,也可以由第三方來創(chuàng)建。

創(chuàng)建型模式:工廠方法模式舌涨、抽象工廠模式糯耍、單例模式建造者模式囊嘉、原型模式

8. 資源庫(Repositories)

資源庫温技,完成對象的持久化存儲、遠(yuǎn)程RPC調(diào)用封裝扭粱。

image

保持模型的一致性(各個模塊/領(lǐng)域如何保持協(xié)作)

我們現(xiàn)在已經(jīng)有了各個模塊舵鳞、子領(lǐng)域,如何確保不同子領(lǐng)域如何協(xié)作琢蛤。

image

1. 界定的上下文(Bounded Context)

當(dāng)我們確定一個模型的時候蜓堕,我們需要確定它的范圍,定出它的上下文的邊界博其,盡最大可能保持模型的統(tǒng)一套才。上下文的界定通常可以從如下幾個方面確定:

(a). 團(tuán)隊的組織結(jié)構(gòu)慕淡。

(b). 應(yīng)用的特定部分中的慣例背伴。

(c). 物理表現(xiàn)(例如代碼倉庫、數(shù)據(jù)庫峰髓、redis集群等)

2. 持續(xù)集成(Continuous Intergration)

持續(xù)集成指的是傻寂,頻繁地(一天多次)將代碼集成到主干。持續(xù)集成的目的携兵,就是讓產(chǎn)品可以快速迭代疾掰,同時還能保持高質(zhì)量。它的核心措施是徐紧,代碼集成到主干之前个绍,必須通過自動化測試勒葱。

(1)快速發(fā)現(xiàn)錯誤。每完成一點更新巴柿,就集成到主干凛虽,可以快速發(fā)現(xiàn)錯誤,定位錯誤也比較容易广恢。

(2)防止分支大幅偏離主干凯旋。如果不是經(jīng)常集成,主干又在不斷更新钉迷,會導(dǎo)致以后集成的難度變大至非,甚至難以集成。

3. 上下文映射(Context Map)

各個模塊如何進(jìn)行協(xié)調(diào)的手段糠聪。不同上下文之間的交互荒椭。

(1). 共享內(nèi)核(Shared Kernel)

image

有點類似于多線程操作共同變量,通過共享內(nèi)存進(jìn)行交互舰蟆。兩個不同領(lǐng)域模型(團(tuán)隊)趣惠,共享部分領(lǐng)域模型子集(模塊),任何對子集的操作都需要知會到其他共享的領(lǐng)域模型(團(tuán)隊)身害,集成的時候味悄,兩個團(tuán)隊都需要開發(fā)和測試介入。

曾經(jīng)跟另外一個業(yè)務(wù)團(tuán)隊共用了一個底層額度(功能)開發(fā)塌鸯,每次涉及公共模塊開發(fā)都需要知會另一個團(tuán)隊侍瑟,這樣做有些問題,溝通效率也不高丙猬,后來改成有一個團(tuán)隊維護(hù)公共模塊涨颜,另一個團(tuán)隊如果有述求,提需求給維護(hù)的團(tuán)隊處理茧球。涉及到下面的模式(客戶-供應(yīng)商)庭瑰。

(2). 客戶-供應(yīng)商(Customer Supplier Teams)

當(dāng)一個系統(tǒng)嚴(yán)重依賴于另一個子系統(tǒng),兩個系統(tǒng)的上下文是不同的袜腥,并且一個系統(tǒng)的處理結(jié)果被作為另外一個的輸入见擦。一個系統(tǒng)如果有述求钉汗,提需求給下游子系統(tǒng)羹令。

(3). 順從模式(Conformist)

上游上下文只能盲目依賴下游上下文。

通常损痰,可以通過MQ福侈、數(shù)據(jù)庫主從復(fù)制,做到隔離卢未。

(4). 開放主機(jī)服務(wù)(Open Host Service)

定義一種協(xié)議肪凛,讓其他上下文來訪問本上下文堰汉。

曾經(jīng),我們的各個業(yè)務(wù)系統(tǒng)(很多子領(lǐng)域)需要訪問中臺訂單系統(tǒng)(中臺服務(wù))伟墙,中臺不可能為每個業(yè)務(wù)系統(tǒng)單獨定制化訪問接口翘鸭,因此提煉出一套通用的標(biāo)準(zhǔn)訂單查詢接口(Published Language),定義好入?yún)⒚杜e值,出參枚舉值戳葵,訪問系統(tǒng)token等信息就乓。各個業(yè)務(wù)系統(tǒng)共用一套訪問接口,減少溝通拱烁、維護(hù)成本生蚁。

(5). 隔離通道(Separate Way)

當(dāng)多個系統(tǒng),沒有任何交集的模型(上下文)的時候戏自,這些系統(tǒng)可以獨立拆分獨立建模邦投,無需集成,各自玩各自的擅笔。

(6). 防腐層(Anticorruption Layer)

image

上游上下文(模型)依賴于下游上下文(模型)志衣,為避免下游上下文嵌入過深,導(dǎo)致下游有調(diào)整剂娄,上游調(diào)整比較大蠢涝,在中間,上游上下文引入適配層阅懦,隔離下游變化和二,訪問下游系統(tǒng)。

4. 提煉(找到重心)

即使在我們改進(jìn)和創(chuàng)建很多抽象之后耳胎,一個大的領(lǐng)域還是會有一個很大模型惯吕,我們需要進(jìn)行提煉和子域劃分,在子域中怕午,提煉出一個核心域(Core Domain)废登,若干個普通子域(Generic Subdomain)。

核心域需投入較多的精力進(jìn)行優(yōu)化和迭代郁惜。

對于普通域來說堡距,有如下幾種方式:

(1). 購買現(xiàn)成的解決方案

這個方法的好處是可以使用別人已經(jīng)完成的全套解決方案。隨之而來的是學(xué)習(xí)曲線的問題兆蕉,而且這樣的方案還會引入一些依賴羽戒。如果代碼有很多 bug,你只得等待別人來解決虎韵。

(2). 外包

將設(shè)計和實現(xiàn)交給另外一個團(tuán)隊易稠,有可能是其他公司的團(tuán)隊。這樣做可以使你專注于核心域包蓝,不再承受處理另一個領(lǐng)域的負(fù)擔(dān)驶社。不便的地方是集成外包的代碼企量。

(3). 已有模型

一個取巧的方案是使用一個已經(jīng)創(chuàng)建的模型。市面上已經(jīng)有一些關(guān)于分析模式的書亡电,可以用來作為我們子域的靈感來源届巩。

(4). 自己實現(xiàn)

這個方案的好處是能夠做到最好的集成,但這也意味著額外的付出份乒,包括維護(hù)的壓力等姆泻。

DDD來講述軟件設(shè)計的術(shù)與器,本質(zhì)是為了高內(nèi)聚低耦合冒嫡。

關(guān)于DDD的思考與疑問

  1. 領(lǐng)域驅(qū)動設(shè)計拇勃,是先有業(yè)務(wù)(領(lǐng)域),再有設(shè)計孝凌。針對未知的環(huán)境或領(lǐng)域方咆,是否還合適(比如創(chuàng)業(yè)團(tuán)隊)?

  2. 重構(gòu)蟀架,隨著業(yè)務(wù)的發(fā)展需要持續(xù)進(jìn)行瓣赂?

參考

領(lǐng)域驅(qū)動設(shè)計精簡版(全新修訂):https://www.infoq.cn/article/domain-driven-design-quickly-new

阿里技術(shù)專家詳解DDD系列 第二彈 - 應(yīng)用架構(gòu):https://mp.weixin.qq.com/s/MU1rqpQ1aA1p7OtXqVVwxQ

領(lǐng)域驅(qū)動設(shè)計在美團(tuán)點評業(yè)務(wù)系統(tǒng)的實踐:https://mp.weixin.qq.com/s/uZmrZ61jB2JERCqHNDqktQ

重讀領(lǐng)域驅(qū)動設(shè)計——如何說好一門通用語言:https://zhuanlan.zhihu.com/p/62959217

23種設(shè)計模式匯總整理:https://blog.csdn.net/jason0539/article/details/44956775

持續(xù)集成是什么?:http://www.ruanyifeng.com/blog/2015/09/continuous-integration.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末片拍,一起剝皮案震驚了整個濱河市煌集,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌捌省,老刑警劉巖苫纤,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異纲缓,居然都是意外死亡卷拘,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門祝高,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栗弟,“玉大人,你說我怎么就攤上這事工闺≌Ш眨” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵陆蟆,是天一觀的道長雷厂。 經(jīng)常有香客問我,道長遍搞,這世上最難降的妖魔是什么罗侯? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任器腋,我火速辦了婚禮溪猿,結(jié)果婚禮上钩杰,老公的妹妹穿的比我還像新娘。我一直安慰自己诊县,他們只是感情好讲弄,可當(dāng)我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著依痊,像睡著了一般避除。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上胸嘁,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天瓶摆,我揣著相機(jī)與錄音,去河邊找鬼性宏。 笑死群井,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的毫胜。 我是一名探鬼主播书斜,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼酵使!你這毒婦竟也來了荐吉?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤口渔,失蹤者是張志新(化名)和其女友劉穎样屠,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缺脉,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡瞧哟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了枪向。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片勤揩。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖秘蛔,靈堂內(nèi)的尸體忽然破棺而出陨亡,到底是詐尸還是另有隱情,我是刑警寧澤深员,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布负蠕,位于F島的核電站,受9級特大地震影響倦畅,放射性物質(zhì)發(fā)生泄漏遮糖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一叠赐、第九天 我趴在偏房一處隱蔽的房頂上張望欲账。 院中可真熱鬧屡江,春花似錦、人聲如沸赛不。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽踢故。三九已至文黎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間殿较,已是汗流浹背耸峭。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留淋纲,地道東北人抓艳。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像帚戳,于是被迫代替她去往敵國和親玷或。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,086評論 2 355