Explore DDD 2017 Review

I just returned from Denver, Colorado, where the first Explore DDD conference was held.  I originally heard about it earlier in the year on Twitter via the organizer Paul Rayner and decided to submit a couple abstracts for the CFP.

Fat Controller CQRS Diet

The talk that was accepted and which I delivered on Friday morning was my Fat Controller CQRS Diet talk.  The talk revolves around trying to decouple your application from top I/O layer or framework.  More info on the talk can be found in my series of blog posts as well as a episode of Software Engineering Daily podcast.

Domain Driven Design

I stumbled upon Domain Driven Design somewhere around 2010.  I actually found it because of watching a talk online from Greg Young making some indirect references to Domain Driven Design and CQRS.  The talk caught my interest and within no time I was captivated by DDD and CQRS.  I instantly went and purchased the book.  That was a very significant point in my software development career.

Explore DDD

The speaker lineup at this conference was simply incredible.  Eric Evans, Rebecca Wirfs-Brock and Ward Cunningham were the keynotes.  Crazy.

I cannot really believe that I was chosen to speak at such a conference. Imposter Syndrome was maxed out to 11.

It didn’t take too long to have some conversations at the conference to realize that I had different experiences and views that proved to be valuable.  This didn’t knock down the imposter syndrome completely, but definitely lowered it a just a tad.  On the other hand, the amount that I learned from discussions and talks were like no other conference.

Community/Family

This really summed it for me.  There was a real sense of community/family.  I can’t really put my finger on why that is but I have a few guesses.

Conference Space/Location

Incredible.  38th Floor of the Grand Hyatt, looking over downtown Denver.  The floor itself was broken down into 3 track rooms, general gathering room where food was served, as well as a unique blue track room.  The blue track was reserved for spontaneous modeling, discussions, problem solving, whatever.  I actually had several interesting discuss here and it was kind of a good place for the “hallway” track in some respects.

Paul Rayner

The conference kicked off on Wednesday evening with the keynote by Eric Evans.  Paul spoke to intro the conference as well as each day with some house keeping notes.  I felt the way Paul gave such a calm welcoming, really set a tone for the entire conference.

Thank You!

Hands down an awesome conference.   Thank you to Paul for organizing an incredible event and selecting my talk.  All the attendees and speakers (from all over the world!) for making it feel like a family.

I highly recommend attending this next year.  I hope to see you there!

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.