Sagas-like DI injection or ICommand/IQuery Pattern

Apr 22, 2013 at 1:57 PM
Hi Steven,
I've been using your blogs that you did on ICommand/IQuery patterns as a guide to develop my domain and facilitate communication between layers.

I've run into where I need to contain a group of command handlers that will perform the following workflow:
  • ValidateEmailCommandHandler
  • EmailCommandHandler (saves to DB that this action was taken by the user)
  • EmailService.Email (if the transaction succeeded, send the email)
This appears to be a saga container. Any suggestions with SimpleInjector or going back to your blog about ICommand/IQuery patterns how this could be restructured or what you've done in your projects.

I have absolutely enjoyed employing your patterns and the way SI simplified orchestrating these patterns, so I'm hoping to continue with your suggestions.
Coordinator
Apr 22, 2013 at 4:17 PM
These classes don't really seem like command handlers to me:
  • The ValidateEmailCommandHandler looks like some validation logic, simply the precondition of the command handler to run. It might be better to give it its own architectural element. For instance, you can define a IValidator<T> abstraction and that validation class can implement IValidator<EmailCommand>.
  • The EmailCommandHandler itself sound like it is reused by multiple other pieces of business logic (called by other command handlers). In my experience it is best not to wrap command handlers in other command handlers. Let a command be atomic. Any reused functionality can be put in a service (such as IMailSender) that you inject into the handlers.
  • Sending mails after a db transaction committed, does sound a bit like a model with Domain Events. Handling (business) events is similar to commands (with a common IEventHandler<TEvent> abstraction), but it would be quite natural to have multiple event handlers handling a single event. In your case you could fire a UserActivatedEvent from within an ActivateUserCommandHandler and this could trigger SendUserActivationMailEventHandler and InformBillingAboutActivatedUserEventHandler classes. I haven't written anything (yet) about Domain Events on my weblog, but perhaps this article is interesting to you. It's hard to say if Domain Events are interesting for your project, but it's worth doing some research on.
Apr 23, 2013 at 8:54 PM
Edited Apr 23, 2013 at 9:05 PM
Thanks Steven,
Definitely have been reading on Domain Events and I believe they would be a nice addition for extra responders (emailing, logging, auditing, etc) to certain domain events.

I've trying to see how I can integrate in a IOC centric way and it looks like if I followed the defacto blog that a lot of these other articles have been based off it seems there is the static class I'll need to have in my concrete implementations.

You provided an answer to this very thing and recommend a possibility of a method injection.
http://stackoverflow.com/questions/13015486/using-ninject-with-udi-dahans-domain-events

Now with my scenario I'm going to provide some more detail as the items seemed a bit misleading now that I look at it:

The scenario I'm working on:

User selects an incident that they want to email. The process for this command requires the following:
  • Perform user authorization (Validation?) that they have access to the incident
  • Create a report (PDF) of this incident
  • Email the report
  • all successful then create a history log that this incident was emailed by this user
  • fail, inform user (permission, service down, generic retry)...
With the pointers to domain events, I am very interested in providing that functionality, so my code work flow would be like so:
  • TransactionDecorator pattern // (you blogged about this, in case anything fails, the data will roll back)
  • ValidatorDecorator pattern // (you blogged about this, with IValidator<IncidentEmailCommand>... this checks for permissions)
  • IncidentEmailCommandHandler.Handle(...) // handles the generating the incident report, so will have IReportService, IEmailService
  • IEmailService.emails and then calls the DomainEvents.
  • IEventHandler<IncidentEmailCommand>.Handle... will handle the logging since at this point everything is assumed as successful.
So, if to integrate domain events capabilities, and somehow avoid the static DomainEvents manager class, any thoughts?

-- edit
Looking at the article you send, it appears he injects his CommandDispatcher or (DomainEvents manager) class into his Domain entity. I might go that route, and set my lifetime scope as singleton with SimpleInjector
Coordinator
Apr 24, 2013 at 9:43 AM
Prevent having a static class, because this makes unit testing simply much harder. I have yet to encounter a situation where using a static class like 'DomainEvent' is actually better. Mark Seemann has an interesting article about this as well.

Consider generating the incident report after the transaction, triggered after the business event was raised. Consider doing only the core work in the command + triggering the domain events. Everything that doesn't have to be done right that second (because there are no consistency needs) or are heavy operations such as sending mails, doing intensive calculations, notifying other systems, generating reports, etc, can (or perhaps even should) be done in event handlers. Jonas Gauffin has an interesting article about what to do in command handlers and what in event handlers. Again, I don't agree about using the service locator / ambient context pattern for sending events (and I don't mind when commands return some data), but his article is very informative. A must read.
Marked as answer by dot_NET_Junkie on 11/5/2013 at 7:39 AM