偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

當我們談論DDD時我們在談論什么

原創(chuàng) 精選
開發(fā)
我嘗試在軟件設計領域,將這些問題劃分到幾個相互獨立的范疇,這可以幫助我和其他人討論,在明確范圍內(nèi)可以更好的交流。

作者 | 祁兮

談論到 DDD,我們會聊事件風暴,會聊限界上下文,會聊六邊形架構,會聊實體值對象。這些概念各不相同,相關的概念也很不一樣,但都屬于DDD的范疇。見過了很多DDD的討論和工作坊,我發(fā)現(xiàn)大家唇槍舌劍無法達成一致,往往是因為各自腦中的問題并不相同。

我嘗試在軟件設計領域,將這些問題劃分到幾個相互獨立的范疇,這可以幫助我和其他人討論,在明確范圍內(nèi)可以更好的交流。

一種比較經(jīng)典的方式是劃分為戰(zhàn)略設計和戰(zhàn)術設計。由于領域模型設計復雜度也很高,所以我又把領域模型設計從戰(zhàn)術設計中劃分出來,形成單獨的范疇,以便更好的討論。

下面我將討論這三個范疇的概念和方法。

一、DDD戰(zhàn)略設計

在這個范疇里,主要討論目標是復雜的業(yè)務需求。有多復雜呢?可能需要多個團隊分工合作,或者一個團隊分階段開發(fā),需要被設計成多個獨立部署運行的服務,會有多個代碼庫。

這個范疇可以有很多名字,比如DDD戰(zhàn)略設計、進程間架構、微服務架構設計等。

在這個范疇里討論的主要問題是,如何將這個復雜的業(yè)務需求合理的分成多個部分,從而分而治之。

為什么要分成多個部分?因為解決復雜問題的一個有效方法是將其分解為多個相對簡單的問題,然后分別解決。如果不進行分解,這個復雜問題往往會讓我們在解決過程中陷入困境,就算設計出了解決方案,也往往由于解決方案過于復雜導致團隊的認知超載。

1.劃分方法

既然戰(zhàn)略設計需要將整個業(yè)務需求分成多個部分,那么如何找到用于劃分的接縫呢?

我看到行業(yè)里有這樣一些方法:

(1) 限界上下文

在《領域驅(qū)動設計》中,Eric提出了限界上下文。從領域模型設計的角度,為了讓模型保持完整獨立和清晰,需要識別出限界上下文,讓其作為模型的邊界。在書中并沒有完善的識別方法,更多的是提出一些概念。限界上下文往往被用來輔助判斷接縫的正確性。

在一個限界上下文中,領域知識是相對完整的。

(2) 核心域

在《領域驅(qū)動設計》中,Eric提出了精煉及核心域。在模型中識別出最有價值的核心域,將其獨立出來。

由于只提到了核心域,所以這也不是一個完整的劃分的方法。我曾在如何劃分限界上下文博客中基于此方法上提出了一種分解問題域的方法。

(3) 事件風暴工作坊

事件風暴工作坊可能是最早用來指導劃分限界上下文的方法。

對前一步(事件風暴)產(chǎn)生的聚合進行分組,通過業(yè)務的內(nèi)聚性和關聯(lián)度劃分邊界,結合限界上下文的定義進行判斷,并給出上下文名稱。

——[服務化設計階段路徑方案]

但是「業(yè)務的內(nèi)聚性和關聯(lián)度」著實不是一個好的劃分依據(jù)。而事件風暴的創(chuàng)始人Alberto曾經(jīng)提出過通過關鍵事件識別不同的階段進而識別限界上下文的方法,看上去是一個更加靠譜的方法。

(4) 8X Flow

8X Flow中提出了一套相對完整的劃分方法。首先定義「業(yè)務」和「領域」,然后將「業(yè)務」和「領域」劃分開來,接著基于合同將業(yè)務劃分成了不同的上下文,最終完成了劃分。

(5) 現(xiàn)代企業(yè)架構白皮書

現(xiàn)代企業(yè)架構白皮書提出通過職責類型劃分。流轉(zhuǎn)類識別不同的業(yè)務流程階段,規(guī)格類提取業(yè)務規(guī)則,視圖類專為統(tǒng)計報表而存在,配置類提供配置工具。

2.重新思考

我也嘗試過一些其他的劃分方法,比如通過時間階段劃分,通過使用者不同劃分,通過使用場景不同劃分,通過變化頻率不同劃分。這些方法和上面的一些方法都有些相似。

不好的劃分方法可能會導致分布式單體:每次變化不得不修改多個服務、每次部署必須同時部署多個服務,服務之間有非常多的通信,同一個團隊管理著多個服務,服務之間共享數(shù)據(jù)庫、同樣的代碼和模型。

也許我們可以總結出一些原則,來幫助我們驗證劃分是否合理。比如高內(nèi)聚低耦合,比如服務有明確的邊界且能自治,可以獨立演進,比如盡可能減少對于其他服務的依賴。

二、DDD戰(zhàn)術設計

在戰(zhàn)略層面劃分好了服務后,我們來看看一個服務內(nèi)部。

在這個范疇里,主要討論在一個服務內(nèi)部,如何劃分和組織代碼。

和上一節(jié)類似,在代碼也有不同的職責;和上一節(jié)不同,對于代碼層面的劃分,已經(jīng)有相對成熟的方法。

這個范疇可以有很多名字,比如DDD戰(zhàn)術設計、進程內(nèi)架構、分層架構等。

需要指出的是,在一個服務內(nèi)部,如果領域模型足夠復雜,在分離領域邏輯和技術實現(xiàn)細節(jié)前,也需要先按照模塊進行一次劃分,然后再按上述的領域邏輯和技術實現(xiàn)細節(jié)的方式劃分。相關討論可以參見前綴分包vs后綴分包。

1.劃分方法

(1)《領域驅(qū)動設計》中的分層架構

Eric在2003年提出的分層架構。和傳統(tǒng)的展示層+業(yè)務邏輯層+數(shù)據(jù)訪問層的三層架構相比多了一層,主要區(qū)別是將業(yè)務邏輯層分成了應用層和領域?qū)印?/p>

圖片

圖片引自《領域驅(qū)動設計》第4章

其中「應用層」這個概念,也指明了它和領域?qū)拥膮^(qū)別:領域?qū)訉W⒈磉_領域概念,而應用層則在領域?qū)又?,加入了諸如持久化概念和事務概念等軟件的典型概念,對外提供了滿足具體場景的功能。展示層則在應用層功能之上,定義了和外部系統(tǒng)通信的具體形式。

這里也將數(shù)據(jù)訪問層變成了基礎設施層?;A設施層為其他層提供支撐其概念的具體技術實現(xiàn)。

(2) 六邊形架構

2005年六邊形架構(翻譯)又稱端口和適配器架構,從設計模式的視角將代碼劃分成了負責業(yè)務邏輯的「應用」和負責同外部系統(tǒng)交互的「適配器」。

圖片

圖片引自《六邊形架構》

在2013的IDDD中Vaughn將六邊形架構和DDD進行了結合,把「應用」又細分成了「應用程序」和「領域模型」。

圖片

圖片引自《實現(xiàn)領域驅(qū)動設計》第4章

2008年的洋蔥架構也是類似的。

六邊形架構從另外一個角度審視了一個理想架構,并將領域?qū)臃旁谥行?,凸顯其核心地位。

(3) 整潔架構

Uncle Bob在2012提出了整潔架構,一般來說我們認為整潔架構的四層(四圈)和IDDD的六邊形架構基本是對應的,只是整潔架構將適配器劃分成了和框架耦合的「Frameworks & Drivers」層和負責內(nèi)外層數(shù)據(jù)轉(zhuǎn)換的「Interface Adapters」層。

圖片

圖片引自《整潔架構》

整潔架構也用「用例」來描述業(yè)務實體之外的一層,對應于「應用層」,更明確的指明了這層的職責是實現(xiàn)各個用例。

