大白話DDD(DDD黑話終結者)

語言: CN / TW / HK

一、吐槽的話

相信聽過DDD的人有很大一部分都不知道這玩意具體是幹嘛的,甚至覺得它有那麼一些虛無縹緲。原因之一是但凡講DDD的,都是一堆特別高大上的概念,然後冠之以一堆讓人看不懂的解釋,。作者曾經在極客時間上買了本DDD實戰的電子書,被那些概念一路從頭灌到尾,灌得作者頭昏腦漲,一本電子書那麼多文章愣是沒有一點點像樣的案例,看到最後也 沒明白那本電子書的作者究竟想寫啥。原因之二是DDD經常出現在互聯網黑話中,如果不能稍微瞭解一下DDD中的名詞,我們一般的程序員甚至都不配和那些説這些黑話的人一起共事。

為了幫助大家更好的理解這種虛無縹緲的概念,也為了更好的減少大家在新詞頻出的IT行業工作的痛苦,作者嘗試用人話來解釋下DDD,並且最後會舉DDD在不同層面上使用的例子,來幫助大家徹底理解這個所謂的“高大上”的概念。

二、核心概念

核心的概念還是必須列的,否則你都不知道DDD的名詞有多麼噁心,但我會用讓你能聽懂的話來解釋。

1、領域/子域/核心域/支撐域/通用域

領域

DDD中最重要的一個概念,也是黑話中説的最多的,領域指的是特定的業務問題領域,是專門用來確定業務的邊界。

子域

有時候一個業務領域可能比較複雜,因此會被分為多個子域,子域分為了如下幾種:

  • 核心子域:業務成功的核心競爭力。用人話來説,就是領域中最重要的子域,如果沒有它其他的都不成立,比如用户服務這個領域中的用户子域
  • 通用子域:不是核心,但被整個業務系統所使用。在領域這個層面中,這裏指的是通用能力,比如通用工具,通用的數據字典、枚舉這類(感歎DDD簡直恨不得無孔不入)。在整個業務系統這個更高層面上,也會有通用域的存在,指的通用的服務(用户服務、權限服務這類公共服務可以作為通用域)。
  • 支撐子域:不是核心,不被整個系統使用,完成業務的必要能力。

2、通用語言/限界上下文

通用語言

指的是一個領域內,同一個名詞必須是同一個意思,即統一交流的術語。比如我們在搞用户中心的時候,用户統一指的就是系統用户,而不能用其他名詞來表達,目的是提高溝通的效率以及增加設計的可讀性

限界上下文

限界上下文指的是領域的邊界,通常來説,在比較高的業務層面上,一個限界上下文之內即一個領域。這裏用一張不太好看的圖來解釋:

image.png

3、事件風暴/頭腦風暴/領域事件

事件風暴

指的是領域內的業務事件,比如用户中心中,新增用户,授權,用户修改密碼等業務事件。

頭腦風暴

用最俗的人話解釋,就是一堆人坐在一個小會議室中開會,去梳理業務系統都有哪些業務事件。

領域事件

領域內,子域和子域之間交互的事件,如用户服務中用户和角色交互是為用户分配角色,或者是為角色批量綁定用户,這裏的領域事件有兩個,一個是“為用户分配角色”,另一個是“為角色批量綁定用户”。

4、實體/值對象

實體

這裏可以理解為有着唯一標識符的東西,比如用户實體。

值對象

實體的具體化,比如用户實體中的張三和李四。

實體和值對象可以簡單的理解成java中類和對象,只不過這裏通常需要對應數據實體。

5、聚合/聚合根

聚合

實體和實體之間需要共同協作來讓業務運轉,比如我們的授權就是給用户分配一個角色,這裏涉及到了用户和角色兩個實體,這個聚合即是用户和角色的關係。

聚合根

聚合根是聚合的管理者,即一個聚合中必定是有個聚合根的,通常它也是對外的接口。比如説,在給用户分配角色這個事件中涉及兩個實體分別是用户和角色,這時候用户就是聚合根。而當這個業務變成給角色批量綁定用户的時候,聚合根就變成了角色。即使沒有這樣一個名詞,我們也會有這樣一個標準,讓業務按照既定規則來運行,舉個上文中的例子,給用户A綁定角色1,用户為聚合根,這樣往後去查看用户擁有的角色,也是以用户的唯一標識來查,即訪問聚合必須通過聚合根來訪問,這個也就是聚合根的作用。

三、用途及案例

目前DDD的應用主要是在戰略階段和戰術階段,這兩個名詞也是非常的不講人話,所謂的戰略階段,其實就是前期去規劃業務如何拆分服務,服務之間如何交互。戰術階段,就是工程上的應用,用工程化做的比較好的java語言舉例子,就是把傳統的三層架構變成了四層架構甚至是N層架構而已。

