主頁 > 軟體設計 > 【實踐篇】領域驅動設計:DDD工程參考架構

【實踐篇】領域驅動設計:DDD工程參考架構

2023-05-23 09:14:09 軟體設計

背景

為什么要制定參考工程架構

不同團隊落地DDD所采取的應用架構風格可能不同,并沒有統一的、標準的DDD工程架構,有些團隊可能遵循經典的DDD四層架構,或改進的DDD四層架構,有些團隊可能綜合考慮分層架構、整潔架構、六邊形架構等多種架構風格,有些在實踐中可能引入CQRS解決讀模型與寫模型的差異化等等,即使無法制定通用的、標準的工程應用架構,但為團隊制定一個遵循領域驅動設計思想的參考架構依然有價值,基于以下原因:

  • 為團隊實踐DDD的戰術設計提供可以快速開始的工程參考
  • 參考工程大量的命名和結構決策,顯式的體現DDD的相關理念,有利于團隊對DDD的戰術實作達成一致認知
  • 同時,參考架構有助于沉淀團隊對領域驅動設計的一些思考和最佳實踐

參考架構的考量因素

雖然無法制定完全通用的DDD參考架構,但制定某個特定背景關系下的參考架構卻具有可行性和實踐價值,針對于背景關系的選擇要盡量貼合實際的工程實踐場景并考慮多維度的因素,

本文所述參考工程架構遵循以下原則:

  • 遵循領域驅動設計的本質思想
  • 充分考慮業務系統建設特點
  • 依賴最小化,保持輕量

希望工程參考架構能涵蓋以下范圍

  • 分離業務域與技術域

參考架構要遵循技術和業務隔離的特性,可以參考多種架構風格,業務與技術關注點的分離并不是DDD獨有的特點,在六邊形、整潔架構、洋蔥架構中都遵循了這一重要原則,

  • 多限界背景關系場景

大多數團隊基于DDD進行微服務拆分的時候,特別是系統建設初期,對單個微服務應用內的限界背景關系的粒度需要權衡,由于團隊組織架構因素及微服務成本問題,單個應用容納的限界背景關系一般是多個(理想情況下是1:1),這些限界背景關系隨著后續的逐步迭代有可能會遷移至獨立應用,因此,參考架構將多背景關系的應用場景作為重要考量因素,

  • 明確的組件、職責邊界及依賴關系
  • 支持領域報表場景:報表場景在業務系統較為常見,DDD并沒有體現該場景的處理方式,作為工程參考架構,還是希望能夠從實際業務出發,體現對寫模型和報表模型的顯示支持
  • 外部依賴最小化:需要排除不必要的依賴,保持工程架構的輕量化

參考架構剖析

應用的多背景關系結構

基于以上原則,參考工程考慮單個應用內多背景關系的場景,以期在模塊化和服務粒度及成本間進行權衡折衷,應用架構對多背景關系的支持的邏輯示意圖如下所示,在解決方案域對限界背景關系進行識別和劃分之后,基于其業務內聚性和關聯性,把多個背景關系實作單個工程應用中,單個應用內的多個限界背景關系間可能存在互動,互動的形式可以是基于事件驅動,也可以是基于行程內呼叫,采用事件驅動的方式背景關系間的耦合性對低一些,但一般需要引入事件總線的支持,額外組件的引入必然會導致復雜性的上升,行程內呼叫則耦合性會高一些,但從實作角度復雜度會低一些,具體選擇哪種方式開發人員可以基于實際情況進行權衡,

需要再次說明的是,這種應用架構決策是一種多因素的權衡,并沒有與子域與限界背景關系1:1的理想化實踐保持一致,

從上圖的邏輯示意圖我們再深入一層,從分層的維度去剖析一下詳細的應用架構的展現形式,如下圖所示:

分層關注點

客戶端

客戶端與應用處于不同的行程,是應用能力的消費端,在實際專案中可能是APP端、PC端、小程式端、公眾號端或三方的業務呼叫端等等,

接入層

