DDD已經(jīng)火了很久,目前在很多項(xiàng)目上都有所應(yīng)用,而這次是我第一次參加DDD相關(guān)的培訓(xùn),對(duì)我來(lái)說(shuō)神秘的DDD一層一層揭開(kāi)了它的面紗。
背景
DDD為什么這么火,它終歸是解決了軟件設(shè)計(jì)與開(kāi)發(fā)過(guò)程中的一些痛點(diǎn)的。
培訓(xùn)過(guò)程中有一句話“任何人類的設(shè)計(jì)都會(huì)隨著時(shí)間腐化,軟件系統(tǒng)也不例外”,可見(jiàn)在軟件開(kāi)發(fā)過(guò)程中,一開(kāi)始做的軟件設(shè)計(jì),隨著時(shí)間的流逝、需求的變更,慢慢變得不再合理,反而成為了負(fù)擔(dān)。
那么在軟件系統(tǒng)整個(gè)開(kāi)發(fā)過(guò)程存在著的挑戰(zhàn)有哪些呢?
- 在軟件開(kāi)發(fā)中存在著不確定性,而這個(gè)不確定性會(huì)一直貫穿軟件工程的生命周期中。
- 沒(méi)有所謂的“銀彈”,能夠用來(lái)解決軟件的復(fù)雜度問(wèn)題。
- 在軟件工程里溝通非常重要,如何讓整個(gè)團(tuán)隊(duì)都保持著信任和良好的溝通就成了要思考的問(wèn)題。
了解了背景和痛點(diǎn)以后再來(lái)看DDD可以為我們帶來(lái)什么改變,讓它成為了“潮流”。
先來(lái)了解一下DDD是什么
Domain-driven design,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì),它是一種處理高度復(fù)雜域的設(shè)計(jì)思想。主要是圍繞業(yè)務(wù)概念來(lái)構(gòu)建領(lǐng)域模型,從而來(lái)控制住業(yè)務(wù)的復(fù)雜性,使得系統(tǒng)不斷演進(jìn)時(shí)仍然可以保持敏捷。
在傳統(tǒng)的方法里,業(yè)務(wù)架構(gòu)和系統(tǒng)架構(gòu)是綁定在一起的,所以當(dāng)我們?nèi)ロ憫?yīng)業(yè)務(wù)變化調(diào)整業(yè)務(wù)架構(gòu)時(shí),系統(tǒng)架構(gòu)也會(huì)隨之改變。
而對(duì)于DDD來(lái)說(shuō),主要聚焦在領(lǐng)域和領(lǐng)域邏輯,所以這種設(shè)計(jì)方式下的系統(tǒng)架構(gòu)是向領(lǐng)域模型靠攏的,領(lǐng)域模型內(nèi)部封裝了數(shù)據(jù)和?為的對(duì)象,所以當(dāng)業(yè)務(wù)發(fā)生變化時(shí),不會(huì)影響整個(gè)系統(tǒng)架構(gòu)。那么是由誰(shuí)來(lái)識(shí)別領(lǐng)域從而做出設(shè)計(jì)的呢?是技術(shù)專家和領(lǐng)域?qū)<乙黄鸷献?,缺一不可,這樣才能不斷切?問(wèn)題領(lǐng)域的核心。
那么在做領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)的時(shí)候有哪些原則呢?下面就來(lái)介紹一下。
DDD三個(gè)原則
上面我們說(shuō)過(guò)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)主要的焦點(diǎn)是領(lǐng)域和領(lǐng)域邏輯,所以第一個(gè)原則就是
1.聚焦核心領(lǐng)域
我們要先了解什么是領(lǐng)域(domain),看下面的圖表可以知道領(lǐng)域中分為核心領(lǐng)域和子域,而子域又分為?撐?域和通用子域。

