DDD戰(zhàn)術(shù)設(shè)計(jì)-聚合

摘自
https://www.zhihu.com/column/p/381540329

設(shè)計(jì)業(yè)務(wù)實(shí)例

辦公用品采購(gòu)系統(tǒng)。

  1. 企業(yè)的員工可以通過該系統(tǒng)提交一個(gè)采購(gòu)請(qǐng)求剖张,一個(gè)請(qǐng)求包含了若干數(shù)量侧甫、若干類型的辦公用品(稱為采購(gòu)項(xiàng))迫像。
  2. 主管負(fù)責(zé)對(duì)采購(gòu)申請(qǐng)進(jìn)行審批。
  3. 審批通過后潭袱,系統(tǒng)會(huì)根據(jù)提供商不同,生成若干訂單谒养。

如果

  1. 采用以數(shù)據(jù)庫(kù)為中心的建模方式
    第一股淡,對(duì)于模型的討論過早地進(jìn)入了實(shí)現(xiàn)領(lǐng)域身隐,和業(yè)務(wù)概念脫開了聯(lián)系,不便于持續(xù)地和業(yè)務(wù)人員協(xié)作唯灵;
    第二贾铝,技術(shù)細(xì)節(jié)和業(yè)務(wù)規(guī)則的細(xì)節(jié)糾纏在一起,很容易顧此失彼

  2. 面向?qū)ο?br> 業(yè)務(wù)規(guī)則如何保證埠帕,在傳統(tǒng)的面向?qū)ο蠓椒ㄖ胁]有嚴(yán)格的實(shí)現(xiàn)約束

針對(duì)類似“修改采購(gòu)項(xiàng)也是修改采購(gòu)請(qǐng)求”的需求忌傻,DDD的做法

image.png

采購(gòu)請(qǐng)求采購(gòu)項(xiàng)組織到一起,看做一個(gè)更大的整體搞监,稱為“聚合”。
這個(gè)聚合內(nèi)部的業(yè)務(wù)邏輯[例如“采購(gòu)申請(qǐng)審核通過后镰矿,不得對(duì)采購(gòu)申請(qǐng)條目進(jìn)行更改”]應(yīng)內(nèi)建于聚合內(nèi)部琐驴。
為了實(shí)現(xiàn)這一目標(biāo),我們約定:對(duì)采購(gòu)項(xiàng)(實(shí)體)的一切操作(增加秤标、刪除绝淡、修改等),都是對(duì)采購(gòu)請(qǐng)求(聚合根)的操作苍姜。

聚合定義

將實(shí)體和值對(duì)象劃分為聚合并圍繞著聚合定義邊界牢酵。選擇一個(gè)實(shí)體作為每個(gè)聚合的根,并僅允許外部對(duì)象持有對(duì)聚合根的引用衙猪。作為一個(gè)整體來定義聚合的屬性和不變量馍乙,并把其執(zhí)行責(zé)任賦予聚合根或指定的框架機(jī)制。
https://www.domainlanguage.com/wp-content/uploads/2016/05/DDD_Reference_2015-03.pdf

聚合本質(zhì)

  • 建立一個(gè)比對(duì)象粒度更大的邊界
  • 聚集緊密關(guān)聯(lián)的對(duì)象 ---> 形成了一個(gè)業(yè)務(wù)上的對(duì)象整體垫释。
  • 使用聚合根作為對(duì)外的交互入口 --> 保證多個(gè)互相關(guān)聯(lián)的對(duì)象的一致性丝格。

合理使用聚合,可以更容易地保證業(yè)務(wù)規(guī)則的一致性棵譬,減少了對(duì)象之間可能的耦合显蝌,提升設(shè)計(jì)的可理解性,降低出問題的可能性订咸。


聚合劃分的幾個(gè)啟發(fā)式規(guī)則

  • 生命周期一致性
  • 問題域一致性
  • 場(chǎng)景頻率一致性
  • 盡量小的聚合

生命周期一致性

如果聚合根消失曼尊,聚合內(nèi)的其他元素都應(yīng)該同時(shí)消失。


如果采購(gòu)請(qǐng)求(聚合根)不存在了脏嚷,那么采購(gòu)項(xiàng)當(dāng)然也就失去了存在的意義骆撇。而商品、作為申請(qǐng)人的用戶等對(duì)象父叙,和采購(gòu)請(qǐng)求之間則不存在此關(guān)系艾船。

商品葵腹、作為申請(qǐng)人的用戶等對(duì)象不納入采購(gòu)請(qǐng)求

