This is part 1 of 5. The entire series is here:
A couple of days ago I held a presentation at DevSum 2012 in Stockholm. The topic was “A Trip to CQRS” and is basically me talking about a project that we’ve been working on for the past year or so. We basically found ourselves refactoring a system from a traditional nTier, CRUD, Entity Framework-solution to something that could be called Event Sourced CQRS (but without the nice DDD-part..) The talk was fairly well-received so I thought I’d take some time to blog about it too.
In this first post I will introduce the sample system and the reasoning behind the refactoring. I have pushed the entire sample system to my github. The code in its “before”-state is in the master branch:
Based on a true story…
The talk (and this article) will not show the actual system since it’s an internal system in a domain that isn’t really well-known by people outside of our company. Instead, I’ve created a mock system that should be easy enough to grasp quickly, but complex enough to show most of the difficulties we faced. The infrastructure code is more or less exactly the same though.
The domain I’ve chosen for the mock system is Hotel Information.
We have a Hotel object that has some basic information about a hotel. The Hotel can have one or more Facts (i.e DistanceToVillage = 500m) and the Fact is of a specific FactType.
The reason why we decided to move to CQRS was the two new requirements that we were handed:
- Several “downstream” systems needs to be integrated in more or less real-time.
- We need to keep a complete log of every change that happens in the system for auditing purposes.
Both of these seemed like a pretty good reason to introduce Events of some sort, and since I had recently listened a lot to Greg Young. Well.. I simply couldn’t help myself.. 🙂
First, let’s examine the state of the system pre-refactoring. As I mentioned, it’s pretty standard nTier/CRUD. A simplified diagram would look something like this:
The client connects to a façade (in the real case it’s a WebService, in the sample code I’m calling the “service layer” directly but that really doesn’t change a lot..). The façade uses DTOs so no domain objects travel across boundaries.
Below the façade sits some kind of business logic (the Application Service layer in this diagram). There is no true DDD-style Domain Model however, so all logic is contained in Transaction Scripts.
Accessing data is done via a quite simple Repository-pattern framework I’ve done (Petite.Repository, available on NuGet) that sits on top of Entity Framework.
Let’s just show you some code. Here are a few snippets from the HotelService. The first one is the method that returns a single Hotel:
[github file=”/andlju/hotel-admin/blob/master/src/HotelAdmin.Service/HotelService.cs” start_line=”23″ end_line=”32″]
Next are the Add and Update methods from the same file.
[github file=”/andlju/hotel-admin/blob/master/src/HotelAdmin.Service/HotelService.cs” start_line=”90″ end_line=”110″]
Nothing fancy and not very exciting.
While I have your attention though, I might as well show you one of the test classes. I’m fairly happy with these actually and they get even better as we move to a more CQRSy model.
[github file=”/andlju/hotel-admin/blob/master/src/HotelAdmin.Service.Tests/When_Updating_An_Existing_Hotel.cs” start_line=”6″ end_line=”56″]
CQRS – The Silver Bullet?
This is not going to be a “Introduction to CQRS” article. If you don’t have a clue of what I’m talking about I very much recommend you to visit the CQRS Info site.
Anyway, as you know, the main point of CQRS is to separate your stuff into Commands and Queries, where Commands are used to change the state of your system (but without returning said state to you) and Queries are used to, you guessed it, return the state of your system (but without changing it).
Keeping compatible with UI and DB
The following conversation never actually happened since I played it up in my head quite a few times, and the result was always the same:
Me: You know the system we’ve been working on for the past 6 months? I’d like to make a few changes.
PM: OK, that’s cool I guess. You need to change a column in the DB or something?
Me: Eh. No. I’d like to replace the DB with an Event Store and some read models in RavenDB. I’d also like to rethink the UI so that it is more in line with the Task Based model that is preferred in CQRS systems.
PM: Ain’t gonna happen.
Instead, I tried to find a model that would let me keep as much as possible of the work that had already been done while still bringing in some of the nicer attributes of a CQRS system. I wanted to keep the Façade compatible so that the UI wouldn’t have to change. Also, the DB was already used by a few SSIS-packages (and I hate making changes to our dbproj-files) so I wanted to keep as much of that as possible too. That pretty much meant that all the work would have to be done right in the middle!
Step by step to CQRS bliss
In the following series of posts I will take you step by step through the process we took. Each step in itself brings something to the table and I think it will be easier to follow my reasoning if we divide it. That said, if you want to do something like this yourself I would probably recommend to do it all in one swoop..
OK, this this first one is very easy. At least for now.
The queries, i.e all the Get, List, and Find-methods: Keep ‘em! As we won’t change the database model this should be fine. Later on we will be able to do a lot of fun stuff with queries though, but we won’t go there yet.
Tune in to the next episode where I’ll show you Commands. That should be at least a bit more interesting. 🙂
Leave a Reply