接入層是外部系統與應用內部業務能力的中間層,接入層是應用層對外的門面,是當前應用對外暴露業務能力的入口,該層的組成可能是對外提供的HTTP介面宣告、分布式定時任務調度、訊息監聽器、RPC服務等等,其重要職責包括對外部系統的請求進行基礎的引數校驗、入參適配和服務路由(轉發至系一層的應用服務)以及回應資料的適配

業務層:

該層是應用的業務邏輯所在層,整個架構風格采用模塊化單體風格,在該層不同的限界背景關系體現為不同的模塊,在每個限界背景關系內采用分層架構,獨立劃分為應用層、領域層和網關層

應用層:

協調領域物件、領域服務或外部依賴服務完成業務用例,該層只做能力協調,不處理任何領域邏輯

領域層:

領域層是整個分層的核心,與技術實作無關,主要負責領域模型、領域事件、領域服務定義,以及業務相關外部服務的介面抽象以及倉庫的介面抽象等,

領域層與應用服務的本質區別是:應用層不包含領域邏輯,領域邏輯全部下沉到領域層實作,

網關層:

網關層定位是應用的出口網關,是應用與外部基礎設施互動的防腐層,處理所有技術相關實作

該組件的命名有多種方式,比如有些團隊將其命名為 “rpc”,也有些團隊將其命名為 “infrastructure”,不同的命名體現了團隊對其背后所表達的隱喻的決策選擇,在本文的參考架構中選擇了 網關-Gateway這一命名,決策原因是:限界背景關系自身是高內聚的,其與外部的互動需要統一出口,Gateway所表達的網關的含義恰當的表現了這種統一出口的理念,如果Facade層是應用的北向網關,是外部系統請求進入內部的入口,則此時的Gateway則表達的是限界背景關系的南向網關,是內部應用連接外部的出口,

組件及依賴

從宏觀的分層我們再深入一層看下每層的組件劃分,如下圖所示:

Start組件:

整個應用的啟動入口、加載應用配置資訊等等,

Common組件

提供在不同的限界背景關系間復用的領域模型元素的抽象,比如對Command、Query、Event、Entity、ValueObjec通用抽象等,當然,領域模型的通用抽象不是必須在Common組件內以提供復用,也可以作為一個獨立的限界背景關系,并以共享內核方式與其它背景關系進行共享,或者也可以實作為獨立的jar包組件,

API 組件

RPC型別服務的介面宣告組件,以公司內部使用的JSF為例,該組件是應用對外部系統暴露的JSF API的組件,該組件可以是獨立的工程,當然,有些團隊會將其作為一個Module放入應用工程中,

統一門面組件:Facade

外部客戶端觸達應用系統的入口,也是內部應用服務的統一門面,類似于六邊形架構風格下的配接器,參考架構中基于不同場景劃分為 provider(RPC服務)、task(定時任務)、listener(MQ監聽)、rest(http介面)等幾個子包,外部請求進入系統后,由Facade組件完成入參基本校驗、入參轉換、服務路由以及出參轉換等操作,另外,還可以承擔處理登錄態、鑒權以及日志等相關能力,

應用服務組件:Application Service

應用服務代表著用例以及系統行為,其通過委托到領域層和基礎設施層(參考架構中的Gateway組件)完成用例的應用邏輯邏輯處理,可以理解為應用服務是領域層的客戶端,該組件典型的職責:

從存盤層加載領域物件、委托領域物件執行領域邏輯、保存領域物件

  • 重要事件通知到外部
  • 出入參轉化適配
  • 事務處理外部
  • 非領域邏輯的服務呼叫

External API

應用服務的邏輯不僅僅需要協調領域層,有時還需要依賴于外部的三方服務,External API 組件負責對這些外部服務進行介面宣告定義,不做具體實作,

應用服務組件不直接依賴這些外部服務實作,而是依賴其介面抽象,同時,此處的模型定義是基于該限界背景關系的語意,是一種對外部模型的適配,

