Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DDD - Modifications of child objects within aggregate

I am having some difficulty working out the best way to handle a fairly complex scenario. I've seen quite a few similar questions, but none addressed this scenario to my satisfaction.

An Order (aggregate root) is created with multiple OrderLines (child entities). According to business rules, each OrderLine must maintain the same identity for the life of the Order. OrderLines have many (20+) properties and can be mutated fairly often before the Order is considered "locked". In addition, there are invariants that must be enforced at the root level; for example, each Order Line has a quantity and the total quantity for the Order cannot exceed X.

I'm not sure how to model this scenario when considering changes to OrderLines. I have 4 choices that I can conceive of, but none seem satisfactory:

1) When the time comes to modify an OrderLine, do it using a reference provided by the root. But I lose the ability to check invariant logic in the root.

var orderLine = order.GetOrderLine(id);
orderLine.Quantity = 6;

2) Call a method on the order. I can apply all invariant logic, but then I'm stuck with a proliferation of methods to modify the many properties of the OrderLine:

order.UpdateOrderLineQuantity(id, 6);
order.UpdateOrderLineDescription(id, description);
order.UpdateOrderLineProduct(id, product);
...

3) This might be easier if I treated the OrderLine as a Value Object, but it has to maintain the same identity per business requirements.

4) I can grab references to the OrderLines for modifications that do not affect invariants, and go through the Order for those that do. But then what if invariants are affected by most of the OrderLine properties? This objection is hypothetical, since only a few properties can affect invariants, but thhat can change as we uncover more business logic.

Any suggestions are appreciated...do not hesitate to let me know if I'm being dense.

like image 694
Cork Avatar asked May 23 '12 21:05

Cork


2 Answers

  1. Is not optimal because it allows breaking domain invariant.

  2. Will result in code duplication and unnecessary method explosion.

  3. Is the same as 1). Using Value Object will not help with maintaining domain invariant.

  4. This option is what I would go with. I would also not worry about potential and hypothetical changes until they materialize. The design will evolve with your understanding of the domain and can always be refactor later. There is really no value in hindering your existing design for the sake of some future changes that may not happen.

like image 50
Dmitry Avatar answered Sep 30 '22 10:09

Dmitry


One drawback of 4 as opposed to 2 is lack of consistency. In certain instances it might be beneficial to maintain a degree of consistency in regards to updating order line items. It may not be immediately clear why certain updates are done through the order while others through the order line item. Furthermore, if order lines have 20+ properties, perhaps that is a sign that there is potential for grouping among those properties resulting in fewer properties on the order line. Overall, approach 2 or 4 is fine as long as you make sure to keep operations atomic, consistent and in correspondence with ubiquitous language.

like image 40
eulerfx Avatar answered Sep 30 '22 10:09

eulerfx