比較有趣的是,整潔架構把Gateway接口放到了領域?qū)又獾摹赣美龑印埂_@使得領域?qū)又魂P注于當前上下文的邏輯,而讓用例層負責和其他上下文/資源庫的協(xié)調(diào)和編排。

整潔架構也討論了如何處理框架和架構的關系。

(4) 清晰架構

2017年更有集DDD、洋蔥架構、整潔架構、CQRS于一體的清晰架構出現(xiàn)。

2.重新思考

以上的架構,指導每一個具體的業(yè)務功能分解來說是非常夠用的。然而在一個真實的項目中,除了每個具體功能的分層,其實還有一些對于平臺和框架的配置,這些其實要和每個業(yè)務功能的代碼有所區(qū)分,從代碼結構上獨立出來。

另外,每一層都會有一些可以復用的代碼。比如領域?qū)拥幕A的業(yè)務異常,應用層的事務處理,適配器層的HTTP客戶端。這些不只用于單個模塊或者單個服務,也可以用于多個服務;有些已經(jīng)有三方工具,有些需要我們自己定義和封裝。

我看到很多項目對于以上兩類代碼并沒有區(qū)分,而是把一切不屬于其他層的代碼都放到了基礎設施層。讓可憐的基礎設施層逐漸變成了垃圾桶。

三、領域模型設計

在戰(zhàn)術層面劃分好架構后,我們來看看位于核心的領域模型。

在這個范疇里,主要討論基于面向?qū)ο蠹夹g,如何用領域模型來表達業(yè)務概念。

為什么要使用領域模型這種模式,而不是用Service+數(shù)據(jù)模型的模式呢?如果復雜的業(yè)務邏輯采用數(shù)據(jù)模型這種模式,那么Service里會存在大量的復雜的邏輯,代碼是很難維護的。而領域模型充分利用了面向?qū)ο蠹夹g的優(yōu)勢,將復雜度轉(zhuǎn)變?yōu)槁氊熋鞔_的組件組合,讓各個組件相對簡單,來降低認知負載,提升可維護性。這就是設計的力量。

那為什么用面向?qū)ο蠹夹g呢?面向?qū)ο笏枷敫臃衔覀冋J知復雜問題的方式,并且現(xiàn)代編程語言都普遍支持面向?qū)ο?,所以DDD選擇了面向?qū)ο蠹夹g。

1.關注點分離模式

在這個范疇里,主要還是使用《領域驅(qū)動設計》中的模式。我們以關注點分離的角度,來解析這些模式。

(1) 領域?qū)ο蟮纳芷陬愋?/h4>

從生命周期的角度,「領域?qū)ο蟆狗譃檫@樣幾個類型:

  • 和應用生命周期一致,應用啟動時被創(chuàng)建出來,應用關閉時才銷毀。比如《領域驅(qū)動設計》5.4.1中的「資金轉(zhuǎn)賬」。
  • 在業(yè)務過程中被創(chuàng)建,會被保留一段時間,不隨著應用關閉銷毀。比如電商系統(tǒng)中的「訂單」。
  • 在業(yè)務過程中被創(chuàng)建,在使用完成后即被銷毀。比如一些在對象之間傳遞的參數(shù)對象。

而在《領域驅(qū)動設計》的第5章,Eric也將領域?qū)ο髣澐譃榱藢嶓w、值對象、領域服務這三個重要模式。這三個模式和生命周期是如何對應的呢?

對于類型1,和應用生命周期一致,就是領域服務這種模式。對于類型2,在業(yè)務過程中被創(chuàng)建,會被保留一段時間,對應于實體和值對象。而對于類型3,在業(yè)務過程中被創(chuàng)建隨即被銷毀,對應于值對象。

VALUE OBJECT 經(jīng)常作為參數(shù)在對象之間傳遞消息。它們常常是臨時對象,在一次操作中被創(chuàng)建,然后丟棄。

——《領域驅(qū)動設計》 5.3 值對象

