懟不過產(chǎn)品經(jīng)理?因?yàn)槟悴欢瓺DD領(lǐng)域建模與架構(gòu)設(shè)計(jì)
那DDD到底是什么呢?有什么技術(shù)落地方案呢?今天我來給大家科普一下。

基本概念

過去系統(tǒng)分析和系統(tǒng)設(shè)計(jì)都是分離的,正如我們國家“系統(tǒng)分析師” 和“系統(tǒng)設(shè)計(jì)師” 兩種職稱考試一樣,這樣割裂的結(jié)果導(dǎo)致,需求分析的結(jié)果無法直接進(jìn)行設(shè)計(jì)編程,而能夠進(jìn)行編程運(yùn)行的代碼卻扭曲需求,導(dǎo)致客戶運(yùn)行軟件后才發(fā)現(xiàn)很多功能不是自己想要的,而且軟件不能快速跟隨需求變化。
DDD則打破了這種隔閡,提出了領(lǐng)域模型概念,統(tǒng)一了分析和設(shè)計(jì)編程,使得軟件能夠更靈活快速跟隨需求變化。
DDD專門為解決復(fù)雜性而誕生,因此解決思路完全不同于傳統(tǒng)的CRUD,但是DDD本身掌握起來并不會(huì)感覺復(fù)雜,從程序員角度看,DDD其實(shí)是研究將包含業(yè)務(wù)邏輯的ifelse語句放在哪里的學(xué)問。
Q:DDD適用于什么場(chǎng)景?
A:在Evans寫的《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》一書,副標(biāo)題已經(jīng)說明一切:軟件核心復(fù)雜性應(yīng)對(duì)之道。領(lǐng)域驅(qū)動(dòng)的真正作用,在于項(xiàng)目中對(duì)日后的維護(hù),當(dāng)系統(tǒng)變得越來越復(fù)雜的時(shí)候,才能體現(xiàn)出它的威力。
那新項(xiàng)目該不該用領(lǐng)域驅(qū)動(dòng)?新項(xiàng)目并不復(fù)雜,產(chǎn)品還在跑模式的階段,雖然它的優(yōu)勢(shì)并不能真正發(fā)揮出來,但我認(rèn)為,DDD同樣適用新項(xiàng)目。項(xiàng)目只會(huì)越做越復(fù)雜,我們從一開始就應(yīng)該考慮日漸發(fā)胖的代碼、隨時(shí)可能獨(dú)立的子業(yè)務(wù)。而新項(xiàng)目更多的是指導(dǎo)戰(zhàn)略層設(shè)計(jì)(如領(lǐng)域建模),戰(zhàn)術(shù)層的技術(shù)落地還是以團(tuán)隊(duì)成員最熟悉的方式進(jìn)行,目標(biāo)是持續(xù)快速交付、降低維護(hù)成本。

領(lǐng)域建模

Q:什么是領(lǐng)域模型?
A:為解決場(chǎng)景下的問題而形成的一套模型,然后使用這套模型來解決業(yè)務(wù)問題。?根據(jù)重復(fù)勞動(dòng)經(jīng)驗(yàn)我們會(huì)形成一套模式,領(lǐng)域模型也一樣會(huì)形成一套模式,包括:實(shí)體、值對(duì)象、模塊、領(lǐng)域服務(wù)。
那領(lǐng)域模型是怎么一步一步確定下來的呢?推薦兩種比較常用的領(lǐng)域發(fā)現(xiàn)方法:事件風(fēng)暴與四色建模法。
一、事件風(fēng)暴
Event Storming(事件風(fēng)暴)是一種輕量級(jí)的系統(tǒng)分析方法,基于 DDD 的概念,能夠?yàn)槲覀兪崂硐到y(tǒng)中的各種相關(guān)元素,其中包括了核心的 Aggregate。它能夠幫助開發(fā)人員梳理核心的業(yè)務(wù)對(duì)象,從某種程度上來說就是就是領(lǐng)域?qū)ο笾械木酆稀?/p>
描述產(chǎn)品愿景
產(chǎn)品愿景的主要目的是對(duì)產(chǎn)品頂層價(jià)值的設(shè)計(jì),使產(chǎn)品目標(biāo)用戶、核心價(jià)值、差異化競(jìng)爭(zhēng)點(diǎn)等信息達(dá)成一致,避免產(chǎn)品偏離方向。
產(chǎn)品愿景的參與角色:領(lǐng)域?qū)<摇I(yè)務(wù)需求方、產(chǎn)品經(jīng)理、項(xiàng)目經(jīng)理和開發(fā)經(jīng)理。
事件風(fēng)暴關(guān)注點(diǎn)
屬性:事件的輸入、輸出
命令:某個(gè)動(dòng)作
實(shí)體:命令的觸發(fā)者

