I am currently working through the domain driven design book by Eric Evans, and there is one concept that I am having trouble with...
According to the book, all aggregates should have an aggregate root, and all members of the aggregate should only be accessed via this root. The root should also be responsible for enforcing invariants. Will this not lead to a lot of method duplication though? Take for example the following scenario:
I have a class Order, that consists of a set of OrderLine's. Class Order is the aggregate root in this case, and it must enforce the invariant that all OrderLine's of a single Order must have a unique order number. To ensure that this invariant is not violated, class Order does not expose its OrderLine's, and simply offers a method updateOrderLineOrderNumber(long orderLineId, int newOrderNumber) via which OrderLines must be updated. This method simply checks whether the newOrderNumber does not conflict with an existing order number, and then calls the method updateOrderNumber(int newOrderNumber) of the appropriate OrderLine. This is fine, since it is only one method, but what happens when class OrderLine has a couple of methods? Since an Order does not expose its OrderLines, all properties of OrderLines will have to be updated via class Order, even if the property changes don't need any invariant checking. This will undoubtedly lead to a lot of method duplication, which will only get worse as more classes are added to the aggregate.
Am I understanding this wrong? Is there any alternative mechanisms or design patterns that I could use to prevent this scenario?
One possible strategy that I thought of using is the concept of validators. Whenever a property of an OrderLine is changed, it must first check with a set of validators whether this change is allowed. The Order can then add an appropriate validator to an OrderLine's name property whenever the OrderLine is added to an Order. What do you guys think of this strategy?
Any help or thoughts would be greatly appreciated!
Domain-Driven Design(DDD) is a collection of principles and patterns that help developers craft elegant object systems. Properly applied it can lead to software abstractions called domain models. These models encapsulate complex business logic, closing the gap between business reality and code.
This method also uses various principles and patterns to close the gap between business reality and software code. Domain-driven design is most helpful in solving domain complexities as it works to maintain the project's primary focus as the core domain.
Advantages of domain-driven design The most obvious advantage of DDD is that it gets everybody using the same language. When development teams use the same language as domain experts, it leads to software design that makes sense to the end user.
Domain-driven design (DDD) is a useful approach that provides excellent guidelines for modeling and building systems, but it is a means to an end, not an end in itself. While the concepts are valid, you lose a lot if you limit yourself to using them only: There actually is a life beyond DDD.
I don't see a problem here to be honest. Firstly why would you want to change orderId? Id should be set once, different id equals different entity.
Usually if you want to update entity of an AR you just get it and update it.
orderLine = order.getOrderLine(index)
orderLine.changeProduct(someProduct)
If you need to keep some invariants in AR, in example that OrderLine.product must be unique, then you call AR method.
order.changeOrderLineProduct(orderLineIndex, someProduct)
Internally that method checks if someProduct is unique and if it is then calls code above. There is no DRY violation in this, AR method checks invariants, orderLine method updates.
I would also think about using more UL in this, like "Client changes product on his orderline on order"
client.changeOrderLineProductOnOrder(orderLineIndex, product, order)
This way you can check if client is an owner of that order.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With