CRUD Do Better

Recently I've been learning about some new and exciting ways to write better software.

Often we need to experience a bit of pain before we start questioning the approach we take to developing applications. For me this came when I created my first application for Windows Azure. Aside from the added complexity that cloud computing can bring, I also started to find that the "traditional" methods of development introduced a lot of friction into my codebase and overall made me quite unhappy with my design.

I expect many developers have been in a similar position.

So at this point you go off looking for answers. Perhaps someone has suggested using a message based architecture, throwing around terms like "Service Bus", "Pub Sub" and "DDD". Before you know it you hear about CQRS, and you're lost in a sea of technical terms you never knew existed in software development.

Furthermore (if you're like me) you'll read up on each of these concepts and find out that what you've spent the last few years doing is completely wrong. You'll get excited by this "new" approach to software development and realize what you've been missing - kicking yourself for not learning about it sooner.

Then you'll read several blog posts telling that you shouldn't use any of the above for your "simple" applications. It's all very confusing.

The problem is that for N-Tier folks there doesn't seem to be a happy medium. Everyone has a different take on when to use X,Y,Z and there seems to be no middle ground - you're either a CRUD/N-Tier developer or an all singing, all dancing, CQRS guy.

What I found however, is that there are parts of CQRS that work just as well in CRUD applications. Things like messaging and Event Driven Architecture. These patterns are not specific to CQRS and can be used by borderline simpletons like you and I.

In this post (with the long intro - sorry) I want to discuss some of these patterns.

Let's start with something we're used to doing. Here's a simple class:

public class Account {
    public string Name {get;set;}
    public decimal Balance {get;set;}
}

This class doesn't really do anything, it just serves as a container for information. This is likely what you are used to writing, mapping it to a similarly structured table in a database using some kind of ORM.

Let's look at how we create an account:

public ActionResult Create(CreateAccountModel model) {
    var account = new Account {
        Name = model.Name,
        Balance = model.Balance
    };

    accountService.Create(account);
    // return
}

Pretty simple. In our MVC controller we "new up" an Account instance, set some properties and hand it over to our "service" to save to our database.

Let's look at that service method:

public void Create(Account account) {
    repo.Save(account);
}

As you can see, completely...pointless. All we've done is provide a wrapper around our repository methods that do exactly the same thing. Why do we do this? Well it's that N-Tier thing - We gotta have those 3 layers - UI, Business, Data Access.

Things get worse when we look at updating an account:

public ActionResult Create(UpdateAccountModel model) {
    var account = accountService.GetById(model.Id);
    account.Balance = model.Balance;
    // return
}

We load our account, set some properties and that's it. But why haven't we explicitly "Saved" our account. Well we don't need to. Our fancy ORM is tracking those objects and we're doing something called "Session-Per-Request" meaning any changes to our entity are saved at the end of the request.

Now if you read back through the last couple of paragraphs you'll see our intentions are quite vague. We're setting "some" properties and our ORM will save "any" changes. This also makes it quite hard to debug problems since we could be modifying our entities in many different places.

The first pattern we can introduce here is Commanding. We create explicit commands to update our model. This makes our code more readable and easier to maintain. It also means we're moving the "logic" out of our ASP.NET MVC controllers into classes that could be reused by any client. Finally we can get rid of those good-for-nothing-repository-wrapper services.

Here's a command:

public class OpenAccountCommand : ICommand {
    public string AccountName { get; set; }
    public decimal InitialBalance { get; set; }
}

As you can see, there's not much to it. It's just a message after all. Look at the name of the command. It's clear what this command is asking.

The work of actually executing the command is done by a "Command Executor". Here's our OpenAccountCommandExecutor:

public class OpenAccountCommandExecutor : ICommandExecutor<OpenAccountCommand>
{       
    public void Execute(OpenAccountCommand command)
    {          
        if (command.InitialBalance <= 0)
        {
            throw new InvalidOperationException(
                "Cannot open an account with a negative balance");
        }

        var account = new Account(command.AccountName, command.InitialBalance);

        // save account
        repo.Save(account);
    }
}

Note that a Command should have only one Executor

Essentially this achieves the same as our original "Create" action result but this time we are being much more explicit. We're also creating the account in a slightly different way:

public class Account
{
    public string Name { get; private set; }
    public decimal Balance { get; private set; }

    public Account(string name, decimal initialBalance)
    {
        Name = name;
        Balance = initialBalance;
    }
}

Our entity is now responsible for maintaining it's own state (see those private setters) which is the DDD approach, and has benefits even in a CRUD application.

Before I discuss how we actually send commands I'll discuss the next subject - Event Based Architecture. Udi Dahan provides more detail here but the short version is that we publish events in response to changes in our domain model. Parties can then subscribe to the events that they are interested in.

Let's back this up with an example. We'll revisit that awesome "service" we had earlier because we've been told we need to log each new account that is created. Simple, we'll just add to our service:

public void Save(Account account) {
    repo.Save(account);

    // log it
    logger.Log("Account {0} with balance {1} was opened",
        account.Name, account.Balance);
}

Great, job done.

A few weeks later our application starts suffering from poor performance. So let's throw caching at it (cause that's how we solve everything :p). Only thing is, we need to make sure we clear the cache if a new account is added. No problem, we'll just add to our service:

public void Save(Account account) {
    repo.Save(account);

    // log it
    logger.Log("Account {0} with balance {1} was opened",
        account.Name, account.Balance);

    // clear the cache
    cache.Invalidate("accounts");
}

Hopefully you'll seeing the problem here. Could you honestly tell what the "Save" method did without looking at the code?

Now lets compare it to the following class:

public class LogWhenAccountIsOpened : IHandleEvents<AccountOpenedEvent> { }

Can you tell what this class does without looking at the code. I'm hoping the answer is "yes, I can see it logs when an account is opened" :)

Similarly to command based systems, an event based design follows the Single Responsibility Principle and makes our code much more explicit.

An event is just a simple message and an event handler, "handles" that event. An event may have 0 or more handlers:

public class AccountOpenedEvent : IEvent
{
    public string AccountName { get; set; }
    public decimal InitialBalance { get; set; }
}

public class LogWhenAccountIsOpened : IHandleEvents<AccountOpenedEvent> 
{ 
    public void Handle(AccountOpenedEvent @event) {
        logger.Log("Account {0} with balance {1} was opened",
            account.Name, account.Balance);
    }
}

As these are "domain" events, they are raised by the "domain". The updated Account entity is as follows:

public class Account
{
    public string Name { get; private set; }
    public decimal Balance { get; private set; }

    public Account(string name, decimal initialBalance)
    {
        var @event = 
            new AccountOpenedEvent { 
                AccountName = name, InitialBalance = initialBalance 
            };

        OnAccountOpened(@event);
        DomainEvents.Raise(@event);
    }

    protected void SetBalance(decimal balance) {
        Balance = balance;
    }

    // events
    public void OnAccountOpened(AccountOpenedEvent @event) {
        Name = @event.AccountName;
        SetBalance(@event.InitialBalance);
    }
}

You can see in the constructor that we create a new event and call DomainEvents.Raise passing the event. We also use the same event to update our internal state.

Connecting it all together

The component that handles the sending of commands and publishing of events (generally, messages) is a Message Bus (or Service Bus).

In almost all cases you will want to use a durable message bus so that messages are not lost if one of your endpoints is down. The most popular Service Bus for .NET, NServiceBus, uses MSMQ as it's transport mechanism.

As a learning exercise I found it useful to create my own simple message bus. Here I just use StructureMap to do most of the work:

public interface ICommandBus {
    void Send<TCommand>(TCommand command) where TCommand : ICommand;
}

public interface IEventBus {
    void Publish<TEvent>(TEvent @event) where TEvent : IEvent;
}

public class DefaultBus : ICommandBus, IEventBus
{
    public void Send<TCommand>(TCommand command) where TCommand : ICommand {
        ObjectFactory.GetInstance<ICommandExecutor<TCommand>>().Execute(command);           
    }

    public void Publish<TEvent>(TEvent @event) where TEvent : IEvent {
        foreach (var handler in ObjectFactory.GetAllInstance<IHandleEvents<TEvent>>()) {
            handler.Handle(@event);
        }
    }
}

Obviously NServiceBus does much more than this, providing asynchronous processing, fault tolerance and scalability, but the general concept is the same, we are routing commands to executors and events to handlers.

Hopefully you can see from this that there are plenty of improvements you can make to an application without completely throwing away your existing design.

I've put together an example aptly named "CRUDDoBetter" that you can download here. Thanks to Yves Goeleven who has helped me out with loads of questions I've had on twitter.

As always, comments are welcome, especially if I've got something wrong.


Ben Foster

About Me

I'm a software engineer and aspiring entrepreneur with 12+ years experience in the tech industry and have worked with startups and SMB’s in areas such as healthcare, recruitment and e-commerce (I even worked in enterprise, once). I founded my first startup Fabrik in 2011.

I now head up the engineering team at Checkout.com. If you're interested in working in an exciting fin-tech company, drop me a message on Twitter.

Creative Commons Licence