Sunday, January 20, 2013

Separating command data from logic and sending it on a bus

In my first post on this topic, I started out with an attempt to limit abstractions to solely commands and queries. Commands and queries were self-contained and could be invoked by passing them to a context-providing generic handler. The drawback of this approach was that it made constructor dependency injection impossible. In a next post, I separated data from logic, but never got around to writing a dispatcher that associates command data with their handlers. Last week, I revisited the first approach, and added an unconventional implementation of injecting dependencies by an Inject method convention.

I still believe that last approach is very simple and works fine if extra dependencies are exceptional. I do admit that it will make architectural shoots harder to handle; everything is rather tightly coupled. So let's look at an alternative architecture which pulls all the bits apart, and should be better equipped to handle change.

Let's first separate command data from logic.
public class CreateSubscriptionCommand 
{     
    public CreateSubscriptionCommand(string value, string category, string emailAddress)
    {
        Guard.StringIsNullOrEmpty(value, "value");
        Guard.StringIsNullOrEmpty(category, "category");
        Guard.StringIsNullOrEmpty(emailAddress, "emailAddress");

        Value = value;
        Category = category;
        EmailAddress = emailAddress;
    }

    public string Value { get; private set; }

    public string Category { get; private set; }

    public string EmailAddress { get; private set; }

    public override bool Equals(Object other)
    {
        if (other == null)
            return false;

        var otherCommand = other as CreateSubscriptionCommand;
        if (otherCommand == null)
            return false;

        return otherCommand.Value == Value && 
            otherCommand.Category == Category && 
            otherCommand.EmailAddress == EmailAddress;
    }    

    public override int GetHashCode()
    {
        return Value.GetHashCode() ^ 
            Category.GetHashCode() ^ 
            EmailAddress.GetHashCode();
    }
}
The data is just a POCO. Notice the equality overrides; this comes in handy when you're testing.

The class that handles on the data needs to implement the ICommandHandler interface.
public class CreateSubscriptionCommandHandler 
    : ICommandHandler<CreateSubscriptionCommand>
{    
    private IDocumentSession _session;

    public CreateSubscriptionCommandHandler(IDocumentSession session)
    {
        _session = session;
    }

    public void Handle(CreateSubscriptionCommand command)
    {
        var subscription = new Documents.Subscription(
            command.Value, command.Category, command.EmailAddress);

        _session.Store(subscription);    
    }
}
Compared to the previous approach, we're now injecting the session instead of having it handy as a property; that coupling is now completely gone.

Last thing left to do is create an interface that consumers can use to send commands on: a bus.
public class Bus : IBus
{
    private readonly IKernel _kernel;
    private readonly IDocumentSession _session;

    public Bus(IKernel kernel, IDocumentSession session)
    {
        _kernel = kernel;
        _session = session;
    }

    public void ExecuteCommand<T>(T command) where T : class
    {
        var handler = _kernel.Get<ICommandHandler<T>>();

        handler.Handle(command);

        _session.SaveChanges();
    }
}
The ExecuteCommand method dispatches data to the correct handler by resolving it from the container, and also commits the unit of work.

The consumer can execute commands like this.
bus.ExecuteCommand(
    new CreateQueryCommand(queryValue, category, emailAddress));
With this approach having all the bits spread, we have a bit more work gluing all the pieces together. The session is now known in the container, and is request scoped. The commandhandlers are also all registered in the container.
protected override void ConfigureRequestContainer(IKernel container, NancyContext context)
{        
        // you don't want to register them all individually
        container
            .Bind<ICommandHandler<CreateSubscriptionCommand>>()
            .To<CreateSubscriptionCommandHandler>();        
        // snip..
        container.Bind<IDocumentSession>()
            .ToMethod((ctx) => { 
                return ctx.Kernel.Get<IDocumentStore>().OpenSession();    
            })
            .InSingletonScope();                          
}

I think this approach might suit a lot of projects better if your commands are dependency heavy.
What I like most is that handling architectural shoots will be easier. For example: right now, all behaviour is in my entities and in my commands; the segregation of application services and domain services is non-existent. And this works fine so far; I yet have to find a use case where I would benefit from more separation. If that would change in the future though, I can introduce abstractions, and concepts, without breaking consumer code, and without having to do awkward stuff managing the newly introduced dependencies.

As always, your thoughts are appreciated.

10 comments:

  1. I like this implementation more than the one with the 'magic' dependencyresolver. But I learned a lot from the comments in the previous version :)

    How do you feel about commands that need to return a value when executed? (eg the id of an entity you just created so you can redirect to it)

    ReplyDelete
    Replies
    1. You could use a GUID for that.

      Delete
    2. I've recently had a interesting discussion with some co-workers about that. To summarize it, you could:
      - Use a GUID but database administrators won't like that because of the indexing performance (even with sequential GUIDs yes).
      - Use the NHibernate HiLo generator.
      - Use an alternate key (just don't use anything that's functional because this can screw you over later). The alternate key would only be used once and from then of on you would use the real object key.

      Delete
  2. Do you still use "Service" class? Every command has its own CommandHandler? It might to too "complicate" because real time application might be end up with dozens of commands similar as "CreateSubscriptionCommand". Where you put the Query object? How query associated with command and command handler?

    Thanks,

    ReplyDelete
    Replies
    1. I don't use service classes anymore; all of that logic is the handlers. You can still group multiple ICommandHandlers in one class if you like that, good namespacing can take you a long way too though.

      Query and commands are not associated. I do have an ExecuteQuery method on my bus.

      Delete
  3. Pretty much my standard architecture nowadays. Lowers my cognitive overhead since i generally only have Commands, Events and Queries in my system. I do have services, but generally infrastructural or wrapping commands and queries for remote execution (ServiceStack in my case)

    ReplyDelete
  4. I just discovered your blog, and it's great and very helpful! Great post in particular, thanks !

    I did experiment with a similar way of structuring things, only not exactly working with strictly separated "Commands" (does not return anything) and "Queries" (does not change anything), because we actually expect a result from the Commands ...
    We have "Requests" that are similar to your "Commands", except that they implement an empty "marker interface" : IRequest , which gives information about the "Response" return type of executing the request.

    In client code (for instance in an MVC controller), you can just create an instance of a request and pass it to a "RequestDispatcher" (similar to your CommandHandler):

    var request = new CapitalizeRequest("bidule");
    var response = dispatcher.Execute(request);

    and we get strongly-type result !

    What the "RequestDispatcher" does is to look inside our IoC container (in our case, Unity) if it finds any implementation of interface IExecutableServiceIExecutableService defined as :

    public interface IExecutableService
    {
    TResponse Execute(TRequest request);
    }

    ... and call that service with the request and return the Response.

    In our case, the implementations of IExecutableService are responsible for committing the changes of the Unit Of Work.
    We also have an Async version : IAsyncExecutableService and corresponding Async version of RequestDispatcher : IAsyncRequestDispatcher

    It is not quite Command-Query Segregation, hence the names Response/Request.

    (if you are curious, I have some code samples in here : https://github.com/tsimbalar/MvcArchiProto ...)

    ReplyDelete
    Replies
    1. Ooops, a few typos in my comment ...

      > and pass it to a "RequestDispatcher" (similar to your CommandHandler)
      actually : "similar to your Bus"

      also, IExecutableService implementations are equivalent to your ICommandHandler implementations...

      Delete
    2. Cool, thanks. Will definitely look at the project this week.

      Delete