大白話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最大的價值其實還是在梳理業務的時候劃分清楚業務領域的邊界,其核心思想其實還是高內聚低耦合而已。至於工程方面,現在微服務的粒度已經足夠細,完全沒必要再多這麼一層。這多出來的這一層,多少有種沒事找事的感覺。更可笑的是,這個概念本身在對外普及自己的東西的時候,玩足了文字遊戲,讓大家學的一頭霧水。真正好的東西,是能夠解決問題,並且能夠很容易的讓人學明白,而不是一昧的造新詞去迷惑人,也希望以後網際網路行業多一些實幹,少說一些黑話。