mercredi 28 février 2018

Circular dependency in the domain layer

In our domain model we have an Order and a Sending entities. They both have among others a ChangeStatus method which changes the status of order and sending respectively. Currently we have many handlers which uses those methods.

But now we need to introduce the behaviour at which changing the status of an Order to some specific value provokes changing of the status of an associated Sending and vise versa. When order is going to be canceled we should also cancel the sending (if any). And when the sending is delivered we should change the order status to "Completed".

Making Order and Sending dependent on each other leads to a circular dependency and bad design in general. Also we just can't instantiate objects which require each other as a dependency (even if they are dependent on interfaces).

My first thoughts were to create OrderStatusChanger and SendingStatusChanger interfaces (both dependent on Order and Sending) and delegate those tasks to them, but with this approach we have to modify every piece of code that changes statuses of orders and sendings to use these interfaces.

Another possible solution is to use pubsub as a workaround but it introduces other problems:

  1. How to cancel (rollback) changes if an error occurs in any of subscribers and the underlying system doesn't support transactions (such as redis)?
  2. It seems to me that event-based design in the domain layer is a bad idea. What is suitable for UI layer can lead to a poor maintability and unclear code in the domain.
  3. Mixing pubsub and classic dependency injection in one layer seems terrible too.

Order and Sending have many other methods and logic on their own, so we can't simply combine them into one entity.

Maybe there is an architecture design pattern or something I've missed completely?

Any help would be greatly appreciated

Aucun commentaire:

Enregistrer un commentaire