二、四色建模法
通過還原業(yè)務(wù)邏輯事件,依據(jù)是否影響公司的運(yùn)營和發(fā)展,確定憑證作為時(shí)標(biāo)型對(duì)象,并補(bǔ)全相關(guān)描述的建模方法。四色建模法一般運(yùn)用于問題分析建模。
四色建模是哪四色?它包括——
時(shí)標(biāo)型(Moment-Interval)對(duì)象:具有可追溯性的記錄運(yùn)營或管理數(shù)據(jù)的時(shí)刻或時(shí)段對(duì)象,用粉紅色表示;
PPT(Party/Place/Thing)對(duì)象:代表參與到流程中的參與方/地點(diǎn)/物,用綠色表示;
角色(Role)對(duì)象:在時(shí)標(biāo)型對(duì)象與 PPT 對(duì)象(通常是參與方)之間參與的角色,用黃色表示;
描述(Description)對(duì)象:對(duì) PPT 對(duì)象的一種補(bǔ)充描述,用藍(lán)色表示。
找到溯源事件
確定時(shí)標(biāo)型對(duì)象
找到周圍的PPT對(duì)象
找到角色
補(bǔ)全描述對(duì)象

對(duì)于不同的人提煉出來的領(lǐng)域模型不可能完全一致,這是因?yàn)?strong>每個(gè)人對(duì)業(yè)務(wù)理解的角度都不同。那么,怎么才能保證建模的正確性?
我給大家梳理以下幾個(gè)步驟:
一、統(tǒng)一語言,梳理業(yè)務(wù)
在做設(shè)計(jì)的時(shí)候,梳理業(yè)務(wù)貫穿了整個(gè)過程。這需要技術(shù)與業(yè)務(wù)專家利用統(tǒng)一語言,描繪需求或問題本身,不斷梳理業(yè)務(wù),提煉出核心的領(lǐng)域模型(而非表設(shè)計(jì))。這有利于拉近技術(shù)人員與業(yè)務(wù)人員之間的關(guān)系,建立信任,達(dá)成統(tǒng)一的業(yè)務(wù)目標(biāo)。
二、識(shí)別聚合、聚合根
如何識(shí)別聚合與聚合根?
一個(gè)Bounded Context(限界上下文)可能包含多個(gè)聚合,每個(gè)聚合都有一個(gè)根實(shí)體,叫做聚合根;
聚合是用來封裝真正的不變性,而不是簡單的將對(duì)象組合在一起 聚合應(yīng)盡量設(shè)計(jì)的小,盡可能小的拆分,可以避免重構(gòu),重新拆分
聚合之間的關(guān)聯(lián)通過ID,而不是對(duì)象引用
聚合內(nèi)強(qiáng)一致性,聚合之間最終一致性
三、劃分限界上下文
第二步完成以后,我們根據(jù)不同的場(chǎng)景來劃分限界上下文,以便進(jìn)行微服務(wù)拆分。通過這種基于業(yè)務(wù)理解的拆分方式,我們的系統(tǒng)就能做到高內(nèi)聚,做到單一職責(zé),拆分出來的每個(gè)微服務(wù)都是軟件變化的一個(gè)原因,不會(huì)因?yàn)槟硞€(gè)原因發(fā)生的變更去修改每個(gè)微服務(wù),“牽一發(fā)而動(dòng)全身”。


架構(gòu)設(shè)計(jì)

架構(gòu)設(shè)計(jì)作為DDD戰(zhàn)術(shù)層面的設(shè)計(jì),關(guān)乎到設(shè)計(jì)如何落地到項(xiàng)目中。下面介紹跨庫關(guān)聯(lián)查詢解決方案及幾種比較流行的架構(gòu)設(shè)計(jì)方案。
方案一:數(shù)據(jù)冗余
方案二:數(shù)據(jù)補(bǔ)填
結(jié)合Wrapper設(shè)計(jì)模式,一般在Dao層實(shí)現(xiàn)數(shù)據(jù)聚合——本地庫分頁查詢完數(shù)據(jù)后,通過查詢條件判斷是否需要填充關(guān)聯(lián)數(shù)據(jù),若需要?jiǎng)t通過跨服務(wù)查詢相關(guān)聯(lián)的服務(wù),再對(duì)各個(gè)服務(wù)的數(shù)據(jù)進(jìn)行填充組裝,最后返回。
如下圖,要實(shí)現(xiàn)患者預(yù)約查詢,并聚合患者、醫(yī)生數(shù)據(jù),則在患者預(yù)約服務(wù)查詢完預(yù)約表數(shù)據(jù)后補(bǔ)填患者服務(wù)和醫(yī)生服務(wù)的數(shù)據(jù)。

