Wednesday 7 October 2009

Application Events vs Domain Events

First thing that made me confused when reading original DDDSample source code were those 'application events' - an interface defined on an the application layer level which defines (possibly) asynchronous operations used to communicate between aggregates.

I used to view application layer as merely orchestrating domain operations. Application layer methods were supposed to be called either by GUI or by messaging infrastructure.This layer was also responsible for managing non-functional requirements, such as transactions and logging. I have always followed zealously the 'no logic in app layer' principle. When I started digging deep into DDD, I encountered Udi Dahan's series about domain events. I got to like the idea of domain object pushing out events.

So, now you understand my confusion when I encountered the events on the app layer level. Who and what is wrong?

I started with examining the Java way of defining app layers. In .NET we usually create one assembly per layer. A fairly complicated solution can contain as few as 4-5 assemblies and that is OK. In Java however, there is no notion of assemblies, only packages. And package is a completely different animal. A package, more or less, resembles a .NET namespace - is much more focused and fine-grained.

Application layer responsibilities which I was used to are divided into 2 main (and some helper) packages in DDDSample: the app layer itself and a facade for calling it from GUI code. The thinner app layer is, naturally, much closer to domain code, than would be in a .NET solution, because it is free of any UI or messaging dependencies. The breech in encapsulation of domain layer is much smaller in this fine-grained package structure then it would by in coarse-grained .NET code.

There is also another issue - an issue of naming. The DDDSample project names its events 'application events'. Udi called his mechanism 'domain events'. It the latter case there is a name clash with events as domain elements: the entities which don't change their state. Both live in the domain and both are events in their nature. Udi's events, however, are transient - their role is to push state change notifications out of the domain. On the contrary, events as domain elements are persistent entities. So, it makes sense, from purely naming perspective, to define these transient event as 'application events' and avoid the naming confusion.

The effect of this name and semantics clash is critical in the HandlingEvent registration function. On one hand HandlingEvent is an event as domain element - an immutable entity. And on the other hand, it is also an event in Udi's sense - it pushes out, from the Handling aggregate, a notification of state change to be processed within the Cargo aggregate. In the original code the application event is published by the app layer and this approach solves the problem quite well. But I wanted bady to use domain events as described by Udi and it came out that there is no object which can be made responsible for publishing the transient 'domain event' since only operations performed on HandlingEvents are create (using constructor) and store (using repository).

I decided to change the design in this particular area and make HandlingHistory object responsible for both storing HandlingEvent persistent events and publishing CargoWasHandler transient events. I think it finally solves my problem, at least for now. And, completely for free, I made the design follow Udi's advice not to create aggregate roots.

1 comment:

  1. Hello, that's a very interesting analysis. The possible confusion between domain events (event as domain elements) and application events (transient and an asynchronous execution mechanism) was something that we noted a while ago and decided to rename to sound a little less domain-like:

    SystemEvents.notifyOfCargoHandling()

    System events is a term that occurs elsewhere in the litterature, so that was selected in favor of application events.

    We use domain events to model (some) things that happen in the domain (cargo shipping), that a domain expert would care about and that is relevant for the problem we're trying to solve (tracking cargo). System events on the other hand are used to let some part of the application know that something has happened in another part of the applicaiton, and to allow interested parties to act upon those events.

    Peter Backlund
    DDDSample Lead developer

    ReplyDelete