圖表中具體的一個(gè)業(yè)務(wù)領(lǐng)域或子域其實(shí)指的是一個(gè)業(yè)務(wù)范圍以及在業(yè)務(wù)范圍內(nèi)進(jìn)?的活動(dòng)。一個(gè)業(yè)務(wù)領(lǐng)域或子域可以包括多個(gè)業(yè)務(wù)能?,?個(gè)業(yè)務(wù)能力一般對(duì)應(yīng)著?個(gè)服務(wù)。
那么圖表中的幾類領(lǐng)域有什么區(qū)別呢?
- 核?子域一般是指業(yè)務(wù)成功的主要促成因素,是項(xiàng)目的核心競(jìng)爭(zhēng)?;
- 通??域雖然不是核心,但被整個(gè)業(yè)務(wù)系統(tǒng)所使用;
- ?撐?域雖然也不是核心,也不被整個(gè)系統(tǒng)使用,但是是完成業(yè)務(wù)的必要能力。
我之前老是分不清通用子域和支撐子域,因?yàn)楹诵淖佑蚝芎脜^(qū)分,但是這兩種子域都是“輔助”型的,就傻傻分不清楚了。后來(lái)想想顧名思義,通用子域,重點(diǎn)在于通用,如果這個(gè)子域被很多個(gè)業(yè)務(wù)系統(tǒng)調(diào)用,它就是通用子域。如果一個(gè)子域單純的只是作為某一個(gè)業(yè)務(wù)領(lǐng)域的“附屬”,沒(méi)有通用的定義,它就是支撐子域。而一個(gè)支撐子域隨著業(yè)務(wù)需求的發(fā)展,也有可能搖身一變成為通用子域。
2.通過(guò)協(xié)作迭代式探索模型
在傳統(tǒng)模式中,是基于所有未來(lái)的假設(shè)需求而做的龐大的設(shè)計(jì)。例如,基于造車的需求,做好一個(gè)龐大的設(shè)計(jì)后,就會(huì)開(kāi)始先造輪子、再造車架子、一步一步往車的模型上走。
而迭代式探索模型是根據(jù)需求的變化來(lái)不斷演進(jìn)模型。在迭代式探索模型中,同樣是造車的需求,就會(huì)先造一個(gè)滑板車、自行車、摩托車、慢慢演進(jìn)成車。在實(shí)際場(chǎng)景中,其實(shí)很難一開(kāi)始就訂好整個(gè)項(xiàng)目的所有需求,一般都是有個(gè)長(zhǎng)期的目標(biāo)或者明確的藍(lán)圖,然后對(duì)于近一個(gè)月的需求比較明確,對(duì)于近2周的需求非常明確。所以真實(shí)實(shí)踐過(guò)程中,迭代探索模型比較適合敏捷開(kāi)發(fā)流程。
3.使用統(tǒng)一語(yǔ)言
在介紹DDD的時(shí)候說(shuō)過(guò),領(lǐng)域驅(qū)動(dòng)的設(shè)計(jì)是由技術(shù)專家和領(lǐng)域?qū)<乙黄鸷献魍瓿傻?。所以通過(guò)良好的溝通協(xié)作,統(tǒng)一語(yǔ)言就很重要。
對(duì)于技術(shù)人員和業(yè)務(wù)人員來(lái)說(shuō),他們各自有著自己的語(yǔ)言,例如技術(shù)人員大部分表達(dá)的是技術(shù)術(shù)語(yǔ)、技術(shù)設(shè)計(jì)模式、關(guān)于技術(shù)方面的設(shè)計(jì),而業(yè)務(wù)人員大部分表達(dá)的是業(yè)務(wù)術(shù)語(yǔ)、業(yè)務(wù)需求,所以需要技術(shù)人員和業(yè)務(wù)人員一起來(lái)統(tǒng)一語(yǔ)言,避免分歧。而這個(gè)被統(tǒng)一后的語(yǔ)言就是領(lǐng)域模型術(shù)語(yǔ)。
了解DDD的三個(gè)原則以后,再來(lái)看看如何在實(shí)施過(guò)程中遵循這三個(gè)原則。
DDD的實(shí)施步驟
1.團(tuán)隊(duì)消化業(yè)務(wù)知識(shí),建議統(tǒng)一語(yǔ)言。
一開(kāi)始就是技術(shù)專家和領(lǐng)域?qū)<乙黄饏f(xié)作,雙方都明確的了解業(yè)務(wù)知識(shí),在整個(gè)討論過(guò)程中建立一個(gè)統(tǒng)一的領(lǐng)域模型術(shù)語(yǔ),在之后設(shè)計(jì)模型時(shí)使用。
2.初步提煉領(lǐng)域模型,識(shí)別領(lǐng)域模型。
技術(shù)專家和領(lǐng)域?qū)<野杨I(lǐng)域模型術(shù)語(yǔ)都明確出來(lái)以后,識(shí)別出哪些術(shù)語(yǔ)是一個(gè)領(lǐng)域的,每一個(gè)領(lǐng)域內(nèi)部承載的職責(zé),初步提煉出領(lǐng)域模型。
3.分解領(lǐng)域模型復(fù)雜度,劃分子域和上下文。
在初步提煉出領(lǐng)域模型后,需要明確的知道每個(gè)領(lǐng)域之間的關(guān)系、交互等等,從而來(lái)劃分出子域和上下文。
4.細(xì)分領(lǐng)域模型內(nèi)部元素,識(shí)別實(shí)體值對(duì)象和聚合根。
前三個(gè)步驟都是在一層一層往上抽象,第四步回歸到領(lǐng)域內(nèi)部,識(shí)別出領(lǐng)域內(nèi)的實(shí)體對(duì)象和聚合根有哪些,這個(gè)就涉及到比較細(xì)節(jié)的業(yè)務(wù)功能。
由上面4個(gè)步驟,我們知道如何去實(shí)施DDD,但是卻不知道,每一步的細(xì)節(jié)是如何做到的,例如怎么去找出領(lǐng)域模型術(shù)語(yǔ)?怎么確認(rèn)哪些術(shù)語(yǔ)是一個(gè)領(lǐng)域?怎么歸納子域和上下文等等。這個(gè)時(shí)候就可以考慮用到事件風(fēng)暴工作坊(Event Storming)了,具體的實(shí)施方式請(qǐng)看下文。
Event Storming
Event Storming是?種領(lǐng)域建模的實(shí)踐,是?種快速探索復(fù)雜業(yè)務(wù)領(lǐng)域的?法。
Event Storming最開(kāi)始是由Alberto Brandolini開(kāi)發(fā)的一種方式。在2015年11月進(jìn)入了ThoughtWorks技術(shù)雷達(dá),這也意味著Event Storming這種方式被大家所認(rèn)可,有著它的實(shí)際價(jià)值。
- Powerful: Event Storming可以讓實(shí)踐者在數(shù)?時(shí)內(nèi)理解復(fù)雜的業(yè)務(wù)模型,是一種快速探索復(fù)雜業(yè)務(wù)的很好的方式。
- Engaging: Event Storming的參與人員就是帶著問(wèn)題的人和擁有答案的人,他們共聚一堂來(lái)構(gòu)建模型。
- Efficient: 它跟DDD的實(shí)現(xiàn)模型?度一致,并能快速發(fā)現(xiàn)聚合和 Bounded Context [1]
- Easy: 在 Event Storming 中的標(biāo)記都很簡(jiǎn)單,沒(méi)有復(fù)雜的UML
- Fun:這整個(gè)過(guò)程非常的愉快,不會(huì)讓人覺(jué)得枯燥乏味。
[1] Bounded Context在DDD是分而治之的意思,就是不要把一整個(gè)很大的系統(tǒng)看成一個(gè)context,而是依據(jù)「某種方式」把整個(gè)大系統(tǒng)分成若干個(gè)有界限的context。
了解 Event Storming 以后,主要是了解怎么進(jìn)行 Event Storming,看看怎么使用這種方式來(lái)構(gòu)建領(lǐng)域模型。
1.確定參與人員
業(yè)務(wù)?員,領(lǐng)域?qū)<?,技術(shù)人員,架構(gòu)師,測(cè)試?員等關(guān)鍵?色。
2.確定產(chǎn)品愿景和價(jià)值定位
產(chǎn)品愿景是對(duì)產(chǎn)品的頂層價(jià)值設(shè)計(jì),主要是對(duì)產(chǎn)品的?標(biāo)?戶、核?價(jià)值、差異化競(jìng)爭(zhēng)點(diǎn)、痛點(diǎn)等策略層面的信息在團(tuán)隊(duì)內(nèi)部達(dá)成共識(shí)。
可以套用模板:
對(duì)于 "目標(biāo)用戶群體"
它們想 "訴求或痛點(diǎn)"
這個(gè) “產(chǎn)品名稱”
是一個(gè) “產(chǎn)品特征”
它可以“不可抗拒的優(yōu)點(diǎn)”
不同于 “其他競(jìng)品”
我們的產(chǎn)品 “核心的差異化競(jìng)爭(zhēng)力”
最后得到的結(jié)果是:

3.事件風(fēng)暴
事件風(fēng)暴顧名思義就是對(duì)于“事件”的頭腦風(fēng)暴,用來(lái)梳理業(yè)務(wù)流程、建立領(lǐng)域模型、劃分邊界。
3.1設(shè)計(jì)好業(yè)務(wù)場(chǎng)景
事件風(fēng)暴第一件事就是設(shè)計(jì)好要討論的業(yè)務(wù)場(chǎng)景。根據(jù)之前定下的產(chǎn)品愿景與價(jià)值定位,設(shè)計(jì)出關(guān)鍵場(chǎng)景,找出業(yè)務(wù)的起點(diǎn)與終點(diǎn)。
因?yàn)橥麄€(gè)產(chǎn)品的功能是很復(fù)雜的,包含了很多業(yè)務(wù)場(chǎng)景,但是在做事件風(fēng)暴時(shí)我們主要聚焦在關(guān)鍵的業(yè)務(wù)場(chǎng)景,然后找出業(yè)務(wù)起點(diǎn)和業(yè)務(wù)終點(diǎn),確定業(yè)務(wù)范圍。例如在我們這個(gè)例子中原本是一個(gè)玩具網(wǎng)上商城,但是它的核心競(jìng)爭(zhēng)力是玩具置換,所以我們?cè)O(shè)計(jì)的關(guān)鍵場(chǎng)景就是玩具置換的流程,業(yè)務(wù)的起點(diǎn)是發(fā)布玩具,終點(diǎn)是玩具置換完成。
3.2識(shí)別領(lǐng)域事件
識(shí)別出業(yè)務(wù)范圍內(nèi)發(fā)生的事件,一個(gè)領(lǐng)域事件指的是業(yè)務(wù)上真實(shí)發(fā)生的事情,必須對(duì)業(yè)務(wù)有價(jià)值,有助于形成完整的閉環(huán)。
事件都是有時(shí)間順序的。列舉事件可以用“名詞+動(dòng)詞”這樣的形式,例如“玩具已發(fā)布”。
3.3事件排序
將上面識(shí)別出來(lái)的事件貼在白板上,并且每個(gè)事件從左到右按時(shí)間順序排列,同時(shí)間段發(fā)生的要保證相對(duì)順序。例如下圖是整理后的玩具置換業(yè)務(wù)模塊的事件圖。

