Big Blue Series — 15 — Staying Well Informed with Domain Events

John Connolly
Domain Intelligence Today
6 min readSep 26, 2022
Photo by Antoine Barrès on Unsplash

When I was growing up, I loved to be with friends so much that I would be out passed the time I should be home. I would forget to call my parents. They would not forget to tell me how upset they were. It was a common occurrence. I am probably not alone in this. If you are an artistic extrovert with a passion for good relationships, other things just take a back seat in life. Sometimes, important things. If I had a cell phone (they were not invented yet — ugh) I would likely have found an app that would automatically, and maybe even slightly annoyingly, notify my parents where I am, about every other hour, give them my heart pulse rate, body temp, and anything else that would prove I am alive and safe — or at least alive. I could get creative on this!

Domain Events are way to inform parts of your system that something happened, and if you needed to know, now you know. This concept has many endless possibilities, with some general guidelines not to make more spaghetti-code in the process. Power tools can be used for good and not so good, and Domain Events are a very powerful tool.

In previous articles, we have talked about Entities and Value Objects that not only are data, but also often perform some function. We have talked about Services that perform some Domain function but does not belong on an Entity or Value Object. Mapping this all out becomes nice and pretty until, you need one function to trigger the process of another function in some other Entity, Value Object or Service. It also gets more complicated when you need several “reactions” to a Domain Event throughout your Domain Model landscape.

In a former life, as a purely procedural developer, when I needed a complex function that accomplished many steps, I would just build a Complex Process Manager. The net effect of that is a dumbing down of the Domain Model or copying and pasting that functionality into more than one location in the code. It was all bad news. I would even get tricky and make “common functions” that could be referenced to reduce the amount of duplication. The net effect of that, pretty much pure spaghetti-code.

If you are stuck in that older model of solving disjointed process, then you are about to be set free. Don’t go wild on this though. Events can get out of control, so proceed with some caution.

If the Domain Model is in need of an alert to a change, program the phone call by “raising” a Domain Event that will let the model know the process has a change result. If any other part of the model wants to react to it, they should. Leave the functionality in the objects they belong. Let them know something happened. Don’t take away their joy of having a reason to live. Let them live where they are and just enable them to know they are needed. You may need the results from the other part of the model, which can be done real time or sent and forgotten about, like leaving a voice mail. They will listen and respond when they need to.

If you need a response from that other “listener” out there before you can move on, then you may have to model this as a dependent action, but that is normal. It is normal to have voicemail, and it is normal to be on hold. It all depends on how the Domain is interested in getting work done.

Now admittedly, Blue (Evans, 2004) did not have Domain Events as a major highlight. However, all of the other instructions about Domain-Driven Design still apply. Name your event with the name that represents what just happened that it wants to let the Domain Model know about. Names can get long, but that is preferable to implicit, ambiguous or otherwise questionable names. Examples of what a Domain Event might look like are NewOrderWasSubmitted, NewCustomerRegistered, NotificationOfStatusSentViaText. This list is endless of what you can name your Domain Events.

What do you put in the Domain Event? Think about great communication. This is not a conversation with a long-lost Aunt (in general). This is supposed to be succinct informative communication. Something happened. What happened? This changed. What was the change and what was it applied too? It was an updated check-in time at this hotel for this reservation and it was for this customer and done by the customer themselves. Thanks. That is more than I needed to know. Of course that is more back and forth than should happen.

In the real world it would look something like this:

CustomerUpdatedCheckinTime {ReservationId int,
UpdatedCheckingDateTime datetime
}

Notice the HotelId and the CustomerId are assumed to be known if you have the reservation. This is a typical type of DomainEvent. Simple. One could argue that the change could be more descriptive. How much of a change was it? Two hours later? Earlier? Maybe the model works that out elsewhere. Maybe it is more efficient to have it on the Event. You will want to play with that.

What is not simple is modeling out what to do about it. Think through all that the hotel might need to do in response to this Domain Event. They might need to notify housekeeping to alter their room cleaning schedule. They might have other processes that are important when a check-in time is move earlier versus moved later.

Now there are more things to think about. One important thing is timing. Ever received a message, and it was a day late and a dollar short. Ever told someone, “Hey, you know, if you would have told me earlier, I would have been able to do something about that!” or “Save that for later, I am busy.” Or, more critically, Emergency personnel might need to know a blood type mislabel before starting an infusion. Timing is everything in some situations.

Now, a major software development company has an article out there on this exact topic. I will not name them, but they state that Domain Events are there to handle side effects. We are mainly not interested in side effects in DDD just like when we take medication. We are generally trying to apply additional benefits not side effects. I am going to disagree with them on this point. It may seem like semantics, but Domain Events should be purposeful, desirable notifications that help the system function well. Please don’t make your software sick by design.

So, when you are modeling, you will get a sense that some actions are worth communicating inside the Domain Model. And some, are even important across several Bounded Contexts and even across multiple Domains, in the integration of those Domains — a different topic but the same concept.

This is a creative process, but the main point of Blue is to learn what the Domain is trying to accomplish and do that to the best of your teams knowledge. Though Domain Events are not really discussed, they can be implemented in the same spirit of understanding the Domain and similarly to the rest of the model. You will improve communication as you learn better ways to represent the Domain. There is not a perfect model. Sometimes the phone calls are annoying and sometimes they are missed. Keep looking for ways to communicate Domain Events more effectively.

All the types of Domain Model elements we have discussed so far might feel like they are floating out there in the software universe of a Bounded Context or beyond. Fortunately, Blue solves this. We will start looking at tactical Model structures that contain all these elements known as Aggregates next. It is all starting to come together in this series.

Until then…

I hope I see you in the next installment of — the Big Blue Series.

Photo by Nick Page on Unsplash

References

Evans, E. (2004). Domain-Driven Design: Tackling Complexity in the heart of software. Addison-Wesley Professional

--

--

John Connolly
Domain Intelligence Today

Domain-Driven Design Consultant. Passionately helping domain experts, architects and developers understand domain models improving product delivery.