DDD 實戰課 -- 學習筆記

目錄

學好了 DDD,你能做什麼?

其次,就是通過戰略設計,建立領域模型,劃分微服務邊界。

最後,通過戰術設計,我們會從領域模型轉向微服務設計和落地。

DDD 的核心知識體系

領域驅動設計:微服務設計爲什麼要選擇 DDD?

我認爲微服務拆分困境產生的根本原因就是不知道業務或者微服務的邊界到底在什麼地方。換句話說,確定了業務邊界和應用邊界,這個困境也就迎刃而解了。

DDD 是一種處理高度複雜領域的設計思想,它試圖分離技術實現的複雜性,並圍繞業務概念構建領域模型來控制業務的複雜性,以解決軟件難以理解,難以演進的問題。DDD 不是架構,而是一種架構設計方法論,它通過邊界劃分將複雜業務領域簡單化,幫我們設計出清晰的領域和應用邊界,可以很容易地實現架構演進。

DDD 戰略設計會建立領域模型,領域模型可以用於指導微服務的設計和拆分。事件風暴是建立領域模型的主要方法,它是一個從發散到收斂的過程。它通常採用用例分析、場景分析和用戶旅程分析,儘可能全面不遺漏地分解業務領域,並梳理領域對象之間的關係,這是一個發散的過程。事件風暴過程會產生很多的實體、命令、事件等領域對象,我們將這些領域對象從不同的維度進行聚類,形成如聚合、限界上下文等邊界,建立領域模型,這就是一個收斂的過程。

在從業務模型向微服務落地的過程中,也就是從戰略設計向戰術設計的實施過程中,我們會將領域模型中的領域對象與代碼模型中的代碼對象建立映射關係,將業務架構和系統架構進行綁定。當我們去響應業務變化調整業務架構和領域模型時,系統架構也會同時發生調整,並同步建立新的映射關係。

DDD 與微服務的關係

DDD 是一種架構設計方法,微服務是一種架構風格,兩者從本質上都是爲了追求高響應力,而從業務視角去分離應用系統建設複雜度的手段。兩者都強調從業務出發,其核心要義是強調根據業務發展,合理劃分領域邊界,持續調整現有架構,優化現有代碼,以保持架構和代碼的生命力,也就是我們常說的演進式架構。

DDD 主要關注:從業務領域視角劃分領域邊界,構建通用語言進行高效溝通,通過業務抽象,建立領域模型,維持業務和代碼的邏輯一致性。

微服務主要關注:運行時的進程間通信、容錯和故障隔離,實現去中心化數據管理和去中心化服務治理,關注微服務的獨立開發、測試、構建和部署。

領域、子域、核心域、通用域和支撐域:傻傻分不清?

DDD 的領域就是這個邊界內要解決的業務問題域。

領域可以進一步劃分爲子領域。我們把劃分出來的多個子領域稱爲子域,每個子域對應一個更小的問題域或更小的業務範圍。

子域可以根據自身重要性和功能屬性劃分爲三類子域,它們分別是:核心域、通用域和支撐域。

決定產品和公司核心競爭力的子域是核心域,它是業務成功的主要因素和公司的核心競爭力。沒有太多個性化的訴求,同時被多個子域使用的通用功能子域是通用域。還有一種功能子域是必需的,但既不包含決定產品和公司核心競爭力的功能,也不包含通用功能的子域,它就是支撐域。

核心域、支撐域和通用域的主要目標是:通過領域劃分,區分不同子域在公司內的不同功能屬性和重要性,從而公司可對不同子域採取不同的資源投入和建設策略,其關注度也會不一樣。

限界上下文:定義領域邊界的利器

在 DDD 領域建模和系統建設過程中,有很多的參與者,包括領域專家、產品經理、項目經理、架構師、開發經理和測試經理等。對同樣的領域知識,不同的參與角色可能會有不同的理解,那大家交流起來就會有障礙,怎麼辦呢?因此,在 DDD 中就出現了 “通用語言” 和“限界上下文”這兩個重要的概念。

通用語言定義上下文含義,限界上下文則定義領域邊界,以確保每個上下文含義在它特定的邊界內都具有唯一的含義,領域模型則存在於這個邊界之內。

在事件風暴過程中,通過團隊交流達成共識的,能夠簡單、清晰、準確描述業務涵義和規則的語言就是通用語言。

爲了避免同樣的概念或語義在不同的上下文環境中產生歧義,DDD 在戰略設計上提出了 “限界上下文” 這個概念,用來確定語義所在的領域邊界。

我認爲限界上下文的定義就是:用來封裝通用語言和領域對象,提供上下文環境,保證在領域之內的一些術語、業務相關對象等(通用語言)有一個確切的含義,沒有二義性。這個邊界定義了模型的適用範圍,使團隊所有成員能夠明確地知道什麼應該在模型中實現,什麼不應該在模型中實現。

