自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

聚合和聚合根:怎樣設(shè)計(jì)聚合?你知道嗎?

開發(fā) 前端
聚合間的引用依靠關(guān)聯(lián)外部聚合根 ID 來實(shí)現(xiàn),而非直接的對象引用。若把外部聚合的對象納入本聚合邊界內(nèi)管理,不僅會(huì)模糊聚合邊界,還會(huì)提升聚合間的耦合程度,所以要通過唯一標(biāo)識(shí)引用其它聚合。

聚合

在 DDD 中,實(shí)體和值對象是很基礎(chǔ)的領(lǐng)域?qū)ο?。?shí)體一般對應(yīng)業(yè)務(wù)對象,它具有業(yè)務(wù)屬性和業(yè)務(wù)行為;而值對象主要是屬性集合,對實(shí)體的狀態(tài)和特征進(jìn)行描述。但實(shí)體和值對象都只是個(gè)體化的對象,它們的行為表現(xiàn)出來的是個(gè)體的能力。

那聚合在其中起什么作用呢?

社會(huì)由個(gè)體組成,我們每個(gè)人都是其中一員。隨著社會(huì)發(fā)展,社團(tuán)、機(jī)構(gòu)、部門等組織應(yīng)運(yùn)而生,我們從個(gè)體逐漸成為組織的一部分。在組織中,大家協(xié)同工作,朝著共同目標(biāo)奮進(jìn),能發(fā)揮出更大的力量。

在領(lǐng)域模型里,實(shí)體和值對象類似于個(gè)體,而聚合則如同讓實(shí)體和值對象協(xié)同工作的組織。聚合確保這些領(lǐng)域?qū)ο笤趯?shí)現(xiàn)共同業(yè)務(wù)邏輯時(shí),數(shù)據(jù)保持一致。簡單來說,聚合由業(yè)務(wù)和邏輯緊密關(guān)聯(lián)的實(shí)體和值對象組合而成,是數(shù)據(jù)修改和持久化的基本單元。每個(gè)聚合對應(yīng)一個(gè)倉儲(chǔ),用于實(shí)現(xiàn)數(shù)據(jù)持久化。

聚合有聚合根和上下文邊界。這個(gè)邊界依據(jù)業(yè)務(wù)單一職責(zé)和高內(nèi)聚原則,界定了聚合內(nèi)部包含的實(shí)體和值對象。而且,聚合之間的邊界是松耦合的。按此方式設(shè)計(jì)的微服務(wù),自然具備“高內(nèi)聚、低耦合”的特性。

在DDD分層架構(gòu)中,聚合屬于領(lǐng)域?qū)?。領(lǐng)域?qū)影鄠€(gè)聚合,共同實(shí)現(xiàn)核心業(yè)務(wù)邏輯。聚合內(nèi)的實(shí)體采用充血模型,實(shí)現(xiàn)個(gè)體業(yè)務(wù)能力以及業(yè)務(wù)邏輯的高內(nèi)聚。

跨多個(gè)實(shí)體的業(yè)務(wù)邏輯通過領(lǐng)域服務(wù)實(shí)現(xiàn),跨多個(gè)聚合的業(yè)務(wù)邏輯則通過應(yīng)用服務(wù)實(shí)現(xiàn)。例如,若某個(gè)業(yè)務(wù)場景需要同一個(gè)聚合中的A和B兩個(gè)實(shí)體共同完成,那么這段業(yè)務(wù)邏輯可用領(lǐng)域服務(wù)實(shí)現(xiàn);若業(yè)務(wù)邏輯需要聚合C和聚合D中的兩個(gè)服務(wù)共同完成,這時(shí)就可以用應(yīng)用服務(wù)來組合這兩個(gè)服務(wù)。

聚合根

聚合根的主要作用,是防止復(fù)雜數(shù)據(jù)模型因?yàn)槿狈y(tǒng)一業(yè)務(wù)規(guī)則的管控,而出現(xiàn)聚合、實(shí)體之間數(shù)據(jù)不一致的情況。在傳統(tǒng)數(shù)據(jù)模型里,每個(gè)實(shí)體地位平等,若任由實(shí)體隨意調(diào)用和修改數(shù)據(jù),極有可能造成實(shí)體間數(shù)據(jù)邏輯的混亂。要是采用鎖的方式來解決,又會(huì)增加軟件復(fù)雜度,降低系統(tǒng)性能。

如果把聚合看作一個(gè)組織,那么聚合根就相當(dāng)于這個(gè)組織的負(fù)責(zé)人,也被稱為根實(shí)體。它既是實(shí)體,又承擔(dān)著聚合管理者的角色。

從實(shí)體角度來看,聚合根具備實(shí)體的屬性和業(yè)務(wù)行為,能夠?qū)崿F(xiàn)自身的業(yè)務(wù)邏輯。

作為聚合的管理者,聚合根在聚合內(nèi)部發(fā)揮著協(xié)調(diào)作用,確保實(shí)體和值對象依照既定的業(yè)務(wù)規(guī)則,協(xié)同完成共同的業(yè)務(wù)邏輯。

在聚合之間,聚合根是聚合對外的接口。它通過聚合根 ID 關(guān)聯(lián)的方式,接收外部任務(wù)和請求,并在上下文范圍內(nèi)實(shí)現(xiàn)聚合之間的業(yè)務(wù)協(xié)作。也就是說,聚合之間是通過聚合根 ID 進(jìn)行關(guān)聯(lián)引用的。外部對象若要訪問其他聚合的實(shí)體,不能直接進(jìn)行訪問,而是要先訪問聚合根,再通過聚合根導(dǎo)航到聚合內(nèi)部的實(shí)體。

怎樣設(shè)計(jì)聚合?

DDD 領(lǐng)域建模通常采用事件風(fēng)暴,它通常采用用例分析、場景分析和用戶旅程分析等方法,通過頭腦風(fēng)暴列出所有可能的業(yè)務(wù)行為和事件,然后找出產(chǎn)生這些行為的領(lǐng)域?qū)ο?,并梳理領(lǐng)域?qū)ο笾g的關(guān)系,找出聚合根,找出與聚合根業(yè)務(wù)緊密關(guān)聯(lián)的實(shí)體和值對象,再將聚合根、實(shí)體和值對象組合,構(gòu)建聚合。

下面我們以保險(xiǎn)的投保業(yè)務(wù)場景為例,看一下聚合的構(gòu)建過程主要都包括哪些步驟。

圖片圖片

在投保過程中構(gòu)建聚合,可按以下步驟進(jìn)行:

第一步:采用事件風(fēng)暴梳理實(shí)體和值對象

基于業(yè)務(wù)行為,運(yùn)用事件風(fēng)暴方法,全面梳理在投保過程中涉及這些行為的所有實(shí)體和值對象。例如,常見的有投保單、標(biāo)的、客戶、被保人等。

第二步:確定聚合根

從眾多實(shí)體中挑選出適合擔(dān)任對象管理者的根實(shí)體,即聚合根。判斷一個(gè)實(shí)體能否成為聚合根,可結(jié)合以下場景展開分析:該實(shí)體是否擁有獨(dú)立的生命周期;是否具備全局唯一 ID;是否能夠創(chuàng)建或修改其他對象;是否存在專門的模塊對其進(jìn)行管理。在相關(guān)圖示中,投保單和客戶實(shí)體就是聚合根。

第三步:構(gòu)建聚合

依據(jù)業(yè)務(wù)單一職責(zé)和高內(nèi)聚原則,找出與聚合根緊密關(guān)聯(lián)、相互依賴的所有實(shí)體和值對象。由此構(gòu)建出一個(gè)對象集合,這個(gè)集合包含唯一的聚合根以及多個(gè)實(shí)體和值對象,這便是聚合。在圖中,我們構(gòu)建出了客戶和投保這兩個(gè)聚合。

第四步:繪制對象引用和依賴模型

在聚合內(nèi)部,根據(jù)聚合根、實(shí)體和值對象之間的依賴關(guān)系,繪制出對象的引用和依賴模型。需要特別說明的是,投保人和被保人的數(shù)據(jù),是通過關(guān)聯(lián)客戶 ID 從客戶聚合中獲取的,在投保聚合里,它們屬于投保單的值對象。這些值對象的數(shù)據(jù)是客戶數(shù)據(jù)的冗余,即便未來客戶聚合的數(shù)據(jù)有所變動(dòng),也不會(huì)對投保單的值對象數(shù)據(jù)產(chǎn)生影響。從圖中還能清晰看到實(shí)體之間的引用關(guān)系,比如在投保聚合中,投保單聚合根引用了報(bào)價(jià)單實(shí)體,而報(bào)價(jià)單實(shí)體又引用了報(bào)價(jià)規(guī)則子實(shí)體。

第五步:劃分限界上下文

將多個(gè)聚合依據(jù)業(yè)務(wù)語義和上下文,劃分到同一個(gè)限界上下文內(nèi)。

聚合的一些設(shè)計(jì)原則

