Search code examples
domain-driven-designaggregateroot

DDD: How many Aggregate roots do I need?


I am a little confused with the Aggregate root concept in DDD. The theory tells then it should be an aggregate root which is relevant to the current operation.

For example, I have a root Account, which represents a company. It has Address, Users who belong to the account, some other properties.

And I have several pages; one is to manage general information, such as name, email, phone... Another is to maintain Address. One more to show all users (and edit user information, which is probably under Account object as well)

In first case I don't care about Address, in second I don't care about Name, Email....

Do I need two separate Account object or I need only one Account? (The model may be more complex than I described)

So, for example, I may end up with classes: BasicAccountInformation, AccountAddress, AccountUsers.... Or just a single: Account which contains all data?

What is the correct DDD approach? What I think, in one case I will get a very complex class containing a lot of properties and logic; or a lot of simple classes with 2-10 properties per class.


Solution

  • How many Aggregate roots do I need?

    At least one.

    Aggregates serve as consistency boundaries. If you model your entire domain as a single aggregate, and provide one "aggregate root" that ensures that your business invariant is maintained by each write, you are good to go.

    Well, you are good to go slowly. The aggregate root serves as a sort of serialization bottleneck for all of the state in the aggregate boundary. If you expect to update two different parts of the model "at the same time", then you are going to need partition the responsibility for the business invariant.

    And I have two pages; one is to manage general information, such as name, email, phone... Another is to maintain Address.

    Reports are great. They tell you what data you need to collect for your model.

    But reports are lousy at telling you where your aggregates are - the primary concern of your aggregates is not reading/presenting/reporting your data, but writing it.

    You find aggregates by finding data on your model that you need grouped together when performing a write. What data do you need to enforce the business invariant?

    That heuristic tends to suck in CRUD domains, because most of the state of your model is independent of the rest.

    You can look at entity relationships; if two aggregates "share" an entity, then that entity probably belongs to a third aggregate.

    Another thing you can look at is entity life cycles. If a child entity can outlive the aggregate root, then you know that you have modeled it wrong.

    Based on what you describe, that doesn't help much here either; you've effectively got account, and a bunch of stuff that lives within it.

    Sometimes all of that fails, and you end up using the heuristic "which data do I only want to load once in a while", and you just crud it into a key value store and go back to delivering business value.