實體和值對象:從領域模型的基礎單元看系統設計

在 DDD 中有這樣一類對象,它們擁有唯一標識符,且標識符在歷經各種狀態變更後仍能保持一致。對這些對象而言,重要的不是其屬性,而是其延續性和標識,對象的延續性和標識會跨越甚至超出軟件的生命週期。我們把這樣的對象稱爲實體。

通過對象屬性值來識別的對象,它將多個相關屬性組合爲一個概念整體。在 DDD 中用來描述領域的特定方面,並且是一個沒有標識符的對象,叫作值對象。

人員實體原本包括:姓名、年齡、性別以及人員所在的省、市、縣和街道等屬性。這樣顯示地址相關的屬性就很零碎了對不對?現在,我們可以將 “省、市、縣和街道等屬性” 拿出來構成一個“地址屬性集合”,這個集合就是值對象了。

同樣的對象在不同的場景下,可能會設計出不同的結果。有些場景中,地址會被某一實體引用,它只承擔描述實體的作用,並且它的值只能整體替換,這時候你就可以將地址設計爲值對象,比如收貨地址。而在某些業務場景中,地址會被經常修改,地址是作爲一個獨立對象存在的,這時候它應該設計爲實體,比如行政區劃中的地址信息維護。

聚合和聚合根:怎樣設計聚合?

領域模型內的實體和值對象就好比個體,而能讓實體和值對象協同工作的組織就是聚合,它用來確保這些領域對象在實現共同的業務邏輯時,能保證數據的一致性。

聚合就是由業務和邏輯緊密關聯的實體和值對象組合而成的,聚合是數據修改和持久化的基本單元,每一個聚合對應一個倉儲,實現數據的持久化。

領域事件:解耦微服務的關鍵

在事件風暴(Event Storming)時,我們發現除了命令和操作等業務行爲以外,還有一種非常重要的事件,這種事件發生後通常會導致進一步的業務操作,在 DDD 中這種事件被稱爲領域事件。

舉例來說的話,領域事件可以是業務流程的一個步驟,比如投保業務繳費完成後,觸發投保單轉保單的動作;也可能是定時批處理過程中發生的事件,比如批處理生成季繳保費通知單,觸發發送繳費郵件通知操作;或者一個事件發生後觸發的後續動作,比如密碼連續輸錯三次,觸發鎖定賬戶的動作。

通過領域事件驅動的異步化機制,可以推動業務流程和數據在各個不同微服務之間的流轉,實現微服務的解耦,減輕微服務之間服務調用的壓力,提升用戶體驗。

領域事件處理包括:事件構建和發佈、事件數據持久化、事件總線、消息中間件、事件接收和處理等。

DDD 分層架構:有效降低層與層之間的依賴

DDD 分層架構

DDD 分層架構有一個重要的原則:每層只能與位於其下方的層發生耦合。

微服務架構的演進

微服務內服務的演進

三層架構向 DDD 分層架構演進

DDD 分層架構包含用戶接口層、應用層、領域層和基礎層。通過這些層次劃分,我們可以明確微服務各層的職能,劃定各領域對象的邊界,確定各領域對象的協作方式。這種架構既體現了微服務設計和架構演進的需求,又很好地融入了領域模型的概念,二者無縫結合,相信會給你的微服務設計帶來不一樣的感覺。

微服務架構模型:幾種常見模型的對比和分析

整潔架構

整潔架構最主要的原則是依賴原則,它定義了各層的依賴關係,越往裏依賴越低,代碼級別越高,越是核心能力。外圓代碼依賴只能指向內圓,內圓不需要知道外圓的任何情況。

六邊形架構

六邊形架構的核心理念是:應用是通過端口與外部進行交互的。

三種微服務架構模型的對比和分析

架構模型通過分層的方式來控制需求變化從外到裏對系統的影響,從外向裏受需求影響逐步減小。面向用戶的前端可以快速響應外部需求進行調整和發佈,靈活多變,應用層通過服務組合和編排來實現業務流程的快速適配上線,減少傳導到領域層的需求,使領域層保持長期穩定。

項目級微服務

項目級微服務的內部遵循分層架構模型就可以了。領域模型的核心邏輯在領域層實現,服務的組合和編排在應用層實現,通過 API 網關爲前臺應用提供服務,實現前後端分離。但項目級的微服務可能會調用其它微服務,你看在下面這張圖中,比如某個項目級微服務 B 調用認證微服務 A,完成登錄和權限認證。

企業級中臺微服務

