精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

戰(zhàn)略設(shè)計(jì)之上下文映射和系統(tǒng)分層架構(gòu)

開(kāi)發(fā) 架構(gòu)
在本節(jié)內(nèi)容中,除了搞定限界上下文的映射之外,我還將對(duì)系統(tǒng)分層架構(gòu)進(jìn)行設(shè)計(jì),并在最終給出項(xiàng)目組可直接用于開(kāi)發(fā)的代碼框架結(jié)構(gòu)。

在完成了限界上下文的識(shí)別(也就是系統(tǒng)“最粗粒度”的模塊劃分)后,我們需要對(duì)這些上下文之間的協(xié)作關(guān)系進(jìn)行分析——即“限界上下文關(guān)系映射”。也只有在完成上下文關(guān)系映射后,我們才能真正的判定自己所做出的“限界上下文識(shí)別”是否真的達(dá)到了自己想要的“低耦合、高內(nèi)聚”的目標(biāo)。因?yàn)椋ㄟ^(guò)“限界上下文映射”我們就能夠看到:

  • 這些上下文之間有哪些協(xié)作關(guān)系?
  • 這些關(guān)系是強(qiáng)關(guān)聯(lián)還是弱關(guān)聯(lián)?

關(guān)于“限界上下文識(shí)別”和“限界上下文關(guān)系映射”,我認(rèn)為這是 DDD 戰(zhàn)略設(shè)計(jì)中最重要的部分,甚至可以說(shuō):這兩個(gè)工作將決定了微服務(wù)切分是否有效的關(guān)鍵因素!

但是,肯定會(huì)有人說(shuō):限界上下文不用 DDD,我憑直覺(jué)就能識(shí)別出來(lái)。我的回答是:是的,你貌似可以!但更重要的是限界上下文的關(guān)系映射,這將決定做微服務(wù)拆分后、這些微服務(wù)之間是怎樣做到“高內(nèi)聚、低耦合”的。如果你不用 DDD 戰(zhàn)略設(shè)計(jì),我可以很負(fù)責(zé)任的告訴你:你將來(lái)的“微服務(wù)”之間的調(diào)用關(guān)系一定會(huì)變得無(wú)法控制!

在我實(shí)際工作中接觸的某大型國(guó)企 IT 系統(tǒng)中,所謂業(yè)務(wù)中臺(tái)上千萬(wàn)行代碼,部署在十多個(gè)微服務(wù)中心,而 80%以上的外圍接口調(diào)用、或前端界面服務(wù)請(qǐng)求,都要從十個(gè)以上的微服務(wù)中心全部走一遍!這是不是很可怕的災(zāi)難?系統(tǒng)的高可用性、業(yè)務(wù)需求的快速響應(yīng)還有什么保障可言?

所以說(shuō):掌握好 DDD 戰(zhàn)略設(shè)計(jì),幾乎是做好微服務(wù)設(shè)計(jì)必不可少的前提!不懂得 DDD,你做的“微服務(wù)拆分”可能還不如不拆分,單體應(yīng)用可能更適合你!

在本節(jié)內(nèi)容中,除了搞定限界上下文的映射之外,我還將對(duì)系統(tǒng)分層架構(gòu)進(jìn)行設(shè)計(jì),并在最終給出項(xiàng)目組可直接用于開(kāi)發(fā)的代碼框架結(jié)構(gòu)。

需要特別說(shuō)明的是:在寫(xiě)到這篇的過(guò)程中,我反復(fù)和多位業(yè)界大拿請(qǐng)教,大家普遍認(rèn)為我前面第三篇中業(yè)務(wù)子域的分類(lèi)上“核心子域”太多了。我經(jīng)過(guò)再三考慮,將“核心子域”進(jìn)行了調(diào)整,這將影響到本篇關(guān)于系統(tǒng)分層結(jié)構(gòu)的設(shè)計(jì),您可以跳回到第三篇重新看下“業(yè)務(wù)子域識(shí)別與分類(lèi)”這一小段。這里再次重申下:您在閱讀中發(fā)現(xiàn)我的任何不妥之處 ,可隨時(shí)與我交流,我發(fā)現(xiàn)不妥之處一定認(rèn)真思考改進(jìn),感謝您的支持!

限界上下文映射

1.跨上下文用例識(shí)別

為了識(shí)別限界上下文之間的映射關(guān)系,我們需要對(duì)跨上下文的業(yè)務(wù)用例(也叫業(yè)務(wù)服務(wù)),從架構(gòu)設(shè)計(jì)的技術(shù)視角繪制服務(wù)序列圖,進(jìn)而識(shí)別它們之間的映射關(guān)系。

首先,第一步,我們識(shí)別出所有的跨限界上下文的業(yè)務(wù)用例。在識(shí)別某個(gè)業(yè)務(wù)用例是否跨限界上下文時(shí),一定要注意兩個(gè)基本事實(shí):1)其實(shí)大部分業(yè)務(wù)用例都是從“群買(mǎi)菜”小程序前端界面發(fā)起的,前端與服務(wù)端的交互,不算跨限界上下文;2)限界上下文提供的是服務(wù)端的業(yè)務(wù)服務(wù),跨限界上下文一定要是服務(wù)端邏輯的相互關(guān)系。

關(guān)于如何識(shí)別“服務(wù)端的跨限界上下文”業(yè)務(wù)邏輯,我認(rèn)為需要逐個(gè)分析前面羅列的所有業(yè)務(wù)用例,從如下兩個(gè)角度篩選:

初步分析業(yè)務(wù)用例內(nèi)部的邏輯,看是否需要多個(gè)上下文來(lái)承擔(dān)職責(zé)。如果是,則需將該用例納入分析范圍;

分析業(yè)務(wù)用例圖中的被包含的“子用例”,看是否存在上下文包含了被歸類(lèi)到別的上下文的情況。如果是,則需將該用例納入分析范圍;為此,識(shí)別結(jié)果如下圖羅列:

需要說(shuō)明的是:有幾個(gè)用例看起來(lái)好像是跨上下文的,其實(shí)不是。分別說(shuō)明如下:

  • “確認(rèn)購(gòu)買(mǎi)并付款”、“創(chuàng)建訂單預(yù)支付”、“完成訂單支付”、“補(bǔ)收客戶(hù)貨款”、“退客戶(hù)貨款”,這幾個(gè)用例其實(shí)是訂單上下文和支付系統(tǒng)之間的關(guān)系。考慮到我們的系統(tǒng)上下文設(shè)計(jì),支付系統(tǒng)其實(shí)不是我們目標(biāo)系統(tǒng)的工作范圍,故這里不納入范圍。
  • “后臺(tái)查詢(xún)店鋪商品”、“后臺(tái)瀏覽店鋪訂單列表”、“管理店鋪客戶(hù)信息”、“管理店鋪員工”、“開(kāi)通店鋪加盟并設(shè)置分成政策”、“添加品牌店鋪到加盟列表”,看起來(lái)每個(gè)用例的名稱(chēng)上都涉及到 2 個(gè)限界上下文、并都跟“店鋪”上下文發(fā)生關(guān)系,其實(shí)它們只是需要店鋪 ID,并沒(méi)有與店鋪上下文發(fā)現(xiàn)任何業(yè)務(wù)交互,故實(shí)際上不作為“跨上下文”的用例來(lái)對(duì)待。

其次,這些業(yè)務(wù)用例中,從跨上下文協(xié)作關(guān)系角度來(lái)看,其中有些用例畫(huà)服務(wù)序列圖是會(huì)出現(xiàn)重復(fù)的,我們需要識(shí)別出來(lái):

  •  “創(chuàng)建新店鋪”、“編輯店鋪信息”,會(huì)用到短信驗(yàn)證碼驗(yàn)證手機(jī)號(hào),故都屬于跨店鋪、平臺(tái)集成兩個(gè)限界上下文的,且交互邏輯一致,故重復(fù)。
  • “加商品到購(gòu)物車(chē)”、“選購(gòu)接龍商品到購(gòu)物車(chē)”,其實(shí)都是涉及到訂單和商品兩個(gè)限界上下文的相同交互關(guān)系,故重復(fù)。
  • “創(chuàng)建接龍活動(dòng)”、“編輯接龍活動(dòng)”,這兩個(gè)業(yè)務(wù)用例的操作序列,從跨上下文協(xié)作關(guān)系角度來(lái)看也是完全一樣的,只是后者需加載原有“接龍”上下文內(nèi)部已持久化的信息、前者不用。
  •  “創(chuàng)建付款訂單”是“確認(rèn)接龍付款”的子用例,故只需要保留“確認(rèn)接龍付款”即可。
  •  “添加品牌店鋪到加盟列表”、“從加盟列表刪除品牌店鋪”,這兩個(gè)業(yè)務(wù)用例都是涉及到店鋪和加盟兩個(gè)上下文的關(guān)系,并且都是獲取店鋪相關(guān)信息、并將店鋪信息傳輸給加盟上下文處理,故重復(fù)。

最終,我們確定下來(lái),被用來(lái)繪制服務(wù)序列圖,進(jìn)而確定各上下文協(xié)作關(guān)系的業(yè)務(wù)用例羅列如下圖:

2.基于跨上下文用例映射上下文關(guān)系

我們接下來(lái)的工作,就是要對(duì)這些業(yè)務(wù)用例,逐個(gè)進(jìn)行技術(shù)分析,設(shè)計(jì)出服務(wù)序列圖,然后根據(jù)服務(wù)序列圖確定限界上下文的關(guān)系映射。

創(chuàng)建新店鋪

創(chuàng)建新店鋪涉及到手機(jī)號(hào)短信驗(yàn)證,故需要跨店鋪和平臺(tái)集成兩個(gè)上下文。服務(wù)序列圖如下:

基于該服務(wù)序列圖識(shí)別出“店鋪”和“平臺(tái)集成”上下文關(guān)系如圖(C 表示服務(wù)調(diào)用客戶(hù)端、S 表示被調(diào)用服務(wù)端,以下同。DDD 標(biāo)準(zhǔn)方法中一般用“上下游關(guān)系”、及諸如“開(kāi)發(fā)主機(jī)服務(wù) OHS”等方式表達(dá),但我認(rèn)為那是廢話(huà),并沒(méi)有清晰的表達(dá)強(qiáng)弱關(guān)聯(lián),故不在這里采用):

初始化店鋪默認(rèn)選項(xiàng)

根據(jù)產(chǎn)品 UI 原型的設(shè)計(jì)方案,新店鋪創(chuàng)建后,系統(tǒng)機(jī)器人需要基于異步事件,對(duì)店鋪的相關(guān)選項(xiàng)立即進(jìn)行初始化:

  • 店鋪默認(rèn)門(mén)頭圖片(UI 允許創(chuàng)建人未設(shè)置門(mén)頭圖片);
  • 店鋪是否開(kāi)通訂單短信提醒(隨著業(yè)務(wù)發(fā)展可能會(huì)調(diào)整,故不放在創(chuàng)建店鋪時(shí)設(shè)定);
  • 店鋪的第一個(gè)員工(就是創(chuàng)建人自己);
  • 店鋪默認(rèn)的加盟分銷(xiāo)政策(隨著業(yè)務(wù)發(fā)展可能會(huì)調(diào)整,故不放在創(chuàng)建店鋪時(shí)設(shè)定);
  • 店鋪的首個(gè)接龍地點(diǎn)(詳見(jiàn)產(chǎn)品 UI 原型,店鋪接龍支持多個(gè)地點(diǎn),但首個(gè)地點(diǎn)就是店鋪地址);
  • 創(chuàng)建商家及商家賬戶(hù)(如果是創(chuàng)建人的第一家店鋪);
  • 店鋪默認(rèn)商品分類(lèi)(系統(tǒng)規(guī)則會(huì)按季節(jié)調(diào)整);
  • 店鋪默認(rèn)的商品搜索熱詞(系統(tǒng)后臺(tái)會(huì)不定期根據(jù)某種策略更新);

這些默認(rèn)選項(xiàng),涉及到“店鋪”、“員工”、“商品”、“接龍”、“商家賬戶(hù)”、“鑒權(quán)”共 6 個(gè)上下文的協(xié)作。服務(wù)序列圖涉及如下:

根據(jù)該服務(wù)序列圖,我們得出這 6 個(gè)限界上下文的協(xié)作關(guān)系如下圖:

