How to get started with CQRS & Event Sourcing

hammernailWhen I first heard about CQRS & Event Sourcing concepts through various blogs and videos, primarily from Greg Young and Udi Dahan, I wanted to apply it everywhere.

It seems really natural to want to take the limited knowledge we have about a new concept or technology and try and apply it to any problem.

Most of us know this is a terrible idea, but we are so tempted to push the concepts on a problem that it just doesn’t fit.

I realize I’m grouping CQRS and Event Sourcing together in this post.  Generally, if you are applying Event Sourcing then you are doing CQRS.  The other way around isn’t always true.

The Problem

In the very beginning I had a difficult time seeing where CQRS and Event Sourcing were best applied.  Again, as a beginner with our new shiny new knowledge we have our blinders on.

We look at any new problem and try to make it fit what we think CQRS and Event Sourcing solves.

There are some pretty good examples scattered around the internet about different situations that CQRS and Event Sourcing have been applied.  You may be able to read these examples and get a better understanding about what the context and how it was a good fit.  Also, you may read horror stories about how it was a complete failure and why.

To be honest, I haven’t read that many horror stories as I assume people are too afraid to admit their failures, although it would be very helpful to the community.

Feeling the Pain

I could read all kinds of blogs about where not to apply CQRS & Event Sourcing, but I need to feel the pain first hand to really understand where it’s best used.

I needed to apply the concepts I read about in a meaningful project.

For me a meaningful project was a side-project I worked on after hours at home that was large enough in scale that wasn’t incredibly trivial.

The learning experience of failure (and success) gave me greater insights and a deeper understanding to the words I’ve previously read from others discussing CQRS & Event Sourcing.

Practice

Start using CQRS and Event Sourcing in a project that is meaningful to you.  Obviously, I’m not recommending it in a project at work.  Do it in on a project where you can fail.  Feel the pain of applying these concepts where they don’t provide enough value or are cumbersome (hint: CRUD).

With real practice, your understanding matures and not everything will look like a nail with your shiny new hammer.

Bounded Context and Subdomains

CarpetIn a previous blog, I discussed how I recently discovered through eventual consistency that I had poor business alignment.  With more thoughts and insights, I wanted to extend that post by discussion bounded contexts and how they fit within subdomains.

1 to 1?

I’ve often thought of a bounded context as being a one-to-one relationship with a subdomain.   To take that further, you may get the impression that they are indeed the same thing.  When I was first introduced to the concept many years ago, I was under the impression that they mapped directly one to one.

I’m not entirely sure why I had this perception early on.  It may be due examples or just the assumption I made.  I do not remember actually ever reading how a subdomain and a bounded context don’t map directly one to one.

Over the years I’ve realized this not to be the case, but always had a tough time giving an explanation that others could visualize.

I heard Eric Evans gave a great example that I will paraphrase, which should help you visualize the difference.

Living Room Floor

Imagine a room in your house.  It may have a closet or some different length walls which makes it not totally uniform.  Imagine there is carpet in this room.  The carpet covers every inch of the floor.  Wall to wall carpet.

This carpet represents your bounded context.

Underneath the carpet, say the cement, is your subdomain.

By Design

It just so happens that your bounded context is mapped to your subdomain exactly.  However, that is just because the bounded context (carpet) was designed that way.

A bounded context doesn’t necessarily need to cover the entire subdomain.  It only needs to cover the aspects of the subdomain which help solve the problem space.

To use the carpet analogy again, I mentioned that the room wasn’t completely uniform as maybe it had a closet in it.  The carpet doesn’t need to cover the entire floor beneath it.  There may be bare floor exposed in the closet because that portion of the subdomain doesn’t require to be modeled as it isn’t needed for problem you are trying to solve.

More Than One?

I’m still trying to determine if a subdomain can have more than one bounded context.  I do think it may be possible if you are implementing something technical apart of that subdomain.  I would love to hear others thoughts on this.

Eventual Consistency and Business Alignment

mapI recently discovered through eventual consistency that my bounded contexts were not properly aligned with the business.   I won’t lie, it took me quite a while to make this realization.

This was most likely the case in many situations I’ve had in the past.  Because of this realization, I wanted to let out some of my thoughts about eventual consistency and business alignment.

Dependent Bounded Context

I’ve often encounter situations where a bounded context requires information that another bounded context is responsible for.  I’d like to use a simple example I’ve heard from Udi Dahan.  In the context of an Ecommerce site.

  • A customer can be a defined as a “preferred” customer.
  • Preferred customers receive a 10% discount on all orders.

Based on the above, the “preferred” flag and any business rules associated to it, most likely exists in some sort of the CRM bounded context.  However, this detail is required in the Sales bounded context in order to apply a discount if eligible.

As you can see, there is information that needs to be shared between bounded contexts.

Publish / Subscribe Domain Events

One approach for decoupling your bounded context is to publish domain events from your domain model.  This allows other bounded contexts to subscribe to those events and handle them accordingly.

Let’s use our example above to see how this would be implemented.  In our CRM bounded context, when a customer is defined as preferred in our domain model, we would publish a CustomerIsPreferred event.

class CustomerIsPreferred
{
	public Guid CustomerId { get; private set; }
	public DateTime Date { get; private set; }
	
	public CustomerIsPreferred(Guid customerId, DateTime date)
	{
		CustomerId = customerId;
		Date = date;
	}
}

In our Sales bounded context, we would subscribe to this event and update our customer model with a preferred flag. This piece of information is used as a local cache in our Sales bounded context.

During our checkout process in Sales, we would then use the preferred flag on the concept of a customer in Sales to determine if they should receive a 10% discount.

However, remember that this preferred flag is not owned by Sales.

Because of the publish / subscribe model (assuming asynchronicity), at any given time, our preferred flag in Sales could be out of sync with current state in our CRM bounded context. Eventually consistency doesn’t mean our data is wrong, it just means it is stale.

Business Alignment

There are many situations where data being eventually consistent is totally acceptable.  I’ve found in the real world we often make decisions with stale data all the time.

However, there are times where full consistency is required.  When describing the example above to the business, does the eventual consistency of the preferred flag have true business impact?  If it truly does matter and the data must be fully consistent, then you may have bad business alignment with your bounded contexts.

Re-evaluate your bounded context and the boundaries as you may have an wrong interpretation of responsibilities.

I’ve found that drawing a context map and the events which are published and subscribed with a domain expert should flush out any of these incorrect interpretations and help you re-align boundaries and responsibilities.