Command-Query Separation and Immutable Builders

In one of my previous posts about Command-Query Separation (CQS) and side effecting functions being code smells, it was pointed out to me again about immutable builders.  For the most part, this has been one area of CQS that I've been willing to let break.  I've been following Martin Fowler's advice on method chaining and it has worked quite well.  But, revisiting an item like this never hurts.  Immutability is something you'll see me harping on time and time again now and in the future.  The standard rules I usually do is immutable and side effect free when you can, mutable state where you must.  I like the opt-in mutability of functional languages such as F# which I'll cover at some point in the near future instead of the opt-out mutability of imperative/OO languages such as C#.

Typical Builders

The idea of the standard builder is pretty prevalent in most applications we see today with fluent interfaces.  Take for example most Inversion of Control (IoC) containers when registering types and so on:

UnityContainer container = new UnityContainer();
container
    .RegisterType<ILogger, DebugLogger>("logger.Debug")
    .RegisterType<ICustomerRepository, CustomerRepository>();

Let's take a naive medical claims processing system and building up and aggregate root of a claim.  This claim contains such things as the claim information, the lines, the provider, recipient and so on.  This is a brief sample and not meant to be the real thing, but just a quick example.  After all, I'm missing things such as eligibility and so on.

    public class Claim
    {
        public string ClaimId { get; set; }  
        public DateTime ClaimDate { get; set; }
        public List<ClaimLine> ClaimLines { get; set; }
        public Recipient ClaimRecipient { get; set; }
        public Provider ClaimProvider { get; set; }
    }

    public class ClaimLine
    {
        public int ClaimLineId { get; set; }
        public string ClaimCode { get; set; }
        public double Quantity { get; set; }
    }

    public class Recipient