從上圖的上下文依賴(lài)關(guān)系中,看到店鋪對(duì)員工、商品、接龍、商家賬戶(hù) 4 個(gè)上下文產(chǎn)生了調(diào)用關(guān)系依賴(lài),這是不合理的。因?yàn)閺臉I(yè)務(wù)角度來(lái)說(shuō),其實(shí)是后 4 者依賴(lài)于店鋪的存在而存在,而不是反過(guò)來(lái)。為此,我們做這樣的調(diào)整:

  • 采用消息發(fā)布者/訂閱者模式,讓后 4 者依賴(lài)店鋪上下文發(fā)布的“店鋪已創(chuàng)建”消息;
  • 去掉“接龍”上下文對(duì)店鋪首個(gè)接龍地點(diǎn)初始化的邏輯。本質(zhì)上,仔細(xì)分析產(chǎn)品 UI 界面設(shè)計(jì)的要去,我們發(fā)現(xiàn)這其實(shí)是“群買(mǎi)菜小程序”在展示創(chuàng)建接龍活動(dòng)的前端界面時(shí),需調(diào)用“店鋪”上下文服務(wù)來(lái)獲取的信息:如果所選擇店鋪已經(jīng)有接龍地址,則返回已有的接龍地址列表供選擇;如果該店鋪尚無(wú)首個(gè)接龍地址,則返回店鋪地址作為默認(rèn)接龍地址。

經(jīng)過(guò)修改后的服務(wù)序列圖如下:

根據(jù)該服務(wù)序列圖,我們修改上下文的協(xié)作關(guān)系如下圖(P 表示消息發(fā)布者,S 表示消息訂閱者,下同):

加商品到購(gòu)物車(chē)

客戶(hù)瀏覽店鋪商品,選中感興趣的商品到購(gòu)物車(chē),以便后續(xù)的購(gòu)買(mǎi)結(jié)算。考慮到添加商品到購(gòu)物車(chē)中去的“時(shí)間”特殊性:我們需要在客戶(hù)將商品加入到購(gòu)物車(chē)時(shí),為商品創(chuàng)建“快照”,以避免商品信息在后面被編輯修改(比如改了圖片或描述、尤其是價(jià)格)時(shí),影響到對(duì)客戶(hù)的購(gòu)買(mǎi)承諾。

為此,該業(yè)務(wù)用例(服務(wù))就涉及到“訂單”和“商品”兩個(gè)上下文,服務(wù)序列圖設(shè)計(jì)如下:

該序列圖展示出訂單和商品的上下文關(guān)系如圖:

發(fā)送訂單提醒

“發(fā)送訂單提醒”需要在訂單上下文中發(fā)起、“通知”上下文中發(fā)送通知,故涉及“訂單”和“通知”兩個(gè)上下文。該用例服務(wù)序列圖如下:

考慮到訂單消息提醒是沒(méi)有副作用的、而且也不需要保證必須成功,故采用消息發(fā)布者/訂閱者模式比較合適。也就是得到如下所示的“訂單”和“通知”上下文的映射關(guān)系:

創(chuàng)建接龍活動(dòng)

與“加商品到購(gòu)物車(chē)”用例類(lèi)似,商家在創(chuàng)建接龍活動(dòng)、添加商品到接龍中去時(shí)也存在“時(shí)間”特殊性,需要為商品創(chuàng)建“快照”,以避免商品在后面被編輯修改(比如改了圖片或描述、尤其是價(jià)格)時(shí),影響到接龍活動(dòng)的開(kāi)展。為此,該業(yè)務(wù)用例(服務(wù))就涉及到“接龍”和“商品”兩個(gè)上下文,服務(wù)序列圖設(shè)計(jì)如下:

該序列圖展示出接龍和商品的上下文關(guān)系如圖:

瀏覽我的接龍

按照產(chǎn)品 UI 設(shè)計(jì)文檔,接龍只能在店鋪下存在。而“瀏覽我的接龍”實(shí)際上是“瀏覽我被授權(quán)操作的所有店鋪發(fā)布的、或其被授權(quán)店鋪所加盟品牌店鋪發(fā)布的、或我參與的”的所有接龍。故該用例涉及到“接龍”、“店鋪”兩個(gè)上下文,服務(wù)序列圖如下:

該服務(wù)序列圖展示出,實(shí)際上“接龍”、“店鋪”這 2 個(gè)上下文沒(méi)有發(fā)生關(guān)聯(lián)關(guān)系。但這個(gè)服務(wù)序列圖設(shè)計(jì),有個(gè)“壞味道”的感覺(jué):讓群買(mǎi)菜小程序客戶(hù)端承擔(dān)了過(guò)多業(yè)務(wù)邏輯,這是不合理的。于是,我們將服務(wù)序列圖調(diào)整為如下:

該服務(wù)序列圖會(huì)導(dǎo)致如下的 2 個(gè)上下文之間的關(guān)系:

確認(rèn)接龍付款

確認(rèn)接龍付款從產(chǎn)品界面原型可以看出,確認(rèn)接龍付款是從“查看接龍?jiān)斍椤苯缑姘l(fā)起的。客戶(hù)在該界面上點(diǎn)擊相應(yīng)的商品加入購(gòu)物車(chē)、或從購(gòu)物車(chē)移除,然后點(diǎn)擊“我要接龍”按鈕進(jìn)入該用例。

該用例允許用戶(hù)設(shè)置提貨方式、提貨時(shí)間、聯(lián)系人等信息后,點(diǎn)擊“確認(rèn)付款”按鈕完成支付。該按鈕點(diǎn)擊后,按照產(chǎn)品原型設(shè)計(jì),需要完成如下任務(wù):

  • 創(chuàng)建訂單;
  • 更新關(guān)聯(lián)商品的銷(xiāo)量,以便于后續(xù)商品列表和詳情頁(yè)面顯示商品銷(xiāo)量;
  • 如果下單客戶(hù)首次購(gòu)買(mǎi)對(duì)應(yīng)店鋪商品,則為該店鋪初始化對(duì)應(yīng)客戶(hù)資料,以便于商家后續(xù)維護(hù)客戶(hù)資料;
  • 記錄客戶(hù)參與了該接龍,以便于客戶(hù)“瀏覽我的接龍”時(shí),可包含該接龍;

