I'm trying to develop my first application using Domain Driven Design rules and patterns.
In my business scenario I have to manage the list of Customers and to track all the package that are sent to a specific customer destination. So, following the rules, it turns out that:
- Customer is an Entity which is also an AggregateRoot.
- Destination is an Entity which is child of Customer (because it doesn’t make sense without a Customer)
- Package is an Entity. It is also another AggregateRoot because is a different transactional boundary I developed the Customer Aggregate with the method AddDestination(string destinationName …) that is responsable of creating a new Destination for the Customer.
Now I need to develop the Package class, where I have to maintain a reference to the destination where the package has been shipped. Following the DDD rules I can't reference the child entity id directly because I can’t reference entity that are child of another aggregate.
What do I have to do?
- Do I have to create a new ValueObejct with the required data of the Destination and expose it? (in this way I'm able to preserve the encapsulation and the rules of the Destionation which is accessible in writing only through Customer AggregateRoot). In this way external classes can access the fields of the Destination and perform logics/check using those but can't alternate the state of the destination.
- Do I have to add a DestinationNumber field (progressive within customer), create a ValueObject that contains CustomerId and DestinationNumber and use it in the Package aggregate?
- ?
Can someone please help me? Please elaborate the reply because I'd like to understand more this cases.
If I understand correctly, I would assume that this Package must be delivered somewhere, to a Destination.
I would also assume that Customer is indeed an Entity and also an Aggregate Root because it would have behaviours such as changing names, etc. Package is also an Entity, and also an Aggregate Root of itself, since it has different transaction boundary from Customer and also has some behavior (like addDestination).
Here, I don't see that Destination should be an Entity, because it does not have any behavior or identity of itself, rather it just contains a fact that this Destination refers to a Customer. So, I would model Destination as a Value Object instead, with an attribute of CustomerId (this can be done because Customer is an Aggregate Root).
Package's addDestination's argument would be a Value Object of Destination. If Package should ever have to change the destination, it can just create another instance of Destination and discard the old one.
Also, it does not make sense if Destination is a child of Customer, since there might be some Customers that are not delivered anything yet. Instead, I would model Destination as a child of Package, since it makes sense that every creation of Package, it should have a Destination (under the assumption that any Package must be delivered). And so Package and Destination are in the same aggregate.