Domain-Driven Design – Creating Aggregate Roots from Multiple Other Aggregates

aggregateArchitecturedomain-driven-designentity

I know the title is confusing, I didn't how to word it.

I'm studying the Domain Driven Design (DDD) and I'm reading the book "NET Microservices Architecture for Containerized NET Applications" from microsoft and I can't understand well how to identify the aggregate roots.

In the book they use an example with an Order being the aggregate root and OrderItem being a child entity:
Order aggregate example

If I understand it correctly the OrderItem has a ProductId which identifies a product that should be another Aggregate Root if I'm not mistaken (note that in the source provided by the book there is no Product Aggregate and the product does not exist in the model, but I suppose it's for simplicity).

Now I expose the problem imagine we have an Aggregate Root TaxesDetail which OrderItem has a reference to it, and this TaxesDetail is added with the taxes of the product and the taxes of the buyerID and some other values when creating an OrderItem. If only the OrderItem could create the TaxesDetail then TaxesDetail will simply be a child entity, but if we have an Aggregate Root of an Offer that has an OfferItem (with some different field than OrderItem) which in turns have a TaxesDetail then what should the TaxesDetail be?
An AggregateRoot?
A Child Entity? If it's a child entity then we would have to create an OrderTaxesDetail and an OfferTaxesDetail which will duplicate the code.

This is just an example but what I'm trying to understand is the concept of Aggregate Root, how to identify one, if it's possible that multiple Aggregates Root can create the same Aggregate Root…

Thanks

EDIT

An edit to respond @Christophe since a comment can't be too long.

In the case of identity I think if you change and OrderDetail you can just delete the old TaxesDetail and create a new one, I don't think there is a need to keep track of the older TaxesDetail.

Now I see how it is a Value Object. In the first point, we can see that it's lifespan is entirely dependant on the Aggregate Roots of OrderDetail and OfferDetail. In the second point, we can see it's immutable if, for example, an OrderDetail it's changed the TaxesDetail won't change, the TaxesDetail will be destroyed and constructed with the new properties.

As you said I had in mind the implementation considerations and how the model was constructed, I didn't start my design from a domain approach and I was mixing the domain layer with the persistence layer. I should pay more attention the next time.

Thanks for your help!

Best Answer

First things first

imagine we have an Aggregate Root TaxesDetail which OrderItem has a reference to it, ...

First, take a deep breadth in. What makes you think that a TaxesDetail could be an aggregate root in the first place ? And what would be the aggregate ?

If only the OrderItem could create the TaxesDetail then TaxesDetail will simply be a child entity, but if we have an Aggregate Root of an Offer that has an OfferItem (with some different field than OrderItem) which in turns have a TaxesDetail then what should the TaxesDetail be?

Why should it be a an aggretate root ? What makes a tax detail ? Does the tax detail have an identity in the first place ?

Basic DDD concepts

Let's look at 3 core definitions in Evan's seminal DDD book:

AGGREGATE: A cluster of associated objects that are treated as a unit for the purpose of data changes. External references are restricted to one member of the AGGREGATE, designated as the root. A set of consistency rules applies within the AGGREGATE’S boundaries.

Is a TaxesDetail changed independently of the OrderDetail or OfferDetail to which it is related ? Or isn't the TaxeDetails consistency rules related to something else which is already in another aggregate ? Honestly, I seriously doubt that this could be an aggregate root.

ENTITY: An object fundamentally defined not by its attributes, but by a thread of continuity and identity.

Does a TaxesDetail have its own identity ? Or asked in another way: suppose I'd change an OrderDetail: could I just delete the old TaxesDetail and create a new one with the new value, or is it vital that I keep track of the old TaxesDetail and modify its attributes ?

VALUE OBJECT: An object that describes some characteristic or attribute but carries no concept of identity.

So what is a TaxesDetail in the end ? Is it just a taxe code (that defines the rates) and a tax value calculated for an item ? In this case it would be a value object that refers to a TaxCode. If you need however to keep the history, it could be an entity in the Order aggregate.

Advice

DDD starts with DOMAIN. And so must you. Start your design from a domain approach. Don't let implementation considerations and reuse fool you:

  • Here, you were mislead by seeing a TaxesDetail as something that is as well related to and OrderItem as to an OfferItem. In fact, you take an implementation perspective and see the similarities, assuming that it is the same thing.

  • But if we look at the domain from a business perspective, a tax detail in an offer is purely virtual. No taxes are due, because nothing guarantees that the offer will be transformed in order. At this stage it's only a calculated value.

  • Later, when the order is passed, the tax item could start to matter, depending on the jurisdiction, because there is a confirmed business transaction. If you take taxes like VAT, the order tax would still be an indicated value, since the event that makes the tax item a tax liability item is the earliest of either the delivery or the payment.

So in conclusion, look at your objects independently of any implementation consideration. Check if the object has an identity, and then only look at the clustering in aggregate root. Only afterwards should you enter into details of which method and property to put where.

Related Topic