This project is read-only.

Command handlers dependent on command handlers... anti-pattern?

Jan 24, 2015 at 9:50 PM
I am using the command pattern in my application. In one of my commands I need to create a tenant AND also create a new user. To achieve this I pass the IHandleCommand for creating a user as a dependency. I'm almost positive I've done this sort of thing before, but I'm having behavior I don't remember having before. When I pass the "other" handler in as a dependency it is ALSO wrapped with all my decorators, which is causing a pain because my UnitOfWork Decorator is marking my transaction complete twice. I'm sure in the past I've not had this issue. Here is how I register my commandhandlers
        //regsiter all the command handlers
        container.RegisterManyForOpenGeneric(typeof(IHandleCommandAsync<>),
            AppDomain.CurrentDomain.GetAssemblies());

        //Register decorators - order is important.
        //register the validation decorator
        container.RegisterDecorator(
            typeof(IHandleCommandAsync<>),
            typeof(ValidationCommandHandlerDecorator<>));

        //register the Unit of Work decorator that commits changes to Raven
        container.RegisterDecorator(
            typeof(IHandleCommandAsync<>),
            typeof(UnitOfWorkCommandHandlerDecorator<>));

        //regsiter the decorator that logs total time
        container.RegisterDecorator(
            typeof(IHandleCommandAsync<>),
            typeof(TotalTimeCommandHandlerDecorator<>));
I'm using 2.6.1.0 of SI.
Coordinator
Jan 25, 2015 at 10:42 AM
I wouldn't call it an anti-pattern per se, but it depends on how you view the role of the IHandleCommand<T> interface.

My view on the matter is that a command describes a business transaction; an atomic operation. In this view it doesn't make sense to let command handlers execute other commands, because that would mean that one command in itself is not atomic; it is part of a bigger transaction. Seeing a command as atomic, results in the IHandleCommand<T> interface becoming a thin layer that connects the business layer with the outside world. It defines the boundary of atomicy and the join point to add cross cutting concerns.

Viewing commands as atomic business operations, makes it much easier to apply cross-cutting concerns, because -as you already noticed- you don't have to handle cross-cutting concerns being applied multiple times within the dependency graph. This however does mean that shared logic needs to be extracted out of a command handler into a conventional service, so it can be called by two command handlers, without causing this layered approach.

This however is my view on this subject. Others see the command as a use case. In UML modelling it is quite natural to build uses cases from smaller (sub) use cases. In this view, it is natural to combine command handlers. Consequence of course is that it becomes much harder to conditionally apply cross-cutting concerns. Many of the cross-cutting concerns for your command handlers only make sense on the boundary; the outer-most command handler. So those decorators need to contain a check to verify whether they are the outer-most and whether they need to be applied. Or you can find a way to register a decorator conditionally by detecting whether or not it is the outer-most decorator in the dependency graph. This however is very complicated to do. Or at least, I'm not sure how to do this reliably in Simple Injector.

In this view, it makes much more sense to see the IHandleCommand<T> interface as an implementation detail and let the outside world communicate with some sort of mediator instead. This mediator becomes the new join point and you can apply the cross-cutting concerns at that point.

So which model you pick, is up
Coordinator
Jan 25, 2015 at 12:40 PM
Edited Jan 25, 2015 at 12:46 PM
Personally I use multiple ICommandHandlers in each business process (aka unit of work) as I like my injected code at a more granular level. One or more ICommandHandler's are injected into an outermost Mediator type abstraction that governs the overarching unit of work, while any number of subscribing side effects (ISubscribers<>'s) can also make use of ICommandHandler's during the processing pipeline.

You have to make a choice as to the abstraction that defines each isolated unit of work and once you have made that choice you should not stray from it. Either the ICommandHandler defines a single, committable unit of work or it doesn't. And if it doesn't then you'll need another abstraction to act as the wrapper for the unit of work.

Assuming you have a Mediator in place you can then confidently wrap all your ICommandHandler's with common aspects that can exist multiple times in the object graph. Likewise you can wrap the Mediator's with code that should only run once either before or after the unit of work (things such as the commit unit of work decorator)
Jan 26, 2015 at 1:35 PM
Thanks guys. I obviously did not notice until this new project that my commands were doubly decorated but it makes sense of course. I think using the mediator makes for a better pattern if command reuse was my goal. In this particular app, I only have one such example and the code is pretty simple so I think I'll skip the reuse and just abstract the code into a service. But... Mediator is a good pattern and I should have thought of it before. Thanks for the help!