Command/Query Responsibility Segregation and Event Sourcing
Podcast: Play in new window | Download (53.5MB) | Embed
Subscribe: Apple Podcasts | Spotify | Email | RSS | More
Command/Query Responsibility Segregation (CQRS) is a way of designing the code in an app that talks to a database. It creates a logical separation between operations that mutate data and operations that merely retrieve it. Because the load characteristics of reading and updating data are often different, this practice can have a profound impact on how well your application runs.
In addition, Event Sourcing can help your application collect data that may not be considered valuable at the time of design but may be very valuable later. Event sourcing is a way of modeling your data as the result of a sequence of events rather than only keeping track of current state.
“It’s like your bank account.”
Command Query Responsibility Segregation and Event Sourcing are both advanced development concepts. Like many advanced concepts, it can be difficult to get your head around their purpose. However, once you understand what they are trying to do, it gets a lot easier to understand what is going on.
Command/Query Responsibility Segregation
14:30 What is Command/Query Responsibility Segregation (CQRS)
A query is an operation that only reads data.A command is an operation that changes data in a data store.
“You probably aren’t going to want to start with event sourcing.”
Essentially, the code that simply returns data needs to follow a separate path than the code that alters data. The idea is to explicitly separate operations that retrieve data from those that alter it, so that they can be reasoned about separately, scaled separately, and even secured separately. This is usually not a good place to start things, but systems often evolve in this direction over time.
15:55 History of CQRS
Coined by Bertrand Meyer as part of working on the Eiffel programming language. He states that methods should either perform an action, command, or return data, query, but not do both. The mere fact of asking a question should not effect the answer to that question. Methods must be referentially transparent meaning they have no side effects.
17:20 Command Components
“Our read speed is constrained by our write speed or our write speed gets constrained by our read speed.”
Separating the command components makes it easier to take advantage of eventual consistency, meaning that your writes to the system don’t necessarily have to be slowed down by indexes that you put in place to make reads faster. Commands only have the information required to execute the command, rather than the entire aggregate upon which the command is run. This gets rid of many consistency concerns and also reduces the surface area for mass-assignment vulnerabilities.
CQRS makes transitioning to a message queue architecture much easier, because the payloads are smaller. Commands become relatively self-documenting in that their signature shows everything that is required to use one. Validation of a command’s requirements can be done by the command, rather than by the receiver of the command, lowering coupling across the application. This in turn makes audit trailing easier, as the audits correspond to what the user did, rather than how the data is stored. Finally, separating the command components makes replaying events easy, which can help when you learn more about what a particular action means as your domain evolves.
27:30 Query Components
“One thing that this does is it makes caching a lot easier.”
An appropriately shaped read model can be cached, without having to include things that only commands care about. You only need the “document” itself. Cache invalidation also becomes easier. Cache keys can be tied to entity identifiers and expired if they are actually changed. Whereas if your model is a CRUD model, developers tend to put side effects into reads in many cases.
CQRS makes it easier to mirror data stores, because the results of one command can be replicated to multiple data stores more easily than database mirroring will allow. Different projections of the data can be cached differently for different pages. This sets the stage for less critical pages being updated more slowly, which can help a lot with scaling.
“Event Sourcing ensures that all changes to application state are stored as a sequence of events. Not just can we query these events, we can also use the event log to reconstruct past states, and as a foundation to automatically adjust the state to cope with retroactive changes.” ~ Martin Fowler
36:20 Event Model
The basic idea is that as commands are processed in an event model, they are captured in event objects, which are stored alongside the current state of the domain objects for as long as the domain objects exist. This is analogous to the way your bank keeps track of your transactions (events) alongside of keeping your account balance (state).
These event objects will then show the sequence of events that caused the object to be in the current state. It’s a recognition that the events leading up to a state are also valuable, both currently and for unknown future purposes.
41:50 Benefits of Event Sourcing
“That was almost 17 years ago why would I remember that, if I had a good event stream I would…”
Event sourcing allows you to completely rebuild the current state. Since you are capturing events alongside the main domain objects, you could rebuild the current state if you were to find an error in your previous implementation. This can be helpful if events arrive out of sequence.
You can also determine the state of an object as it existed at a particular point in time. Then replay the stream of events on a particular domain model, but process them into a different structure for reporting purposes. You can also reverse an event, it can also be useful to allow them to reverse themselves.
45:54 Practical Application
Events are stored in their own objects alongside the domain object. Often, a read model of the domain at its present state will be stored, and will be updated as each event occurs. If an event was made in error, an adjusting event is sent, to reverse the change. Sort of like adjusting entries in accounting.
“This is something that I had a hard time understanding.”
In complex systems with an ORM, you may be tempted to lazy load. In an event-sourcing scenario, you can just load all the events (from one table, no joins) for a particular aggregate root, and then replay them on the item in memory. This can reduce the need for joins on the database server and is occasionally handy.
Synchronization requires getting all the events for an aggregate root since the last one you got and then replaying them. It’s far easier than a database synchronization and doesn’t require both sides to represent the object the same way. If there will be a lot of events for a particular aggregate, you can also have rolling snapshots. You would then pull the snapshot down and apply the events in sequence to get it up to the current state. These can be built in off-hours or when there are more than a given number of events since the last snapshot.
Note that this is a processing model, not a reporting model. If you need things projected for reports, you can process events and store the results in an appropriate way elsewhere. This also does a decent job of reducing the impedance mismatch between your code and the database, at least for the purposes of OLTP.
Intel Vaunt Smart Glasses
Intel picks up where Google left off. Unlike Google though, intel didn’t go for the sci-fi look they went more hipster with full rimmed fake lense glasses. They actually look like you are wearing a pair of regular if not a bit bulky glasses. You don’t have get fake lenses either they’ll work with prescriptions. Intel’s goal isn’t to change the way you look at the world but to integrate into your life as seamlessly as possible. The glasses have to be fitted to your face, those of us that wear regular glasses know the process though this is a little more involved as pupillary distance has to be measured. Going along with the unobtrusive nature of the glasses the HUD (Heads Up Display) disappears when you aren’t looking at it.
Tricks of the Trade
People get angry when you don’t have basic information that they have forgotten they had to learn. You do it too. When you can realize what is going on and what information they (or you) are missing, you can build bridges and out-compete other people who might have better technical skills, simply because you can actually get things done.
Here is some example code. Very easy code for understanding this. I can provide an example in any programming language you like. https://twitter.com/adymitruk/status/973380830239191040