Sunday, May 12, 2013

CQRS Simplified - Part 2 (Commands & Command Handlers)


Every imperative operation in the system represents a command in CQRS. A Command is simply a DTO-type of object that contains the data necessary to make one specific change to the state of the system. The service method that accepts a command does not returns any values. In case of WCF services, if the command execution failed, a fault contract exception is thrown. The method that accepts the command is responsible for validating the command via a command validator object (remember SRP :)) before passing it to a handler object to execute the command.

Below is an example of a DTO that encapsulates the command information in our sample. Note that the commands have an Identity object in our sample.
public class RespondToRsvpCommand : ICommand
{
    public Guid RsvpReferenceId { get; set; }
    public bool Response { get; set; }


    public override string ToString()
    {
        return "Respond to RSVP";
    }
}

The command handlers are responsible for executing the commands. You can normally group commands to an aggregate in a command handler as given below.

public class RsvpCommandHandler : ICommandHandler<RespondToRsvpCommand>, ICommandHandler<ConfigureRsvpCommand>,
                                    IDependencyResolver
{
    [InjectionConstructor]
    public RsvpCommandHandler()
    {
        ResolveDependencies();
    }

    private ICommandValidator<RespondToRsvpCommand> RespondToRsvpCommandValidator { get; set; }

    private ICommandValidator<ConfigureRsvpCommand> ConfigureRsvpCommandValidator { get; set; }

    public void Process(RespondToRsvpCommand command)
    {
        //RSVP processing logic goes here
    }

    public bool Validate(ConfigureRsvpCommand command)
    {
        return true;
    }

    public void Process(ConfigureRsvpCommand command)
    {
        //throw new NotImplementedException();
    }

    public bool IsValid(RespondToRsvpCommand command)
    {
        return RespondToRsvpCommandValidator.Validate(command);
    }

    public bool IsValid(ConfigureRsvpCommand command)
    {
        return ConfigureRsvpCommandValidator.Validate(command);
    }

    public void ResolveDependencies()
    {
        RespondToRsvpCommandValidator = Container.Current.Resolve<ICommandValidator<RespondToRsvpCommand>>();
        ConfigureRsvpCommandValidator = Container.Current.Resolve<ICommandValidator<ConfigureRsvpCommand>>();
    }
}

As you can see, I've used the ICommandValidator instances to validate the respective commands in the context. I've also used the unity dependency container as my dispatcher object to dispatch the respective command handlers.

Next : Events

No comments: