SomeSayIAmAnAsshole
SomeSayIAmAnAsshole

Reputation: 31

Repository and Aggregate Roots in Domain Driven Design

I am building a notification system, where I have users that can create subscriptions which define when a notification will be delivered to them and by which endpoint. I have established that a User is an Aggregate Root, and will have a Repository for them. I am having a bit of trouble wrapping my head around this concept though. From my understanding, only Aggregate Roots should be pulled from a Repository.

Let's say I have a User

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

This User has a collection of Subscriptions and Endpoints. Both of these are Entities themselves, as their contents can change without it being a different object. For instance, both these entities can be enabled/disabled. They cannot exist outside the context of a User, as only a User can create a Subscription or an Endpoint.

My Subscription also contains a reference to an Endpoint, as this Subscription needs to know where to deliver.

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

So, as I have defined the User as the Aggregate Root, I now have a UserRepository for persisting my users. Any modifications to an Endpoint or a Subscription would be done within the context of a User being the Aggregate Root. This makes sense to me. But what if I want to retrieve a list of Subscriptions which meet a set of Criteria. The system which handles triggering a notification will receive an event, and need to query for a set of Subscriptions that are relevant to that event. The event is not user based, as multiple Users can have Subscriptions which are valid for this event. Would I put a method on my UserRepository which returns these Subscriptions? Or would I create a SubscriptionRepository? If I create the SubscriptionRepository, would that not mean that a Subscription is an Aggregate Root as well? If the answer to that question is yes, then does my design violate the concept of an AggregateRoot since both User and Subscription contain a reference to an Endpoint entity?

Upvotes: 3

Views: 1358

Answers (2)

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57194

From my understanding, only Aggregate Roots should be pulled from a Repository.

That's not quite right. The repository is an abstraction in front of your persistence solution. Any state that you pull from the book of record should come through a repository.

Aggregates are specific to use cases where you are modifying the book of record -- in other words, when you are doing writes.

If you aren't going to change anything, then you don't need to (re)check that the data within the aggregate boundaries is consistent. Views, reports, analytics -- these use cases don't need aggregates, because they don't produce any new state that needs to be preserved in the book of record.

(CQRS: reads have different requirements than writes).

The key idea is that only aggregate roots should be saved in the repository.

So if you have a use case that needs to read snapshots of the state of Endpoints across multiple aggregates, then design a repository interface that documents that requirement, and make sure that repository doesn't include save.

Upvotes: 2

civan
civan

Reputation: 263

First of, it puzzles me why do you have Endpoints in a User and Subscriptions? Can you maybe delete the Endpoints in User or that doesn't make sense?

Second, ask yourself

If I delete a User, do I always have to delete all of his subscriptions and endpoints?

If the answer is no, then a User is not an aggregate root. By your description I believe that you defined your Aggregate Roots wrong. If you'd really have an AR, you'd never have a need for a separate repository that questions for its entities. They're only called with the AR and manipulated (filtered, changed etc.) within its context.

Subscription could be a part of the process that involves a User and adding Subscriptions to it. Maybe Subscription is AR with its Enpoints.

Upvotes: 2

Related Questions