1、微服務的服務領域劃分

這是對於DDD在戰略階段做的事情:假如目前我司有個客服系統,內部的客服人員使用這個系統對外上億的用户提供了形形色色的服務,同時內部人員覺得我們的客服系統也非常好用,老闆覺得我們的系統做的非常好,可以拿出去對外售賣以提高公司的利潤,那麼這時候問題就來了,客服系統需要怎樣去改造,才能夠支持對外售賣呢?經過激烈的討論,大致需求如下:

  • 對外售賣的形式有兩種,分別是SaaS模式和私有化部署的模式。
  • SaaS模式需要新開發較為複雜的基礎設施來支持,比如租户管理,用户管理,基於用户購買的權限系統,能夠根據購買情況來給予不同租户不同的權限。而私有化的時候,由於客户是打包購買,這時候權限系統就不需要再根據用户購買來判斷。
  • 數據同步能力,很多公司原本已經有一套員工管理系統,通常是HR系統或者是ERP,這時候客服系統也有一套員工管理,需要把公司人員一個一個錄入進去,非常麻煩,因此需要和公司原有的數據來進行同步。
  • 老闆的野心還比較大,希望造出來的這套基礎設施可以為公司其他業務系統賦能,能支持其他業務系統對外售賣

在經過比較細緻的梳理(DDD管這個叫事件風暴/頭腦風暴)之後,我們整理出了主要的業務事件,大致如下:

1、用户可以自行註冊租户,也可以由運營在後台為用户開通租户,每個租户內默認有一個超級管理員,租户開通之後默認有系統一個月的試用期,試用期超級管理員即可在管理端進行用户管理,添加子用户,分配一些基本權限,同時子用户可以使用系統的一些基本功能。

2、高級的功能,比如客服中的機器人功能是屬於要花錢買的,試用期不具備此權限,用户必須出錢購買。每次購買之後會生成購買訂單,訂單對應的商品即為高級功能包。

3、權限系統需要能夠根據租户購買的功能以及用户擁有的角色來鑑權,如果是私有化,由於客户此時購買的是完整系統,所以此時權限系統僅僅根據用户角色來鑑權即可。

4、基礎設施還需要對其他業務系統賦能。

根據上面的業務流程,我們梳理出了下圖中的實體

image.png

最後再根據實體和實體之間的交互,劃分出了用户中心服務以及計費服務,這兩個服務是兩個通用能力服務,然後又劃分出了基於通用服務的業務層,分別是租户管理端和運營後台以及提供給業務接入的應用中心,架構圖如下:

image.png

基礎設施層即為我們要做的東西,為業務應用層提供通用的用户權限能力、以及售賣的能力,同時構建開發者中心、租户控制枱以及運營後台三個基礎設施應用。

2、工程層面

這個是對於DDD在戰術設計階段的運用,以java項目來舉例子,現在的搞微服務的,都是把工程分為了主要的三層,即控制層->邏輯層->數據層,但是到了DDD這裏,則是多了一層,變成了控制層->邏輯層->領域能力層->數據層。這裏一層一層來解釋下:

| 分層 | 描述 |
| :------------- | :----------: | | 控制層 | 對外暴漏的接口層,舉個例子,java工程的controller | | 邏輯層 | 主要的業務邏輯層 | | 領域能力層 | 模型層,系統的核心,負責表達業務概念,業務狀態信息以及業務規則。即包含了該領域(問題域)所有複雜的業務知識抽象和規則定義。 | | 數據層 | 操作數據,java中主要是dao層 |

四、總結

在解釋完了各種概念以及舉例子之後,我們對DDD是什麼有了個大概的認知,相信也是有非常多的爭議。作者搞微服務已經搞了多年,也曾經在梳理業務的時候被DDD的各種黑話毒打過,也使用過DDD搞過工程。經歷了這麼多這方面的實踐之後覺得DDD最大的價值其實還是在梳理業務的時候劃分清楚業務領域的邊界,其核心思想其實還是高內聚低耦合而已。至於工程方面,現在微服務的粒度已經足夠細,完全沒必要再多這麼一層。這多出來的這一層,多少有種沒事找事的感覺。更可笑的是,這個概念本身在對外普及自己的東西的時候,玩足了文字遊戲,讓大家學的一頭霧水。真正好的東西,是能夠解決問題,並且能夠很容易的讓人學明白,而不是一昧的造新詞去迷惑人,也希望以後互聯網行業多一些實幹,少説一些黑話。