IDDD 實現領域驅動設計 理解限界上下文

2022-01-13 04:18:37 字數 4135 閱讀 4954

《實現領域驅動設計》前兩章內容,基本上讀完了,和《領域驅動設計》不同的是,它把很多的概念都放在前面進行講述了,比如領域精煉、界限上下文等等,在《領域驅動設計》中,是很靠後的內容,不過這樣也好,可以讓你從乙個大局的視角去看待問題,由廣到細的思路學習,我覺得也蠻好的。另外,隨著一點一點的學習,你會發現,領域驅動設計越來越有意思了,有很多「新鮮」的東西等待發現。

一張很重要的圖(無意間搜到),引自:《implementing ddd reading - strategic design》

戰略建模和戰術建模,其實是《實現領域驅動設計》最前面的內容,位於《如何使用本書》部分,當時看的時候並沒有很注意,但在前兩章的內容中,發現有很多這樣的字眼:「團隊有人花額外的時間去了解戰術模式、團隊採用的是戰略模式的建模方式。。。」,這就不得不讓你回過頭看下,什麼是戰略建模和戰術建模?其實,關於這兩點,作者並沒有很準確的進行定義,只是分別描述了這兩點內容的關鍵字,我們來總結一下:

戰術建模:聚合(aggregate)、實體(entity)、值物件(value objects)、資源庫(repository)、領域服務(domain services)、領域事件(domain events)、模組(modules)。

像聚合、實體、值物件等,都可以稱之為戰術建模的工具,戰略建模和戰術建模的區別,你可以從字面上進行理解,戰略的意思,就是從大局出發,是一種運籌帷幄的感覺,那為什麼和界限上下文有關呢?在《理解領域和子域》中,有一張很重要的圖,領域是業務系統的全部,其中包含核心域、子域和通用子域,相對應的就是限界上下文,你可以把某一塊的領域和限界上下文進行對映,他們都是通用語言的一種表述,在專案之初,領域專家和開發人員的工作就是**限界上下文的劃定,這個非常重要,如果限界上下文的劃定有問題,那麼將來戰術建模的進行將「一塌糊塗」,就像作者乙個例子一樣,團隊成員將使用者和許可權限界上下文劃到具體的子域中實現,最後導致了一系列的問題,後來,團隊發現問題後,將使用者和許可權限界上下文重新定義為身份和安全限界上下文,並劃分到通用子域中,最後的效果顯而易見,避免了很多問題的發生,也增加了業務系統的靈活性。

如果你注意的話,會發現上面說的只是「紙面」上的**,也就是說都沒有進行實施,所以才稱之為戰略建模,而戰術建模可以理解為戰略建模的實現,前提是界限上下文都已經劃定好,並確定無誤。

和戰略建模、戰術建模一樣,又是乙個概念性的問題,在問題空間中,我們思考的是業務所面臨的問題和挑戰,而在解決方案空間中,我們思考的是如何實現軟體以解決這些業務挑戰。

具體什麼意思呢?其實,問題空間和戰略建模的概念有些類似,但只是思考的方式類似,他們是兩個不同的概念,在上面圖中,問題空間包括兩部分:業務所面臨的挑戰、核心域+其他子域的組合,注意其中並不包含限定上下文的劃分,領域專家和開發人員在**領域的設計中,首先,就是對問題空間的**,用來確定核心域和其他子域,並列出業務系統中可能會存在的一些問題。

在上面圖中,解決方案空間包含的內容很多,它是什麼的解決方案?其實就是針對問題空間的解決方案,當問題空間被確定下來後,我們就會對核心域以及其他子域進行**和實施,然後在其中劃分出很多的限界上下文,並用軟體的方式進行實現。

如果這樣進行思考,你會發現,問題空間和解決方案空間對應於戰略建模和戰術建模,他們之間是有一些相似處,比如乙個是**、戰略,乙個是實施、實現,但還是有些不同,比如界限上下文是戰略建模中的概念,對應與問題空間和解決方案空間,界限上下文卻是解決方案空間中的的概念,可以說問題空間和解決方案空間涵蓋的東西很多,像戰術建模就可以看作是解決方案空間實施的一種手段。

問題空間和解決方案空間,你可以不把它看作是領域驅動設計中的概念,因為在原著《領域驅動設計》中並沒有這些概念,並不是說沒有就不重要,在實現領域驅動設計中,還是非常重要的,你可以把它看作是一種思考的方式,就像你切乙個西瓜,橫切、豎切、還是直接用拳頭爆掉,這些方式都可以,不管怎麼實施,只要最後能吃到西瓜就行。對於領域專家和開發人員所建立的通用語言,到底該如何溝通,或者相互直接如何表達?我覺得**問題空間和解決方案空間,是乙個很好的方式,你可以把他們看作是切西瓜的「刀」,很鋒利,也高效。

上面的四點概念,在領域驅動設計的時候,可以不必了解,因為它只是實現領域驅動設計的一種概念方式,理解它也只不過可以讓你少走些彎路,你完全可以按照自己的方式去實現,當然,偏離了大道,也怨不得別人。

限界上下文的概念很重要,我之前在做訊息專案的時候,不是很了解這個概念,只是隱約記得什麼限定上下文、界限上下文,然後就是實體、值物件和領域服務了,其實最準確的名字是限界上下文,限的意思就是劃分、規定,界就是界限、或者乙個邊界,上下文就是業務的整個流程,總的來說,可以稱限界上下文為業務流程在乙個劃定的界限中,我們知道,業務的描述是通過通用語言來表述的,限界上下文和通用語言的關係就是:在乙個特定的限界上下文只使用一套通用語言,並且保證它的清晰性和簡潔性。