根據(jù)上面的邏輯,我們畫(huà)出服務(wù)序列圖設(shè)計(jì)如下:

該服務(wù)序列圖展示的相關(guān)限界上下文關(guān)系如下圖:

這里可以看到上下文之間的調(diào)用關(guān)系比較多,并且“訂單”與“商品”、“訂單”與“客戶(hù)”之間,還存在數(shù)據(jù)一致性的要求,不利于系統(tǒng)的“松耦合”。為了降低上下文之間的耦合性,我們分析業(yè)務(wù)需求發(fā)現(xiàn):其實(shí)“訂單創(chuàng)建”后“增加商品銷(xiāo)量”、以及“為指定店鋪初始化客戶(hù)”是可以有一定的數(shù)據(jù)延遲的,并不需要通過(guò)“強(qiáng)”服務(wù)調(diào)用關(guān)系保障嚴(yán)格的數(shù)據(jù)一致性。為此,我們將服務(wù)序列圖修改如下:

根據(jù)改進(jìn)后的服務(wù)序列圖,可以調(diào)整上下文映射關(guān)系如下圖:

結(jié)算訂單收入

結(jié)算訂單收入分為兩步:第一步,在客戶(hù)確認(rèn)訂單完成、或機(jī)器人超時(shí)自動(dòng)確認(rèn)訂單完成時(shí),訂單上下文通知商家賬戶(hù)上下文記錄待結(jié)算的訂單 ID(由于訂單上下文缺乏“判斷什么訂單屬于待結(jié)算狀態(tài)”這樣的領(lǐng)域知識(shí),故只能由商家賬戶(hù)上下文來(lái)記錄);第二步,系統(tǒng)機(jī)器人定時(shí)觸發(fā)商家賬戶(hù)上下文對(duì)待結(jié)算訂單進(jìn)行收入結(jié)算。服務(wù)序列圖設(shè)計(jì)如下:

其中第一步的操作,可以和“發(fā)送訂單提醒”中的“訂單已完成”領(lǐng)域事件合并處理。不過(guò),因?yàn)檫@里是不可丟失的領(lǐng)域事件,所以這就要求采用“可靠事件模式”。基于該服務(wù)序列圖,識(shí)別出“訂單”和“商家賬戶(hù)”上下文的關(guān)系如圖:

結(jié)算傭金收入

結(jié)算傭金收入可以和結(jié)算訂單收入同時(shí)進(jìn)行,也可以分開(kāi)在兩個(gè)用例中異步執(zhí)行。考慮到為了將來(lái)支持允許品牌商在加盟政策中設(shè)置結(jié)算周期,故將其分開(kāi)在兩個(gè)業(yè)務(wù)用例異步執(zhí)行。為此,設(shè)計(jì)其服務(wù)序列圖如下:

該序列圖展示出商家賬戶(hù)和訂單的上下文關(guān)系如圖:

3.限界上下文映射圖

我們將上面針對(duì)各跨上下文業(yè)務(wù)用例分析后,得到的上下文映射關(guān)系進(jìn)行匯總后最終得出下圖:

圖中實(shí)線(xiàn)是服務(wù)調(diào)用關(guān)系,屬于“強(qiáng)關(guān)系”;虛線(xiàn)是消息通知關(guān)系,屬于“弱關(guān)系”。

通過(guò)該限界上線(xiàn)文映射關(guān)系可以看出:我們總共有 9 個(gè)限界上下文,其中有強(qiáng)依賴(lài)關(guān)系的涉及到 9 個(gè)、強(qiáng)依賴(lài)關(guān)系鏈有 9 條。分別是:接龍依賴(lài)于店鋪、商品和訂單,店鋪依賴(lài)于平臺(tái)集成,訂單依賴(lài)于商品,商家賬戶(hù)、員工、客戶(hù)依賴(lài)于鑒權(quán),商家賬戶(hù)依賴(lài)于訂單。9 個(gè)上下文,理論上最多有 72 條依賴(lài)鏈條,我們分析匯總后只有 11 條,已經(jīng)是很好的設(shè)計(jì)。

基于這樣的綜合評(píng)估,我們認(rèn)為目前的設(shè)計(jì)已經(jīng)到了“可接受程度”,暫時(shí)不再做更多的優(yōu)化和調(diào)整了,以避免“過(guò)度設(shè)計(jì)”。

系統(tǒng)架構(gòu)和代碼框架

1.業(yè)務(wù)子域與上下文的映射

完成了限界上下文的關(guān)系映射,其實(shí)就有了對(duì)整體系統(tǒng)架構(gòu)進(jìn)行分層設(shè)計(jì)的基礎(chǔ)。系統(tǒng)整體架構(gòu)設(shè)計(jì)從分層角度來(lái)看,包括:邊緣層、業(yè)務(wù)價(jià)值層、基礎(chǔ)層。邊緣層一般都是各種針對(duì)前端 UI 的控制器,業(yè)務(wù)價(jià)值層和基礎(chǔ)層包含所有的限界上下文,其中基礎(chǔ)層放的是對(duì)應(yīng)到支撐子域、通用子域的限界上下文,而核心子域?qū)?yīng)的限界上下文作為業(yè)務(wù)價(jià)值層。

為了區(qū)分業(yè)務(wù)價(jià)值層和基礎(chǔ)層,我們先將前面得出的業(yè)務(wù)子域(見(jiàn)第三篇中全局分析內(nèi)容)、與限界上下文進(jìn)行如下表所示的關(guān)系映射:

需要說(shuō)明的是:其中“商家管理”和“店鋪管理”雖然是支撐子域,但由于分別被合并到“商家賬戶(hù)”、“店鋪”上下文來(lái)開(kāi)發(fā)實(shí)現(xiàn),故其中邏輯的代碼實(shí)現(xiàn)也被劃分到了“業(yè)務(wù)價(jià)值層”。

2.菱形對(duì)稱(chēng)架構(gòu)簡(jiǎn)介

在對(duì)整個(gè)系統(tǒng)進(jìn)行“分層架構(gòu)設(shè)計(jì)”之前,我們還需要先熟悉一個(gè)軟件架構(gòu)模式——菱形對(duì)稱(chēng)架構(gòu)(以下簡(jiǎn)稱(chēng)菱形架構(gòu)),如下圖所示:

對(duì)“菱形架構(gòu)”的說(shuō)明如下:

菱形架構(gòu)的基礎(chǔ),是依賴(lài)于“領(lǐng)域?qū)印钡慕缍ā_@涉及到后面才會(huì)進(jìn)行的 DDD 戰(zhàn)術(shù)設(shè)計(jì)內(nèi)容,這里不做展開(kāi),您只需要知道:“領(lǐng)域?qū)印狈诺氖菢I(yè)務(wù)領(lǐng)域的關(guān)鍵業(yè)務(wù)知識(shí),包括“聚合(內(nèi)含實(shí)體對(duì)象、值對(duì)象)”和“領(lǐng)域服務(wù)”兩類(lèi)內(nèi)容。事實(shí)上,我們所追求的“高內(nèi)聚”主要體現(xiàn)的“領(lǐng)域?qū)印保驗(yàn)闃I(yè)務(wù)需求變化而引起的變化,我也希望主要通過(guò)“領(lǐng)域?qū)印钡摹熬酆稀焙汀邦I(lǐng)域服務(wù)”的變化來(lái)實(shí)現(xiàn)。所以說(shuō),“領(lǐng)域?qū)印笔? DDD 的“核心代碼所在地”。

所有非“領(lǐng)域邏輯”層的代碼,我們都希望封裝到“北向網(wǎng)關(guān)”或“南向網(wǎng)關(guān)”中去。具體說(shuō)明如下:

“北向網(wǎng)關(guān)”其實(shí)就是上下文向外提供服務(wù)、或接受消息通知的入口處。如果上下文只需要向外提供同一個(gè)進(jìn)程內(nèi)部的應(yīng)用服務(wù)調(diào)用接口、或接受消息通知(通過(guò)消息總線(xiàn)),則需要“本地”服務(wù);如果上下文需要作為獨(dú)立進(jìn)程(這時(shí)候一般是云原生的獨(dú)立“微服務(wù)”)向外輸出服務(wù)、或接受消息通知(通過(guò)消息中間件),則需要將“本地服務(wù)”包裝為“遠(yuǎn)程”服務(wù)。

也就是說(shuō):北向網(wǎng)關(guān)中的“本地服務(wù)”和“遠(yuǎn)程服務(wù)”是一一對(duì)應(yīng)的,“遠(yuǎn)程服務(wù)”只負(fù)責(zé)將遠(yuǎn)程調(diào)用的出入?yún)⒆龈袷睫D(zhuǎn)換并傳給“本地服務(wù)”,而“本地服務(wù)”負(fù)責(zé)調(diào)用領(lǐng)域?qū)拥摹熬酆稀被颉邦I(lǐng)域服務(wù)”來(lái)完成具體的業(yè)務(wù)邏輯(關(guān)于“聚合”和“領(lǐng)域服務(wù)”的內(nèi)容,我會(huì)在本專(zhuān)題后面的章節(jié)中演示)。

“南向網(wǎng)關(guān)”其實(shí)就是上下文用來(lái)將這 3 類(lèi)技術(shù)細(xì)節(jié)從業(yè)務(wù)邏輯中“剝離”出來(lái)的主要手段(圖中只畫(huà)了第一種):訪(fǎng)問(wèn)底層數(shù)據(jù)庫(kù)、調(diào)用其它上下文服務(wù)、向其它上下文發(fā)布消息通知。這 3 個(gè)技術(shù)細(xì)節(jié)的封裝,在 DDD 戰(zhàn)術(shù)設(shè)計(jì)中分別叫“資源庫(kù)”、“客戶(hù)端(也可以叫防腐層——ACL)”、“消息發(fā)布者”。

從圖中可以看出,“南向網(wǎng)關(guān)”有“端口”和“適配器”兩種角色。簡(jiǎn)單點(diǎn)來(lái)說(shuō),“端口”是抽象接口(以 java 為例就是 interface),而“適配器”則是“接口實(shí)現(xiàn)”(以 java 為例就是實(shí)現(xiàn)了對(duì)應(yīng) interface 的類(lèi))。并且,一般來(lái)說(shuō)“適配器”都是通過(guò)依賴(lài)注入(DI,控制反轉(zhuǎn) IoC 的一種)的方式集成到限界上下文的代碼中(java spring 中一般是 bean 注入)。

“南向網(wǎng)關(guān)”區(qū)分“端口”和“適配器”兩個(gè)角色的好處:一方面是可以讓限界上下文內(nèi)的任何代碼都不直接依賴(lài)于具體的底層技術(shù)細(xì)節(jié),如:采用哪種數(shù)據(jù)庫(kù)(oracle 還是 mysql、甚至 nosql 數(shù)據(jù)庫(kù))、怎么調(diào)用其它上下文服務(wù)(本地調(diào)用還是遠(yuǎn)程 RPC)、怎么發(fā)布消息通知(本地消息總線(xiàn)、還是消息中間件);另一方面的好處是允許我們隨時(shí)將構(gòu)建在一個(gè)“微服務(wù)”甚至“單體應(yīng)用”中的多個(gè)限界上下文進(jìn)行拆分到多個(gè)進(jìn)程(即多個(gè)“微服務(wù)”中),而并不會(huì)引起“領(lǐng)域?qū)印薄⒁约啊氨毕蚓W(wǎng)關(guān)”的任何代碼修改(只要替換并重新打包被依賴(lài)注入的“適配器”類(lèi)即可)。

很明顯可以看出,“菱形架構(gòu)”其實(shí)是限界上下文內(nèi)部所采用的一個(gè)“軟件架構(gòu)模式”。而在整個(gè)系統(tǒng)范圍內(nèi),因?yàn)榘鄠€(gè)限界上下文,DDD 設(shè)計(jì)理念并沒(méi)有要求所有的上下文都嚴(yán)格遵循“菱形架構(gòu)”——而完全可以根據(jù)實(shí)際需要(尤其是“基礎(chǔ)層”的上下文),視情況而采用其它架構(gòu)模式(如 MVC 三層架構(gòu)、大數(shù)據(jù)計(jì)算架構(gòu)等)。

3.系統(tǒng)分層架構(gòu)圖