該組件不依賴其它組件,且僅被應用服務組件和Gateway組件依賴,網關組件依賴External API 組件的介面宣告并提供底層技術實作,應用服務組件依賴其介面,并通過IOC方式將具體實作注入完成服務呼叫,

注意,該組件所依賴的服務不涉及領域邏輯,只是用于支撐應用服務的編排,如果是涉及了領域邏輯,則對外部服務依賴的介面定義需要下沉到Domain層,

Query

Query組件解決領域相關的報表查詢場景,在限界背景關系內作為與應用服務對等的組件存在,兩個組件分別負責業務的查詢和命令邏輯,

雖然引入了Query組件對報表場景提供支持,但沒有完全的引入CQRS這一模式,在很多資料中CQRS與DDD同時提及的概率比較高,因為,在DDD下我們解決了復雜的面向領域的寫側模型,但在報表場景下,這種富領域模型有可能并不是最佳選擇,如果讀側和寫側都基于統一的領域模型,一般會導致領域模型的折衷設計,為了滿足查詢側訴求,領域模型不得不引入額外的、領域無關的屬性,由此造成領域模型的污染,

Domain

Domain組件是領域邏輯核心,承擔整個系統領域邏輯的實作,其定義了領域模型、領域服務、領域事件以及倉儲層的抽象,該組件不依賴其它組件(除了通用的領域模型抽象組件Common之外,

上圖所體現的參考架構使用了DDD的戰術設計的經典建模元素,比如聚合、物體、值物件、倉儲、工廠以及領域事件等,在實際落地程序中,這些設計元素的抽象具有一定的挑戰,設計程序中需要經過不斷分析、權衡和重構以完成建模,這正是核心設計所在,

Gateway

網關層承擔整個技術相關性的實作,是內部應用的出口網關,

技術相關性是網關組件區別于其它組件的根本特性,在該組件內要處理技術實作的所有細節,比如與外部服務、中間件、DB的互動等,同時,其與Domain組件以及External API組件的介面抽象協作,共同承擔了系統與外部依賴間(包括外部服務以及應用依賴的中間件、DB等基礎設施)的防腐層職能,負責內部模型到外部模型轉化、外部模型到內部模型轉化以及具體互動,基于網關組件的特性,也非常適合在該層做統一的外部服務資料快取及降級熔斷處理,

網關層依賴于Domain、Application Service、External API和Query組件,負責上述四個組件定義的介面實作,在Gateway組件通過子包對實作進行隔離:

  • query:查詢服務組件的實作
  • external:External API 組件中依賴外部服務的介面實作
  • repository:倉儲介面的實作

最后

應用架構模式的選擇是系統架構設計的重要維度之一,結構不僅僅是簡單的包結構和命名,其傳達的是一種頂層抽象,背后包含了大量的實踐和知識,制定符合團隊情況的工程參考架構,并在團隊成員間達成共識非常重要,領域驅動設計并沒有統一的、通用的架構,試圖定義標準架構是不切實際的,本文描述的工程架構只是一個參考,實踐程序中應該基于團隊特定情況而有所差異,但原則上都應該遵循業務域與技術域分離的核心理念

作者:京東科技 倪新明

內容來源:京東云開發者社區

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/553124.html

標籤:領域驅動設計

上一篇:實際業務中使用策略模式對代碼進行重構

下一篇:返回列表

標籤雲
其他(159507) Python(38162) JavaScript(25443) Java(18096) C(15230) 區塊鏈(8267) C#(7972) AI(7469) 爪哇(7425) MySQL(7204) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5871) 数组(5741) R(5409) Linux(5340) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4574) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2433) ASP.NET(2403) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1975) 功能(1967) Web開發(1951) HtmlCss(1940) C++(1919) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1878) .NETCore(1861) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【實踐篇】領域驅動設計:DDD工程參考架構

    不同團隊落地DDD所采取的應用架構風格可能不同,并沒有統一的、標準的DDD工程架構。即使無法制定通用的、標準的工程應用架構,但為團隊制定一個遵循領域驅動設計思想的參考架構依然有價值。 ......

    uj5u.com 2023-05-23 09:14:09 more
  • 實際業務中使用策略模式對代碼進行重構

    一.業務描述 最近在負責公司一個語音的微服務模塊優化,這個模塊主要的業務是:1.天貓精靈、小度、若琪、小京魚、小愛同學、思必馳這些第三方音響對我們的用戶進行oauth2/JWT授權; 2.這些第三方音響服務呼叫我們的設備發現介面對公司的設備資訊在第三方平臺進行一個存盤;3.第三方平臺對用戶發出的語音 ......

    uj5u.com 2023-05-21 07:57:43 more
  • asp.net core 一種基于token 和 Permission 的權限管理中間件示

    1. 先上封裝后的使用效果 [Permission(Key = "/User/AddUser")] [HttpPost] public Result AddUser([FromBody] SaUser user) { //Do sth. throw new NotImplementedExcepti ......

    uj5u.com 2023-05-21 07:57:34 more
  • 實際業務中使用策略模式對代碼進行重構

    一.業務描述 最近在負責公司一個語音的微服務模塊優化,這個模塊主要的業務是:1.天貓精靈、小度、若琪、小京魚、小愛同學、思必馳這些第三方音響對我們的用戶進行oauth2/JWT授權; 2.這些第三方音響服務呼叫我們的設備發現介面對公司的設備資訊在第三方平臺進行一個存盤;3.第三方平臺對用戶發出的語音 ......

    uj5u.com 2023-05-21 07:57:16 more
  • asp.net core 一種基于token 和 Permission 的權限管理中間件示

    1. 先上封裝后的使用效果 [Permission(Key = "/User/AddUser")] [HttpPost] public Result AddUser([FromBody] SaUser user) { //Do sth. throw new NotImplementedExcepti ......

    uj5u.com 2023-05-21 07:56:51 more
  • 【實踐篇】教你玩轉JWT認證---從一個優惠券聊起

    關于JWT,可以說是分布式系統下的一個利器,我在我的很多專案實踐中,認證系統的第一選擇都是JWT。它的優勢會讓你欲罷不能,就像你領優惠券一樣。 ......

    uj5u.com 2023-05-19 10:39:50 more
  • ET介紹——強大的MongoBson庫

    強大的MongoBson庫 后端開發,統計了一下大概有這些場景需要用到序列化: 物件通過序列化反序列化clone 服務端資料庫存盤資料,二進制 分布式服務端,多行程間的訊息,二進制 后端日志,文本格式 服務端的各種組態檔,文本格式 C#序列化庫有非常非常多了,protobuf,json等等。但是這 ......

    uj5u.com 2023-05-19 10:39:33 more
  • 領域驅動設計DDD架構決議和繪圖模板分享

    DDD整潔架構 DDD整潔架構為了解決強呼叫的關系,出現了洋蔥架構(六邊形)架構,就是為了實作依賴倒置 它的思想就是把領域模型放到核心的位置,領域模型是獨立的,不會直接強依賴其他層,而通過配接器來完成領域模型和外層的資料交換。 DDD分層架構和三層架構的區別與關系 DD分層架構和三層架構的區別與關系 ......

    uj5u.com 2023-05-19 10:39:16 more
  • 架構師日記-從代碼到設計的性能優化指南 | 京東云技術團隊

    性能優化是個系統性工程,宏觀上可分為網路,服務,存盤幾個方向,每個方向又可以細分為架構,設計,代碼,可用性,度量等多個子項。 本文將重點從代碼和設計兩個子項展開,談談那些提升性能的知識點。 ......

    uj5u.com 2023-05-19 10:39:00 more
  • 【實踐篇】教你玩轉JWT認證---從一個優惠券聊起

    關于JWT,可以說是分布式系統下的一個利器,我在我的很多專案實踐中,認證系統的第一選擇都是JWT。它的優勢會讓你欲罷不能,就像你領優惠券一樣。 ......

    uj5u.com 2023-05-19 10:37:45 more