我們不妨先看一下《實(shí)現(xiàn)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》一書中對聚合設(shè)計(jì)原則的描述,原文是有點(diǎn)不太好理解的,我來給你解釋一下。

在一致性邊界內(nèi)建模真正的不變條件是 DDD 設(shè)計(jì)中的重要原則。聚合的意義在于封裝真正的不變性,并非簡單拼湊對象。每個(gè)聚合內(nèi)部都有一套既定的業(yè)務(wù)規(guī)則,其中的實(shí)體和值對象遵循這些規(guī)則運(yùn)轉(zhuǎn),以此保證對象數(shù)據(jù)的一致性。而在聚合邊界之外的事物,與該聚合毫無關(guān)聯(lián),這也正是聚合能夠達(dá)成業(yè)務(wù)高內(nèi)聚的關(guān)鍵因素。

設(shè)計(jì)小聚合也十分關(guān)鍵。聚合規(guī)模若設(shè)計(jì)得過大,會(huì)因涵蓋過多實(shí)體,使實(shí)體間管理難度大增。在高頻操作場景下,易引發(fā)并發(fā)沖突或數(shù)據(jù)庫鎖問題,最終降低系統(tǒng)可用性。與之相對,小聚合設(shè)計(jì)能減少因業(yè)務(wù)擴(kuò)張導(dǎo)致聚合重構(gòu)的幾率,讓領(lǐng)域模型對業(yè)務(wù)變化的適應(yīng)性更強(qiáng)。

聚合間的引用依靠關(guān)聯(lián)外部聚合根 ID 來實(shí)現(xiàn),而非直接的對象引用。若把外部聚合的對象納入本聚合邊界內(nèi)管理,不僅會(huì)模糊聚合邊界,還會(huì)提升聚合間的耦合程度,所以要通過唯一標(biāo)識(shí)引用其它聚合。

聚合內(nèi)部數(shù)據(jù)需保持強(qiáng)一致性,而聚合之間實(shí)現(xiàn)最終一致性即可。一次事務(wù)中,最多只能改變一個(gè)聚合的狀態(tài)。要是業(yè)務(wù)操作涉及多個(gè)聚合狀態(tài)變更,應(yīng)借助領(lǐng)域事件異步修改相關(guān)聚合,從而實(shí)現(xiàn)聚合間的解耦(領(lǐng)域事件相關(guān)內(nèi)容會(huì)在后續(xù)詳細(xì)講解),這就是在邊界之外使用最終一致性的原則。

為實(shí)現(xiàn)微服務(wù)內(nèi)聚合間的解耦,以及滿足未來以聚合為單位的微服務(wù)組合與拆分需求,應(yīng)規(guī)避跨聚合的領(lǐng)域服務(wù)調(diào)用和數(shù)據(jù)庫表關(guān)聯(lián),也就是要通過應(yīng)用層實(shí)現(xiàn)跨聚合的服務(wù)調(diào)用 。

不過,要牢記 “適合自己的才是最好的”。在系統(tǒng)設(shè)計(jì)時(shí),必須充分考量項(xiàng)目的實(shí)際情況。面對使用便利性、高性能需求、技術(shù)能力短板以及全局事務(wù)管理等因素時(shí),這些原則并非不可變通,一切都應(yīng)以解決實(shí)際問題為根本出發(fā)點(diǎn)。

責(zé)任編輯:武曉燕 來源: 二進(jìn)制跳動(dòng)
相關(guān)推薦

2022-12-12 09:13:45

global聚合filters

2010-10-11 16:19:30

Mysql聚合函數(shù)

2024-02-28 09:07:58

鏈路聚合模式

2022-03-04 08:00:00

Java Strea數(shù)據(jù)函數(shù)

2018-05-21 08:07:35

聚合MongoDBSchema

2022-12-28 08:16:16

metric聚合java

2010-10-25 17:08:34

oracle聚合函數(shù)

2023-10-06 23:14:07

VLAN網(wǎng)絡(luò)性能

2011-12-26 15:19:20

聚合

2024-01-01 08:25:53

ViewSurface框架

2024-11-26 14:29:48

2012-08-06 15:59:17

MongoDB

2021-11-18 13:14:08

DDD聚合代碼

2018-09-27 11:25:07

開源日志聚合

2010-09-10 14:05:12

SQL聚合函數(shù)

2025-02-10 02:00:00

2023-09-12 07:11:33

Prometheus聚合告警GPT

2024-04-07 00:00:00

ESlint命令變量

2024-05-28 09:12:10

2023-12-12 08:41:01

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)