domain driven design method duplication
Asked Answered
I

1

6

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!

Imray answered 22/7, 2014 at 6:2 Comment(4)
I'm just wondering why an OrderLine would ever be updated?Epstein
Well this is just an example I made up for illustration purposes. I do have similar scenarios in my own code though, this example was just easier to explain...Imray
I had asked the very same question here #11727173 and got no concrete answer, However in practice i do think it becomes a concern for the following reason 1) Aggregates will not home many entities (transactionality will become a concern) 2) For the entities it does house it will very rarely act just as a proxy to the entities interface without adding any value. Your example here is a hypothetical one i guess. Having said this i am still looking for answers :)Monomial
I agree with you, that it does not cause too many problems in practice. And normally too many methods don't have to be duplicated, but it just seems like it violates the DRY principle, and like there should be some better solution. Anyways, for now it will have to do :)Imray
D
1

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.

Deathful answered 13/8, 2014 at 7:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.