Domain Driven Design, CQRS and Event Sourcing
It’s taken quite a while, but I think I’ve had a bit of a revelation in really grokking the application of CQRS, Event Sourcing and DDD.
I’ve been considering the application of CQRS to a multi-user collaborative application (actually suite of applications) at the company I work. For some parts of the application, it is really easy to visualise how the application of CQRS would provide great benefits, but for others, I couldn’t quite figure out how the mechanics of such a system could be put into place, and yet maintain a decent user experience.
Let me try to elaborate with a couple of examples:
In one application I work on, a user may make a request for a reservation. I can see this working well under CQRS. The command can be issued expecting to succeed, and the response needn’t be instant; a message informing the user that their request is being processed, and that they will be notified of the outcome should suffice. The application can then take responsibility of checking the request against its business rules, and raising relevant events accordingly (reservation accepted, reservation denied etc). Supporting services could also notify users of the system when other events they might be interested in, become available.
For another scenario in the same application, a user may wish to update their address details. The application must store this information, however the application does not use this information in any way shape or form. It is there for other users to reference. When applying CQRS to this area, we start to see some oddities. A user receiving a notification that their request to update address is being processed seems ridiculous; there is no processing required here. In addition to this, this canonical example of “capturing intent” doesn’t really apply to our domain; in our domain no one cares why the user is updating their address, be it because of a typo, or because of a change of address. This information isn’t interesting in to any of the users of the system.
Then it hit me.
CRUD actions like modifying the contact address of an employee and other ancillary tasks – provide only supporting value in our domain. For all intents and purposes, the contact address of an employee is just reference data; it is there to support our actual domain. Arguably then, there is no benefit for modelling this interaction within our domain model. It’s quite the contrary in fact; diluting our core domain model with uninteresting concerns blurs the focus from what’s important. Paraphrasing Eric Evans’ blue book: anything extraneous makes the Core Domain harder to discern and understand.
Taking this idea further, there can be significant benefit in separating this kind of functionality from actions that belong to our core domain. In code terms, this means that our domain model will not have an “Employee” entity with a collection of type “ContactAddress”. This association isn’t interesting in our core domain. It is likely that it is part of supporting model which could be implemented quickly and effectively using any one of Microsoft’s (or any other manufacturer’s) RAD tools.
In the big blue DDD book, I think Evans describes this separation as a generic sub-domain. In generic/supporting sub-domains there may be little or no business value in applying complex modelling techniques even though the function they provide is necessary to support our core domain. Alternatively, the core-domain of one application may become a supporting domain of another. In either case, the models should be developed, and packaged separately.
Our product, in its various forms, contains enough complexity in its problem domain itself, without complicating things further by tangling up the core domain with supporting concerns. I do not wish to be in the situation (again) where one application needs to know the ins and outs of what is supposed to be another discrete application. If understanding the strengths and limitations of modelling techniques such as CQRS, Event Sourcing and DDD can help me achieve this, then I’m making small steps in the right direction!
NB: this post originated from an email discussion I had with a colleague. I’ve removed/replaced the specifics of our core domain (hopefully this hasn’t diluted the points I’m trying to make too much!)