Fat Controller CQRS Diet: Trade-offs

Trade-OffsIn my Fat Controller CQRS Diet series, I’ve shown the mediator pattern and the MediatR library. After a recent discussion with Reid Evans, he made me realize I haven’t really described the trade-offs.  This post is going to focus on trade-offs and an alternative to using the mediator pattern.

If you’re new to this series, here are earlier posts to get you up to speed:

  1. Overview of Series
  2. Simple Query
  3. Simple Command
  4. Command Pipeline
  5. Notifications
  6. Vertical Slices

Coupling

With the mediator pattern, communication between objects is encapsulated with a mediator object. Objects no longer communicate directly with each other, but instead communicate through the mediator. This reduces the dependencies between communicating objects, thereby lowering the coupling.

For me the purpose of using the mediator pattern is to limit the coupling between integration boundaries.  Those boundaries in my applications are typically the Web/UI Framework and my core application.

This means I’ll have my controllers take a dependency on the mediator and not my core application.

Runtime Resolution

The downside to this that there is no compile time type checking.  When the mediator is invoked at runtime, it could fail to send the request if there is no handler defined.

In the code example above, if there is no IAsyncRequestHandler<Home, List<Album>> then an exception will be thrown on _mediator.SendAsync(new Home());

Coupling to Handler (or Interface)

We could get around this and get our type checking at compile time by having the request handler injected into our controller.

This is fairly reasonable since I often have one controller per command or query.  This then limits the dependencies I’d be putting into the constructor.

Messaging

One aspect that I haven’t touched on (yet) in this series is about background processing and queues.  I really enjoy using Hangfire to create background jobs.   I’ve blogged about it before and how to integrate MediatR and Hangfire together.

The general approach I take is to use messaging between MediatR and Hangfire to keep it consistent on how commands or queries are made.  That means messaging with MediatR done in-process or done on out of process (on other machines) via Hangfire but routing them through MediatR.

Comments

GitHub

I love hearing your comments, questions and recommendations!  Please post a comments or on Twitter.