Mediator Pattern using MediatR and Unity

MediatRIn a couple previous posts I’ve discussed using Query Objects instead of Repositories and the Mediator pattern.  I find creating query objects being used with the command pattern much cleaner than polluting repositories with a ton of query methods.

The concept is nothing new as many people already use the command pattern in the context of executing commands/behavior following CQRS.   However, there is nothing wrong with using the same patterns for the query side.

I’ve been using my own home grown solution of the mediator pattern in a few different projects but had nothing really formalized.  I was thinking about creating a simple library until I stumbled upon MediatR created by Jimmy Bogard.

It is incredibly simple and only has one dependency, CommonServiceLocator.

The Github repo has a good set of docs and some examples with different dependency injection containers.

Unity RegisterType

I did notice the Unity example didn’t quiet work as described in the example.

The Mediator class takes a ServiceLocatorProvider in its constructor which was not being resolved properly by Unity.

In order to get it functioning correctly, I defined an injection factory and created the Mediator and passed in the UnityServiceLocator.

My complete Unity configuration which is also using MediatR to publish events from NEventStore:

MediatR v2.0

Although v1 has a dependency on CommonServiceLocator, it appears that v2.0 will not have any external dependencies.

MediatR

 

 

Domain Driven Design: “What” not “How”

Common LanguageMany years have past since Eric Evans release the blue book: Domain Driven Design.  A lot has changed over the years but I find the core ideas still hold very true.

In some ways, I think some of the concepts outlined are even more prevalent now than they have ever been.

Ubiquitous Language

The Ubiquitous Language is a shared language developed by the team.  The team is everyone working on the project: developers, domain experts, QA, BA.

Everyone on the team.

The ubiquitous language isn’t developed by the domain expert(s) alone.  If you have more than one domain expert, they may struggle with language between each other to define concepts.

Everyone apart of the team is building, growing and refining the language.

Language is critical to not only verbal communication but how it’s represented in the software we are writing.  It represents the concepts and terms specific to the core business domain we are trying to model.

All the expressions, nouns and verbs are what the team is formally defining with an ubiquitous language.

Bounded Context

Boundaries

One of my favorite concepts is of the bounded context.  Bounded context should be autonomous.

Meaning, a bounded context should be independent and self governing.

It defines a set of business capabilities within the domain and represents a conceptual boundary.

One way of determining where the boundaries lie is with the ubiquitous language.

If a term or phrase has a different meaning in another context, you may have discovered a boundary and therefor another bounded context.

“What”, not “How”

With the rise/hype of microservices, the concept of a bounded context continues to hold true.

How do functional languages impact domain driven design?  As I’m leaning F#, I’m not overly concerned about the “how”.

The important part modeling a domain for me is the verbs, not the state.  I do think that will translate well to a functional language.

Focusing on the what not the how is what makes Domain Driven Design still very important and applicable so many years later.

 

Clean up your Domain Model with Event Sourcing

Vacuum cleaner - Workers collectionI recently had a discussion with a developer who was new to Domain Driven Design, CQRS and Event Sourcing.  They were using Greg Young’s Simple CQRS Example to create there own simple app as learning exercise.

After taking a quick look at their aggregate root, one thing that immediately stood out to me was a class field that contained current state.  Why this is interesting is because this field was not in any invariant.

When I first started reading and exploring Event Sourcing, this was a big “ah ha!” moment for me.

The realization that only certain data within my domain model was really important.

We will use a simple shopping cart example.

First, lets look at what our shopping cart would look like without being event sourced. We would be probably persisting this to a relational database using an ORM or perhaps storing it in a NoSQL document store.

public class ShoppingCart
{
    public Guid Id { get; set; }
    public IList<ShoppingCartLineItem> LineItems { get; set; }
    public bool IsComplete { get; set; }
    public DateTime CompleteDate { get; set; }

    public ShoppingCart(Guid id)
    {
        Id = id;
        LineItems = new List<ShoppingCartLineItem>();
    }

    public void AddProduct(string productSku, int quantity)
    {
        if (string.IsNullOrEmpty(productSku)) throw new ArgumentException("productSku");
        if (quantity <= 0) throw new ArgumentException("quantity");

        LineItems.Add(new ShoppingCartLineItem(productSku, quantity));
    }

    public void Complete()
    {
        if (IsComplete) throw new InvalidOperationException("Already completed.");
        if (LineItems.Any() == false) throw new InvalidOperationException("Cannot complete with no products.");

        IsComplete = true;
        CompleteDate = DateTime.UtcNow;
    }
}

