CQRS Myths: 3 Most Common Misconceptions

Although Command Query Responsibility Segregation (CQRS) seems to be a term a lot of developers are aware of, I do think the majority have the wrong definition. Like many terms in the software development industry, things over time get confused, and then those confusing ideas propagate. These are the 3 CQRS Myths I see or hear the most often.

YouTube

Check out my YouTube channel where I post all kinds of content that accompanies my posts including this video showing everything that is in this post.

CQRS Myths

I do understand why people can be confused by CQRS as if you do a search, you’re bound to find blog posts that explain CQRS very differently. Some posts get it right, however a lot of others conflate CQRS with other concepts.

So which blog posts are right? Who has the correct definition? How do you even know what I’m writing is correct?

CQRS Definition

Greg Young, who coined the term, used to blog on CodeBetter.com and his own personal site, goodenoughsoftware.net.

Unfortunately, neither of those sites exist anymore. However thanks to archive.org, we can go back to a blog post that Greg wrote in 2010.

Example

Instead of having a single object that has both write & read operations, you would split that into two separate objects. For example:

CustomerService has methods that return state (read) and mutate state (write). In order apply CQRS, we simply need to split these up into separate objects that will do one or the other, but not both.

That’s it. CQRS applied.

So why the confusion?

I assume most of the confusion is because most examples showing CQRS are also showing a bunch of other things, which is where these myths come in.

CQRS Myths

There are so many blog posts that will show a diagram like the one above, that are applying CQRS, but also doing other things.

Myth #1: Multiple Databases

CQRS does not require you to have multiple databases. You can use the same database for writes (commands) as you can for reads (queries).

CQRS Myths

It’s not a physical separation but more of a logical one. If you’re using a relational database, you could create SQL Views that only your query side accesses.

Myth #2: Event Sourcing

Event Sourcing is the concept of storing immutable events derived from actions within your system that represent state change. Greg Young has been at the forefront of Event Sourcing, and since he coined the term CQRS, I can see how Event Sourcing often gets lumped into it.

Most often times if people are referring to both CQRS and Event Sourcing, they will use the label “CQRS/ES”. I think it’s a good idea as I hope it’s preventing more confusion.

You do not need to be Event Sourcing in order to be doing CQRS.

Myth #3: Asynchronous Messaging

You do not need to be using a message bus to apply CQRS. Commands do not need to be asynchronous. Everything can be done in a synchronous request/response manner.

I think this myth stems from people using a message bus along with Event Sourcing so they can create projects for a separate read model.

More

Greg wrote on his blog in 2012 common misconceptions that I don’t think if left us yet. Hopefully, this post shining a light on his original posts help clear things up.

Follow @CodeOpinion on Twitter

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.

Links

Avoiding the Repository Pattern with an ORM

For many years now I’ve advocated not using the repository pattern on top of an ORM such as Entity Framework. There are many reasons why that I’ll try and cover throughout this post based on ways that I’ve seen it implemented. Meaning, this post is talking about poorly implemented approaches or pitfalls that I’ve seen.

To clarify, since this topic seems to really fire people up, I’m not saying that you shouldn’t use the repository pattern. I’m going to clarify why I don’t think under certain situations it’s very useful and other situations that I do find it useful.

This post was spurred on by a blog post and tweet:

IQueryable

The first thing I’ve seen with a repository is exposing IQueryable<T> (or DbSet<T>) from the underlying DbContext in your repository. This serves no purpose. It’s not abstracting anything at all.

What’s even worst is the consumers/callers don’t necessarily know at what point will they actually be retrieving data (doing I/O), unless you’re aware that the underlying IQueryable is coming from Entity Framework., Now when you call a method that materializes your query and actually hits the database (such as ToListAsync()).

Lazy Loading

Second, to this point is now if you have any type of navigation properties and are accessing IQueryable<T> from repository consumers, you must either eager load (via Include()) or have your consumers do the Include() or not realize all navigation properties are lazy loading.

Again, consumers are now aware of the underlying implementation that is Entity Framework.

