This is part 4 of 5. The entire series is here:
I left you in the previous post with a bit of a cliff-hanger, didn’t I? So what is the “rather major flaw” in our nice Event publishing system?
Well, the big problem is that it may be hard for us, and for the business, to really trust our Events. Let’s have a quick look back into the code where a Command Handler publishes an event:
[github file=”/andlju/hotel-admin/blob/events/src/HotelAdmin.Service/CommandHandlers/AddHotelCommandHandler.cs” start_line=”41″ end_line=”51″]
What if we made a mistake here? I mean, not that I would ever consider using Copy&Paste for any kind of coding, but.. Let’s say that we accidentally set the Description property in the event to message.Name instead of message.Description. Then imagine this conversation, three years from now:
PM: We have a customer complaining that the hotel she stayed at didn’t have AC even though the description clearly stated that it would. She claims we changed the text the day after she got home.
Me: Yes! We finally get to use our Event Log! I’ll get right on it!
PM: I was hoping you’d say something like that.
Me: Ehh.. Uhm.. Hang on.. Ouch.. What if I told you we never actually saved the Description field…?
PM: You’re FIRED!
What we need is a way to really be able to trust that the data we store in our Event Log contains *all* the data that we may need in the future.
Event Sourcing
Usually, Event Sourcing is used together with DDD to replay state into aggregates. But taking the term literally, it just means that our Events are used as the source for all changes in our system. And that is exactly what we’ll do next.
Instead of letting the Command Handler update the database, all that logic is moved into one or more corresponding Event Handlers. The Command Handler will now validate the Command to make sure it makes sense given the state of the system, then publish an Event:
[github file=”/andlju/hotel-admin/blob/authoritative-events/src/HotelAdmin.Service/CommandHandlers/UpdateHotelCommandHandler.cs” start_line=”10″ end_line=”40″]
The Event will be picked up by the Event Handler which will perform any updates:
[github file=”/andlju/hotel-admin/blob/authoritative-events/src/HotelAdmin.Service/EventHandlers/HotelEventHandlers.cs” start_line=”8″ end_line=”92″]
How you divide your Event Handlers is pretty much up to you. We decided to have one class per Aggregate-thingy (They are not true DDD-style aggregates, but in my mind that’s still how I prefer to think about them..)
Testing
Testing now becomes even cleaner. We can separate the Command Handler tests from the Event Handlers. When testing the Command Handler we make sure that the correct Event is published (if validation is ok):
[github file=”/andlju/hotel-admin/blob/authoritative-events/src/HotelAdmin.Service.Tests/CommandHandlers/UpdateHotel/When_Handling_UpdateHotelCommand.cs” start_line=”10″ end_line=”71″]
And testing the Event Handler we just have to make sure that given a specific Event, the correct changes are persisted:
[github file=”/andlju/hotel-admin/blob/authoritative-events/src/HotelAdmin.Service.Tests/EventHandlers/Hotels/When_Handling_HotelUpdatedEvent.cs” start_line=”9″ end_line=”71″]
Benefits
A rather simple refactoring that makes ALL the difference. Our Events are now Authoritative. Since we base all changes to the system on them, we can be pretty sure that any change that our users see will also be stored for good in the Event Log.
Well, enough with the architectural changes. Let’s see if we can use this for something cool! Oh.. Right.. That’ll have to wait until the next, and final post of the series.
Leave a Reply