限界上下文(簡稱BC)是一個很難講的部分。我尋思著是不是再多找一找文章,看看其它人怎麼講的,但猶豫再三還是決定按自已的理解去聊,各種找材料就有點剽竊的行為了。至於說的是否正確,您務必也要做好判斷,畢竟每個人都會有自己的理解。做為溫故而知新的一部分,在此把前面總結的BC的特點再重複一下,也不是為了湊字兒,DDD這東西就得靠多多的囉嗦才能記得住,畢竟概念忒多。此外,為提升您的閱讀體驗,限界上下文分為兩節分別講解。
BC的特點包括四個方面:1)是系統的物理劃分;2)應根據子域的定義進行推導;3)限定了領域模型的邊界,是對領域模型的一種劃分和限定;4)BC內每個領域術語都有且只有一個明確的含義(即通用語言)。
BC的設計一般是通過子域進行推導。假如將DDD的指導分成三部分:子域設計、BC設計和程式碼設計,BC屬第二層,起到承上啟下的作用,在將業務模型轉換為技術的過程中提供巨集觀指導。BC定義的過程其實就是確認有幾個子系統(或Java中的包、.NET中的名稱空間),有哪些領域模型(此處的領域模型是一種業務術語不是指‘類’或‘介面’)以及子系統間如何互動。從上述概念上可以看出來,討論BC時既有業務的部分也有技術的內容。
領域模型 1、領域模型的使用貫穿了“分析”、“設計”、“開發”的整個流程,各類人員都應該使用領域模進行溝通和交流,避免系統在實現過程中需求走樣 2、領域模型只反映業務與技術無關,其不僅包括業務中的實體如“訂單”、“客戶”等還包含業務流程如“下訂單” 3、領域模型是有邊界的,我們只應該關注業務所關注的部份 |
在進入BC的討論之前,首先介紹一些基本概念避免後續我們用到的時候作為讀者的您一臉的蒙圈,怪我不事先說事後賣關子。第一個介紹的詞叫“建模”,第二個要介紹的詞是“模型”。不論是作為軟體開發老炮兒還是菜鳥,您可能在無數的場合聽了無數次的這個詞。遙想當前我初來乍到,但凡聽誰說在做軟體建模,給我的第一印象就是這人妥妥的大牛一個。那它到底是什麼意思呢?我們換成人話就是:比如有這麼一個事兒,我嘴笨和您說不明白,那就寫一段兒或者畫個圖。反正不管用什麼手段,只要您懂了我的意圖我們這目的就達到了。這裡所說的“一段文字”或“圖”就是模型,幹這個事情的過程就叫“建模”。所以您不管是做設計子域還是BC還是畫流程圖,都是建模,不知道為什麼非得用“建模”,IT圈就是不喜歡說人話。
題外話:中國IT圈對一些詞的翻譯我覺得真是前無古人:控制程式碼、多型、建模、閉包……這翻譯,不服來戰。
回到正題,在軟體設計活動中(嚴謹的說是在UML建模過程中)包含三類模型:業務模型、分析模型和設計模型,具體解釋如下列表。不過我們得多說一句,我們常見的類圖啊、時序圖啊,你可別認為這些模型僅用於實施前的設計階段,在業務分析階段也是可以用的,只是目的不一樣。您可別回頭一說類圖就認為只在軟體設計階段專用,對外行說說就行了,內行我們得有內行的專業素養。
- 業務模型:用於解釋與說明業務邏輯的各類文件或圖,與是否有電腦無關係,是對客觀的業務的描述。子域設計即是業務模型設計。
- 分析模型:用於說明哪些業務可在軟體系統中實現(並非所有的業務都可被落實到軟體中,這就是為什麼常常見到開發與產品經理互撕),其上面連線了業務模型下面對應到設計模型。BC設計即分析模型設計。
- 設計模型:用於說明軟體在程式碼層次上的設計方式,常見的如類圖、活動圖、時序圖等。DDD戰術階段所建模型如聚合、實體即為設計模型。
我不僅說了三個模型還能套在DDD上,一是沒跑題,二是顯得專業。能這個事兒圓回來,我自己都佩服自己。另外著重說一點,所有的模型裡,文件是最重要的,具體您自行體會。關於文件這個事情,也再多囉嗦幾句。一般來說不建議花精力在程式碼設計階段編寫大量的文件,一是會很佔用時間二是幾乎沒有多少公司能保證程式碼變化的同時文件也隨之變化,在此情況下文件不僅不能說明問題還特別耽誤事兒。But,業務模型文件是必需的,這東西變化率不是很高。您也別跟我抬扛,一個企業的業務模型天天變化,我勸您趁早離職,他自己都沒找到方向。至於分析模型,屬於過渡型文件,視具體情況而定。
上一章中展示了個人微信的域圖,為避免誤會本節以一款“即使通訊軟體”的後端架構為例展示限界上下文的設計圖,由於並無實際的軟體,您仍可以微信為對照。我得先避個嫌疑,回頭騰訊公司找過了就蝦米了……另外,實際的系統架構比案例複雜的多的多,劃分得也會更加的詳細。此處僅做為引子告訴您如何進行BC設計,您在日常工作中需要學會舉一反三,這也是治學問的正確姿勢。時間久了,你就能體會何為“眾裡尋他千百度,驀然回首,那人卻在,燈火闌珊處”。
為能說明問題,本例中把“小程式管理子域”和“鑑權子域”去掉了,圖不好畫(其實主要是影響您的閱讀體驗)。此外,上一章針對“通訊錄子域”和“聊天子域”的設計不夠細緻,需要進行細化。下圖為兩個子域的細化結果,注意:此處的設計仍為子域圖,尚未到BC設計階段。
子域經過細化後我們建立了下面的BC圖,需要注意的是BC設計圖中應該以實線表示每一個限界上下文,因為BC具備物理特性已非概念上的模型, BC間的互動通過實線進行連線。
BC的設計不僅需要子域設計為參考,還需要結合您的團隊與公司的實際情況進行計。本案例的建設由同一部門的人數為200的成員所組成的團隊,包括研發、測試、運維、產品經理、專案經理等基本角色,因資源充沛且崗位齊全,確定使用微服務架構作作為系統落地時的方案。我們來詳細解釋一下本方案的設計依據。
- 聊天子域:分為“通訊管理”和“歷史訊息管理”兩個子系統,前者用於聊天場景比如傳送各類文字、圖片等;後者用於對歷史訊息進行儲存以用於記錄查詢。這兩個BC所關注的業務點有很大差異,邊界較為明顯,兩個BC可使用不同的系統架構並可獨立進化。
- 訊息審計使用了第三方採購的實時審計系統用於對使用者所發的朋友圈或訊息進行審計以避免非法內容的存在。
- 通訊錄子域分為兩個BC:“聯絡人管理”和“好友關係管理”分別用於管理本賬戶的聯絡人和用於朋友推薦的推薦系統。
一般來說BC和子域是可以一一對應的。當然,具體情況還要視您所在公司和團隊的架構。假如說子域的設計是專案的開端,那BC的設計的好壞幾乎可以決定系統的成敗,應當是設計過程中投入精力最多的地方。其原因前面已然說過:子域劃定了一個個小的物理系統,天然具備隔離效果,當您的系統具備良好的BC設計時,即便某個BC出現失敗也不會導致整個系統的業務雪崩。後面我們談到DDD的隔離機制時您就會發現為什麼BC的隔離是最為核心和關鍵的。
BC的設計粒度,往大了看其實可以是一個子系統本身,單體系統只有一個BC(此種情況下,單系統已經不能算是純粹上的BC,應當以“包”或“名稱空間”作為BC的基本單位);往小的方面看,最小的粒度為“聚合”,切記!真的不能再小了。無論其大小,關鍵的設計原則是“完整”即BC可以完整的支撐某項業務,換另外的說法就是每個BC應該是自治的且與其它BC有清晰的邊界。實際上,當您在BC設計時會發現大部分情況下尋找BC邊界是一個非常自然的過程,還是那句話:人是有靈性的。
注意! 系統的建設過程(開發階段)中,請務必保證您的領域模型不能外洩到BC之外,這裡的BC可以是一個專案也可以是一個包或名稱空間。BC間的互動只能通過DTO或訊息(其實訊息也是一種DTO) |
實際上,BC的設計過程中還是有許多的原則可以遵守的,在此一一列舉出來。
- BC的設計是系統的巨集觀架構設計,一經確認後就需要以此為依據進行實施
- 以業務維度為準進行BC設計。這一條會存在例外:前後端分離架構,是一種比較典型的以技術為參照的的BC設計方式。就前端是否屬於BC一部分的問題目前還是有一定的爭議的,比較權威的書上的回答也是“Yes”,為此還引入了微前端的技術。我個人建議您視自己的公司與團隊情況而定,不必拘泥於理論。
- BC設計需要以您的組織結構包括團隊技術層次、團隊組織結構、是否跨部門、人力資源情況等為參考以免雖有設計方案但無法落地,陷入紙上談兵的境界,造成前期工作浪費。
- BC也需要保持隨時變更,尤其是在子域有變更的情況下
- DDD中最為重要的規律是“運動與適應”,一切事務皆在變化中,您需要隨時根據變化做調整
- 現實中,有些帶頭大哥喜歡根據開發任務來設計BC,這種情況最好少用以減少甩鍋的情況。另外,個人建議BC的開發工作只由一個人負責即由上面的service到最下面的dao,不要針對同一個聚合讓過多的人蔘與,每個人都有自己的設計思路,非常容易出現重複性的內容;一個研發人員的連貫性思路也很容易被打斷。如果BC較大,也請限制在一個團隊內以減少溝通成本
- 限界上下文的識別實際上並沒有標準可言,可以通過業務複雜度、管理複雜度和技術複雜度去分析和識別,迭代化的進行分析 。
為了讓您明白,我們再整一個例子。這裡以一個電商購物系統為例,展示其BC的設計方式。本案例中,團隊人員較少,由開發人員承擔著運維的職責;系統客戶物件以企業內部使用者為主。為方便說明,我們仍只展示部分子域:核心域中的銷售子域,如下圖所示。
依據上圖所示的子域說明,推匯出如下BC設計。
不同於第一個案例,本例未使用微服務架構,而是使用了單體架構作為其落地方式。我知道有些人是強烈的微服務架構擁護者,但我仍然需要在此強調:系統的架構選擇時,技術能力僅僅是一方面,而且還只是很小的一個方面。決策我們架構選擇的因素有許多,比如團隊的綜合能力(注意:不能以團隊中是否有一兩個高手來決策團隊綜合能力)、團隊結構、公司的總體結構(尤其您要做的系統是業務中臺時)等。專案背景中已說明“開發兼職運維”,說明當前團隊使用容器化部署、鏈路追蹤、全棧監控等技術時會比較勉強,即使強加到系統中也會由於資源的不足造成您想要的結果與期望不匹配。
最後需要說一句,我們都知道微服務架構有各種優勢,也知道單體系統有各種不足。但任何事務都有其兩面性,在您使用的時候需要首先綜合評估自身所具備的條件。再說了,您做的系統不是一錘子買賣,隨著後續資源的投入,您是可以進行架構優化的。