There are a few things to point out in the above code.

Take note of the public properties which represent our current state.  These are the pieces of data that we be persisted to data storage.

Notice we have a IList<ShoppingCartLineItem> which is our collection of products that are in our shopping cart.  The ShoppingCartLineItem class contains the Product SKU and the quantity ordered.

One invariant in this example to mention is in the Complete() method.  There must be at least one product added to the shopping cart in order to mark it as complete.

if (LineItems.Any() == false) throw new InvalidOperationException("Cannot complete with no products.");

Next, let’s implement the above with event sourcing.

public class ShoppingCart : AggregateRoot
{
    private Guid _id;
    private bool _completed;
    private DateTime _completedDate;
    private readonly IList _lineItems;
 
    public override Guid Id
    {
        get { return _id; }
    }

    private void Apply(ShoppingCartCreated e)
    {
        _id = e.Id;
    }

    private void Apply(ProductAdded e)
    {
        _lineItems.Add(new ShoppingCartLineItem(e.ProductSku, e.Quantity));
    }

    private void Apply(Completed e)
    {
        _completed = true;
        _completedDate = e.DateCompleted;
    }

    public ShoppingCart(Guid id)
    {
        _lineItems = new List();

        ApplyChange(new ShoppingCartCreated(id));
    }

    public void AddProduct(string productSku, int quantity)
    {
        if (string.IsNullOrEmpty(productSku)) throw new ArgumentException("productSku");
        if (quantity <= 0) throw new ArgumentException("quantity");

        ApplyChange(new ProductAdded(_id, productSku, quantity));
    }

    public void Complete()
    {
        if (_completed) throw new InvalidOperationException("Already completed.");
        if (_lineItems.Any() == false) throw new InvalidOperationException("Cannot complete with no products.");

        ApplyChange(new Completed(_id, DateTime.UtcNow));
    }
}

In our event sourced implementation above we still are holding current state in the same fashion as our non event sourced version.  I’ve changed them from public properties to private fields since they are not being persisted to data storage.  Instead our events raised through ApplyChange() are what are persisted to data storage.

The example above is typical of a first implementation of event sourcing.  We are taking the concept we know and use of persisting current state along with this new idea of using events as state transitions.

There is actually a lot of code that can be removed from our event sourced example above.

ShoppingCartLineItem class is no longer needed because the data it encapsulates is now encapsulated in our ProductAdded event.  So if we delete that class, then we have the issue with:

private readonly IList<ShoppingCartLineItem> _lineItems;

This private member will no longer be valid since we just deleted the ShoppingCartLineItem class.  So we can remove this private member as well.

Now let’s go back to that invariant that we have:

if (_lineItems.Any() == false) throw new InvalidOperationException("Cannot complete with no products.");

How can we maintain this invariant since we are no longer keep track of the line items?

You only need the data applicable to an invariant

Because of this, we don’t really care what products or quantities are on the shopping cart, just that there is at least one.

Any data that is not used by an invariant does not need to be in your aggregate.

private DateTime _completedDate;

We also no longer need the date the shopping cart was completed because it is not used by an invariant and it is also contained in the Completed event.

Now let’s take a look at our shopping cart with these ideas applied:

public class ShoppingCart : AggregateRoot
{
    private Guid _id;
    private bool _containsProducts;
    private bool _completed;

    public override Guid Id
    {
        get { return _id; }
    }

    private void Apply(ShoppingCartCreated e)
    {
        _id = e.Id;
    }

    private void Apply(ProductAdded e)
    {
        _containsProducts = true;
    }

    private void Apply(Completed e)
    {
        _completed = true;
    }

    public ShoppingCart(Guid id)
    {
        ApplyChange(new ShoppingCartCreated(id));
    }

    public void AddProduct(string productSku, int quantity)
    {
        if (string.IsNullOrEmpty(productSku)) throw new ArgumentException("productSku");
        if (quantity <= 0) throw new ArgumentException("quantity");

        ApplyChange(new ProductAdded(_id, productSku, quantity));
    }

    public void Complete()
    {
        if (_completed) throw new InvalidOperationException("Already completed.");
        if (_containsProducts == false) throw new InvalidOperationException("Cannot complete with no products.");

        ApplyChange(new Completed(_id, DateTime.UtcNow));
    }
}

The invariant is now based on a boolean set when a product has been added.  The aggregate does not care about what products were added or their quantity.  It doesn’t even need to have them in a collection.

With the implementation of event sourcing in our aggregate, we get a much clearer view of what data drives business logic and is important in our domain model.