I'm having some issues to correctly design the domain that I'm working on.
My straightforward use case is the following:
The user (~5000 users) can access to a list of ads (~5 millions)
He can choose to add/remove some of them as favorites.
He can decide to show/hide some of them.
I have a command which will mutate the aggregate state, to set Favorite to TRUE, let's say.
In terms of DDD, how should I design the aggregates?
How design the relationship between a user and his favorite's ads selection?
Considering the large numbers of ads, I cannot duplicate each ad inside a user aggregate root.
Can I design a Ads aggregateRoot containing a user "collection".
And finally, how to handle/perform the readmodels part?
Thanks in advance
Cheers
Two concepts may help you understand how to model this:
1. Aggregates are Transaction Boundaries.
An aggregate is a cluster of associated objects that are considered as a single unit. All parts of the aggregate are loaded and persisted together.
If you have an aggregate that encloses a 1000 entities, then you have to load all of them into memory. So it follows that you should preferably have small aggregates whenever possible.
2. Aggregates are Distinct Concepts.
An Aggregate represents a distinct concept in the domain. Behavior associated with more than one Aggregate (like Favoriting, in your case) is usually an aggregate by itself with its own set of attributes, domain objects, and behavior.
From your example,
Useris a clear aggregate.An
Adhas a distinct concept associated with it in the domain, so it is an aggregate too. There may be other entities that will be embedded within the Ad likevalid_until,description,is_active, etc.The concept of a favoriting an Ad links the
Userand theAdaggregates. Your question seems to be centered around where this linkage should be preserved. Should it be in theUseraggregate (a list ofAds), or should anAdhave a collection ofUserobjects embedded within it?While both are possibilities, IMHO, I think
FavoriteAdis yet another aggregate, which holds references to both theUseraggregate and theAdaggregate. This way, you don't burden the concepts ofUseror theAdwith favoriting behavior.Those aggregates will also not be required to load this additional data every time they are loaded into memory. For example, if you are loading an
Adobject to edit its contents, you don't want the favorites collection to be loaded into memory by default.These aggregate structures don't matter as far as read models are concerned. Aggregates only deal with the write side of the domain. You are free to rewire the data any way you want, in multiple forms, on the read side. You can have a subscriber just to listen to the
Favoritedevent (raised after processing theFavoritecommand) and build a composite data structure containing data from both theUserand theAdaggregates.