2017-08-03 49 views
0

我嘗試瞭解從一個Aggregare Root填充屬性到另一個Aggregare Root的最佳方式。從一個聚合根向另一個聚合根填充更新數據的最佳方式是什麼?

我有Model Aggregate RootCategory Aggregate RootFilter Aggregate Root

每個Model可以有一些Filter列表,並且可以在Category之一。 Category可以有一個Filter繼承到Model。當ModelCategory屬性更新,Filter必須從Category繼承到Model,當Filter財產在Category更新,從Category所有Models必須繼承新的價值。所有繼承的Filters無法更新,但可以編輯手動添加的過濾器。

「發明」的一種方式是使用Process manager,其狀態包含Category filterModels list

所以我纔會有這樣的行爲:

  1. Category AR UpdateCategoryFilter(命令) - > CategoryFilterUpdated(事件)
  2. Model AR AddCategory(命令) - > CategoryAdded(事件),RemoveCategory(命令) - > CategoryRemoved (事件),InheritFilter(命令) - > FilterInherited(事件),RemoveInheritedFilter(命令) - > InheritedFilterRemoved(事件)
  3. Filter AR CreateFilter(命令) - > FilterCreated(事件)
  4. 個流程管理FilterInheritancecorrelationIdResolver通過categoryId,會觸發[CategoryFilterUpdatedCategoryUpdated]事件

PM的行爲是這樣的:

current State(filter, models) => 
    if CategoryFilterUpdated(... newFilter ...) => 
    set new State(... newFilter ...) { 
     models.forEach(send InheritFilter(model, newFilter)) 
    } 
    if CategoryAdded(.... modelId ...) => 
    set new State(... models.add(modelId) ...) { 
     send InheritFilter(modelId, filter) 
    } 
    if CategoryRemoved(.... modelId ...) => 
    set new State(... models.remove(modelId) ...) { 
     send RemoveInheritedFilter(modelId, filter) 
    } 

這是一個正確的方式?有其他方法嗎?

+1

你爲什麼稱這個代碼爲「過程管理器」?它管理的是什麼類型的流程,流程什麼時候開始,什麼時候結束? –

+0

這是一些僞代碼。當它出現相關事件('CategoryFilterUpdated','CategoryUpdated')時,它會偵聽事件流並改變其狀態('State(filter,models)')與發送命令('InheritFilter(model,filter)') 。 –

+0

這不是我的問題。我的問題是你的過程是什麼?那裏沒有進程,只有幾個事件處理程序。 –

回答

2

它看起來非常像您正在執行CRUD樣式的數據操作操作,而不是採取域方法。

您可能遇到的另一個問題是假設您可以使用Aggregate's在UI上顯示信息。聚合體原則上不具有任何外部可見的屬性(除了ID之外沒有其他獲取者)。如果他們這樣做,他們將不會被封裝。您最好使用讀取模型在UI上使用。這篇文章可以讓您更好地瞭解一個典型的CQRS應用程序的結構:CQRS + Event Sourcing – A Step by Step Overview

假設你正在尋找使用DDD風格的方法,我首先看看你的聚合。我不知道你的域,但從表面上看,它看起來只有1個聚合根。不知道它會被稱爲什麼,因爲我對你的域名一無所知。

我不希望,例如,真正的用戶會說「繼承過濾器」的東西。你也可以看看這篇文章,以幫助你如何命名你的事件和暗示,你的命令:6 Code Smells with your CQRS Events – and How to Avoid Them

我希望這有助於清理你的一些問題。我個人發現讓我的頭腦很難接受DDD,CQRS和事件採購。我不得不忘記一堆東西。但是因爲它,我是一個更好的開發者。

希望這會有所幫助。

3

請記住,集合用於在進行狀態更改時保護域不變量,而不用於簡單的CRUD。目前尚不清楚您的域名是什麼,以及可以將哪種命令發送到保護不變量的'模型'中,因此需要知道模型的「過濾器」是什麼。

如果命令需要根據聚合的狀態進行驗證,或者該命令將影響將來發送給聚合的命令的處理,那麼只需要向聚合發送命令。目前還不清楚這是否適合您。模型聚合是否必須根據它所具有的過濾器來驗證命令/發出事件?如果不是,處理這個問題的方法就是純粹在讀取端執行 - 讀取端可以跟蹤模型的當前過濾器,客戶端/進程可以根據需要使用它。因此,您的模型讀取投影只需要監聽CategoryAdded,CategoryFilterUpdated等來更新模型的讀取視圖。

如果您確實需要過濾器來驗證模型命令或發出適當的事件來響應這些命令,那麼您看起來像是一個選項。但是檢查你的業務需求以查看是否可以在Model集合之外進行過濾等等,這是非常有價值的,因爲在集合之間複製命令增加了耦合性 - 在發送InheritFilter等命令和客戶端發送之間也有競爭條件一個需要過濾器的模型的命令,這看起來像是一個可能需要客戶端處理來輪詢模型以準備好執行命令的問題。

+0

感謝您的「聚合是用於保護域不變量時進行狀態更改,而不是簡單的CRUD」。我認爲這是主要的「核心」,這是從CRUD模式中邁出的艱難的一步。 –

相關問題