識別限界上下文的工作坊演練
01
業務相關性
識別限界上下文的第一步是按照業務相關性對業務服務進行歸類和歸納,歸納後得到的內容可以將其稱之爲 “業務主體” 或者候選的限界上下文。業務相關性可以認爲是領域維度的高內聚低耦合劃分原則。
問題 1:技術實現影響邊界判斷
識別限界上下文時,我們一定要注意識別的順序:
-
領域維度
-
技術維度
-
團隊維度
這個順序不能亂!之所以名爲 “領域驅動設計”,就在於它將領域作爲設計的驅動力,因此,首要影響限界上下文邊界的,不是技術維度,也不是團隊維度,而是領域維度。
下圖是一位讀者識別的兩個限界上下文:
顯然,這兩個限界上下文是技術維度輸出的結果。因爲站在 how to do 的角度,它確實需要完成和微博與 Github 兩個外部系統(我的書中將其稱之爲伴生系統)的集成。
讓我們切換一下視角,單從領域維度來思考這兩個業務服務:
-
獲取微博動態
-
獲取 GitHub 賬戶最新提交記錄
雖然二者沒有語義上的相關性,但從功能相關性角度看,二者其實提供了一個共同的業務目標:爲用戶提供更爲豐富的個人信息。不要讓技術實現干擾你的判斷,顯然,這兩個業務服務更適合放在 “用戶上下文”。
問題 2:動詞作爲業務相關性判斷依據
業務服務由動詞短語構成。如果動詞短語包含了名詞類型的賓語,則該名詞往往體現了領域概念,可以作爲語義相關性的判斷標準。下圖所示的限界上下文就是通過語義相關性獲得的:
如果要使用業務服務的動詞進行判斷,切忌不要以動詞的語義相關性進行判斷。下圖給出的限界上下文恰恰犯了這個錯誤:
文章和部落上下文的獲得確實符合語義相關性,而部落推薦、部落搜索與文章推薦上下文的獲得,依據的就是動詞相關性了。這一劃分顯然是不合理的。下圖所示的劃分結果犯了同樣的錯誤:
真要以動詞相關性來劃分限界上下文,那倒是簡單了。所有的業務功能無外乎增刪改查,難道我們該由此將每個系統都劃分爲增、刪、改、查四個限界上下文嗎?
判斷動詞的相關性,考慮的其實是它對應的領域行爲向外輸出的業務能力,也就是功能相關性需要判斷的業務目標。
例如下圖的直播上下文:
爲何要將以下沒有任何語義相關性的業務服務放在同一個直播限界上下文?
-
打開攝像頭
-
關閉攝像頭
-
共享屏幕
-
轉移主持人
-
發言
-
打賞
不還是因爲它們都是在爲直播功能服務嗎?
根據動詞相關性識別限界上下文的錯誤還有不少例子,例如一位讀者識別出來的審批上下文與關注列表上下文,都是不合理的:
在歸納業務服務的共同特徵時,應以名詞作爲候選限界上下文的名稱。如果名稱爲動詞,或動詞形式的名詞,就需檢查和判斷:我們是否錯誤地以動詞作爲業務相關性的判斷依據了。
02
親密度
根據業務相關性的強弱對業務服務進行歸類,實則遵循了 “高內聚低耦合” 原則。如果分配合理,必然遵循:同一限界上下文內業務服務之間的親密度一定要高於跨限界上下文間的業務服務。若違背這一規律,說明業務服務的歸類存在問題。
檢查下圖分配的業務服務:
毫無疑問,屬於賬戶信息上下文的 “查詢積分” 業務服務,與同一限界上下文其他業務服務的親密度,顯然不及它與禮品上下文業務服務之間的關係強度。
03
限界上下文的本質特徵
根據業務相關性對業務服務進行歸類,不過是一種分類的方法,如果只限於此,劃分出來的不過是按照功能進行分解的模塊罷了。既然是識別限界上下文,自然要從限界上下文的本質特徵着手。
如《闡釋限界上下文》一文所述,限界上下文的本質特徵爲:
-
領域模型的知識語境
-
業務能力的縱向切分
在檢查我們識別出的限界上下文時,需要結合這兩個本質特徵作進一步甄別。
領域知識的知識語境
語義相關性體現了對領域知識的歸類,然而限界上下文不僅如此,它還是領域概念的邊界,通過它可以限定當前上下文的領域知識,避免領域概念在理解上的分歧與衝突,形成當前上下文的統一語言。
例如在技術部落平臺中,用戶、企業用戶和會員有着不同的知識語境。其中,企業用戶與之對應的是個人用戶,它們都是用戶的一種類型,在對用戶進行身份管理時,應該一視同仁,區別只在於用戶的屬性不同,應該將它們都放在用戶上下文。至於會員,表示該用戶屬於部落的會員,實際體現的是用戶與部落之間的關係,與之相關的業務服務應該放在部落上下文。
有的讀者將用戶上下文命名爲賬戶上下文,這沒有問題,但需要明確統一語言。例如賬戶代表的含義?不要將代表用戶身份的賬戶與支付相關的賬戶混爲一談。
業務能力的縱向切分
分配在一起的業務服務應該對外提供相同或相似的業務能力。以下圖爲例:
用戶上下文對外提供的應該是用戶身份認證與用戶基本信息管理的業務能力。放在該限界上下文內部的以下業務服務則不然:
-
設置工作經歷
-
設置項目經歷
-
設置技能信息
-
生成個人簡歷
它們爲個人簡歷提供了必要的領域知識,形成了與求職相關的業務能力。這些領域知識也只有在求職或招聘時纔會使用到,因此,以上分配並不合理。
圖中 “關注活動” 業務服務的分配也不合理,它主要違背了 “親密度” 的原則,因爲該業務服務與活動上下文的親密度更高。
04
驗證原則
識別的限界上下文是否正確,分配的業務服務是否合理,還需要進一步通過我總結的驗證原則進行驗證。
原則 1:單一抽象層次原則
如果識別合理,獲得的限界上下文應該儘可能處於同一個抽象層次。不同層次的抽象可能導致限界上下文的含義互相包含。例如:
即使部落推薦上下文和部落搜索上下文的識別是合理的,它也違背了單一抽象層次原則,因爲部落上下文的抽象實際上已經涵蓋了部落推薦和部落搜索的含義。
遵循單一抽象層次原則,還意味着我們在歸納業務服務時,需要適度的抽象,千萬不要抽象過猛。下圖歸納獲得的限界上下文都是抽象過猛的反例:
社交、工具、服務、互動、售後都是含義極爲寬泛的通用概念,矛盾的是,如此抽象的限界上下文,卻僅僅包含了數量極少的業務服務,如此大的反差,足以說明抽象層次的不合理。
有時候,又可能因爲抽象不夠導致概念的不一致。如下圖所示:
雖然抽象爲招聘上下文,但其中包含的業務服務一部分提供了招聘的業務能力,另一部分則提供了求職的業務能力。顯然,招聘這一抽象不足以涵蓋整個限界上下文的業務服務。要將這些業務服務歸類在一起,需要建立一個更高的抽象,例如工作或者人才,如此抽象就合理了。
原則 2:奧卡姆剃刀原則
將奧卡姆剃刀原則翻譯成能理解的中文,就是 “若無必要勿增實體”。這裏所謂的實體,當然是指限界上下文。也就是說,在切分限界上下文時,一定要有拆分的充足理由,如果沒有理由,就應該優先考慮合併,避免因爲增加太多不必要的限界上下文,從而增加架構的複雜度。
例如有一位讀者將直播室的業務服務單獨剝離出來,定義了直播室上下文:
這樣的細分有何依據呢?直播室和直播的差別又在哪裏呢?如果直播室要分開,那麼直播上下文的其他業務服務,如打開攝像頭、關閉攝像頭爲何又不分開呢?
分開之前,還是先找一個能夠自圓其說的理由吧!
原則 3:正交原則
遵循正交原則,可以保證限界上下文之間不存在交叉或重疊的領域知識,如此就能將變化帶來的影響降到最低。
如下圖的活動上下文:
該限界上下文有多個業務服務都與 “報名” 有關。報名不僅僅是體現了領域行爲的動詞,它同時還涵蓋了與報名有關的領域知識,如報名通道、報名流程和報名的規則。
現在,直播上下文也有與報名有關的業務服務,如 “報名參加直播”,如果二者都需要操作和報名相關的領域知識,就存在領域知識的重疊。要遵循正交原則,可以考慮單獨定義一個報名上下文。
**說明:**雖然在中文中,報名通常解釋爲動詞,但這裏的上下文名稱實際上並非使用報名的動詞語義,如果翻譯爲英文,可以理解爲是名詞 enrollment,而非動詞 enroll。
原則 4:最小驚訝法則
識別出來的限界上下文,無論是限界上下文的名稱,還是業務服務與限界上下文之間的關係,都要保證合理性,不能讓人莫名驚訝。
例如,技術部落提供了提問、回答的功能,如果將這些業務服務歸類在一起,將其命名爲 “問答”,就能讓人一望而知其含義,如果非要將其命名爲 BBS 或者論壇,就很容易讓人產生誤解了。
只要能夠說明其含義,限界上下文的命名可以力求精簡。如一位讀者識別出了技術文章上下文和技術部落上下文,實際上,在技術部落平臺這個大背景下,何必增加 “技術” 這個修飾詞呢?更何況,技術部落上下文還很容易與技術部落平臺混淆,不如直接命名爲文章上下文與部落上下文。
仔細分析如下圖識別出來的工具上下文,對照其名稱,它包含的業務服務足夠讓人驚訝了。
限界上下文的名稱一定要足以涵蓋其內部所有業務服務的概念,做到觀其名,就能大致推測出內部有哪些業務服務,而不應產生意外驚訝。上圖的業務服務分配產生的不是驚喜,而是不可思議的驚詫,違背了最小驚訝法則。
以上分析了從領域維度識別限界上下文暴露的諸多問題,並一一做了解答。可以看到,我們並不滿足於識別出限界上下文,還需要獲得限界上下文與業務服務的映射關係,如此才能對後續的設計和建模工作產生指導作用。
行文至此,文章已經足夠長了。
關於技術維度和團隊維度對限界上下文邊界的影響,就留待下一篇文章吧。在下篇文章,我還會給出我的參考答案,大家可以結合自己的結果進行對比。
對於踊躍參加本次工作坊演練的讀者,請稍安勿躁,我希望再保留一點點懸念,留待下一篇文章再公佈最終的獲勝者。謝謝大家!祝大家聖誕快樂!
聖誕節快樂
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/sakHmhks6n5eSSXR0WnRbg