4.命令風(fēng)暴
命令指的是產(chǎn)?事件的領(lǐng)域?為或領(lǐng)域活動(dòng),命令一般由三種方式觸發(fā):(1)用戶從UI界?進(jìn)行的操作 (2)外部系統(tǒng)觸發(fā)(3)定時(shí)任務(wù)
4.1識(shí)別命令
命令風(fēng)暴這個(gè)過(guò)程中,需要識(shí)別出命令有哪些,把它貼在事件的左邊,如果有命令產(chǎn)生了多個(gè)事件,就用包含箭頭的虛線連接起來(lái)。如下圖中的藍(lán)色小方塊就是命令。

在上圖中“確認(rèn)意向”這個(gè)命令會(huì)觸發(fā)“意向單已確認(rèn)”、“置換單已創(chuàng)建”、“玩具已下架”等三個(gè)事件,所以用包含箭頭的藍(lán)色虛線連接起來(lái)。
4. 2識(shí)別出觸發(fā)命令的?色
找出命令對(duì)應(yīng)觸發(fā)它的角色并標(biāo)識(shí)出來(lái)。如下圖中的黃色小方塊,就是觸發(fā)這個(gè)命令的角色。例如玩具置換發(fā)起方會(huì)發(fā)起一個(gè)意向,然后意向單就會(huì)被創(chuàng)建。

5.尋找領(lǐng)域模型
在前面的步驟中,已經(jīng)分析出領(lǐng)域事件,主要是根據(jù)事件來(lái)尋找領(lǐng)域模型。在上面事件的模板都是“名詞+動(dòng)詞”的方式,所以很容易識(shí)別出事件中有業(yè)務(wù)含義的名詞,需要確保事件中的名詞代表的業(yè)務(wù)概念清晰完整并且沒(méi)有歧義。
上面的事件例子歸納總結(jié)后,發(fā)現(xiàn)領(lǐng)域模型只有“玩具”、“意向單”、“置換單”、“物流單”。