IEnumerable

To overcome these issues, usually what comes next is avoiding the IQueryable<T> by returning an IEnumerable<T>.

The issue now is since you’re taking away control from the consumer, you must decide what data to Include() and Select() behind query methods.

What this often turns into is a pile of methods with various filtering parameters that could have been much easier expressed via a LINQ expression against the DbSet directly.

Query Objects

So if I don’t generally use the repository pattern, what do I use? Query Objects.

For querying, I’d rather have specialized objects that can return very specific data for the given use case. When implementing in vertical feature slices, as opposed to layers, each query is responsible for how it retrieves data.

The simplest solution is to use the DbContext and query directly.

The primary benefit is query objects only have dependencies that they actually require. Because each query object defines its own dependencies, you can change those dependencies without affecting other query objects.

A simple example of this is if you wanted to migrate from Entity Framework 6 to Entity Framework Core. You could migrate one query object at a time to EF Core instead of having to change over an entire repository that is highly coupled.

Testing

I can see the argument for using a repository because testing was difficult with EF6. However, with EF Core using the SQLite or the InMemory Provider, testing is incredibly easy.

I’ve written a post on how to use the SQLite provider with an in-memory database.

Testing a Query Object becomes incredibly easy without the need to mock.

Caching

Another argument for using the repository pattern is being able to swap out the implementation for a “cached repository”. I do use this pattern but in very select cases. Most times this is across bounded context were cached or stale data is acceptable.

If you decide to swap out the implementation of your repository, which was previously always hitting the database (point of truth) and now is using a cache implementation, how does that affect the callers? How quickly is the data invalidated?

Data can be stale the moment you retrieve it from the database, however adding caching to your repository without your callers knowing it can have a big impact on behavior.

Aggregate Root

One place I do often use a repository is when accessing an aggregate (in DDD Terms). My repositories often only contain two methods, Get(id) and Save(aggregateRoot).

The reason I do use a repository in this situation is that my repository usually returns an object that encapsulates my EF data model. I want it to fetch the entire object model and construct the aggregate root. The aggregate root does not expose data but only behavior (methods) to change state.

Repository Pattern Related

Follow @CodeOpinion on Twitter

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.

Event Sourcing: Projections with Liquid Projections

Liquid Projections

Projections are an important yet pretty simple concept when working with event-centric or event sourcing systems. The concept is to build a state from a stream of events. In my previous post, Event Sourcing with SQL Stream Store, I made a pretty basic projection to keep the current account balance. In this post, I’ll use Liquid Projections to accomplish the same task.

I recommend checking out my post on SQL Stream Store as I’m using the same example/demo application in this post.

Liquid Projections

Liquid Projection is a library for building projections. The concept and API are pretty simple, and I’ll cover the basics in this post.

First I’ll update my Demo Application to use the Liquid Projections NuGet package.

Event Map

The first building block is creating an event map. The idea is to map an event to an action that we want to be invoked when the event occurs. We can use the EventMapBuild<TContext> to create all of our event mappings. The TContext can be anything but I’ll be using it to mutate the state that represents the current balance.

As a refresher from my previous post, here is the Balance

Now using the EventMapBuilder<Balance> to handle the Deposited and Withdrawn events.

You’ll notice call Build() on the EventMapBuilder<Balance> which will return us the EventMap<Balance>. At this point, you can call Handle() to pass in the events incoming from our subscription with our current Balance.

Conditions

There are also some nice additions such as providing conditions for when to execute a map. For example, if you wanted to handle only deposited events where the amount was greater than 100.

Inheritance

There is also support for inheritance, which means since my Deposited and Withdrawn events inherit from the AccountEvent base class, I could also have done

Event Store Integration

The next on my list is write this up directly with to something like Event Store or SQL Stream Store. Stay tuned.

Check out Liquid Projections on GitHub for more.

All the source code shown in this post is available on GitHub.

If you’d like a more detailed contented related to various aspects of event sourcing, let me know in the comments or on twitter.

Related Links:

Follow @CodeOpinion on Twitter

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.