DDD戰略設計相關核心概念的理解
阿新 • • 發佈:2019-06-05
前言
本文想再討論一下關於領域、業務、業務模型、解決方案、BC、領域模型、微服務這些概念的含義和關係。初衷是我發現現在DDD領域建模以及解決方案落地過程中,常常對這些概念理解不清楚或者有歧義,導致我們不知道如何運用這些概念來落地我們的軟體。
領域、業務、業務模型
- 領域,即問題域、問題空間,領域是一種邊界、範圍。所以,一個領域代表了一個問題域的邊界,也可以理解為是一個業務的邊界。領域邊界越大,業務範圍就越大,反之則相反;通常我們大家交流都比較喜歡用業務這一詞,比如這塊業務,那塊業務,業務的邊界,我是一個業務開發人員(區分於我是一箇中間件開發人員)。而領域一詞,相對比較抽象,不是那麼容易懂。
- 領域既然是一個邊界,所以可以劃分領域的大小,即領域劃分,劃分出來的子領域簡稱子域,每個子域對應一個小的問題域和和小的業務;當然,不同的子域的重要性也是不同的,所以才有了核心子域、支撐子域的說法,這點顯而易見。
- 每個業務都有一個對應的業務模型(注意這個業務模型不是領域模型,而是一個業務概念的模型,領域模型下面會提到),這個業務模型設計的時候,完全不需要考慮任何軟體設計的思想,比如物件的抽象、繼承、儲存、效能,等。我們是從業務本身出發,分析業務邊界範圍內的各種業務概念,以及業務概念之間的關係,通常我們可以使用一個業務模型的圖來表達這些業務概念以及業務概念之間的關係。那麼如何得到一個業務模型呢?最常見的有名詞動詞形容詞分析法,還有比如四色原型分析法,都可以。找一個適合自己的就行;業務模型本身非常有價值,它提煉了領域內業務的核心概念及其關係,可以幫助我們更好的理解業務本身。
解決方案
- 什麼是解決方案?我們在進行DDD領域驅動設計的實踐時,會進行需求分析、領域劃分、領域建模等工作。而我們的系統要落地,則需要有一套解決方案。例如,我們要實現一個電商平臺,需要一個複雜的系統解決方案,但是如果這個解決方案過大,各模組、元件都揉在一起,那麼就不利於整個系統的維護、演進、伸縮,等。所以,我們需要把解決方案拆分為一個個獨立的小的解決方案;所以,我們可以發現,領域和解決方案,是兩個完全不同的概念,領域代表問題空間,解決方案代表解決方案空間。
- 解決方案該如何拆分呢?簡單的回答是:看情況,憑經驗。說的具體點,就是我們需要使用軟體設計的各種原則、最佳實踐、設計模式、非功能特性的需求,以及團隊成員的情況來指導我們進行解決方案的拆分或者直接不拆分,最終得出一個綜合考慮後的拆分結果。所以,我們發現解決方案的拆分的維度可能有很多,沒有一個單一的在任何情況下都合理的切分維度。有時我們可能從效能的角度來拆分,有時從不同架構分開演進(如CQRS架構)的角度,有時從分開伸縮的角度,有時從切合團隊組織架構的維度。但是拆分的時候,多考慮一些各個因素,才能讓我們更好的進行解決方案空間的拆分。
BC
- BC,即Bounded Context,中文翻譯為限界上下文。BC在DDD一書中首次出現,BC的理解分為兩個層面:1)Bounded,表示邊界的意思;2)Context,即上下文,我理解為是一個場景的上下文,這個場景不侷限於普通的業務場景,而是各種上下文都涵蓋在內,是一個時空感知的概念。比如我們兩個人在公司交談時的上下文是一個上下文,但是在路上交談時,則切換到另一個上下文了,因為交談的地點發生了變化;所以,BC合起來理解,就是一個上下文的邊界。
- BC有什麼用呢?就是為了表達上面介紹的某個粒度的解決方案的上下文邊界。那為何要強調這個邊界呢?有了這個邊界,我們才可以定義這個邊界內的領域模型中所有物件概念的明確含義。如果沒有這個上下文邊界,對同意概念在不同上下文的理解,大家就會產生偏差。舉個栗子:商品,在商品中心的解決方案BC中,商品中心負責管理電商平臺的所有商品,所以商品在商品中心BC中,是一個聚合根;但是在訂單中心解決方案BC中,雖然也叫商品,但是它只是一個值物件。我們知道訂單中心的訂單是一個聚合,訂單內聚合了多條訂單明細,每個明細是一個實體,每個訂單明細對應了一個商品。雖然叫做商品,但是這個商品本質上只是商品中心的商品的一部分資訊,如商品ID、標題、價格,且是隻讀的。
- 那為何解決方案的邊界要叫做BC呢?對,我們可以不用叫做BC,比如你就叫做解決方案邊界,也沒問題。只是Eric在寫作DDD這本書時,把他叫做BC,所以我們沿用了他的概念。我們主要的目的是為了用BC來表達解決方案空間的邊界。
- BC和子域的關係?沒有關係。因為它們是不同的東西被劃分後的產物,對解決方案空間進行劃分產生了BC,對領域劃分後產生了子域。而且它們劃分的依據也不同,所以必定會出現BC與子域的關係是1對1,1對多,多對1的各種可能性。注意,我說的是被劃分後的產物,所以這個產物叫什麼其實不重要,我們真正要學會的是劃分的原則、依據、經驗,有了這些,我們才能合理地劃分BC和子域。
領域模型
- 什麼是領域模型?這裡討論的領域模型是指DDD一書中提到的領域模型,領域模型是DDD軟體設計方法論中的核心概念,它是業務分析、軟體設計的綜合結果,是一個系統設計模型。領域模型存在於某個粒度解決方案空間裡。所以,任何一個領域模型,都是在特定的BC邊界內才有意義;
- 領域模型和業務模型的區別:我覺得領域模型有一個引起人們誤會的地方,就是它的名稱。很多人容易把領域模型理解為上面提到的業務模型,因為領域容易聯絡到業務,所以領域模型就是業務模型,比如非常著名的一本書《UML和模式應用》中,就認為領域模型是需求分析階段的業務模型,是一種業務概念實體的模型。實際上兩者是不同的,因為業務模型是對業務概念及其關係的表達,而領域模型在業務模型的基礎上,用OOA/D的思想進行進一步抽象的軟體設計模型,而且領域模型中有聚合、實體、值物件的區分。舉亮個栗子:1)業務模型中,我們可能會有買家、賣家、讀者、教師的業務概念,但是在領域模型中,我們已經把這些概念抽象為了賬號這個模型。2)再比如一個讀者持借書卡去圖書館借書這個場景,在業務模型中會存在一個借書卡的業務概念,而在領域模型中,我們很可能會去掉借書卡,因為它只是一個借書的工具,是借書系統用來識別讀者的一個工具,系統真的的目的是為了知道哪個賬號在借書,而不關心如何識別出這個賬號。如果我們有一個網上借書系統,那就不需要借書卡了,而是要提供賬號登入功能。在DDD一書中,作者一步到位直接根據需求設計出領域模型,在提煉需求分析需求的過程中直接應用軟體設計思想和抽象思維一步到位產出領域模型,我個人覺得是有點快的,更好的做法應該是先分析出業務模型,再對業務模型進行精煉,得到領域模型;
- 既然領域模型存在於某個粒度的解決方案空間中,而這個粒度的解決方案空間可能會對應多個子域。所以,這個領域模型則基於多個子域的業務模型結合起來推匯出來的一個系統模型。
- 那如何進行領域建模得到領域模型呢?這個就比較複雜了,不過經過前面的討論,大致分為兩個大的階段:1)先得到業務模型;2)再對業務模型進行模型精煉;如何精煉?運用軟體設計思想和原則,以及歸納演繹的抽象思維;所以,領域建模歸根結底也是要“看情況,憑經驗”,是不是很沮喪:)
微服務
最近幾年,微服務開始流行起來,把DDD也帶火了一把。那為何微服務的流行會讓DDD也火起來呢?是因為微服務需要劃分,而DDD中的BC的概念,大家發現正好可以和微服務的邊界完全契合。雖然DDD中實際上對BC的描述沒有太多,尤其是如何得到BC的邊界這塊沒有展開。可能這塊對大師來說是自然而然的事情,不需要過多介紹吧。
概念總結
- 領域=問題域=問題空間=業務邊界
- 每個粒度的問題域都會推匯出一個業務模型
- 領域拆分、業務模型,是需求分析階段該做的事情
- 解決方案的邊界即BC,解決方案可拆分
- 每個粒度的解決方案都會推匯出一個領域模型
- BC邊界即微服務邊界