?????????在DDD限界上下文:定義領域邊界的利器領域建模和微服務建設過程中,會有很多項目參與者,包括領域專家、產品經理、項目經理、架構師、開發經理和測試經理等。對于同樣的領域知識,不同的參與者可能會有不同的理解。而且有的時候同一個領域內的名詞和術語也可能不統一,團隊成員交流起來就會出現障礙,嚴重時甚至會傳達出錯誤的信息。
如果出現這種情況應該怎么辦呢?
在DDD中有“通用語言(Ubiquitous Language)”和“限界上下文(Bounded Context)”這兩個重要概念。兩者相輔相成,通用語言用于定義上下文對象的含義,而限界上下文則用于定義領域邊界,以確保每個上下文對象在它特定的邊界內具有唯一的含義,在這個邊界內,組合這些對象構建領域模型。
這段描述可能有點抽象,接下來我會一一詳細講解。不過,在這之前,我想先請你看一下這幾個問題,這也是本章要講解的核心內容。
DDD為什么要有限界上下文的概念?除了解決交流障礙,還有其他原因嗎?限界上下文在微服務拆分和設計時的作用和意義是什么呢?希望你能帶著這幾個問題一起進入下面的學習。
1、什么是通用語言
為了更好地理解限界上下文,回答上面的問題,我們先從通用語言講起。
在事件風暴過程中,通過團隊交流達成共識的,能夠簡單、清晰、準確地描述業務含義和規則的語言就是通用語言。也就是說,通用語言是團隊的統一語言,不管你在團隊中擔任什么樣的角色,在同一個領域的軟件生命周期里都使用統一的語言進行交流。
那么,通用語言的價值也就很明了了,它可以解決交流障礙的問題,避免因為語言不統一而導致的理解偏差和溝通成本的增加。通用語言不僅能夠幫助團隊成員更好地理解業務需求,還能夠確保在領域模型設計和實現過程中,所有成員都能夠準確地理解和傳達業務邏輯。
2、什么是限界上下文
那剛剛上面提到的限界上下文又是用來做什么的呢?
我們知道語言都有它的語義環境,同樣,通用語言也有它的上下文環境。為了避免同樣的概念或語義在不同的上下文環境中產生歧義,DDD在戰略設計上提出了“限界上下文”這個概念,用來確定語義所在的領域邊界。
因為“限界”這個詞很少見,而在漢語里“限界”一般是指“鐵路建筑物及設備不得超過的輪廓尺寸線”,所以很多人初次接觸限界上下文時,就有點犯迷糊,理解成本似乎有點高。
我們不妨先來看一下限界上下文的英文原文:“Bounded Context”,翻譯成中文,其實可以理解為“限定了邊界的上下文環境”。
為了更好地理解限界上下文的含義,我們可以將它拆解為兩個詞來理解:“限界”和“上下文”。“限界”是指具體的領域邊界,而“上下文”則是業務語義所在的上下文環境。通過限定領域的上下文邊界,項目團隊就可以在這個特定的業務邊界內用無歧義的通用語言進行交流了。
綜上,限界上下文就是在限定的上下文環境內,用來封裝通用語言和領域對象,保證領域內的一些術語、領域對象等有一個確切的含義,沒有語義二義性的一個業務邊界。相信你在深入研究DDD后,就能更好地理解它的含義和價值了。它定義了領域模型的邊界和業務適用范圍,使得團隊所有成員能夠明確地知道,什么內容應該在領域模型中實現,什么不應該在模型中實現。
如果這個邊界限定的是業務領域的邊界,那你可以理解為業務上下文邊界。
定義限界上下文時通常會考慮領域業務職責單一這個因素。在確定了領域的職責邊界后,會將所有與實現該領域職能相關的對象都放在同一個限界上下文邊界內,而將所有與該領域職能無關的對象都排除在上下文邊界之外。限界上下文就是這樣一個強制邊界,它可以保證領域職責的單一性和領域模型的純潔性。
舉個例子,其實企業在設置組織架構(如部門、處室等)時,就是在定義企業的限界上下文邊界。企業設置組織架構時,往往會從企業的職能邊界出發,根據這些職能邊界來設置部門,劃定部門的邊界,比如:可以為人力資源管理相關的職能設置人力資源部,為財務核算管理相關的職能設置財務會計部,還有產品線相關的業務部門以及后勤部門等。
部門的職能邊界就是企業組織架構的限界上下文邊界。在部門內會聚集與部門職能相關的所有角色,他們在部門內各司其職,共同完成部門所承擔的職責。這些角色就類似領域模型中的領域對象。
在確定了部門的職責邊界后,不同部門之間的職能就不應該出現重疊和混淆,也不應該將與部門職能不相干的角色放在部門內了,因為這樣會破壞組織架構的限界上下文邊界。有的企業為了縮減部門編制,會將一些彼此不相干的職能放在一個部門,但是這樣在對外提供服務時,就很容易讓人產生誤解或者困惑,甚至鬧出笑話,這就不是一個好的企業限界上下文邊界了。
3、進一步理解限界上下文
我們可以通過一些例子進一步理解限界上下文這個概念。不要小看它,徹底弄懂它會給你后面實踐DDD和微服務設計打下一個堅實的基礎。
都說中文這門語言非常豐富,在不同的時空和背景下,同樣的一句話會有不同的含義。
有一個例子你應該聽說過。在一個明媚的早晨,孩子起床問媽媽:“今天應該穿幾件衣服呀?”媽媽回答:“能穿多少就穿多少!”那到底是穿多還是穿少呢?
簡短的幾句對話,如果沒有具體的上下文語義環境,還真不太好理解。但是,如果你已經知道了這句話所在的語義環境,比如是寒冬臘月或者是炎炎夏日,那么理解這句話的含義就會容易得多了。
所以,語言離不開它的語義環境。同樣的,DDD的通用語言也離不開它的語義環境,這個語義環境就是它的業務上下文邊界。
在中臺領域建模的過程中,我們不大可能用一個簡單的名詞術語沒有歧義地描述一個復雜的業務領域,因此我們就用子域或限界上下文來細分領域,通過縮小術語的業務語義范圍,從而限定通用語言所在的上下文邊界。
現在我們用一個保險領域的例子來講解通用語言的限界上下文邊界。保險業務領域有投保單、保單、批單和賠案等保險術語,它們分別作用于保險的不同業務流程邊界內。
客戶投保時,業務人員會記錄投保信息,在這個領域內會有投保單實體對象。
繳費完成后,業務人員將投保單轉為保單,在這個領域內會有保單實體對象,保單實體與投保單會關聯。
如果客戶需要修改保單信息,保單會變為批單,在這個領域內會有批單實體對象,批單實體會與保單關聯。
如果客戶發生理賠,生成了賠案,在這個領域內會有報案實體對象,報案實體對象與保單或者批單關聯。
投保單、保單和批單等這些保險術語雖然都跟保單有關,但由于它們在不同的業務階段,表現形式不一樣,也被賦予了特殊的業務含義,我們需要針對不同的業務階段加以區分,避免出現歧義。因此我們不能簡單地用“保單”這個術語作用在保險的全業務領域。通用術語有它的作用邊界,超出這個邊界就容易出現理解上的問題。
如果你對保險領域不大了解也沒關系,電商領域肯定再熟悉不過了吧?正如電商領域的商品一樣,商品在不同的階段也有不同的表達形式。商品在銷售階段是商品,這是它的原始含義。在銷售階段結束后,商品就進入了運輸階段,這時商品就變成了貨物。可見,同樣的一件商品,由于業務領域邊界的不同,這些通用語言的術語就有了不同的含義。
限
界上下文就是用來定義這些通用語言的上下文邊界的。這個邊界既是業務領域的邊界,也是微服務拆分的邊界。
看到這,我想你應該非常清楚了,業務領域的邊界就是通過限界上下文來定義的。
4 限界上下文和微服務的關系
接下來,我們來對限界上下文概念做進一步的延伸理解,看一看限界上下文和微服務到底存在怎樣的關系?
我們以購買車險為例進行說明。車險承保的流程包含投保、繳費、出單等幾個主要流程。如果出險了還會有報案、查勘、定損、理算等理賠流程。
保險領域很復雜,在這里我用一個簡化的保險模型來說明限界上下文和微服務的關系,如圖6-2所示,還會用到我們在5.1節學到的一些基礎知識,比如領域和子域。
圖6-2 保險模型的限界上下文
首先,領域可以拆分為多個子領域。一個領域相當于一個問題域,領域拆分為子域的過程就是大問題拆分為小問題的過程。在圖6-2里,保險領域被拆分為:投保、支付、保單管理和理賠四個基本的子域。
每個子域可以進一步拆分為更小的子域,比如支付子域還可以進一步拆分為收款和付款子子域。拆分到一定程度后,有些子子域的領域邊界就可能變成限界上下文邊界了。
子域可能會包含多個限界上下文,如理賠子域就包括報案、查勘和定損等多個限界上下文,這里限界上下文與理賠的子子域領域邊界正好重合。也有可能子域的邊界正好就是限界上下文邊界,如投保子域。
每個領域模型都有它對應的限界上下文,團隊在限界上下文內用通用語言交流。領域內所有限界上下文的領域模型構成了整個業務領域的領域模型。
限界上下文是微服務拆分過程中可以參考的業務領域邊界。不過,這里還是要提示一下,雖然限界上下文理論上可以作為微服務的拆分邊界,但實際落地時,微服務的拆分還是需要結合企業的實際情況,考慮其他非業務因素的限制條件。比如,如果不考慮技術異構、團隊溝通等其他外部因素,一個領域模型是可以被設計為一個微服務的。
但需要記住一點:“不宜過度拆分微服務”,這樣會增加你的集成和運維成本。
那這個度要如何把握呢?有關微服務拆分和設計的原則,我會在第23章詳細講解。
5、限界上下文與子域的關系
學完第5章和本章后,有人可能會對子域與限界上下文的關系有些困惑。子域和限界上下文的映射關系到底是什么樣的?一對多?或者多對一?還是一對一?
其實,在DDD中包括問題域和解決方案域兩個不同的維度。問題域主要從業務視角來考慮,完成從領域到子域的分解,而解決方案域則主要從技術實現的角度,通過劃分限界上下文和采用DDD戰術設計來確定領域模型的技術實現邊界。
限界上下文本質上就是子域,只不過它會更多地考慮領域對象的語義邊界和技術實現細節。限界上下文的劃分體現的是一種更為詳細的設計過程,這個過程劃分了業務的上下文語義邊界,完成了領域模型,明確了領域對象以及領域對象之間的依賴關系等。至此,我們依據限界上下文和領域模型就可以完成微服務設計和落地了。
6、本章小結
通用語言是項目團隊內部交流的統一語言,而通用語言的語義上下文環境則是由限界上下文來限定的,這個邊界可以確保通用語言無二義性。在確定限界上下文邊界時,會用到領域專家的經驗。
領域專家和項目團隊的主要工作,就是在業務領域內采用事件風暴,來劃分限界上下文,建立領域模型。將領域模型映射到微服務,就完成了從業務領域到系統域的映射和系統落地。
限界上下文確定了微服務拆分和設計邊界,是微服務拆分和設計的主要依據。如果不考慮技術異構、團隊溝通等其他外部因素,一個限界上下文理論上就可以拆分為一個微服務。
可以說,限界上下文在微服務設計中具有很重要的意義,如果劃分限界上下文的方向出現了偏離,那微服務設計的結果也就可想而知了。我們只有理解了限界上下文的真正含義和它在微服務設計中的作用,才能真正發揮DDD在微服務拆分和設計中的價值,這是基礎也是前提。
7、通俗易懂的限界上下文解釋
1、什么是限界上下文
限界上下文(Bounded Context)是領域驅動設計(DDD)中的一個核心概念,用來劃分和定義不同業務領域的邊界。在每個限界上下文內,特定的術語和概念有明確的含義,確保它們在這個邊界內是無歧義的。通過限界上下文,團隊可以在復雜的系統中明確各個部分的職責和范圍,避免混淆和沖突。
2、通俗的解釋
假設我們有一個大雜院,院子里住了很多不同的家庭,每個家庭都有自己的生活空間和規則,這些家庭可以看作是不同的上下文。每個家庭內部都有自己的一套說話方式和做事規則(通用語言),這個家庭的界限就是限界上下文。
舉個例子:
-
家庭A:家庭A的成員在家里說“爸爸”,指的是家庭A的父親。
-
家庭B:家庭B的成員在家里說“爸爸”,指的是家庭B的父親。
如果沒有家庭這個邊界(限界上下文),大家都住在一個大房子里,那么說“爸爸”的時候就會很混亂,因為不知道指的是哪家的父親。但是有了家庭這個邊界之后,家庭A說的“爸爸”只在家庭A的邊界內有效,家庭B說的“爸爸”只在家庭B的邊界內有效,這樣就不會混淆。
3、在軟件中的應用
在軟件設計中,限界上下文的概念類似于上述家庭的例子。假設我們在開發一個大型的電商系統,這個系統包括用戶管理、訂單處理、庫存管理等多個部分。每個部分都可以看作是一個限界上下文。
-
用戶管理上下文:在這個上下文中,術語“用戶”指的是電商平臺的注冊用戶。
-
訂單處理上下文:在這個上下文中,術語“訂單”指的是用戶在平臺上的購買記錄。
-
庫存管理上下文:在這個上下文中,術語“庫存”指的是平臺上商品的存儲數量。
每個上下文都有自己的一套規則和數據,彼此獨立。當我們在用戶管理上下文中談論“用戶”時,不會與訂單處理上下文中的“訂單”混淆。
4、具體例子
假設我們在開發一個在線圖書銷售平臺,這個平臺包括以下幾個限界上下文:
-
用戶上下文:處理用戶注冊、登錄、信息管理等。
-
書籍上下文:管理圖書的信息,包括書名、作者、價格等。
-
訂單上下文:處理用戶購買書籍的訂單,包括訂單創建、支付、發貨等。
在用戶上下文中,“用戶”是一個核心概念,指的是注冊并登錄的平臺用戶。在書籍上下文中,“書籍”是一個核心概念,指的是平臺上出售的圖書。在訂單上下文中,“訂單”是一個核心概念,指的是用戶購買行為的記錄。
這些上下文之間雖然有聯系,但它們的核心概念和術語在各自的邊界內是明確且獨立的。這樣,即使在不同上下文中使用相同的術語,也不會產生混淆。
小結
限界上下文通過明確定義每個業務領域的邊界和通用語言,確保了復雜系統中各個部分的職責和術語不會混淆。在每個限界上下文內,團隊成員可以無歧義地交流和合作,從而提高系統的可維護性和可擴展性。通過這個通俗的解釋,希望你對限界上下文有了更清晰的理解。