.NET Backend

CQRS/ES #3 Commands and Command Handlers

So far we got acquired with a theory that stands behind the CQRS and Event Sourcing. Moreover, we implemented a (business) heart of our calendar application consisting of a domain objects. Today we are going to reveal next two pieces of our puzzle – Commands and Command Handlers. Once again, I encourage you to share your opinions and suggestions in the comments (if you have any).

 

Commands

So, what exactly the commands are? In short, these objects represent intentions of a user. They are in fact imperatives. For instance: „send an email to John” or „book room 111”. A command for a second example would look like this:

 


public class BookHotelRoomCommand
{
    public Guid Id { get; set; }

    public string UserId { get; set; }

    public int RoomNumber { get; set; }

    public DateTime StartDate { get; set; }

    public DateTime EndDate { get; set; }
}

 

Some of you may ask now if there are any differences between commands and DTOs. After all, both contain only data, and they don’t execute any business logic inside them. Well, that’s correct, but in fact, these two should be used in slightly different scenarios. The DTO is data-centric, which means that it the only thing we care about is data itself. And that is fine for typical CRUD applications consisting of forms for creating, editing and deleting a particular object (entities). On the other hand, commands are behavior-centric. In that approach, we care more about user’s intention which should be realized using the given data. That allows us to create UI in a different way, which might be more comfortable for a user. Okay, let us move to implement a command in our calendar application. We would like to represent the user’s intent of creating a calendar item. Therefore, knowing our database model, we could achieve that using this object:

 



public interface ICommand
{
    Guid Id { get; }
}

public class CreateCalendarItemCommand : ICommand
{
    public Guid Id { get; } = Guid.NewGuid();

    public string UserId { get; set; }

    public string Name { get; set; }

    public string Description { get; set; }

    public DateTime StartDate { get; set; }

    public DateTime EndDate { get; set; }

    public IEnumerable<CalendarItemCycle> Cycles { get; set; }
}

public class CalendarItemCycle
{
    public Guid Id { get; set; }

    public DateTime StartDate { get; set; }

    public DateTime? EndDate { get; set; }

    public CalendarItemCycleType Type { get; set; }

    public int Interval { get; set; }
}


 

Notice that we created an interface called ICommand which contains only Id property. We will use that interface later to build constraints in a couple of places in our code. Having data in our command, we are able to create every kind of the calendar item assumed in our requirements.

 

Command Handlers

So far, so good. We have a command for creating a calendar item. What we need now is a class which based on the passed command will create proper domain object(s) and execute some business logic on it using given data. We need a Command Handler. The implementation of Command Handler for created command is given below:

 


public interface ICommandHandler<in TCommand> where TCommand : class, ICommand
{
    Task HandleAsync(TCommand command);
    void Validate(TCommand command);
}

public class CreateCalendarItemCommandHandler : ICommandHandler<CreateCalendarItemCommand>
{
    IEventStore EventStore { get; }

    public CreateCalendarItemCommandHandler(IEventStore eventStore)
    {
        EventStore = eventStore;
    }

    public async Task HandleAsync(CreateCalendarItemCommand command)
    {
        ((ICommandHandler<CreateCalendarItemCommand>) this).Validate(command);

        var calendarItem = new CalendarItem(command.Id, command.UserId, command.Name,command.Description,command.StartDate,command.EndDate,command.Cycles);
        await EventStore.PersistAsync(calendarItem);
    }

    void ICommandHandler<CreateCalendarItemCommand>.Validate(CreateCalendarItemCommand command)
    {
        if(command == null)
            throw new AwesomeCalendarException(AwesomeCalendarExceptionType.NullCommand, typeof(CreateCalendarItemCommand));

        if(command.Id == Guid.Empty || string.IsNullOrEmpty(command.UserId) || string.IsNullOrEmpty(command.Name) || command.StartDate > command.EndDate)
            throw new AwesomeCalendarException(AwesomeCalendarExceptionType.InvalidCommand, typeof(CreateCalendarItemCommand));
    }
}

 

We can distinguish three steps here:

  • Command validation
  • Creating a CalendarItem Aggregate
  • Saving our Aggregate into Event Store

 

In this case, we didn’t have to execute any Aggregate’s method since user’s intention was only to create a new calendar item. At this point it’s worthwhile asking a few questions such as:

  • How to inform the user of an incorrect command, if the Handle method returns void?
  • What happens inside the CalendarItem after its creation?
  • How does the Persist method save an Aggregate’s state into Event Store?

 

Don’t  worry; everything will be discussed in the following parts of the series. We are just not ready yet 😉

 

Summary

In the next part, we will find out what events are and what they are used for. In addition, we will build Event Store using Entity Framework and we will answer today’s questions. However, if you are impatient (like me), go check out github of our calendar application which contains the whole project (not completed yet). As always, I encourage you to follow me on Twitter or leave a like on Facebook just to be up to date with my next posts.