Domain-Driven Design – Choosing Between Domain Event or Application Layer Orchestration

cdomain-driven-designpatterns-and-practices

I'm setting my first steps into domain driven design, bought the blue book and all, and I find myself seeing three ways to implement a certain solution. For the record: I'm not using CQRS or Event Sourcing.

Let's say a user request comes into the application service layer. The business logic for that request is (for whatever reason) separated into a method on an entity, and a method on a domain service. How should I go about calling those methods?

The options I have gathered so far are:

  • Let the application service call both methods
  • Use method injection/double dispatch to inject the domain service into the entity, letting the entity do it's thing and then let it call the method of the domain service (or the other way around, letting the domain service call the method on the entity)
  • Raise a domain event in the entity method, a handler of which calls the domain service. (The kind of domain events I'm talking about are: http://www.udidahan.com/2009/06/14/domain-events-salvation/)

I think these are all viable, but I'm unable to choose between them. I've been thinking about this a long time and I've come to a point where I no longer see the semantic differences between the three. Do you know of some guidelines when to use what?

Best Answer

Let the application service call both methods

The application service is usually a great starting place for this, however you should always try to shift behavior as close to the entity as possible. The application service plays an orchestrating role and it sets up the stage for executing domain behavior and as such it provides all required dependencies. However, when possible, it should delegate behavior to the domain model.

Use method injection/double dispatch to inject the domain service into the entity, letting the entity do it's thing and then let it call the method of the domain service (or the other way around, letting the domain service call the method on the entity)

This is a better approach because more of the behavior is delegated to the entity or domain service. The most decoupled way to implement this is to have an entity express a dependency on a service is as a parameter of the method providing the behavior at hand.

Raise a domain event in the entity method, a handler of which calls the domain service.

The domain event pattern, as explain by Udi and also Evans himself, is quite versatile and can be applied in a variety of scenarios. There are a few complications that come with it however. First, you have to make sure that you have proper scoping within the domain event publisher. Most of the time, your domain event handlers will have dependencies and if you are using an IoC container, you have to make sure that a proper instances are injected. For example, in a web application, the [ThreadStatic] attribute is problematic for scoping. Another complexity is that of transcriptional boundaries. You have to take transactions into consideration, because if an entity raises a domain event, but a subsequent commit to the database fails, all domain event handlers will need a way to roll back, otherwise you will end up raising an invalid event. If however you've got these bases covered, then domain events are a great pattern for encapsulating domain logic within the entities themselves.

The difference between approach 2 and 3 depends on the use case. A domain event applies when you want to invoke additional behaviors in response to an event, which is in the past tense. This is an important constraint, since the domain event handler can't affect behavior of the entity. On the other hand, with approach 2, the injected service has the potential to affect behavior because it is declared a dependency for that particular behavior.