DDD 即領域驅動設計(Domain-Driven Design)。它來源於著名建模專家 Eric Evans 發表的很是具備影響力的書籍:《domain-driven design –tackling complexity in the heart of software》(中文:領域驅動設計—軟件核心複雜性應對之道)。其最先普遍應用於傳統軟件架構設計中。前端
今年4月,InfoQ 發佈了軟件架構與設計的趨勢報告。在報告中能夠看出,微服務、領域驅動設計等已成爲目前軟件開發行業的主流趨勢,筆者也瞭解到,DDD 已成爲大部分企業微服務落地、中臺建設的指導思想。web
(圖片來源:infoQ)spring
隔離變化和沉澱複用數據庫
在互聯網時代,業務系統構建初期,場景一般簡單清晰,基於數據庫表設計+CRUD 就能支撐業務的敏捷迭代。隨着時間的推移,場景和業務邏輯變得複雜、定製,模塊之間彼此耦合,系統變得愈來愈臃腫,每每牽一髮而動全身。即便加一個字段這樣看似簡單的邏輯,光梳理對其餘功能點和模塊的影響,就至少須要一個對業務和代碼都很熟悉的團隊老成員才能穩妥敲定。相信一個實現1年以上的業務系統,其架構和代碼就有可能正在經歷着以上這些,開始慢慢腐化。後端
一個最經典的例子——電商系統裏面諸如如下 product 類的設計(現實中字段數可能幾百個),它是不符合高內聚低耦合這個架構設計原則的:restful
DDD 經過劃分限界上下文,拆分子領域,實現解耦和複用:網絡
如下圖片來自軟件開發教父:Martin Fowler。誠然,爲應付愈來愈複雜的業務邏輯,以自頂向下設計的領域聚合模型替代數據表模型,才能真正實現以業務實體爲核心的靈活拓展:架構
以上,讓經歷互聯網泡沫存活下來的系統弄潮兒逐漸重燃對 DDD 的熱情,但願藉助 DDD 能重拾建造更合理軟件架構的信心。但在落地上,荊棘環生,困境各異。下面咱們來介紹一下 DDD 在京東 DevOps 項目協做領域的落地實踐。app
將 DDD 應用到組件化
框架
在京東內部,項目協做領域有兩個用戶羣體覆蓋特別廣(總用戶數 8W+)的系統:PMP 和行雲。
PMP是一個更面向項目經理的項目管理軟件,包含項目流程管理、需求管理、里程碑管理、任務管理、工時管理、成本管理、OKR 管理、ROI 驗證和滿意度評分等。在架構設計上,PMP 是一個很是龐大的單體應用,其先後端不分離,全部業務邏輯糅雜在一塊兒,項目表單字段數達到了 100+。通過時間和組織的變遷,在可擴展性和可維護性上,簡直是場災難。
行雲起初的定位是面向研發的敏捷協同軟件,包含跨部門需求管理、敏捷迭代和任務管理等。隨着行雲的普遍使用,將 PMP 功能融合到行雲的呼聲愈來愈高。
同時,行雲對公司外部提供 ToB 服務。內外部存在着大量差別化的場景和業務,單純靠以往的不斷添加 if else 揉泥球的方式,已經徹底行不通。新的定位和背景下,要求咱們必須將業務邏輯拆分爲一個個靈活的組件,作到複用與邏輯沉澱;另外一方面,差別化的邏輯能夠靈活擴展。這其中有着巨大的挑戰:
上圖中間圓弧描述的是咱們在對組件拆分時參考的原則(業務可獨立運營、高內聚低耦合、數據完整性、漸進性),以此爲基礎,在應對業務和技術視角上的挑戰時,咱們採起的相關 DDD 戰略和戰術。
業務的挑戰
PMP 和行雲中都有需求管理、任務管理。這其中需求、任務是否是一個概念?項目、需求、迭代、任務等之間是什麼關係?如何對內和對外沉澱一套清晰可複用的業務組件?
DDD 中概念比較多,包含限界上下文、聚合、聚合根、實體、值對象等,本文先不關注這些細節,直接聚焦如下問題:
一、 劃分邊界,識別領域對象或者領域類,保證其職責清晰純粹;
二、 明確領域類之間的關聯、依賴,界定調用關係和方式。
經過領域分析建模,造成統一語言,最終將項目協做管理這個總體,拆分爲一個個功能完整、業務邏輯明確的業務域,如項目域、任務域、工時域等等。每個業務域對外提供明確的領域服務,一個業務領域能夠管理多個業務實體。
x_lazy=1&wx_co=1)
技術的挑戰
在劃分完領域後,理想的狀況是各領域高度自治,減小依賴,甚至各領域能夠由不一樣的團隊來實現,各團隊聚焦沉澱該領域核心能力。
最終,咱們造成了一個組件化方案:根據劃分出來的領域,將系統拆分紅業務組件(核心子領域)和基礎組件(通用和支撐子領域),各組件先後端分離。即會有如下前端應用:需求管理、項目管理、缺陷管理、用例管理等;後端應用相應提供不一樣的領域服務,領域服務採用分層架構(interface, application, domain, infrastructure)。權限管理、網關服務、消息服務等基礎組件下沉,實現最大化組件複用。
按照領域拆分紅業務組件,對系統來講,最終提供給終端用戶還需是一個總體。但組件化意味着分離,那對於業務組件的先後端應用又面臨怎樣的協同挑戰呢?**
業務組件前端應用的挑戰
爲了實現各業務組件能並行、獨立演進,理想狀況下,前端子應用需知足獨立編譯、打包、部署,並最終集成到一個平臺上呈現統一的 UI 風格和一致的交互體驗。
以上業界將此歸結爲微前端架構:實現一種架構風格,能夠將衆多獨立交付的前端應用組合成一個大型總體,對客戶表現爲一件單一完整的產品。
最終,咱們行雲團隊落地了一個 Jmodule 微前端組件框架。
前端應用經過微前端架構和前端組件框架註冊到平臺,系統層實現組件元數據管理、運行時熱加載靜態資源和組件間通訊,對用戶側提供徹底可插拔可配置的組件。具體原理和實現等將在後續另外一篇章節中展開。
業務組件後端應用的挑戰
行雲在設計之初,後端服務採用的是微服務的架構(利用spring cloud gateway、Eureka 等實現服務註冊、網關調用等),這和 DDD 相得益彰。在覈心業務組件內,領域服務按照經典分層架構(interface, application, domain, infrastructure)來組織。
除了界定組件內部分層的邊界,還須要明確組件間的調用和依賴關係,進一步明確組件的職責。在 DDD 中相應地定義了限界上下文之間的映射關係:
在組件的調用和依賴關係上,咱們能夠借鑑以上映射關係的理念來落地。
舉個例子,咱們已經沉澱了項目組件和任務組件。假設須要實現的業務場景:當刪除某個項目時,須要檢查項目中是否已有進行的任務,無則刪之,有則提示不能刪。根據 DDD 的映射關係,任務被項目依賴,任務處在上游的位置,理想狀況下它不須要知道項目業務領域刪除的具體邏輯規則,同時儘可能減小項目業務規則的變化所帶來的影響。
因而,咱們在落地的時候,淘汰了下圖左側的實現方式——合做關係(項目和任務網狀式相互調用,我中有你,你中有我),而是在下游項目領域加了一層適配層,來隔離業務的變化對上游的影響。同時,也確保任務這層邏輯乾淨、清晰,以供更多其餘組件複用。
總結
總結一下,本文大致給出了 DDD 思潮在如下方面落地上的指導意義:
敬請期待
以後會在後續章節中分享 DDD 在插件落地的實踐,解決以下問題:
如何快速響應五花八門的定製化需求,同時保持自身不腐化?