2017-04-12 55 views
1

我正在構建通知系統,其中有用戶可以創建訂閱,以定義通知何時傳遞給他們以及通過哪個端點。我已經確定用戶是一個聚合根,並且會爲他們建立一個存儲庫。不過,我在圍繞這個概念時遇到了一些麻煩。根據我的理解,只有Aggregate Roots應該從存儲庫中提取。域驅動設計中的存儲庫和聚合根

比方說,我有一個用戶

public class User 
{ 
    public ICollection<Subscription> Subscriptions {get; set;} 
    public ICollection<Endpoint> Endpoints {get; set;} 
} 

該用戶訂閱和端點的集合。這兩者都是實體本身,因爲它們的內容可以改變而不會成爲不同的對象。例如,這兩個實體都可以啓用/禁用。它們不能存在於用戶的上下文之外,因爲只有用戶才能創建訂閱或端點。

我的訂閱還包含對端點的引用,因爲此訂閱需要知道在哪裏提供。

public class Subscription 
{ 
    public ICollection<Endpoint> Endpoints {get; set;} 
} 

所以,我已經定義了用戶的聚合根,現在我有我的堅持用戶UserRepository。任何對端點或訂閱的修改都將在作爲聚合根的用戶的上下文中完成。這對我有意義。但是,如果我想檢索符合一系列標準的訂閱清單,該怎麼辦?處理觸發通知的系統將收到一個事件,並且需要查詢與該事件相關的一組訂閱。該事件不是基於用戶的,因爲多個用戶可以擁有對該事件有效的訂閱。我會在我的UserRepository上放置一個返回這些訂閱的方法嗎?或者我會創建一個SubscriptionRepository?如果我創建了SubscriptionRepository,那麼這是否意味着Subscription也是一個聚合根?如果對該問題的答案是肯定的,那麼我的設計是否違反了AggregateRoot的概念,因爲User和Subscription都包含對Endpoint實體的引用?

回答

0

首先,它讓我困惑,爲什麼你在用戶和訂閱中有端點?你可以刪除用戶中的端點還是沒有意義?

二,問自己

如果我刪除一個用戶,我總是要刪除他的所有訂閱和終點的?

如果答案是否定的,那麼用戶不是聚合根。根據你的描述,我相信你定義你的聚合根源是錯誤的。 如果你真的有一個AR,你永遠不會需要一個單獨的存儲庫,其實體的問題。他們只能用AR調用並在其上下文中進行操作(過濾,更改等)。

訂閱可能是涉及用戶並向其添加訂閱的過程的一部分。也許訂閱是AR與它的Enpoints。

+0

我的域中的端點是PhoneNumbers,EmailAddresses等等。我在用戶中有Endpoints,因爲用戶有PhoneNumbers和EmailAddresses。我在訂閱中有端點,因爲用戶將訂閱將通知發送到他的PhoneNumber或EmailAddress。是的,當我刪除用戶時,所有用戶終端和訂閱也會被刪除。沒有創建它們的用戶,它們就不能存在。 我希望檢索一個擁有所有端點和訂閱的用戶,並且我希望檢索與事件匹配的一組訂閱。 – SomeSayIAmAnAsshole

1

從我的理解,只有聚合根應該從一個存儲庫中提取。

這並不完全正確。 存儲庫是您的持久性解決方案之前的抽象。您從記錄簿中提取的任何狀態都應通過存儲庫進行。

集合特定於您正在修改記錄簿的用例 - 換句話說,當您在進行寫入操作時。

如果你不打算改變任何東西,那麼你不需要(重新)檢查聚合邊界內的數據是否一致。視圖,報告和分析 - 這些用例不需要聚合,因爲它們不會產生任何需要保存在記錄簿中的新狀態。

(CQRS:讀取具有與寫入不同的要求)。

關鍵的想法是,只有聚合根應該是保存在存儲庫中的

所以,如果你有需要讀取的多個聚集Endpoints狀態的快照,然後設計一個repository interface,其中記錄這一要求,並確保資料庫不包括保存的使用情況。

+0

好的,那麼只要我的存儲庫只允許保存聚合根,我應該可以以只讀方式檢索任何子實體。改變這個孩子的唯一方法就是通過一個Aggregate Root來修改它,在我的情況下這是一個User。由於存儲庫只允許用戶保存,所以我很安全。 – SomeSayIAmAnAsshole