6.尋找聚合
聚合是一組相關(guān)領(lǐng)域模型的集合,是為了保證邊界內(nèi)領(lǐng)域?qū)ο蟮臉I(yè)務(wù)不變性。
它通過(guò)定義對(duì)象之間清晰的所屬關(guān)系和邊界來(lái)確保關(guān)聯(lián)關(guān)系緊密的領(lǐng)域模型能夠內(nèi)聚在一起,從?避免錯(cuò)綜復(fù)雜的對(duì)象關(guān)系網(wǎng)形成。聚合內(nèi)部的領(lǐng)域?qū)ο笫蔷哂?致的?命周期的。
如何來(lái)尋找聚合?是通過(guò)前?的領(lǐng)域模型來(lái)確定的:
- 領(lǐng)域模型是否可以被獨(dú)?訪問(wèn),如果可以被獨(dú)?訪問(wèn)就是一個(gè)聚合。
- 如果領(lǐng)域模型不能被獨(dú)?訪問(wèn),就應(yīng)該屬于它依賴的聚合
下圖就是整理出來(lái)的聚合,不巧,剛好每一個(gè)領(lǐng)域模型都是一個(gè)聚合,然后把命令放在聚合的左面,事件放在聚合的右面。

7.提煉子域
子域的概念,我們?cè)诮忉孌DD的部分的時(shí)候說(shuō)過(guò),簡(jiǎn)單來(lái)說(shuō)?域就指的是一個(gè)業(yè)務(wù)范圍以及在業(yè)務(wù)范圍內(nèi)進(jìn)?的活動(dòng)。
我們需要回顧產(chǎn)品愿景與價(jià)值定位,找出用戶痛點(diǎn)和產(chǎn)品的核心價(jià)值。然后根據(jù)前?步識(shí)別的領(lǐng)域模型圖來(lái)討論子域,并確定映射關(guān)系,最后驗(yàn)證我們的?案是否解決并覆蓋全部問(wèn)題空間。
例如在我們的例子中:核?子域就是置換子域,支撐域是商品子域,通用域是物流子域。關(guān)于支撐域和通用域也在DDD部分解釋過(guò),一個(gè)子域的定位完全根據(jù)你制定的業(yè)務(wù)需求來(lái)。在這里就只假設(shè)物流系統(tǒng)是共用的。

