领域驱动设计(DDD):领域和子域
領(lǐng)域和子域
在很長(zhǎng)一段時(shí)間里,我們認(rèn)為技術(shù)是主導(dǎo)項(xiàng)目成功的關(guān)鍵因素,這種關(guān)鍵因素通常表現(xiàn)在項(xiàng)目使用的編程語(yǔ)言、框架、架構(gòu)(如:分層架構(gòu))、中間件、數(shù)據(jù)庫(kù)等等方面(如:生態(tài))。但技術(shù)真的是項(xiàng)目成功的關(guān)鍵因素嗎?
在一個(gè)軟件項(xiàng)目里除了技術(shù)層面的這部分,我們最主要的事情是實(shí)現(xiàn)業(yè)務(wù)。實(shí)現(xiàn)業(yè)務(wù)其實(shí)是在實(shí)現(xiàn)所在業(yè)務(wù)領(lǐng)域中所需要的業(yè)務(wù)。技術(shù)也是一個(gè)領(lǐng)域,稱之為技術(shù)領(lǐng)域。領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中的領(lǐng)域是指的業(yè)務(wù)領(lǐng)域。
大多數(shù)的技術(shù)人員對(duì)技術(shù)領(lǐng)域中的知識(shí)比較感興趣(狂熱),因?yàn)檫@能夠使得自己在技術(shù)方面有一些前沿性和探索性的實(shí)踐。然而對(duì)于業(yè)務(wù)領(lǐng)域中的知識(shí)就顯得比較暗淡一些。
當(dāng)項(xiàng)目的進(jìn)展隨著對(duì)業(yè)務(wù)領(lǐng)域的深入,大家又開始為各種曾經(jīng)沒有分析到的需求忙的焦頭爛額。這個(gè)時(shí)候?qū)?strong>技術(shù)領(lǐng)域的探索也基本成熟。接著又一輪新技術(shù)的出現(xiàn),使得大家又開始對(duì)新技術(shù)進(jìn)行探索實(shí)踐,并試圖使用新技術(shù)來解決掉以前遺留下來的沒有解決的新需求,此時(shí)就出現(xiàn)了所謂的“全盤重構(gòu)”。正是這種周而復(fù)始的對(duì)技術(shù)領(lǐng)域的不斷探索,使我們對(duì)業(yè)務(wù)領(lǐng)域里重要的核心知識(shí)被埋沒。但有一天我們認(rèn)識(shí)到業(yè)務(wù)領(lǐng)域十分重要時(shí),你可能已經(jīng)不在這個(gè)業(yè)務(wù)領(lǐng)域中探索技術(shù)了。
讓一個(gè)技術(shù)水平較高的技術(shù)人員去深入研究分析領(lǐng)域中的業(yè)務(wù)是需要勇氣的,這種勇氣不是來自對(duì)未知的復(fù)雜業(yè)務(wù)領(lǐng)域的挑戰(zhàn)而是讓自己不在無時(shí)無刻沉靜在對(duì)技術(shù)探索的環(huán)境中。
這要求一些技術(shù)人員需要花費(fèi)一些時(shí)間去深入到業(yè)務(wù)領(lǐng)域中去分析領(lǐng)域知識(shí)并最終形成領(lǐng)域模型。
問題:領(lǐng)域中的業(yè)務(wù)是由什么組成的呢?
回答:需求。
問題:需求又是有什么組成的呢?
什么是領(lǐng)域?
百度百科對(duì)領(lǐng)域的解釋:
學(xué)術(shù)思想或社會(huì)活動(dòng)的范圍。
具體指一種特定的范圍或區(qū)域。
《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》中領(lǐng)域指的是一個(gè)特定的業(yè)務(wù)范圍,大家在這個(gè)業(yè)務(wù)域范圍內(nèi)開展工作。
領(lǐng)域這個(gè)詞承載了太多的含義。在大多數(shù)人的理解中會(huì)使用領(lǐng)域代替行業(yè)、項(xiàng)目或者系統(tǒng),這樣會(huì)使一些人認(rèn)識(shí)領(lǐng)域就是行業(yè)、項(xiàng)目或者系統(tǒng)。在認(rèn)識(shí)領(lǐng)域時(shí)一定要注意所指的業(yè)務(wù)域,行業(yè)、項(xiàng)目或系統(tǒng)都不能準(zhǔn)確地表達(dá)領(lǐng)域所指的業(yè)務(wù)域。
一個(gè)系統(tǒng)可能由一個(gè)領(lǐng)域或者多個(gè)領(lǐng)域組成。如果一個(gè)系統(tǒng)是由一個(gè)領(lǐng)域組成時(shí),這會(huì)給大家一種錯(cuò)覺。
子域(Subdomain)
在初識(shí)子域概念時(shí),可能會(huì)認(rèn)為子域與領(lǐng)域的是父子關(guān)系。其實(shí)他們并不是父子關(guān)系,而是包含關(guān)系。當(dāng)多個(gè)業(yè)務(wù)域(領(lǐng)域)的組合形成了一個(gè)更大的業(yè)務(wù)域(領(lǐng)域)時(shí),其中每一個(gè)領(lǐng)域(業(yè)務(wù)域)是這個(gè)更大的業(yè)務(wù)域的一部分,每一個(gè)業(yè)務(wù)域相對(duì)于這個(gè)更大地業(yè)務(wù)域稱之為這個(gè)更大領(lǐng)域的子業(yè)務(wù)域,簡(jiǎn)稱子域。組合而成的這個(gè)更大地業(yè)務(wù)域統(tǒng)稱為領(lǐng)域。
補(bǔ)充:領(lǐng)域與子域的關(guān)系更好的描述是餅狀圖,領(lǐng)域相當(dāng)于整個(gè)餅狀圖,子域相當(dāng)于這個(gè)餅狀圖中的某一個(gè)塊。
這是一個(gè)有關(guān)“零售商在線銷售產(chǎn)品”的例子,來源于《實(shí)現(xiàn)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》。
把零售商中的所有業(yè)務(wù)看做成一個(gè)領(lǐng)域(業(yè)務(wù)域),把這個(gè)整體業(yè)務(wù)域中的每一個(gè)業(yè)務(wù)域看做成子域。所以這個(gè)零售商業(yè)務(wù)域中包括:產(chǎn)品目錄子域、訂單子域、物流子域、發(fā)票子域、庫(kù)存子域等。
這張業(yè)務(wù)域圖已經(jīng)為我們呈現(xiàn)了一個(gè)近似完整地子域劃分圖。那么這張圖是如何完成劃分的呢?
對(duì)一個(gè)業(yè)務(wù)域劃分子域時(shí),往往會(huì)把一個(gè)領(lǐng)域劃分為:核心域、支撐子域、通用子域三種類型的子域集。其中核心域是整個(gè)業(yè)務(wù)域(領(lǐng)域)的核心,支撐子域和通用子域完成非核心的業(yè)務(wù)。不管怎么樣,在對(duì)一個(gè)整體業(yè)務(wù)域進(jìn)行劃分時(shí),首先要做的是劃分核心域。
注意:三種類型的子域不是三個(gè)類型的子域,每種類型的子域數(shù)量可能有多個(gè)。
核心域(Core Domain)
核心域是整個(gè)業(yè)務(wù)系統(tǒng)的核心,所有的業(yè)務(wù)都要圍繞著核心業(yè)務(wù)域展開。如何明確核心域呢?
通常明確核心的方式是精煉業(yè)務(wù)域。精煉是一個(gè)持續(xù)的過程,具體來說有以下幾種方式:
領(lǐng)域愿景說明(Domain Vision Statement)
突出核心(Highlighted Core)
內(nèi)聚機(jī)制(Cohesive Mechanism)
分離的核心(Segregated Core)
抽象核心(Abstract Core)
領(lǐng)域愿景說明(Domain Vision Statement)
這部分的內(nèi)容在《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》中表達(dá)地非常簡(jiǎn)潔,沒有必要再做過度的解讀。具體內(nèi)容如下:
并且還給出了兩個(gè)“領(lǐng)域愿景說明”的示例:
在這兩個(gè)示例中提到的模型并不是一個(gè)領(lǐng)域模型,而是一組領(lǐng)域模型。更具體地來說是要告訴我們這一組領(lǐng)域模型要解決什么問題,而這個(gè)要解決的問題正是由客戶來提出的最需要的那個(gè)功能,這個(gè)最需要的功能正是業(yè)務(wù)域中的核心。
為業(yè)務(wù)域編寫“領(lǐng)域愿景說明”是有必要的,因?yàn)樗梢宰屨麄€(gè)團(tuán)隊(duì)的人員都能明確什么是核心域。正是明確了核心域,才可以使整個(gè)團(tuán)隊(duì)朝著統(tǒng)一地方向前進(jìn)。
突出核心(Highlighted Core)
我們通過“領(lǐng)域愿景說明”可以明確什么是核心域,但這是從一個(gè)較為寬泛的角度對(duì)核心域進(jìn)行說明的。我們明確核心域的目的是為了形成核心領(lǐng)域模型,此時(shí)我們需要突出核心。
突出核心域中的領(lǐng)域模型有兩種方式:
精煉文檔
標(biāo)明核心(Core)
精煉文檔要做的事情是創(chuàng)建一個(gè)最核心的概念對(duì)象的清單文檔。
標(biāo)明核心(Core) 要做的事情是從一個(gè)完整的領(lǐng)域模型文檔中標(biāo)記出最核心的領(lǐng)域模型。
分離的核心(Segregated Core)
分離的核心的主要目的有兩個(gè):
將核心域中的非核心元素(模型)分離出去。
將非核心域中的核心元素(模塊)移動(dòng)到核心域中。
這兩個(gè)目的都是為了讓核心域更加清晰和增強(qiáng)核心域的內(nèi)聚性。
有關(guān)核心域的更多內(nèi)容請(qǐng)閱讀《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》中的第十五章,其中非常詳細(xì)地闡述了如何明確核心域和實(shí)現(xiàn)核心域。
《實(shí)現(xiàn)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》中通過問題空間和解決方案空間對(duì)核心域做了更直接的說明:
問題空間是領(lǐng)域的一部分,對(duì)問題空間的開發(fā)將產(chǎn)生一個(gè)新的核心域。[IDDD, P48]
核心域的范圍并不一定是一次就能確認(rèn)的,可能需要迭代很多次,每一次都有可能擴(kuò)大或縮小。
通用子域
如果一個(gè)子域不是核心域并且被用于整個(gè)業(yè)務(wù)系統(tǒng),那么這個(gè)子域便是通用子域。[IDDD, P44]
通用子域:模型中由你想當(dāng)然的部分。不可否認(rèn),它們確實(shí)是領(lǐng)域模型的一部分,但它們抽象出來的概念是很多業(yè)務(wù)都需要的。比如:各個(gè)行業(yè)(如:運(yùn)輸業(yè)、銀行業(yè)或制造業(yè))都需要某種形式的企業(yè)組織圖。[DDD, P282]
這兩段摘取為我們描述出什么是通用子域,從業(yè)務(wù)域的角度來看,通用子域也是一種業(yè)務(wù)域,和核心域一樣。只是沒有核心域的優(yōu)先級(jí)高。因?yàn)楹诵挠蚴钦麄€(gè)系統(tǒng)的核心,整個(gè)系統(tǒng)因?yàn)楹诵挠虿啪哂懈?jìng)爭(zhēng)性。而通用子域只是那些提供的增強(qiáng)功能,比如電商系統(tǒng)中的商品收藏、店鋪收藏、用戶信息等等這些功能,它們確實(shí)是電商系統(tǒng)中的業(yè)務(wù),但是并不是核心業(yè)務(wù),這些增強(qiáng)性的業(yè)務(wù)就是通用子域。
注意:有些小伙伴會(huì)把通用子域與共享內(nèi)核混淆,是因?yàn)楣蚕韮?nèi)核的組成部分既有可能是核心域、支撐子域或者通用子域。
支撐子域
在業(yè)務(wù)域中,會(huì)有一些比較重要的業(yè)務(wù),但卻不是核心,那么它便是一個(gè)支撐子域。創(chuàng)建支撐子域的原因在于它們專注于業(yè)務(wù)的某個(gè)方面。它不像核心域在整個(gè)系統(tǒng)中那么重要,也不像通用子域。
開源電商
Mallfoundry 是一個(gè)完全開源的使用 Spring Boot 開發(fā)的多商戶電商平臺(tái)。它可以嵌入到已有的 Java 程序中,或者作為服務(wù)器、集群、云中的服務(wù)運(yùn)行。
領(lǐng)域模型采用領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(DDD)、接口化以及面向?qū)ο笤O(shè)計(jì)。
項(xiàng)目地址:gitee.com/mallfoundry…
總結(jié)
在一個(gè)業(yè)務(wù)域中,基本由三種類型的子域組成,分別是:核心域、通用子域和支撐子域。在分析業(yè)務(wù)域時(shí),首先要做的事情是分析核心域,然后設(shè)計(jì)核心域,這樣就能明確系統(tǒng)的最主要的功能。圍繞著這個(gè)核心域進(jìn)行展開,慢慢添加其它子域,比如通用子域和支撐子域。在開發(fā)核心域和其它子域時(shí),要為核心域分配最高的優(yōu)先級(jí),其它子域可以根據(jù)任務(wù)的多方面因素在分配優(yōu)先級(jí)。
總結(jié)
以上是生活随笔為你收集整理的领域驱动设计(DDD):领域和子域的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: CTO 技术管理的“三板斧”
- 下一篇: OpenCV 计算物体的凸包