有了前面的將上下文分為“基礎(chǔ)層”和“業(yè)務(wù)價(jià)值層”、以及菱形架構(gòu)概念的基礎(chǔ),再考慮到“群買(mǎi)菜”系統(tǒng)前端界面針對(duì) 3 類(lèi)用戶(hù):商家、客戶(hù)、平臺(tái)運(yùn)營(yíng),前兩者使用微信小程序,最后一個(gè)使用 PC 端,以及相應(yīng)“伴生系統(tǒng)”的協(xié)作邊界。我們最后畫(huà)出系統(tǒng)架構(gòu)分層設(shè)計(jì)圖如下:

對(duì)于上圖,需要特別說(shuō)明的是:

其中騰訊地圖、短信系統(tǒng)、微信公眾號(hào)因?yàn)椴簧婕暗綐I(yè)務(wù)流程,只是一個(gè)功能點(diǎn),故前面的業(yè)務(wù)子域、上下文、業(yè)務(wù)用例都沒(méi)有展現(xiàn)。

有的上下文有“事件訂閱”。這是根據(jù)我們前面“限界上下文映射圖”中的描述,需要進(jìn)行消息訂閱的上下文才有。

其中比較特殊的一點(diǎn):“平臺(tái)集成上下文”沒(méi)有“領(lǐng)域?qū)印保@是因?yàn)樗饕瓿蓪?duì)微信公眾號(hào)接口、短信接口、微信開(kāi)放平臺(tái)接口的封裝,并不存在 DDD 戰(zhàn)術(shù)設(shè)計(jì)所需要的“實(shí)體”對(duì)象這一“領(lǐng)域?qū)印北仨毜幕疽亍?/p>

4.代碼框架結(jié)構(gòu)

基于前面的系統(tǒng)分層架構(gòu)設(shè)計(jì),結(jié)合菱形架構(gòu)模式,我們給出目標(biāo)系統(tǒng)的如下代碼框架結(jié)構(gòu)(采用 java spring 框架開(kāi)發(fā)):

對(duì)上圖中各目錄的劃分和命名說(shuō)明如下:

foundation 目錄存放的是“基礎(chǔ)層”限界上下文,valueadded 目錄存放的是“業(yè)務(wù)價(jià)值層”限界上下文,edge 目錄存放的是“邊緣層”限界上下文;

本質(zhì)上,每個(gè)限界上下文都可以作為獨(dú)立的 java 工程存在。但因?yàn)楸卷?xiàng)目由我一個(gè)人開(kāi)發(fā),所以就沒(méi)有劃分工程了;

每個(gè)限界上下文,采用“上下文名稱(chēng)+context”命名風(fēng)格。如:“訂單上下文”命名為 ordercontext;

每個(gè)限界上下文中,其內(nèi)部目錄結(jié)構(gòu)說(shuō)明如下:

north 目錄存放的是“北向網(wǎng)關(guān)”的內(nèi)容,包括 local 和 remote 子目錄,分別對(duì)應(yīng)北向網(wǎng)關(guān)的“本地服務(wù)”和“遠(yuǎn)程服務(wù)”。有的上下文的 north 目錄下有 subsrciber 子目錄,是為了存放消息訂閱者代碼的。

south 目錄存放的是“南向網(wǎng)關(guān)”的內(nèi)容,包括 port 和 adapter 子目錄,分別對(duì)應(yīng)南向網(wǎng)關(guān)的“端口”和“適配器”。

domain 目錄存放的是“領(lǐng)域?qū)印眱?nèi)容,也就是核心的業(yè)務(wù)邏輯所在。

pl 目錄存放的是“發(fā)布語(yǔ)言”,其實(shí)就是北向網(wǎng)關(guān)的“本地服務(wù)”向外提供服務(wù)時(shí),允許外部調(diào)用服務(wù)所使用的出入?yún)?duì)象類(lèi)型。之所以將出入?yún)?duì)象類(lèi)專(zhuān)門(mén)設(shè)定一個(gè)目錄來(lái)管理,是因?yàn)檫@些出入?yún)⑵鋵?shí)是和 domain 目錄下的“實(shí)體類(lèi)”是不同的,我們不希望將“領(lǐng)域?qū)印眱?nèi)部的業(yè)務(wù)邏輯暴露出去(也就是不將“實(shí)體類(lèi)”的業(yè)務(wù)邏輯暴露出去)。

業(yè)務(wù)價(jià)值層有個(gè) sharedcontext,這是因?yàn)榭紤]到代碼復(fù)用、可能會(huì)出現(xiàn)某些“值對(duì)象”、“發(fā)布語(yǔ)言(即服務(wù)接口出入?yún)?”類(lèi)被多個(gè)上下文共用,具體細(xì)節(jié)我在后面的戰(zhàn)術(shù)設(shè)計(jì)中會(huì)講到。

對(duì)于“群買(mǎi)菜”系統(tǒng)來(lái)說(shuō),由于小程序前端界面已經(jīng)存在,本次是服務(wù)端做 DDD 改造,故不打算對(duì)前后端交互接口進(jìn)行調(diào)整。為此,我為其設(shè)計(jì)了“邊緣層”,也就是 BFF 層。這就是 edge 目錄存放的代碼內(nèi)容。

責(zé)任編輯:武曉燕 來(lái)源: 逸言
相關(guān)推薦

2017-05-11 14:00:02

Flask請(qǐng)求上下文應(yīng)用上下文

2021-01-26 05:19:56

語(yǔ)言Go Context

2012-07-30 16:29:40

架構(gòu)架構(gòu)模式.NET

2012-12-31 10:01:34

SELinuxSELinux安全

2022-09-14 13:13:51

JavaScript上下文

2022-09-15 08:01:14

繼承基礎(chǔ)設(shè)施基礎(chǔ)服務(wù)

2012-08-10 13:32:08

.NETAOP架構(gòu)

2021-09-07 09:53:42

JavaScript變量提升

2024-07-16 10:20:44

2023-07-11 10:02:23

2022-10-28 16:24:33

Context上下文鴻蒙

2024-09-30 14:10:00

2025-03-18 08:14:05

2017-12-17 17:01:23

限界上下文系統(tǒng)模型

2020-07-24 10:00:00

JavaScript執(zhí)行上下文前端

2021-07-26 07:47:36

Cpu上下文進(jìn)程

2025-06-06 08:00:00

上下文管理器Python開(kāi)發(fā)

2025-10-13 08:00:00

2024-12-05 09:06:14

ORM框架.NET

2019-05-06 14:36:48

CPULinux寄存器
點(diǎn)贊
收藏

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

午夜av电影一区| 高清成人在线观看| 色av中文字幕一区| 性高潮久久久久久| 色网在线免费观看| 亚洲色图制服丝袜| 精品乱码一区二区三区| 综合久久中文字幕| 激情欧美一区| 这里只有精品丝袜| 久久国产免费视频| 日本一区二区三区视频在线| 一区二区三区加勒比av| 欧美日韩高清在线一区| 国产视频在线观看视频| 国产欧美日本| 久久成人18免费网站| 亚洲久久久久久| 精品久久国产一区| 欧美亚洲丝袜传媒另类| 成年人午夜视频在线观看 | 精品精品欲导航| 亚洲乱码国产一区三区| 丁香花视频在线观看| 亚洲国产精品黑人久久久| 国产精品乱码一区二区三区| 中文字幕一区二区三区免费看| 亚洲日本激情| 欧美日韩第一页| 四虎永久免费地址| 国产一区二区三区日韩精品| 亚洲国产精品久久久久秋霞不卡 | 国产精品伦一区二区| 午夜精品视频在线观看| 热久久最新网址| 日本三级视频在线观看| 久久伊人蜜桃av一区二区| av成人综合网| 国产黄a三级三级三级| 男女男精品视频| 国产精品久久99久久| 日韩美女视频网站| 国内揄拍国内精品久久| 久久99精品视频一区97| 成人在线观看免费完整| 91中文字幕精品永久在线| 一区二区亚洲精品国产| a天堂中文字幕| 欧美激情在线精品一区二区三区| 欧美va日韩va| 日本亚洲一区二区三区| 4438五月综合| 欧美精品高清视频| www.成年人| 亚洲老司机网| 欧美一三区三区四区免费在线看| 色播五月综合网| 色猫猫成人app| 欧美最猛性xxxxx直播| 日本激情视频在线| 97欧美成人| 欧美午夜精品一区二区三区| 日韩中文字幕免费在线| 韩国成人在线| 欧美日韩成人在线一区| 国产成年人视频网站| 欧美高清免费| 欧美精品tushy高清| 国产亚洲视频一区| 国产乱码精品一区二区三区亚洲人 | 秋霞在线一区二区| а√天堂资源地址在线下载| 亚洲日本电影在线| 欧美黄色免费网址| gratisvideos另类灌满| 天天综合天天综合色| 99999精品视频| jizz免费一区二区三区| 欧美日韩二区三区| 久久久久99人妻一区二区三区| 国产精品xxx在线观看| 亚洲精品国产精品国自产在线| 国产制服丝袜在线| 欧美一区二区麻豆红桃视频| 久久精品国产亚洲7777| 国产真人真事毛片| 视频一区中文字幕| 成人免费视频网址| 免费的黄色av| 国产欧美一区二区精品婷婷| 在线视频福利一区| av福利导福航大全在线| 欧美在线短视频| 在线观看视频在线观看| 亚洲精品激情视频| 日韩综合av| 日韩女同互慰一区二区| 国产精品成人99一区无码| 一区二区三区日本久久久| 中文字幕亚洲无线码a| 免费人成在线观看| 先锋影音久久| 91久久精品美女| 神马久久久久久久久久| 欧美韩国一区二区| 屁屁影院ccyy国产第一页| 欲香欲色天天天综合和网| 欧美日韩国产乱码电影| 国产女人18毛片水真多18| 日韩理论电影院| 97碰碰碰免费色视频| 最新在线中文字幕| av在线这里只有精品| 色婷婷精品国产一区二区三区| 宅男网站在线免费观看| 色综合久久久网| 91亚洲一区二区| 国产成人三级| 韩国日本不卡在线| 97视频免费在线| 国产日韩欧美高清在线| 免费看黄在线看| 精品久久亚洲| 日韩在线中文字幕| 波多野结衣啪啪| 成人aaaa免费全部观看| 国产奶头好大揉着好爽视频| 日韩欧美少妇| 日韩极品精品视频免费观看| 久久r这里只有精品| 美女www一区二区| 欧美一区二区福利| av中文在线资源库| 欧美va亚洲va在线观看蝴蝶网| 中文字幕观看av| 青椒成人免费视频| 日本在线视频一区| 中文字幕人成乱码在线观看| 精品久久五月天| 亚洲国产成人精品综合99| 蜜臀精品一区二区三区在线观看 | 日韩精品欧美大片| 久久久久久国产精品| 国产精品女同一区二区| 日本一区二区三区在线观看| 日本三区在线观看| 西瓜成人精品人成网站| 97热精品视频官网| 天天操天天射天天舔| 亚洲国产一区二区三区| 日批视频在线看| 亚洲天天综合| 亚洲自拍高清视频网站| 成人黄色网址| 日韩视频在线永久播放| 青草影院在线观看| 国产精品77777竹菊影视小说| 五月天男人天堂| 91丨精品丨国产| 久久九九国产精品怡红院| 91精品国产乱码久久| 亚洲天天做日日做天天谢日日欢| 一区二区三区四区毛片| 天天射综合网视频| 91视频8mav| 羞羞的视频在线看| 日韩免费一区二区| 精品人妻在线播放| 欧美一区二区高清在线观看| 少妇久久久久久久| 日本一区二区高清| 日韩肉感妇bbwbbwbbw| 青青草综合网| 成人有码在线视频| 18网站在线观看| 日韩你懂的在线播放| 日本熟妇成熟毛茸茸| 26uuu亚洲综合色欧美| 欧美一级日韩免费不卡| 国产精品果冻传媒| 日韩视频久久| 欧洲视频一区二区三区| 日韩福利影视 | 黄色一级片一级片| 久草资源在线观看| 伊人久久婷婷| 亚洲黄色一区| 国产视频一区免费看| 四季av一区二区凹凸精品| 免费看日本一区二区| 欧美一二区在线观看| 伊人青青综合网| 老牛嫩草一区二区三区日本| 日本伊人色综合网| 久久九九免费| 亚洲国产专区校园欧美| 奶水喷射视频一区| 国产高清在线观看免费不卡| 国产极品人妖在线观看| 精品毛片在线观看| 天天综合网在线观看| 国产毛片在线| 国产白丝在线观看| 日本另类视频| 日韩高清成人在线| 日韩免费高清| 亚洲制服少妇| 国产午夜精品美女毛片视频| 999色成人| 精品国内亚洲2022精品成人| 亚洲激情综合| 久久午夜国产精品| 欧美一区二区三区小说| 免费观看久久av| www.日韩高清| 蜜桃视频m3u8在线观看| 国产日产一区| 粉嫩一区二区三区性色av| 狠狠久久亚洲欧美专区| 日韩中文字幕欧美| 国产精品一区二区不卡视频| www.亚洲天堂网| 欧美一区二区三区爽爽爽| 毛片网站在线观看| 午夜久久av| 蜜桃视频第一区免费观看| 第一sis亚洲原创| 少妇精品久久久一区二区| 国产精品自在在线| 一本色道久久综合精品竹菊| 亚洲男人天堂久| 国产97在线亚洲| 在线一区高清| 亚洲av午夜精品一区二区三区| 久久久久成人片免费观看蜜芽| 深爱五月激情五月| 永久免费观看精品视频| 日韩五码在线| 国产精品久久久久久久久免费丝袜| 777xxx欧美| 日韩av免费一区| 日韩欧美猛交xxxxx无码| 强迫凌虐淫辱の牝奴在线观看| 中文字幕激情视频| 黄色的视频在线观看| 精品免费视频| 国产成人综合在线观看| 一本大道久久a久久精品综合 | 日本精品一区二区| 久久无码专区国产精品s| 伊人久久国产精品| 日韩性xxx| 国产精品普通话对白| 亚洲第一综合色| 美女精品久久久| 天堂一区二区三区| 日本黄色网址大全| 日批视频免费播放| 99a精品视频在线观看| 国产精品一区2区| 欧美精品九九99久久| 91中文字幕在线观看| 天堂在线一区二区三区| 国产精品欧美激情在线| 国产精品亚洲四区在线观看| 精彩视频一区二区| 日韩视频一区二区三区在线播放| www.在线成人| 精品久久久久久无| 国产精品国产精品国产专区蜜臀ah| 97人人模人人爽人人澡| 成人黄色免费视频| 国产精品videossex| 国产日韩精品一区二区三区 | 一区二区在线免费播放| 国产午夜亚洲精品羞羞网站| 久久亚洲国产精品| 成人亚洲视频在线观看| 国产乱码精品一区二区| 亚洲另类春色校园小说| 夜色激情一区二区| 国产精品高潮粉嫩av| 久久久久亚洲av无码专区首jn| 高清在线观看av| 一区二区国产在线| 欧美日韩视频在线观看一区二区三区 | 精一区二区三区| 亚洲国产成人精品电影| a级黄色片网站| 精品乱码一区内射人妻无码| 韩国女主播一区二区三区| 国产精品青草久久| 97精品国产97久久久久久春色| www.精品在线| 国产九色在线| 美女诱惑一区| 亚洲香蕉成人av网站在线观看 | 五十路在线观看| 99精品美女| 欧美日韩精品一区二区在线播放| 国产区二精品视| 日本少妇高清视频| 精品国产不卡一区二区| 一区二区三区在线免费播放 | 亚洲 欧美 视频| 欧美激情极品| 欧美亚洲高清一区二区三区不卡| 欧美成人蜜桃| 欧美特级黄色片| 99久久亚洲精品蜜臀| 在线不卡一区二区| 国产成人亚洲综合无码| 亚洲欧美强伦一区二区| 在线不卡视频| 亚洲三级黄色在线观看| 日韩精品电影网| 日韩欧美xxxx| 国产日产一区二区三区| 国产呦萝稀缺另类资源| 久久久久久网址| 午夜在线观看一区| 欧美9999| 日韩欧美中文在线| 神马午夜伦理影院| 日本又骚又刺激的视频在线观看| 久久国产福利国产秒拍| 欧美一级大片视频| 中文在线观看免费网站| 午夜精品毛片| 日韩在线观看精品| 亚洲女人毛茸茸高潮| 国产不卡av一区二区| 亚洲精品国产免费| 国产伦精品一区二区三区88av| 欧美高清影院| 欧美日韩亚洲综合在线| 欧美日韩亚洲自拍| 精品福利在线| 丰满岳妇乱一区二区三区| 中文字幕久精品免| 91网在线播放| 中文字幕高清一区| 麻豆av一区| 亚洲男女视频在线观看| 国产美女娇喘av呻吟久久| 国产精品久久久久久一区二区| 五月天婷婷久久| 蘑菇福利视频一区播放| 精品国产老师黑色丝袜高跟鞋| 国产精品视频一区国模私拍| 中文字字幕在线中文| 亚洲精品社区| 性亚洲最疯狂xxxx高清| 999这里只有精品| 自拍视频亚洲| 国产+人+亚洲| 日韩av在线播| 麻豆精品91| 欧美最顶级丰满的aⅴ艳星| 在线免费观看毛片| 香蕉av777xxx色综合一区| 国产精品99久久久久久www| 波多野结衣不卡| 久久精品欧洲| 国产99久久久欧美黑人| 中文字幕av资源| 成人午夜视频在线观看| 精品国产乱码久久久久| 黄色片免费在线| 国产精品日韩成人| 在线观看成人av电影| 黄网av在线| 91国产精品成人| 免费网站在线观看黄| 丝袜美腿中文字幕| 亚洲国产精品免费视频| 欧美日韩免费一区二区三区| 一级黄色香蕉视频| 亚洲黄色免费看| 69堂国产成人免费视频| 日韩Av无码精品| 国产激情视频在线播放| 日韩大片欧美大片| 亚洲综合色视频| 久久久久狠狠高潮亚洲精品| 农村妇女一区二区| 日韩精品视频免费| 强乱中文字幕av一区乱码| 免费在线看成人av| 精品乱色一区二区中文字幕| 国产精品久久久久久久久久久久久久久久久 | 国产在线不卡精品| 亚洲欧美一区二区三| 一区二区三区不卡在线观看| 99sesese| 久久高清精品| 国内精品一区二区三区| 五月激情丁香婷婷| 欧美日韩性视频| av无码一区二区三区|