限界上下文:定義領域邊界的利器
在 DDD(領域驅動設計)的領域建模以及系統建設之旅中,諸多參與者紛紛登場,領域專家憑藉深厚的專業知識爲項目奠基,產品經理把控整體方向與功能規劃,項目經理統籌資源、推進流程,架構師精心勾勒系統藍圖,開發經理組織代碼編寫,測試經理保障質量底線。然而,面對同一套領域知識,不同角色基於自身專業背景與職責範疇,理解往往大相徑庭,這無疑在溝通交流時築起了一道道高牆,阻礙着項目的順暢推進。
正是爲了打破這一困境,DDD 祭出了兩大 “法寶”——“通用語言” 與 “限界上下文”。它們宛如溝通的橋樑與精準的導航,引領各角色跨越理解的鴻溝,確保在複雜的領域開發進程中,大家心往一處想、勁往一處使,攜手共創契合業務需求的優質系統。
這兩者相輔相成,通用語言定義上下文含義,限界上下文則定義領域邊界,以確保每個上下文含義在它特定的邊界內都具有唯一的含義,領域模型則存在於這個邊界之內。你是不是感覺這麼描述很抽象?沒關係,接下來我會給你一一詳細講解。
在這之前,我想請你先看這樣兩個問題,這也是今天內容的核心。
爲什麼要提出限界上下文的概念(也就是說除了解決交流障礙這個廣義的原因,還有更具體的嗎)?
限界上下文在微服務設計中的作用和意義是什麼?
什麼是通用語言?
深入探尋限界上下文之前,讓我們先來揭開通用語言的神祕面紗,弄清楚它究竟是怎樣一個概念。
想象一下,在充滿激情與創意碰撞的事件風暴環節,團隊成員們各抒己見、熱烈討論。就在這你來我往的交流過程中,逐漸達成一種共識,由此孕育出的一種能夠以簡單、明快且精準無誤的方式去闡述業務內涵與規則的語言,這,便是通用語言。簡單來說,通用語言就像是團隊內部的 “普通話”,無論你是深耕專業領域多年的專家,還是整日與代碼爲伴的開發人員,亦或是把控項目流程的項目經理等,只要身處同一個領域的軟件從誕生到迭代的全生命週期之中,都得操着這門 “通用語言” 進行溝通交流。
既然如此,通用語言的價值自是不言而喻。它宛如一把神奇的鑰匙,能夠輕鬆解鎖交流障礙這把 “大鎖”,讓領域專家與開發人員得以並肩攜手,順暢地協同合作,進而保障業務需求得以原汁原味、精準無誤地呈現出來。不過,僅僅知曉這些,對於通用語言的理解還只是停留在表面。
事實上,通用語言涵蓋了豐富的內容,其中既有專業術語,又有用例場景,並且它還有着一項極爲獨特的 “超能力”—— 能夠直接映射到代碼世界當中。通用語言裏的名詞,如同夜空中的啓明星,爲領域對象指引命名方向,像大家耳熟能詳的商品、訂單之類,它們在代碼中往往對應着實體對象;而其中的動詞,則好似一個個活力四射的 “行動派”,代表着特定的動作或事件,諸如商品已下單、訂單已付款等等,這些在代碼裏大概率對應的是領域事件或者命令。
可以毫不誇張地說,通用語言貫穿了 DDD 的整個設計流程,從最初的構思藍圖,到中間的精雕細琢,再到最後的落地實踐,它都如影隨形。作爲項目團隊通過溝通協商精心打磨出來的統一語言,依託它的力量,開發人員得以雕琢出可讀性極高的代碼,就如同一位位技藝精湛的工匠,將紛繁複雜的業務需求巧妙、精準地轉化爲精妙絕倫的代碼設計。
下面我帶你看一張圖,這張圖描述了從事件風暴建立通用語言到領域對象設計和代碼落地的完整過程。
當開啓事件風暴之旅時,領域專家、設計人員以及開發人員如同並肩作戰的夥伴,齊聚一堂,共同投身於構建領域模型這一關鍵任務之中。在這場充滿思維碰撞的建模過程裏,通用的業務術語以及鮮活的用戶故事如同閃耀的星星,漸次浮現。
值得注意的是,事件風暴可不單單是一場構建模型的頭腦風暴,它更是項目團隊邁向統一語言的重要征程。藉助對用戶故事細緻入微的剖析,一個個領域對象應運而生,它們宛如精準的 “翻譯官”,與領域模型中的業務對象緊密相連,精準對應。無論是業務對象,還是新生的領域對象,都被賦予了通用的名詞術語作爲獨特標識,彼此之間形成了清晰、精準的一一映射關係。
而在微服務架構的世界裏,代碼模型有着自己的 “身世之謎”—— 它脫胎於精心雕琢的領域模型。就像孩子繼承了父母的基因一般,每個代碼模型中的代碼對象,都嚴格遵循着與領域對象一一對應的 “傳承法則”,確保從業務需求到代碼實現的轉換過程精準無誤,流暢自然。
在這裏,我想跟大家分享一條我日常工作中屢試不爽的寶貴經驗。在設計工作推進期間,善用表格能夠起到事半功倍的效果。我們可以精心繪製一些表格,將事件風暴與微服務設計進程中孕育而生的領域對象,以及它們所附帶的各類屬性逐一記錄下來。
具體而言,這些表格能夠清晰呈現領域對象處於 DDD 分層架構中的具體層級位置,詳細羅列每個領域對象自身獨有的屬性信息,精準梳理出它們與其他領域對象之間錯綜複雜的依賴關係,並且還能直觀展現其與代碼模型對象之間那種嚴絲合縫的一一映射對應關係。如此一來,整個設計流程便如同在地圖上前行,方向明晰、路徑可循,讓後續的開發等工作得以有條不紊地推進。
來看一個微服務設計實例的部分資料,表格裏的這些名詞術語,其實是項目團隊在事件風暴階段,大家你一言我一語、充分交流探討後達成一致意見所形成的,如今已成爲團隊成員之間順暢溝通的通用語言。
深入探究這個表格,會有不小的收穫。一方面,DDD 分析流程中產生的全部領域對象,連同它們各自具備的屬性,都被完整且細緻地記錄在此處,就像是一份領域對象的詳細檔案。另一方面,除了這些領域對象,在微服務設計推進過程中,與之對應的代碼對象也被納入其中,並且二者之間建立起了明確無誤的一一映射關聯,確保從業務領域到代碼實現的轉換精準流暢,讓項目的開發工作得以沿着清晰的路線前行。
到這裏,我要再強調一次。DDD 分析和設計過程中的每一個環節都需要保證限界上下文內術語的統一,在代碼模型設計的時侯就要建立領域對象和代碼對象的一一映射,從而保證業務模型和代碼模型的一致,實現業務語言與代碼語言的統一
如果你做到了這一點,也就是建立了領域對象和代碼對象的映射關係,那就可以指導軟件開發人員準確無誤地按照設計文檔完成微服務開發了。即使是不熟悉代碼的業務人員,也可以很快找到代碼的位置。
什麼是限界上下文?
那剛剛提到的限界上下文又是用來做什麼的呢?
大家都清楚,任何一種語言都依託於特定的語義環境而存在,通用語言自然也不例外。爲了有效規避同一概念或語義在不同情境下出現混淆、引發歧義的問題,DDD 在戰略規劃層面祭出了一個極具巧思的概念 ——“限界上下文”,其核心要義便是精準錨定語義所處的領域疆界。
倘若我們把 “限界上下文” 一詞拆分開來細究,它實則由 “限界” 與 “上下文” 兩個關鍵要素構成。所謂 “限界”,直白來講就是劃分出明確的領域邊際,宛如一道清晰的界線,將相關範疇與外界隔離開;而 “上下文” 呢,它等同於營造出的語義環境,爲各類概念和表達賦予確切的背景支撐。有了這一利器,我們便能在劃定好的統一領域邊界之內,心無旁騖地運用統一的語言暢所欲言、協同合作。
將這些要點融會貫通之後,再來剖析限界上下文的定義,便會有更爲通透的理解。它仿若一個精妙的 “知識寶盒”,專門用於封裝通用語言以及與之緊密關聯的領域對象,同時巧妙營造出適配的上下文環境。如此一來,處於這個特定領域之內的專業術語、業務關鍵對象等通用語言元素,都被賦予了獨一無二、確鑿無疑的含義,徹底杜絕了模棱兩可的情況出現。而且,這個精心界定的邊界還清晰勾勒出模型的適用範疇,讓項目團隊中的每一位成員都能一目瞭然:哪些內容應當在模型構建中落地實現,哪些又該被排除在外。簡而言之,限界上下文就是保障 DDD 項目高效、精準推進的關鍵密碼,讓團隊在複雜的業務領域中找準方向,穩步前行。
進一步理解限界上下文
咱們不妨藉助幾個實例,把 “限界上下文” 這個概念嚼得更透一些,千萬別小瞧它,一旦真正喫透,那可就爲後續實踐 DDD 築牢根基了。
大家都知道,中文博大精深,同樣一句話,置於不同的時空場景、背景條件之下,含義能千差萬別。就拿生活中的一個小片段來說,在某個陽光燦爛的清晨,孩子睡眼惺忪地爬起牀,向媽媽拋出一個日常小問題:“媽,今天得穿幾件衣服呀?” 媽媽瞅了瞅窗外,隨口回了句:“能穿多少就穿多少!” 這下可把孩子弄迷糊了,到底是得多穿點,還是少穿點呢?要是脫離了具體的情境去琢磨這句話,還真讓人摸不着頭腦。可要是事先知曉這話所處的語義環境,比方說是寒風凜冽的數九寒冬,那自然明白得裹得嚴嚴實實;要是正值驕陽似火的三伏天,那肯定是能少穿就少穿。由此可見,語言這東西,必須依託於特定的語義環境才能精準表意。
同樣的道理,業務領域裏的通用語言也有它自身的 “勢力範圍”,也就是業務邊界。畢竟,想用一個簡簡單單的術語,毫無偏差、毫無歧義地把一整個複雜的業務領域描述得明明白白,這幾乎是不可能完成的任務。而此時,限界上下文就閃亮登場了,它就像是一把精準的手術刀,把龐大複雜的業務領域細細切割、劃分,進而爲通用語言圈定出清晰、準確的 “活動範圍”,讓每一個術語、每一句業務表述都能在所屬的邊界內精準傳達信息,避免混淆與誤解。
現在我們用一個保險領域的例子來說明下術語的邊界。保險業務領域有投保單、保單、批單、賠案等保險術語,它們分別應用於保險的不同業務流程。
-
客戶投保時,業務人員記錄投保信息,系統對應有投保單實體對象
-
繳費完成後,業務人員將投保單轉爲保單,系統對應有保單實體對象,保單實體與投保單實體關聯。
-
如客戶需要修改保單信息,保單變爲批單,系統對應有批單實體對象,批單實體與保單實體關聯。
-
如果客戶發生理賠,生成賠案,系統對應有報案實體對象,報案實體對象與保單或者批單實體關聯。
投保單、保單、批單、賠案等,這些術語雖然都跟保單有關,但不能將保單這個術語作用在保險全業務領域。因爲術語有它的邊界,超出了邊界理解上就會出現問題。
如果你對我從事的保險業不大瞭解也沒關係,電商肯定再熟悉不過了吧?
拿電商領域的實物流轉舉例,便能清晰地感知到其中的門道。就說 “商品” 這一概念,它在業務推進的不同環節有着截然不同的稱謂。當處於面向消費者的銷售環節時,大家統一稱其爲 “商品”,這個名稱承載着吸引顧客、展示特性、促成交易的使命;然而,一旦進入物流配送的運輸流程,它搖身一變,被叫做 “貨物”,此時的重點在於追蹤物流軌跡、確保按時交付、保障運輸安全,其內涵與職責已悄然改變。
明明是同一實體物件,僅僅因爲所處業務領域發生變化,對應的術語含義以及所肩負的責任範圍就大不一樣了。而這一道隱形卻又真實存在的 “楚河漢界”,極有可能成爲後續微服務設計時劃分模塊、界定功能的關鍵參照。講到這兒,想必大家已經心中有數,沒錯,領域的邊界正是依靠限界上下文這一關鍵要素來精準界定的,它就像是航海圖上的經緯線,爲錯綜複雜的業務領域指明方向、劃分疆域。
限界上下文和微服務的關係
接下來,我們對這個概念做進一步的延伸。看看限界上下文和微服務具體存在怎樣的關係。
我想你買過車險吧,或者聽過吧。車險承保的流程包含了投保、繳費、出單等幾個主要流程。如果出險了還會有報案、查勘、定損、理算等理賠流程。
領域可以被拆分成多個子領域,每個子領域代表一個更小的、具體的問題域。將一個大問題拆解爲多個小問題的過程,正是領域拆分的核心。在這一圖示中,保險領域被劃分爲四個主要子域:投保、支付、保單管理和理賠。每個子域都可以根據需求進一步拆解成更小的子子域。例如,支付子域可以進一步拆分爲收款和付款兩個子子域。
當拆分到一定程度時,某些子子域的邊界可能就與限界上下文的邊界相重合。限界上下文是領域模型中非常重要的概念,它代表着在一定範圍內,團隊使用的通用語言和模型的邊界。舉個例子,理賠子域可能會包括多個限界上下文,如報案、查勘和定損等,這些限界上下文共同構成了理賠子域的完整領域模型。而有些子域的邊界本身就可能與限界上下文的邊界一致,比如投保子域。
每個子域的領域模型都會對應一個限界上下文,而整個領域的領域模型則是由各個限界上下文的領域模型組合而成。理論上來說,限界上下文就是微服務的邊界。在設計微服務時,我們會將限界上下文內的領域模型映射到微服務上,從而將問題域轉化爲軟件的解決方案。因此,限界上下文實際上是微服務設計和拆分的核心依據。在領域模型的構建中,若不考慮技術異構、團隊溝通等外部因素,理論上每個限界上下文都可以獨立設計爲一個微服務。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/AO45OgKM_CdUHjSrXVThsA