問題域一致性

聚合表示的模型一定會(huì)位于同一個(gè)限界上下文之內(nèi)


一個(gè)在線論壇,用戶可以對(duì)論壇上用戶的文章發(fā)表評(píng)論屿岂。文章顯然應(yīng)該是一個(gè)聚合根践宴。如果文章被刪除,那么爷怀,用戶的評(píng)論看起來也要同時(shí)消失阻肩。那么評(píng)論是否可以屬于文章這個(gè)聚合?
一個(gè)圖書網(wǎng)站运授,用戶可以對(duì)圖書發(fā)表評(píng)論烤惊,那么評(píng)論是否可以屬于圖書這個(gè)聚合?

評(píng)論這一個(gè)概念吁朦,在本質(zhì)上和文章/圖書這個(gè)概念相去甚遠(yuǎn)柒室,因此不屬于同一個(gè)問題域的對(duì)象
則不應(yīng)該出現(xiàn)在同一個(gè)聚合中

image.png

需要依賴”最終一致性“來實(shí)現(xiàn)聚合之間的一致性。例如逗宜,在文章刪除的時(shí)候雄右,發(fā)送一個(gè)文章刪除的消息。評(píng)論系統(tǒng)接收到文章刪除消息之后纺讲,刪除文章對(duì)應(yīng)的評(píng)論擂仍。

場(chǎng)景頻率一致性

場(chǎng)景(scenario)

  • 是業(yè)務(wù)用例的具體化描述
  • 反映了用戶使用系統(tǒng)達(dá)成業(yè)務(wù)目標(biāo)的方式。

經(jīng)常被同時(shí)操作的對(duì)象熬甚,它們往往屬于同一個(gè)聚合逢渔。而那些極少被同時(shí)關(guān)注的對(duì)象,一般不應(yīng)該劃為一個(gè)聚合乡括。


考慮軟件開發(fā)中的產(chǎn)品版本以及功能的關(guān)系肃廓。產(chǎn)品版本算不算是同一個(gè)問題域?

更合理的聚合

操作場(chǎng)景不一致的對(duì)象诲泌,或者說如果一個(gè)對(duì)象在不同場(chǎng)景下都會(huì)被使用亿昏,應(yīng)該考慮把它們分到不同的聚合中。

盡量小的聚合

凡是不破壞以上三個(gè)一致性的情況档礁,都沒有必要把它們放到同一個(gè)聚合中

聚合之間如何關(guān)聯(lián)?

采購(gòu)申請(qǐng)及其屬性(如狀態(tài)角钩、提交時(shí)間等)以及采購(gòu)項(xiàng)屬于一個(gè)聚合。但是呻澜,商品递礼、用戶(提交人,審批人...)這些不能屬于采購(gòu)申請(qǐng)這個(gè)聚合羹幸。聚合之間如何關(guān)聯(lián)?

引入ID對(duì)象來解決這個(gè)問題


image.png

引入ID對(duì)象帶來的問題

  1. 某些場(chǎng)景下需要對(duì)信息進(jìn)行第二次查詢脊髓,而且無法利用 ORM 的 EagerFetch/LazyFetch 加載機(jī)制的遍歷
    這不是損失,這類問題應(yīng)該由外部服務(wù)栅受,例如應(yīng)用層服務(wù)來完成将硝。
    好處恭朗,斷開聚合,加快查詢速度
  2. 為了斷開聚合而額外引入的 Id 值對(duì)象依疼,還能算是領(lǐng)域模型或者是 “統(tǒng)一語言” 的一部分嗎痰腮?
    這是 DDD 的實(shí)現(xiàn)機(jī)制的一部分,它屬于領(lǐng)域模型律罢,但是請(qǐng)把其可見性控制在開發(fā)團(tuán)隊(duì)膀值。沒有必要和業(yè)務(wù)人員溝通這些概念
  3. 注意
    這個(gè) Id 對(duì)象引用的只能是其他聚合根的 Id
    聚合根的 ID 應(yīng)該做到全局唯一
    聚合內(nèi)部的實(shí)體對(duì)象/值對(duì)象,保證內(nèi)部的 ID 唯一即可误辑。

代碼實(shí)現(xiàn)方面的考慮

