I'm reading the DDD blue book and there is one thing that's pretty unclear to me as of yet and that is how to efficiently perform simple operations on Aggregates that have a lot of child Entities in them.
An example
- Considering I have an
Order
, (Aggregate Root) that hasLine Item
s. - Each
Order
can only have 1000Line Item
s. (Business Rule).
Steps
In order for me to add a Line Item
to the Order
I'd have to:
- Reconstitute the
Order
with all it'sLine Item
s from it's repository.orderRepo.getById(1)
- Add the
Line Item
to theOrder
,order.addLineItem(lineItem)
- Save the
Order
via the repository again.orderRepo.save(order)
Unless I'm missing something, this strikes me as terribly innefficient. What if I have 900 Line Items
on that Order
? I'd have to load a lot of data from the DB to perform this simple operation.
Yes, I could lazy load the LineItems
but even then I won't be able to check the business rule that requires that <1000 Line Items
must exist in an Order
, unless all the Line Items
are loaded.
Also, lazy loading implementations strike me as an anti-pattern because they usually tie the property accessors with repositories.
Best Answer
When using DDD, you compromise performance for better domain model. And this is an area where that compromise might be made.
Looking at your problem, I would question of
LineItem
should be part ofOrder
aggregate. The point of aggregate is to group entities that multiple, complex operations are made on. Imagine you have an aggregate with internal entity and 10 operations. In one case, 9 of the operations work on the entities. In such a case, it would drastically complicate the situation if the entities weren't always loaded. If on the other hand only 1 of the operations need those entities, then I would question if those entities should be part of the aggregate. In case of complexity of the operations, your case is relatively simple. Taking count of items is trivial operation, that can be done on DB side. But imagine if the limit was for price and not for count. In this case, you have to run complex "price calculation" logic, which will probably require all order items with all the data. Meaning, you cannot afford not loading line items.