理解限界上下文


理解限界上下文

上一篇:《IDDD 實現領域驅動設計-理解領域和子域

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


一張很重要的圖(無意間搜到),引自:《Implementing DDD Reading - Strategic Design

戰略建模(Strategic Modeling)和戰術建模(Tactical Modeling)

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

  • 戰略建模:界限上下文(Bounded Context)、上下文映射圖(Context Mapping)。
  • 戰術建模:聚合(Aggregate)、實體(Entity)、值對象(Value Objects)、資源庫(Repository)、領域服務(Domain Services)、領域事件(Domain Events)、模塊(Modules)。

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

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

問題空間(Problem Space)和解決方案空間(Solution Space)

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

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

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

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

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

理解限界上下文(Bounded Context)

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

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

上面的圖來自《實現領域驅動設計》,這個圖我們可以和上一篇進行對比下,在之前的團隊開發中,是把身份與訪問上下文划分到協作上下文中了,並導致了一系列的問題,協作上下文包含的內容有論壇、博客、及時消息、留言板等,但這些都不是核心域,核心域是敏捷項目管理,也就是一開始說的那個簡單業務用例:待定項提交到沖刺中,協作上下文只不過是支撐子域,它的作用就是用來支撐敏捷項目管理上下文的,可以這樣說,如果協作上下文出現了問題,並不影響這個項目的運行,頂多是影響某一模塊的運行,比如待定項提交到沖刺中,這個業務操作完成后,會有一個消息通知,協作上下文出現了問題,消息通知發不出去,但是待定項是可以提交到沖刺中的,因為這兩個業務操作分別處於不同的限界上下文中,也可以這樣說,對於敏捷項目管理上下文,協作上下文是可以替換的。

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

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

我們再來看一張圖:

上面是協作上下文所包含的內容,你可以看到有好多的聚合根、領域對象等等,對於協作上下文的開發,IDDD 作者的做法是,新建一個程序集項目,也就是我們所說的類庫項目,這個每個限定上下文都互不影響,而不是像我那樣包含在一個 Domain 項目中,分開開發更新也方便,如果限界上下文足夠復雜,比如上面的協定上下文,包含的聚合根太多,我們也可以進行細分。還有個問題是,比如用戶的概念,在博客、論壇、日歷等場景中,所表達的概念是不同的,那我們的身份與訪問上下文該如何進行設計,還有就是協定上下文中的用戶概念改如何進行設計,這是一個很重要的問題,如果是我的話,我以前肯定會把用戶的概念放在協定上下文中進行開發,因為消息項目我就是這么干的,但這樣造成的問題也是很嚴重的。

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

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

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

  • 細胞膜不僅能把細胞內部和外部區分開來,而且還能決定通過的物質。

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM