Event sourcing the past and today
It’s been quite some time since I first read about event sourcing on Mark Nijhof‘s blog (Mark has moved his blog several times since then). My understanding of the subject has been evolving for few years. Same with other people in the community. Greg Young, the father of the event sourcing and CQRS ideas, might tell you that the biggest mistake community did during these years was building frameworks. To some extent I agree but on the other hand I think that bashing all frameworks is like throwing out the baby with the bathwater.
Problems with frameworks
The biggest problem with CQRS frameworks of the past (and I know this because I contributed to one of them) was in my opinion the fact that we focused on wrong things. We, as a community, didn’t understand the whole concept well enough. Sure, there were always people who did and tried to warn the others but we were not listening because we were too busy coding The Most Beautiful And Complete Implementation Of Aggregate. Standard CQRS framework from the past looked like this:
The most important concept is the aggregate. This is logical, right? It is the place where business logic lives so it must be the most important concept. Aggregates produce events which are also quite important because they are used to maintain the state of the aggregate. Events themselves are stored in an event store. In those early days there was no mature ready-made event store implementation so a framework had to include one. Event versioning and commands manage to attract some attention but not a lot. In case of commands, this attention was mostly focused not on commands themselves but rather on how we handle them. Concepts like messages, integration, duplication/transactions and read models were in most cases out of scope.
One can summarize this approach as storing business object state by serializing state-mutating method calls. We surely missed the whole point.
Value of frameworks
This is the baby and bathwater part. Although as I wrote, we missed the whole point, I still see value in what we created. Frameworks do lower the entry barrier for people who want to try a new approach. NCQRS, a framework I contributed to (kudos to Pieter for building it) did help some people to grasp the concept of event sourcing. Frameworks also (at least the good ones) remove the need of writing boilerplate code and let us focus on the business problem we try to solve. In case of event sourcing and CQRS the problem was that we initially misidentified the areas where framework would have most value. Frameworks did provide ready-made solutions for things that most people wanted to be custom-made while failing to help in tough and/or generic problems such as:
- read models
- transactions and coordination
A better approach
While I won’t say that I know The Best Approach To CQRS now, I would argue that I at least know one that is better than the ones we used in the past. The diagram of today’s framework should look like this:
The whole thing is more balanced. No longer a single concept dominates the whole picture. An event store has been moved out of scope of the framework as we have at least two production-ready implementations provided by Jonathan Oliver and Greg Young. The former is an abstraction layer built on top of other data stores (e.g. RDBMS) while the latter is an event store build from the ground up.
The key concept is message — an atomic piece of information we can package and send between processes, machines and systems. Not all messages are created equal though. A smart framework would distinguish commands (messages that tell the recipient to perform some action) from events (ones that inform everybody that something has happened). Handling duplication of messages is key to build a robust message-driven system. A good framework should provide a solution for this.
Event versioning should get some attention also as it is critical for maintainability of the system in the long run. Another interesting bit is integration — how do we communicate with other systems? The general answer is we allow them to read our event store. This requires however that we have durable subscription feature somewhere in our stack, either within the store or the framework.
If we are building a CQRS framework, there need to be a decent support for the read side also. Problems like automatic view rebuilding when code changes are the ones that a framework should be able to take care of.
The last thing in the picture in an aggregate. Noticed the different from the previous diagram? In a modern approach is has a servant role. In modelling phase aggregates are a corollary of command-event chains. We simply group related command-event pairs into aggregates according to their consistency requirements. In the implementation phase aggregates provide deduplication capabilities which are essential to most business logic.
All the things I’ve just mentioned can be built in less than a month by a single person so the effort can be easily accommodated by even a medium size project. So far not much value added, at least for people who know messaging and event sourcing sourcing inside-out. True, but the thing I described, if done right, would be a very solid platform that we can use to build value added services on top of it. I am thinking of things like:
- enforcing SOA/EDA architecture using best practices preached by Udi Dahan
- being able tell the software to upgrade service A from version X to Y and having all dependencies upgrade automatically (and one-by-one to limit any down time)
- monitoring any aspect of both the infrastructure and the user code running on top of it
- and many, many others