資源庫(kù)(Repository)沧踏、工廠(Factory)面向聚合定義

  • 使用工廠來構(gòu)造聚合對(duì)象是一種更好的對(duì)復(fù)雜性的封裝
    在聚合以外,只應(yīng)該有一個(gè)工廠對(duì)外可見巾钉,那就是聚合的工廠
  • 資源庫(kù)是聚合的倉(cāng)儲(chǔ)機(jī)制
    一個(gè)聚合只能有一個(gè)資源庫(kù)對(duì)象翘狱,那就是以聚合根命名的資源庫(kù)。除此之外的其他對(duì)象砰苍,都不應(yīng)該提供資源庫(kù)對(duì)象潦匈。

代碼結(jié)構(gòu)與聚合保持一致

限界上下文,模塊
└━聚合
???????└━實(shí)體(包含聚合根)對(duì)象师骗、值對(duì)象、資源庫(kù)讨惩、工廠

聚合不可跨越部署的邊界

  1. 如果系統(tǒng)采用了微服務(wù)架構(gòu)辟癌,應(yīng)該保持部署邊界和限界上下文邊界的一致
    不要讓部署的粒度大于限界上下文的粒度,這樣可以帶來更好的業(yè)務(wù)靈活性和可伸縮性
  2. 從服務(wù)的最小邊界上荐捻,不可讓最小邊界小于聚合的粒度黍少,否則會(huì)帶來大量的數(shù)據(jù)的一致性問題
    因?yàn)槲⒎?wù)之間的一致性一般需要通過最終一致性來保證,如果聚合跨越了部署邊界將會(huì)是一致性的災(zāi)難

聚合改進(jìn)了系統(tǒng)性能和可伸縮性

使用小的聚合
每個(gè)涉及訪問的對(duì)象(事實(shí)上就是聚合)不可能很大处面,而所需的數(shù)據(jù)又恰如其分的都在厂置,數(shù)據(jù)完整性和業(yè)務(wù)完整性就有了保障,還可以方便地進(jìn)行水平擴(kuò)展魂角,性能和可伸縮性也就同時(shí)得到了滿足昵济。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市野揪,隨后出現(xiàn)的幾起案子访忿,更是在濱河造成了極大的恐慌,老刑警劉巖斯稳,帶你破解...
    沈念sama閱讀 222,464評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件海铆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡挣惰,警方通過查閱死者的電腦和手機(jī)卧斟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,033評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門殴边,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人珍语,你說我怎么就攤上這事锤岸。” “怎么了廊酣?”我有些...
    開封第一講書人閱讀 169,078評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵能耻,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我亡驰,道長(zhǎng)晓猛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,979評(píng)論 1 299
  • 正文 為了忘掉前任凡辱,我火速辦了婚禮戒职,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘透乾。我一直安慰自己洪燥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,001評(píng)論 6 398
  • 文/花漫 我一把揭開白布乳乌。 她就那樣靜靜地躺著捧韵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪汉操。 梳的紋絲不亂的頭發(fā)上再来,一...
    開封第一講書人閱讀 52,584評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音磷瘤,去河邊找鬼芒篷。 笑死,一個(gè)胖子當(dāng)著我的面吹牛采缚,可吹牛的內(nèi)容都是我干的针炉。 我是一名探鬼主播,決...
    沈念sama閱讀 41,085評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼扳抽,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼篡帕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起贸呢,我...
    開封第一講書人閱讀 40,023評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤赂苗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后贮尉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拌滋,經(jīng)...
    沈念sama閱讀 46,555評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,626評(píng)論 3 342
  • 正文 我和宋清朗相戀三年猜谚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了败砂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赌渣。...
    茶點(diǎn)故事閱讀 40,769評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖昌犹,靈堂內(nèi)的尸體忽然破棺而出坚芜,到底是詐尸還是另有隱情,我是刑警寧澤斜姥,帶...
    沈念sama閱讀 36,439評(píng)論 5 351
  • 正文 年R本政府宣布鸿竖,位于F島的核電站,受9級(jí)特大地震影響铸敏,放射性物質(zhì)發(fā)生泄漏缚忧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,115評(píng)論 3 335
  • 文/蒙蒙 一杈笔、第九天 我趴在偏房一處隱蔽的房頂上張望闪水。 院中可真熱鬧,春花似錦蒙具、人聲如沸球榆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,601評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽持钉。三九已至,卻和暖如春篱昔,著一層夾襖步出監(jiān)牢的瞬間每强,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,702評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工旱爆, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留舀射,地道東北人窘茁。 一個(gè)月前我還...
    沈念sama閱讀 49,191評(píng)論 3 378
  • 正文 我出身青樓怀伦,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親山林。 傳聞我的和親對(duì)象是個(gè)殘疾皇子房待,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,781評(píng)論 2 361

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