那限界上下文和子域有什麼關係呢?在上面圖中,可以看到是一一對應的,比如通用子域對應於身份與訪問上下文,但其實並不是這樣,請注意那個虛線,虛線表示的意思是核心域和子域的界限,但界限中很多都是空白的,比如通用子域除了包含身份與訪問上下文,還可以包含訊息與通知上下文、日誌記錄上下文等等,同樣,支撐子域也是如此。

我記得我在開發訊息專案的時候,在領域層只有乙個 messagemanager.domain 專案,並且專案下有很多的資料夾,比如 entity、domain service 等等,然後我就認為這個 domain 專案,是整個訊息專案的核心,並且,如果我再開發乙個新的專案的時候,我也會這樣做,這樣有什麼問題呢?好像沒什麼問題,因為對於訊息專案,業務場景很簡單,domain 專案所代表的是整個領域層,也就是上面圖中整個的概念,其實這種命名是有問題的,實體、值物件和領域服務等概念,是存在於一定的限界上下文中,而不是整個領域概念,也就是說,我當時在設計 domain 專案的時候,就完全沒有把限界上下文設計好,暴露出來最明顯的乙個問題,就是 domain 專案中包含有 user 實體的概念,你明白了吧,我和作者描述的那個團隊開發都犯了同乙個問題。

我們再來看一張圖:

上面是協作上下文所包含的內容,你可以看到有好多的聚合根、領域物件等等,對於協作上下文的開發,iddd 作者的做法是,新建乙個程式集專案,也就是我們所說的類庫專案,這個每個限定上下文都互不影響,而不是像我那樣包含在乙個 domain 專案中,分開開發更新也方便,如果限界上下文足夠複雜,比如上面的協定上下文,包含的聚合根太多,我們也可以進行細分。還有個問題是,比如使用者的概念,在部落格、論壇、日曆等場景中,所表達的概念是不同的,那我們的身份與訪問上下文該如何進行設計,還有就是協定上下文中的使用者概念改如何進行設計,這是乙個很重要的問題,如果是我的話,我以前肯定會把使用者的概念放在協定上下文中進行開發,因為訊息專案我就是這麼幹的,但這樣造成的問題也是很嚴重的。

對於上面所描述的問題,我們來分析一下,不管在部落格、論壇、日曆等場景中,使用者的概念是唯一的,也就是說它必須是唯一標識的,不能有兩個同樣的使用者同時存在,這是首要基本條件,還有就是,使用者的一些基本屬性,比如使用者名稱、郵箱、密碼等等,這些在不同的場景中都是可以確定的,也都是同樣存在的,對待這些共有屬性,我們可以抽離出來,除了屬性之外,還有一些業務操作也是公用的,比如身份驗證操作,我們也同樣抽離出來,對於這些抽離出來的屬性和操作,我們應該在哪邊進行實現?該如何實現?是在協定上下文中嗎?不是,我們應該把這些使用者屬性和操作放在身份與訪問上下文中,並進行隔離實現,為什麼要進行隔離?因為身份與訪問上下文是在通用子域中,也就是說並不是在支撐子域中,通用子域和核心域、其他支撐子域都有聯絡,也就是說,不要把協定上下文中所包含的獨有使用者概念,放到身份與訪問上下文中進行開發,如果這樣做,那麼身份與訪問上下文就不是通用子域了,而變成了協定上下文的乙個附屬上下文。

乙個模型應該要與乙個上下文相適應,上下文可能是指一段**,也可能是指特定團隊的工作,如果乙個模型是在一次頭腦風暴會議上誕生的,那麼它的上下文就可能會限制在這些討論的範圍中,在有特定意義的模型中,不管模型的上下文是什麼,必須要說明模型中的術語是什麼意思。以上是《領域驅動設計》中,關於模型和上下文的內容,注意,上面所說的上下文並不是限界上下文,上面所說的上下文可以是一段通用語言的表述,也可以是一段**,如果概括的話,可以認為是限界上下文的一部分。

關於限界上下文,我只是了解冰山一角,有太多的內容需要進行**學習,但不可否認,限界上下文是領域驅動設計中,最重要的概念之一,可以稱之為最重要的首要概念,因為它是領域驅動設計的開始,自己肚裡知識有限,我希望後面可以再次對這部分內容進行補充,最後,引用《領域驅動設計》中的一段描述:

有人會說,你搞這麼多的概念有什麼用?還不如直接實踐來的有用,但有時候,你會發現,實踐是建立在一定基礎之上的。

《實現領域驅動設計》筆記

1 不要用貧血物件 雖然do是貧血的,但目前的do實際是dataobject,domainservice是實際的domainobject 2 多跟領域專家溝通 3 計費核心域為計費執行 1 計費執行包括計費條件 計費過程 計費結果 2 建立計費上下文,如計費時間 4 應用服務應當是無狀態的 5 分層...

領域驅動設計系列(一) 為何要領域驅動設計?

領域驅動設計最近貌似開始火起來了,越來越多的人開始認識到領域設計的重要性,從我做過的專案來看,似乎歐洲已經有很多的公司開始實施領域驅動設計了,我看領域驅動設計也有些時間了,但是網上不管是文章還是 都顯得太過 高大上 一談領域驅動設計,一大堆的概念一股腦的給你上上來,搞的有點暈頭轉向,而我想在一些中小...

領域驅動設計之我見 領域業務

談到領域驅動設計 ddd 人們很容易想到如下這張圖,那麼是不是你的軟體做了如下的分層設計就是領域驅動設計的了?顯然不是,以下分層只能說明的軟體做了分層架構,領域驅動設計的核心在領域模型,領域模型的核心在業務知識。如果能夠採用物件導向思維將業務抽象為恰當的模型,不管用什麼架構都稱得上領域驅動設計。在大...