這種方法的缺點(diǎn)就是,當(dāng)一個(gè)完整的數(shù)據(jù)涉及到N個(gè)微服務(wù),就會(huì)增加N-1個(gè)服務(wù)調(diào)用,數(shù)據(jù)全量查詢/導(dǎo)出的場(chǎng)景也不好使。
CQRS(Command Query Responsibility Segregation)指的是命令查詢職責(zé)分離。Command服務(wù)專門寫數(shù)據(jù),使用關(guān)系型數(shù)據(jù)庫以保證ACID;Query服務(wù)專門讀數(shù)據(jù),一般使用NoSQL數(shù)據(jù)庫,實(shí)現(xiàn)寬表查詢,如MongoDB、ElasticSearch等。這是一種索引外置方案。

Event Sourcing事件溯源——簡單來說就是,通過事件來管理領(lǐng)域?qū)ο蟮纳芷?,事件即領(lǐng)域?qū)ο笠寻l(fā)生的事實(shí),只增不改。一個(gè)對(duì)象從創(chuàng)建開始到消亡會(huì)經(jīng)歷很多事件,以前我們是在每次對(duì)象參與完一個(gè)業(yè)務(wù)動(dòng)作后把對(duì)象的最新狀態(tài)持久化保存到數(shù)據(jù)庫中,也就是說我們的數(shù)據(jù)庫中的數(shù)據(jù)是反映了對(duì)象的當(dāng)前最新的狀態(tài)。
下圖為一種支持讀寫分離的演化:

與上面的單Dao實(shí)現(xiàn)類似,建立統(tǒng)一的Controller與通用的倉庫與工廠,利用數(shù)據(jù)庫第三范式實(shí)現(xiàn)服務(wù)內(nèi)數(shù)據(jù)補(bǔ)填,利用服務(wù)調(diào)用實(shí)現(xiàn)跨服務(wù)數(shù)據(jù)補(bǔ)填。整潔架構(gòu)的核心思想是通過適配器層解耦業(yè)務(wù)層與技術(shù)框架層代碼,使得業(yè)務(wù)代碼與技術(shù)框架可以各自升級(jí)迭代,互不影響。我們都知道,技術(shù)架構(gòu)一直以來都在不斷變化,對(duì)項(xiàng)目的技術(shù)架構(gòu)調(diào)整成本是非常高的,如何降低這種成本?這時(shí)候整潔架構(gòu)就派上用場(chǎng)了。

如上圖所示,中間的Entities與Use Cases屬于業(yè)務(wù)領(lǐng)域?qū)樱珽ntities表示業(yè)務(wù)領(lǐng)域模型的核心業(yè)務(wù),Use Cases表示與用戶交互的Service;最外層技術(shù)框架層是各種技術(shù)實(shí)現(xiàn),與業(yè)務(wù)無關(guān)的一層;那業(yè)務(wù)與技術(shù)怎么進(jìn)行關(guān)聯(lián)呢?通過中間綠色的接口適配器層實(shí)現(xiàn)。適配器層分離了技術(shù)實(shí)現(xiàn)與業(yè)務(wù)邏輯。

六邊形架構(gòu)是微服務(wù)設(shè)計(jì)的基礎(chǔ)。

如圖,我們把微服務(wù)封裝在六邊形里,每個(gè)微服務(wù)的核心業(yè)務(wù)是六邊形里的應(yīng)用程序與領(lǐng)域模型。與整潔架構(gòu)類似,外部接口與內(nèi)部應(yīng)用層通過各種適配器進(jìn)行關(guān)聯(lián)解耦,當(dāng)發(fā)生變更的時(shí)候,只需要修改六邊形內(nèi)部即可,不需要修改其它微服務(wù)。
清晰架構(gòu)融合了DDD、整潔架構(gòu)、CQRS……曾在高水準(zhǔn)的平臺(tái)生產(chǎn)代碼中應(yīng)用,其中一個(gè)是擁有數(shù)千家遍布全球的網(wǎng)上商店的 SaaS 電子商務(wù)平臺(tái),另一個(gè)是已經(jīng)在兩個(gè)國家上線的市場(chǎng),擁有可以每月處理超過兩千萬條消息的消息總線。

以上給大家介紹了DDD的基本概念、領(lǐng)域建模及幾種主流的架構(gòu)設(shè)計(jì)方案。DDD是一個(gè)非常大的課題,工程師們對(duì)DDD的各種爭(zhēng)論從不休止,但存在即合理,我們并不一定要把DDD落地到項(xiàng)目中去,在戰(zhàn)略層設(shè)計(jì)可以指導(dǎo)我們準(zhǔn)確梳理業(yè)務(wù)。
無論如何,將來想要成為業(yè)務(wù)架構(gòu)師,DDD領(lǐng)域建模與架構(gòu)設(shè)計(jì)是一堂必修課,參與到這場(chǎng)思想運(yùn)動(dòng)與實(shí)踐中是非常有必要的。
End
回復(fù)「題庫」領(lǐng)取海量算法題庫
回復(fù)「設(shè)計(jì)」學(xué)習(xí)UML設(shè)計(jì)技巧

