領域驅動設計(DDD):領域和子域

領域和子域

在很長一段時間裏,我們認爲技術是主導項目成功的關鍵因素,這種關鍵因素通常表現在項目使用的編程語言、框架、架構(如:分層架構)、中間件、數據庫等等方面(如:生態)。但技術真的是項目成功的關鍵因素嗎?

在一個軟件項目裏除了技術層面的這部分,我們最主要的事情是實現業務。實現業務其實是在實現所在業務領域中所需要的業務。技術也是一個領域,稱之爲技術領域。領域驅動設計中的領域是指的業務領域。

大多數的技術人員對技術領域中的知識比較感興趣(狂熱),因爲這能夠使得自己在技術方面有一些前沿性和探索性的實踐。然而對於業務領域中的知識就顯得比較暗淡一些。

當項目的進展隨着對業務領域的深入,大家又開始爲各種曾經沒有分析到的需求忙的焦頭爛額。這個時候對技術領域的探索也基本成熟。接着又一輪新技術的出現,使得大家又開始對新技術進行探索實踐,並試圖使用新技術來解決掉以前遺留下來的沒有解決的新需求,此時就出現了所謂的 “全盤重構”。正是這種週而復始的對技術領域的不斷探索,使我們對業務領域裏重要的核心知識被埋沒。但有一天我們認識到業務領域十分重要時,你可能已經不在這個業務領域中探索技術了。

讓一個技術水平較高的技術人員去深入研究分析領域中的業務是需要勇氣的,這種勇氣不是來自對未知的複雜業務領域的挑戰而是讓自己不在無時無刻沉靜在對技術探索的環境中。

這要求一些技術人員需要花費一些時間去深入到業務領域中去分析領域知識並最終形成領域模型。

問題:領域中的業務是由什麼組成的呢?

回答:需求。

問題:需求又是有什麼組成的呢?

什麼是領域?

百度百科對領域的解釋:

《領域驅動設計》中領域指的是一個特定的業務範圍,大家在這個業務域範圍內開展工作。

領域這個詞承載了太多的含義。在大多數人的理解中會使用領域代替行業、項目或者系統,這樣會使一些人認識領域就是行業、項目或者系統。在認識領域時一定要注意所指的業務域,行業、項目或系統都不能準確地表達領域所指的業務域。

子域(Subdomain)

在初識子域概念時,可能會認爲子域與領域的是父子關係。其實他們並不是父子關係,而是包含關係。當多個業務域(領域)的組合形成了一個更大的業務域(領域)時,其中每一個領域(業務域)是這個更大的業務域的一部分,每一個業務域相對於這個更大地業務域稱之爲這個更大領域的子業務域,簡稱子域。組合而成的這個更大地業務域統稱爲領域。

補充:領域與子域的關係更好的描述是餅狀圖,領域相當於整個餅狀圖,子域相當於這個餅狀圖中的某一個塊。

這是一個有關 “零售商在線銷售產品” 的例子,來源於《實現領域驅動設計》。

把零售商中的所有業務看做成一個領域(業務域),把這個整體業務域中的每一個業務域看做成子域。所以這個零售商業務域中包括:產品目錄子域、訂單子域、物流子域、發票子域、庫存子域等。

這張業務域圖已經爲我們呈現了一個近似完整地子域劃分圖。那麼這張圖是如何完成劃分的呢?

對一個業務域劃分子域時,往往會把一個領域劃分爲:核心域、支撐子域、通用子域三種類型的子域集。其中核心域是整個業務域(領域)的核心,支撐子域和通用子域完成非核心的業務。不管怎麼樣,在對一個整體業務域進行劃分時,首先要做的是劃分核心域。

注意:三種類型的子域不是三個類型的子域,每種類型的子域數量可能有多個。

核心域(Core Domain)

核心域是整個業務系統的核心,所有的業務都要圍繞着核心業務域展開。如何明確核心域呢?

通常明確核心的方式是精煉業務域。精煉是一個持續的過程,具體來說有以下幾種方式:

領域願景說明(Domain Vision Statement)

這部分的內容在《領域驅動設計》中表達地非常簡潔,沒有必要再做過度的解讀。具體內容如下:

並且還給出了兩個 “領域願景說明” 的示例:

在這兩個示例中提到的模型並不是一個領域模型,而是一組領域模型。更具體地來說是要告訴我們這一組領域模型要解決什麼問題,而這個要解決的問題正是由客戶來提出的最需要的那個功能,這個最需要的功能正是業務域中的核心。

爲業務域編寫 “領域願景說明” 是有必要的,因爲它可以讓整個團隊的人員都能明確什麼是核心域。正是明確了核心域,纔可以使整個團隊朝着統一地方向前進。

突出核心(Highlighted Core)

我們通過 “領域願景說明” 可以明確什麼是核心域,但這是從一個較爲寬泛的角度對核心域進行說明的。我們明確核心域的目的是爲了形成核心領域模型,此時我們需要突出核心。

突出核心域中的領域模型有兩種方式:

精煉文檔要做的事情是創建一個最核心的概念對象的清單文檔。

標明核心(Core) 要做的事情是從一個完整的領域模型文檔中標記出最核心的領域模型。

分離的核心(Segregated Core)

分離的核心的主要目的有兩個:

這兩個目的都是爲了讓核心域更加清晰和增強核心域的內聚性。

有關核心域的更多內容請閱讀《領域驅動設計》中的第十五章,其中非常詳細地闡述瞭如何明確核心域和實現核心域。

《實現領域驅動設計》中通過問題空間和解決方案空間對核心域做了更直接的說明:

核心域的範圍並不一定是一次就能確認的,可能需要迭代很多次,每一次都有可能擴大或縮小。

通用子域

如果一個子域不是核心域並且被用於整個業務系統,那麼這個子域便是通用子域。[IDDD, P44]

通用子域:模型中由你想當然的部分。不可否認,它們確實是領域模型的一部分,但它們抽象出來的概念是很多業務都需要的。比如:各個行業(如:運輸業、銀行業或製造業)都需要某種形式的企業組織圖。[DDD, P282]

這兩段摘取爲我們描述出什麼是通用子域,從業務域的角度來看,通用子域也是一種業務域,和核心域一樣。只是沒有核心域的優先級高。因爲核心域是整個系統的核心,整個系統因爲核心域才具有競爭性。而通用子域只是那些提供的增強功能,比如電商系統中的商品收藏、店鋪收藏、用戶信息等等這些功能,它們確實是電商系統中的業務,但是並不是核心業務,這些增強性的業務就是通用子域。

注意:有些小夥伴會把通用子域共享內核混淆,是因爲共享內核的組成部分既有可能是核心域、支撐子域或者通用子域。

支撐子域

在業務域中,會有一些比較重要的業務,但卻不是核心,那麼它便是一個支撐子域。創建支撐子域的原因在於它們專注於業務的某個方面。它不像核心域在整個系統中那麼重要,也不像通用子域。

開源電商

Mallfoundry 是一個完全開源的使用 Spring Boot 開發的多商戶電商平臺。它可以嵌入到已有的 Java 程序中,或者作爲服務器、集羣、雲中的服務運行。

項目地址:gitee.com/mallfoundry…

總結

在一個業務域中,基本由三種類型的子域組成,分別是:核心域、通用子域和支撐子域。在分析業務域時,首先要做的事情是分析核心域,然後設計核心域,這樣就能明確系統的最主要的功能。圍繞着這個核心域進行展開,慢慢添加其它子域,比如通用子域和支撐子域。在開發核心域和其它子域時,要爲核心域分配最高的優先級,其它子域可以根據任務的多方面因素在分配優先級。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/Z5S6FwINeyomodAUFFmWEQ