我們可以在中臺微服務之上增加一層,你看下面這張圖,增加的這一層就位於紅色框內,它的主要職能就是處理跨中臺微服務的服務組合和編排,以及微服務之間的協調,它還可以完成前端不同渠道應用的適配。如果再將它的業務範圍擴大一些,我可以將它做成一個面向不同行業和渠道的服務平臺。

在微服務架構中,應用層、領域層和基礎層解耦是通過倉儲模式,採用依賴倒置的設計方法來實現的。在應用設計中,我們會同步考慮和基礎資源的代碼適配,那麼一旦基礎設施資源出現變更(比如換數據庫),就可以屏蔽資源變更對業務代碼的影響,切斷業務邏輯對基礎資源的依賴,最終降低資源變更對應用的影響。

DDD 分層架構、整潔架構、六邊形架構都是以領域模型爲核心,實行分層架構,內部核心業務邏輯與外部應用、資源隔離並解耦。

中臺:數字轉型後到底應該共享什麼?

中臺的關鍵詞:共享、聯通、融合和創新。聯通是前臺以及中臺之間的聯通,融合是前臺流程和數據的融合,並以共享的方式支持前端一線業務的發展和創新。

我認爲,中臺首先體現的是一種企業級的能力,它提供的是一套企業級的整體解決方案,解決小到企業、集團,大到生態圈的能力共享、聯通和融合問題,支持業務和商業模式創新。通過平臺聯通和數據融合爲用戶提供一致的體驗,更敏捷地支撐前臺一線業務。

數字化轉型中臺應該共享什麼

在中臺設計和規劃時,我們需要整體考慮企業內前臺、中臺以及後臺應用的協同,實現不同渠道應用的前端頁面、流程和服務的共享,還有核心業務鏈路的聯通以及前臺流程和數據的融合、共享,支持業務和商業模式的創新。

如何實現前中後臺的協同?

如果把業務中臺比作陸軍、火箭軍和空軍等專業軍種的話,它主要發揮戰術專業能力。前臺就是作戰部隊,它需要根據前線的戰場需求,對業務中臺的能力進行調度,實現能力融合和效率最大化。而數據中臺就是信息情報中心和聯合作戰總指揮部,它能夠彙集各種數據、完成分析,制定戰略和戰術計劃。後臺就是後勤部隊,提供技術支持。

前臺主要面向客戶以及終端銷售者,實現營銷推廣以及交易轉化;中臺主要面向運營人員,完成運營支撐;後臺主要面向後臺管理人員,實現流程審覈、內部管理以及後勤支撐,比如採購、人力、財務和 OA 等系統。

前臺通過頁面和流程共享實現不同渠道應用之間的前臺融合,中臺通過 API 實現服務共享。而前臺、業務中臺和數據中臺的融合可以實現傳統應用與互聯網應用的融合,從而解決 “後端雙核心、前端兩張皮” 的問題。能力複用了,前臺流程和數據融合了,才能更好地支持業務的融合和商業模式的創新。

DDD、中臺和微服務:它們是如何協作的?

中臺是抽象出來的業務模型,微服務是業務模型的系統實現,DDD 作爲方法論可以同時指導中臺業務建模和微服務建設,三者相輔相成,完美結合。

中臺在企業架構上更多偏向業務模型,形成中臺的過程實際上也是業務領域不斷細分的過程。在這個過程中我們會將同類通用的業務能力進行聚合和業務重構,再根據限界上下文和業務內聚的原則建立領域模型。而 DDD 的戰略設計最擅長的就是領域建模。

那在中臺完成領域建模後,我們就需要通過微服務來完成系統建設。此時,DDD 的戰術設計又恰好可以與微服務的設計完美結合。可以說,中臺和微服務正是 DDD 實戰的最佳場景。

DDD、中臺和微服務的協作模式

如果將企業內整個業務域作爲一個問題域的話,企業內的所有業務就是一個領域。在進行領域細分時,從 DDD 視角來看,子域可分爲核心域、通用域和支撐域。從中臺建設的視角來看,業務域細分後的業務中臺,可分爲核心中臺和通用中臺。

從領域功能屬性和重要性對照來看,通用中臺對應 DDD 的通用域和支撐域,核心中臺對應 DDD 的核心域。從領域的功能範圍來看,子域與中臺是一致的。領域模型所在的限界上下文對應微服務。建立了這個映射關係,我們就可以用 DDD 來進行中臺業務建模了。

中臺如何建模?

中臺業務抽象的過程就是業務建模的過程,對應 DDD 的戰略設計。系統抽象的過程就是微服務的建設過程,對應 DDD 的戰術設計。

DDD 戰略設計包括上述的第一步到第四步,主要爲:業務域分解爲中颱,對中臺歸類,完成領域建模,建立中臺業務模型。DDD 戰術設計是第五步,領域模型映射爲微服務,完成中臺建設。

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