8.劃分限界上下文
限界上下文可以分為限界和上下文兩個(gè)詞來(lái)理解,限界指?個(gè)界限,具體的某?個(gè)范圍;上下文指的是場(chǎng)景、環(huán)境,所以限界上下文是在某個(gè)場(chǎng)景或環(huán)境下的業(yè)務(wù)邊界。
隨著業(yè)務(wù)的擴(kuò)展?jié)u漸的會(huì)產(chǎn)生越來(lái)越多的領(lǐng)域模型,任何一個(gè)比較大型的項(xiàng)目都會(huì)存在著很多的領(lǐng)域模型。如果把很多個(gè)領(lǐng)域模型相對(duì)應(yīng)的軟件代碼全部放在一起,避免不了存在著很多有歧義的對(duì)象,使得代碼難于理解,找不到真正該改動(dòng)的代碼導(dǎo)致 bug,所以需要通過(guò)限界上下文來(lái)明確定義領(lǐng)域模型的范圍和職責(zé),來(lái)消除歧義。
要知道如何去劃分限界上下文,就需要知道劃分的規(guī)則:
術(shù)語(yǔ)相同,含義不同
在一個(gè)系統(tǒng)中,可能一個(gè)術(shù)語(yǔ)有著多重含義,這個(gè)時(shí)候就需要將領(lǐng)域模型分拆在多個(gè)界限上下文中,以避免歧義。一個(gè)上下文中的術(shù)語(yǔ)應(yīng)該只有一種含義。
例如:術(shù)語(yǔ)“賬號(hào)”在不同的限界上下文中,含義是不同的。在上下文A中,賬號(hào)跟是和外部系統(tǒng)A對(duì)應(yīng)的賬號(hào);在上下文B中,它是這個(gè)系統(tǒng)本身的賬號(hào),與外部系統(tǒng)A只有部分信息是一致的。
概念相同,用法不同
另一種情況就是雖然底層的概念是相同的,但是使用的?式不同,最終導(dǎo)致了不同的模型。
例如例子中的“玩具”,在整個(gè)系統(tǒng)中,物理上都對(duì)應(yīng)著同一個(gè)玩具,共享了SKU數(shù)據(jù)。但置換上下文不能修改玩具的詳情,但其實(shí)在置換上下?中也不該關(guān)心玩具的具體詳細(xì)信息(玩具的圖片、破損情況、原本購(gòu)買價(jià)格等等)。所以“玩具”雖然物理上是一個(gè)玩具,但是存在于不同的上下文中。
外部系統(tǒng)
一個(gè)系統(tǒng)常常避免不了與外界系統(tǒng)對(duì)接,為了避免內(nèi)部系統(tǒng)受外部系統(tǒng)的影響所以需要分離上下文。
例如:玩具的具體物流情況是與一個(gè)物流系統(tǒng)對(duì)接的。如果以前是用的物流系統(tǒng)A,但是后面對(duì)接了物流系統(tǒng)B,那么就出現(xiàn)了不同的外部物流模型。這個(gè)時(shí)候內(nèi)部的物流模型會(huì)受這些外部物流模型的影響,為了避免這種情況就要分離上下文,保持內(nèi)部物流模型不受影響。
以上就是Event storming得到的一些結(jié)果,會(huì)發(fā)現(xiàn)最后得出的內(nèi)容是向DDD靠攏的。那么在通過(guò)Event storming進(jìn)行領(lǐng)域建模之后,如何根據(jù)構(gòu)造好的模型來(lái)拆微服務(wù)呢?
微服務(wù)拆分原則
在這里對(duì)于微服務(wù)的內(nèi)容不做過(guò)多的描述,只是單純的闡述如何根據(jù)領(lǐng)域模型來(lái)拆分微服務(wù)。
對(duì)于微服務(wù)的拆分原則,業(yè)界已有的共識(shí):
1.【?選】依據(jù)業(yè)務(wù)限界上下?邊界拆分。這種方式拆分的微服務(wù)在顆粒度上?較適合剛開(kāi)始做服務(wù)化架構(gòu)的團(tuán)隊(duì),而且自然的在業(yè)務(wù)層面實(shí)現(xiàn)了高內(nèi)聚[2]和低耦合[3]。
2.對(duì)于技術(shù)能??較成熟的團(tuán)隊(duì),可以依據(jù)聚合關(guān)系拆分服務(wù)。這種方式就將事物實(shí)時(shí)強(qiáng)?致性的要求,控制在了聚合范圍內(nèi),服務(wù)間則通過(guò)最終一致性保證事物的一致。通過(guò)聚合來(lái)拆服務(wù)使得服務(wù)的顆粒度更更?,拆出的服務(wù)也更多。但是這種方式對(duì)于開(kāi)發(fā)和運(yùn)維團(tuán)隊(duì)的能力要求更?。
3.實(shí)際中也有一些別的服務(wù)拆分原則。例如按照變更的頻率拆分、按照?非功能需求拆分、按照組織結(jié)構(gòu)拆分等等,這里就不詳細(xì)描述了,這些都是根據(jù)實(shí)際情況具體分析比較好。
[2] 高內(nèi)聚:就是把相關(guān)的?為聚集在?起,把不相關(guān)的行為放在別處。如果你要修改某個(gè)服務(wù)
的行為,最好只在?處修改。
[3] 低耦合:如果做到了服務(wù)之間的松耦合,那么修改?個(gè)服務(wù)就不需要修改另?個(gè)服務(wù)。?個(gè)松耦合的服務(wù)應(yīng)該盡可能少地知道與之協(xié)作的那些服務(wù)的信息。
總結(jié)
可以看出我們通過(guò)Event Storming的方式來(lái)構(gòu)建DDD模型。通過(guò)構(gòu)建好的模型,我們可以根據(jù)模型中的上下文或者聚合來(lái)拆微服務(wù),這是實(shí)際場(chǎng)景中的應(yīng)用。當(dāng)然不是說(shuō)這個(gè)模型只有拆微服務(wù)一個(gè)好處,它也能夠體現(xiàn)在軟件分層架構(gòu)上,讓實(shí)際的代碼和模型相匹配,真正落地到項(xiàng)目實(shí)踐中,只是文中沒(méi)有這個(gè)部分的描述而已。