前言
任何人類的設計都會腐化,軟件系統也不例外html
腐化之謎數據庫
隨着系統的規模增加和複雜度膨脹,系統會慢慢腐化。編程
因而改一個很簡單的下單地址,就會牽動整個交易系統十幾處的改動。markdown
如何解決這種腐化之謎呢?架構
參考計算機系統架構:框架
一個複雜的計算機系統架構包括:軟件系統元素,元素之間的聯繫,元素自己有本身特有屬性。微服務
因而咱們能夠在架構角度參考計算機系統架構的實現。post
架構建模
爲達到上面提到的架構建模的目的,引入領域驅動。測試
領域驅動圍繞業務概念構建領域模型,經過分離技術的方式實現應對複雜業務,及系統難以演進問題的解決方案。url
DDD帶來的不一樣:
- 將原有以技術角度審視架構演進的視角,轉換到以業務視角切入架構。
- 業務複雜度來源於領域自己,深刻領域,正確識別出領域深層次概念及關係。
- 將領域知識進行結構性表達,同時與編程模型保持一致,便造成了DDD。
基於問題空間的DDD模式
基於解空間的DDD模式
界限上下文
由顯示邊界限定的特定內聚職責,領域模型便存在於上下文以內。
界限上下文識別過程:
領域分析
如何經過真實業務驅動需求演化出DDD模型呢?
能夠採用事件風暴進行領域分析。
流程:
- PM,運營,RD共聚一堂
- 數小時內理解複雜領域
- 標記簡單的UML
- 工做流程與DDD完美匹配
- 事件流演化
以電商系統爲例
事件風暴
事件:PM關心真實事件
如:用戶訂單已發佈,商品已發佈
說明:關注點在於什麼領域模型發生了什麼變化。
命令風暴
命令:經過什麼活動產生了事件
如:用戶提交了訂單,開放平臺同步商品
說明:命令幫助咱們明確系統對外提供的能力,同時明確業務上的輸入
命令來源:用戶UI界面的操做,外部系統調用觸發,定時任務觸發
尋找聚合
聚合:一組相關性領域模型的聚合,用來封裝業務不變性,確保關聯緊密的領域模型內聚在一塊兒
如:訂單和商品
聚合的目的在於業務內聚,強迫RD進行簡化領域模型的關聯,實現業務設計高內聚低耦合的目的
劃分界限上下文
- 業務模型的問題是否同一個,是則放在同一個界限上下文中
- 若是一個聚合同時解決了多個問題,則須要定義不一樣的上下文肯定解決特定問題
界限上下文以內能夠自由選擇架構模式,如MVC,CQRS,微服務,SOA等。
不是全部界限上下文都採用領域驅動方式,非核心子域可參考數據驅動下的面向過程編程。
提取出面向切面的聚合層,以工程技術因素爲主要考慮點。
DDD的核心價值在於指導劃分界限上下文。
DDD分層設計
領域模型建設思路:
- 業務與技術關注點分離,依賴倒置,內部不依賴於外部且外部可替換
- 接口適配器架構
- 防腐層建設,領域模型依賴穩定性
參考六邊形架構:
架構目標:
- 獨立於框架
- 與數據庫分離
- 可測試性
- 與外部結構分離
- 與UI分離
架構原則:
- 關注點分離,切割不一樣層
- 依賴原則:外部依賴內部,依賴倒置
- 架構設計圍繞用例
結合CQRS設計
CQRS:命令查詢職責分離
將更復雜的領域模型拆分爲讀取和寫入兩部分。
將消息傳遞,數據日誌同步,領域事件和事件溯源使用到特定上下文。
領域驅動實踐
目前咱們活動營銷系統中,存在大量迭代需求都是針對運營需求所設計,需求自己具備複雜性和持續迭代性,故均已轉換採用領域驅動設計方式實現。
對現有及可預期的玩法需求進行了邏輯抽象,提供了統一業務領域玩法模型,爲運營提供統一玩法配置管理平臺,進行玩法需求配置,通過領域系統內核進行集成,對用戶輸出統一玩法活動UI及流程。
在局部演進及擴展需求,採用元數據+大字段應對信息的不肯定性,流程引擎+規則引擎構造玩法,DSL提供動態建立玩法資源配置的能力。
梳理事件風暴,抽象命令風暴,尋找履行命令的業務名詞,對相似的名詞玩法進行共性提取,作合適的抽象,同時創建通用語言描述及定義。
採用DDD分層架構+六邊形架構+CQRS模型,使得系統具有面向領域驅動的演進能力。
最後
DDD不是銀彈
哪些產品適用於DDD:
- 是不是複雜問題,或者子域內具備複雜性
- 業務是否重要且有很高的預期
- 是否可讓運營和PM介入
- 遵循迭代式的開放方法
領域模型好壞的標準:
- 模型反映了對於問題的抽象,抽象沒有統一的標準
- 模型是迭代演進的,須要持續集成,改進
- 通用語言,領域模型和代碼目標意圖一致
更多交流: