Recently I have been investigating the use of the Command and Query Responsibility Segregation (CQRS) pattern combined with event sourcing for a personal project. I need individual client applications to be able to run completely disconnected from my server processes, but when they come back online they need to synchronise both their changes and changes made by others while they were disconnected.
Currently the software tries to achieve this by capturing each change to the data as events detailing what changed. The problem with this approach is that we lose the “why” of the change. This becomes a problem when we have conflicting or duplicate changes which can’t determine that they are duplicates. For example someone might end up charging a client twice for something. The domain classes would normally not allow that to happen, but the data sync doesn’t know about domain rules so puts the invalid data in the database anyway.
While investigating CQRS + Event Sourcing I have found Mark Nijhof’s articles and sample code to be particularly helpful in demonstrating an effective implementation of those two patterns. I highly recommend checking them out.
I have been developing a proof of concept to prove that I will be able to solve my main problems by applying these patterns. For the prototype I have been borrowing heavily from Mark’s sample code, but making modifications as I need to. One change that I have made to Mark’s code is to add a convention for registering domain event handler methods. In the sample solution Mark is registering each method manually. In his article about event handlers he does mention the possibility of setting up some sort of convention for registering them automatically, which is what I have done and I am going to share my implementation in this post.
The only way to find methods that meet the conventions criteria is to use reflection. Calling methods by using reflection is slower than calling them from statically compiled code. I wanted my solution to be fast, but I was willing to sacrifice some speed for more painless setup. The first thing whenever performance is a question is to measure your current performance so you have something to compare against.
My first step was to setup the following test program:
I haven’t shown the Account class’ implementation here, but it isn’t really important. With manually registered event handlers as used in the Fohjin.DDD project it produces the following output:
For the sake of completeness the apply event method looks like this:
My first attempt was to simply use reflection each time an event is applied to find the method that should handle the event. My implementation looked like this:
And produced the following output:
We can see from this that using reflection takes about twice as much time as manually mapping the call. That sounds bad, but the reality is that this solution is still performing well enough that it would only be in rare situations anyone would care, but seeing as how I am a little OCD when it comes to optimising things I decided to see if I could do better.
My next approach was to do my reflection search once and then cache the results to be shared between all instances of the class. I use a static class called EventHandlerMappings (I don’t quite like that name so if you can think of a better one let me know) to manage the mapping and get my reference to the handler dictionary in the constructor and then uses it in the Apply method like so:
We now arrive at the following performance results.
Now we are taking roughly 1.5 times the baseline instead of twice as long, but I still think we can do better. Instead of just caching the method info we can create a delegate from it and use that instead. The downside to this is that the first time we will pay a higher price for the conversion. This isn’t quite as straight forward as it sounds, because delegates parameters are strongly typed. We want the parameters of our delegate to be for the base types of IDomainEvent and AbstractAggregateRoot, but our method will take a specific type. To solve this problem we need to wrap our delegate call in another delegate that will cast the parameters to the correct type.
Here is my implementation for the EventHandlerMappings:
And here is my implementation of the Apply method now:
Which give me the following output:
This result surprised me at first, because it is faster than the original manual implementation. After looking over things I am fairly certain that the reason it is faster is that our original code creates the handler mapping dictionary for each instance and I am guessing that is where the extra time comes from.
It is worth mentioning that the caching code puts additional overhead on the first call for a given type. So if you are only running one or two iterations worth of code in a typical application life time then you would be better off with the straight reflection implementation.
So there you have it, convention based automatic wireup of event handlers in an Event Sourced entity.