背景
為什么要制定參考工程架構
不同團隊落地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/553128.html
標籤:其他
下一篇:返回列表
