本文書接上回《為了落地DDD,我是這樣“PUA”大家的》,關注公眾號(老肖想當外語大佬)獲取信息:
- 最新文章更新;
- DDD框架源碼(.NET、Java雙平台);
- 加羣暢聊,建模分析、技術實現交流;
- 視頻和直播在B站。
https://mp.weixin.qq.com/s/DjC0FSWY1bgJyLPIND5evA
什麼是最重要的事
如果你認真讀過前面的文章,那麼一定知道我們的核心邏輯:領域驅動是一種價值觀,這個價值觀是:“領域(邊界)”的明確是軟件設計掌控複雜度最重要的事。
那麼整個軟件交付過程中,架構師的職責就是持續保持“需求”、“模型”、“代碼”三者的邊界範圍明確且一致。再回過頭看整個軟件交付存在的意義,就是為了滿足需求,因此本質上來説,“需求”的邊界就決定了一切,那麼結論就不言而喻了:
最重要的事,就是需求的邊界(範圍)。
什麼叫邊界明確
假如説我有兩個需求A和B,那麼我們建模的時候就有如下幾種結果,大家感受一下,通常情況下,自己給出的結果是哪個選項?哪個選項又是最理想的?
我相信大部分人都會認同,其中B和D是符合邊界明確、需求與模型邊界一致的原則的,而現實的情況大部分結果是A和C,各種各樣的“join”充斥着系統的各個角落,一個典型的例子,就是用户-角色系統的設計。
用户-角色系統,通常會有這樣幾個關鍵需求:
- 創建用户
- 創建角色
- 為用户設置角色
- 查看用户有哪些角色
- 查看一個角色包含多少個用户
我們用最傳統的設計方法來做,模型大體是這樣的:
這樣的結果是不是對應到了前面選項A和C比較類似?因為“用户聚合”與“角色聚合”連線的存在,導致需求與模型的邊界不一致。
而我們要做的,就是在滿足所有需求的同時,消除打破邊界的連線。
如何操作
首先我們分析上圖,假如我們把下面幾個需求先去掉:
- 為用户設置角色
- 查看用户有哪些角色
- 查看一個角色包含多少個用户
那麼我們會得到一個符合邊界明確原則的設計:
然後我們再思考,下面兩個需求,應該哪個聚合負責:
- 為用户設置角色
- 查看用户有哪些角色
答案很顯然是“用户聚合”,那麼我們可以得到下面的設計:
這時你會疑問,如果沒有“用户聚合”和“角色聚合”的連線,怎麼設置用户有哪些角色呢?
問題的關鍵,就在這裏,通常我們總是會把“關係表”在圖中用一條線來表示,那如果我説,“用户聚合”有一個集合屬性,叫做“用户角色”,你會認同嗎?如果我們知道用户對象有一個集合屬性叫“用户角色”,那麼是不是上圖就很合理?
如果順着這個思路,我們再來看需求“查看一個角色包含多少個用户”,它應該由哪個模型來解決?我想你已經知道答案了,就是“用户聚合”,最終我們得到如下設計:
到此,所有的需求可以滿足,需求被劃分為兩個範圍,分別對應兩個模型。
為什麼説它很難
如果你一直跟着我的思路,完成了上面的過程,那麼你會發現,需求的邊界不是客觀存在的,而是我們主觀的劃分,這個劃分的目的是為了在一個確定的範圍內,能夠解決這個問題。因為它是主觀的,就不可衡量和判斷,每個人都可以有自己的劃分思路。另外它又是簡單的,因為你可以像上圖一樣,這樣劃分邊界,給出對應的模型解決它,就像在給自己家的襪子分配收納盒一樣簡單。
所以,我常常嘆息,關於領域驅動設計:
説它難,難的是做出取捨。
説它簡單,是因為能明確知道取什麼舍什麼。