DDD – Performing simple operations on complex Aggregates

domain-driven-designobject-oriented-design

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 has Line Items.
  • Each Order can only have 1000 Line Items. (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's Line Items from it's repository.
    • orderRepo.getById(1)
  • Add the Line Item to the Order,
    • 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 of Order 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.