(2) 分離領域?qū)ο蟮膭?chuàng)建、查詢、保存和使用

從生命周期角度,對于這三類領域?qū)ο蟮膭?chuàng)建邏輯,可以使用Factory模式,將其封裝在Factory中。對于類型2的領域?qū)ο蟮谋A艏爸蟮牟樵?,可以使用Repository模式,將其模擬成一個集合從而進行存取操作。

Eric把Factory和Repository被歸為「支持對象」,以和其他用于表示模型的領域?qū)ο蠓珠_。

(3) 分離函數(shù)和命令

使用無副作用的函數(shù)模式,把沒有副作用的查詢邏輯提取出來,成為無副作用的函數(shù),而讓有副作用的命令盡可能簡單。

基于同樣的理由,我也在考慮將有IO操作的邏輯提取出來,直接讓應用層調(diào)用,而不是和其他業(yè)務邏輯組合。

(4) 分離領域中的算法

使用Strategy模式,把業(yè)務邏輯中的變化點放到策略對象中,讓不同的實現(xiàn)可以互換,從而實現(xiàn)關注點分離。

(5) 分離領域中的規(guī)則

使用Specification模式,將領域中用于判斷是非的業(yè)務規(guī)則放到規(guī)格對象中。

(6) 分離做什么和怎么做

采用Intention-Revealing Interface和Cohesive Mechanism模式,把「做什么」和「怎么做」分離。讓釋意接口專注于表明意圖,方便調(diào)用方使用;讓內(nèi)聚機制封裝實現(xiàn)細節(jié),在釋意接口背后解決問題。

2.重新思考

我發(fā)現(xiàn)在OO BootCamp中得到的模型往往無法直接用于真實項目中,這讓我用新的角度重新學習和思考了領域模型。

在實際項目中,設計者往往過早陷入對于一些具體模式的識別,比如實體、聚合、領域服務,而忽略了如何設計一個可以表達領域概念的模型。我們應該基于領域概念設計領域模型,然后再采用合適的模式降低領域模型的復雜度,進一步增加領域模型的表達能力。

很多項目雖然也使用了以領域為核心的架構,但是設計者仍然是數(shù)據(jù)模型/貧血模型的思考方式,把大量領域邏輯放置在了萬能的Service中,讓領域概念隱藏在了冗長的過程代碼中,絲毫沒有享受到DDD帶來的收益。

軟件的核心是其為用戶解決領域相關的問題的能力。

——《領域驅(qū)動設計》 第一部分

在學習了讓我們眼花繚亂的眾多方法后,我們重新回到DDD的初衷,重新審視軟件設計和DDD之間的關系,讓DDD幫助我們提升軟件設計能力。

原文鏈接:??當我們談論DDD時我們在談論什么 (qq.com)??

責任編輯:趙寧寧 來源: 51CTO
相關推薦

2024-07-26 08:35:29

2020-11-16 15:47:05

SaaS軟件轉(zhuǎn)型

2016-08-12 10:11:22

2022-07-05 09:31:46

基礎設施容器Docker

2019-02-19 10:22:07

5G5G手機5G技術

2017-04-05 17:59:29

思科CTO下午茶

2024-03-28 14:16:43

容災云計算

2022-04-28 13:02:32

cpu指令編程

2019-03-18 10:08:18

RSACRSA大會 網(wǎng)絡安全

2019-06-04 14:36:04

高并發(fā)Java架構

2014-02-06 12:21:35

軟件集成

2022-03-11 21:28:31

部署開發(fā)服務器

2023-08-28 10:33:09

敏捷Scrum理念

2019-07-30 13:12:22

2019-12-24 11:19:44

容器DockerLinux

2016-11-22 23:44:56

2017-03-07 15:43:28

編程語言函數(shù)數(shù)據(jù)結構

2017-10-11 08:40:29

VR服務器移動端

2021-11-18 21:09:50

流批場景引擎

2017-10-11 13:25:00

前端
點贊
收藏

51CTO技術棧公眾號