Introducing DomainEvents, a library that empowers your domain entities to be awesome and filthy RICH!

The Problem:

As an excellent software developer, you want to be sure that your code is maintainable, testable, expressive, and beautiful. But sometimes those desires seem to conflict with one another. For instance, an expressive domain should contain entities that, not only include well-named properties, but also the behavior of the business’s domain. But, if you include behavior in your domain entities, you run the risk of harming the application’s maintainability by having classes with more than one “reason to change” or “responsibility” (see Single Responsibility Principle).

The Solution:

Well, the solution really has two parts: 1) Double Dispatch and 2) Domain Events. Since this article is all about Domain Events, I’ll let you read about Double Dispatch on your own and stick to the subject at hand. So, consider the following POCO class:

The above POCO is how all of my domain entities used to look. It’s clean, but boring… this class does absolutely nothing. Before I met Domain Events, I would have created any number of domain “services” that performed actions on this Account class. The problem with this is that, in order to read the code and decypher what the Account does, you have to go service fishing and search for all the services that touch Account. It’s a bit of a shame that we have such a clean code base, but one that expresses very little of the actual domain.

Now, let’s add some behavior. Our imaginary business has passed down a new requirement from on high: “As an account, I can change my name.”

So, consider the same POCO class with a bit of behavior:

This is great. We’re starting to make our Account entity a little more interesting. But, we have done very little and are pretty restricted to what we can actually do. But we still have three more pieces of the requirement to implement (found in a pencil-written footnote):

When account name changes…

  • account should be saved to the database.
  • should email the account owner notifying of the change
  • should log the change

How can we do all that from inside a POCO domain entity? Well, the answer is that you can’t (or shouldn’t). BUT, what you CAN do is send out a signal to the rest of the domain that the name has changed and allow the domain to respond to the signal.

So, consider the same POCO, now equipped with DomainEvents:

Behavior-Rich Domain Model – BAM!

That’s more like it! Now, our domain entity has behavior that expresses the requirements of the business AND empowers the domain to respond to the behavior that has occurred. At this point, any number of event handlers (observers) can respond to the TheNameChanged “event”. To fulfill our client’s requirements, here are some possible event handlers:

  • UpdateTheAccountInTheDatabaseAfterNameChange
  • EmailAccountOwnerAfterNameChange
  • LogThatAccountNameWasChanged
Domain entities that are rich with behavior can transform a domain layer from boring/limp/confusing to interesting/strong/easy-to-understand.

For more information on how to install, implement or use DomainEvents, check out the wiki.

For sample code, check out the sample app in the source code.

  • mcintyre321

    You have a new problem now, which is a lack of visibility of what events are going to be fired. You might find that 

    public void ChangeName(string newName)    {      new UpdateTheAccountInTheDatabaseAfterNameChange.Execute(this);              new EmailAccountOwnerAfterNameChange.Execute (this );
                  new LogThatAccountNameWasChanged.Execute (this);    }

    Of course this is a little less flexible, and doesn’t allow for dynamic composition, but in some code-bases and with some teams this will be easier to work with. 

    • sommardahl

      I like the way you think, Mr McIntyre. My aim is definitely to increase visibility in the domain. Adding meaningful behavior to domain entities makes their functionality SUPER visible, and, with intellisense (Visual Studio), discoverable. I would argue, though, that the use of domain events doesn’t hide functionality any more than lots of disparate “domain services” that act upon domain entities. In fact, quite possibly, the handlers that respond to domain events are much more visible in modern IDE’s like Visual Studio. If you want to know what handlers deal with a certain domain event, just right-click and “find usages”. For me, what follows is a navigable list of visible domain behavior. So, I’d say that domain events help increase overall visibility of domain behavior.