代碼改變世界

DDD應對運營活動系統腐化實踐

2019-06-03 08:13 春哥大魔王 閱讀(...) 評論(...) 編輯 收藏

前言

任何人類的設計都會腐化,軟件系統也不例外

腐化之謎

隨著系統的規模增長和復雜度膨脹,系統會慢慢腐化。

于是改一個很簡單的下單地址,就會牽動整個交易系統十幾處的改動。

如何解決這種腐化之謎呢?

參考計算機系統架構:

一個復雜的計算機系統架構包括:軟件系統元素,元素之間的聯系,元素本身有自己特有屬性。

于是我們可以在架構角度參考計算機系統架構的實現。

架構建模

為達到上面提到的架構建模的目的,引入領域驅動。

領域驅動圍繞業務概念構建領域模型,通過分離技術的方式實現應對復雜業務,及系統難以演進問題的解決方案。

DDD帶來的不同:

  1. 將原有以技術角度審視架構演進的視角,轉換到以業務視角切入架構。
  2. 業務復雜度來源于領域本身,深入領域,正確識別出領域深層次概念及關系。
  3. 將領域知識進行結構性表達,同時與編程模型保持一致,便形成了DDD。

基于問題空間的DDD模式

基于解空間的DDD模式

界限上下文

由顯示邊界限定的特定內聚職責,領域模型便存在于上下文之內。

界限上下文識別過程:

領域分析

如何通過真實業務驅動需求演化出DDD模型呢?

可以采用事件風暴進行領域分析。

流程:

  1. PM,運營,RD共聚一堂
  2. 數小時內理解復雜領域
  3. 標記簡單的UML
  4. 工作流程與DDD完美匹配
  5. 事件流演化

以電商系統為例

事件風暴
事件:PM關心真實事件
如:用戶訂單已發布,商品已發布
說明:關注點在于什么領域模型發生了什么變化。

命令風暴
命令:通過什么活動產生了事件
如:用戶提交了訂單,開放平臺同步商品
說明:命令幫助我們明確系統對外提供的能力,同時明確業務上的輸入
命令來源:用戶UI界面的操作,外部系統調用觸發,定時任務觸發

尋找聚合
聚合:一組相關性領域模型的聚合,用來封裝業務不變性,確保關聯緊密的領域模型內聚在一起
如:訂單和商品
聚合的目的在于業務內聚,強迫RD進行簡化領域模型的關聯,實現業務設計高內聚低耦合的目的

劃分界限上下文

  1. 業務模型的問題是否同一個,是則放在同一個界限上下文中
  2. 如果一個聚合同時解決了多個問題,則需要定義不同的上下文確定解決特定問題

界限上下文之內可以自由選擇架構模式,如MVC,CQRS,微服務,SOA等。

不是所有界限上下文都采用領域驅動方式,非核心子域可參考數據驅動下的面向過程編程。

提取出面向切面的聚合層,以工程技術因素為主要考慮點。

DDD的核心價值在于指導劃分界限上下文。

DDD分層設計

領域模型建設思路:

  1. 業務與技術關注點分離,依賴倒置,內部不依賴于外部且外部可替換
  2. 接口適配器架構
  3. 防腐層建設,領域模型依賴穩定性

參考六邊形架構:

架構目標:

  • 獨立于框架
  • 與數據庫分離
  • 可測試性
  • 與外部結構分離
  • 與UI分離

架構原則:

  • 關注點分離,切割不同層
  • 依賴原則:外部依賴內部,依賴倒置
  • 架構設計圍繞用例

結合CQRS設計

CQRS:命令查詢職責分離

將更復雜的領域模型拆分為讀取和寫入兩部分。
將消息傳遞,數據日志同步,領域事件和事件溯源使用到特定上下文。

領域驅動實踐

目前我們活動營銷系統中,存在大量迭代需求都是針對運營需求所設計,需求本身具有復雜性和持續迭代性,故均已轉換采用領域驅動設計方式實現。

對現有及可預期的玩法需求進行了邏輯抽象,提供了統一業務領域玩法模型,為運營提供統一玩法配置管理平臺,進行玩法需求配置,經過領域系統內核進行集成,對用戶輸出統一玩法活動UI及流程。

在局部演進及擴展需求,采用元數據+大字段應對信息的不確定性,流程引擎+規則引擎構造玩法,DSL提供動態創建玩法資源配置的能力。

梳理事件風暴,抽象命令風暴,尋找履行命令的業務名詞,對類似的名詞玩法進行共性提取,做合適的抽象,同時建立通用語言描述及定義。

采用DDD分層架構+六邊形架構+CQRS模型,使得系統具備面向領域驅動的演進能力。

最后

DDD不是銀彈

哪些產品適用于DDD:

  1. 是否是復雜問題,或者子域內具有復雜性
  2. 業務是否重要且有很高的預期
  3. 是否可以讓運營和PM介入
  4. 遵循迭代式的開放方法

領域模型好壞的標準:

  1. 模型反映了對于問題的抽象,抽象沒有統一的標準
  2. 模型是迭代演進的,需要持續集成,改進
  3. 通用語言,領域模型和代碼目標意圖一致

更多交流:

四川金7乐历史开奖号码查询