6

I've been working in MVC web frameworks since its they started getting popular with RoR and ASP.NET MVC. I have always been careful to never put "business logic" on my controllers since that couples the framework with the logic. These days, like many of you, I'm not really using the MVC part of my framework, since I'm not returning "views" and framework artifacts. Instead, I'm just using routes to controller actions to build API's that return xml or json.

In the past couple years, I've been trying to move closer to CQRS, so my business logic ends up being packaged in commands and handlers with a dispatcher to connect the two. The "real" business logic is actually in my entities, but my command handlers drive the operations. I have also started allowing multiple services to expose different bounded contexts (micro-services). Then I started thinking "outside the box" (outside for me, at least).

Why do I bother with dispatcher, commands, and command handlers? Now that my framework is only a networking layer over my bounded context, why not let my controllers be my command handlers? Why not let my dispatcher be the routing system in my framework? Why not let the content of the HTTP request be my command?

2 Answers 2

1

Short Answer

The primary benefit of decoupling application logic from any presentation/external interfacing layers is to allow consumers to vary independently without duplicating logic. Therefore, the necessity of decoupling is dependent upon how many consumers your application will have.

Long Answer

Using Domain-Driven Design nomenclature, your question could be recast as "Why include an 'Application Layer' within your solution architecture?".

The Application Layer is intended to serve as the interface to the domain and infrastructure needs of your application, translating request and response messages into interactions with the underlying components. By 'translating' here, we mean the conversation of a logical message in some standard format into zero or more operations upon the underlying components. Ideally, a request to a "Fund Transfer Application Service", which verifies the input, instructs the domain to perform a transfer, persists the domain state, logs the operation, and notifies the world by calling a "Notify World Infrastructure Service", could be called by either a component or subcutaneous-level test, a Web Application, a console application, or be exposed as a Web service without modification. That said, the degree any given solution benefits from such separation of concern strategies depends upon the context.

There are, however, other factors which may lead you to want some degree of decoupling from the consuming interface aside from a need to service multiple consumers. For example, the ASP.Net MVC architecture tends to steer developers into grouping operations together for a given view/Web page. For operations that go beyond simple CRUD operations on a single aggregate root, Microsoft's design has a tendency to lead to controllers which lack cohesion with respect to the adapter role-stereotype they are meant to serve.

To explain further, while you might have a CustomerController who's actions are all about customers and nothing but customers, each action may require different collaborators to accomplish their goal, not all of which are needed for every operation. One action might need to save something to a database, another may need to send an email, and another may need to cache data or place something on a message queue. Just because all these actions center around a single aggregate root doesn't mean the role the controller is meant to play (i.e. adapter) is cohesive with respect to its own responsibilities. Ideally, a Web framework would take an inbound HTTP message and map it onto a command handler within the Application Service layer without requiring the Application Service Layer to take a dependency upon the Web framework.

Architecture theory and Feng shui motivations aside, it really all boils down to your need to reuse the application logic that you are going to either place in your Web page/code behind/controller/command handler. Typically, the first client that should consume your application logic is your executable specifications and the second is the production interface. Depending upon your approach to testing (none, user acceptance, isolation, etc.) along with the ease in which any framework dependencies you take on as part of the application logic implementation effort allow you to implement the specification's observations, this will often determine the degree of decoupling you want to include within your application.

4
  • Isn't the application layer just a way of exposing the domain logic to the "outside world?" If so, why not allow a framework provide that application layer? May 2, 2015 at 18:35
  • I dont think I'm suggesting removing the application layer. I think I'm really talking about merging the concept of app layer with the API routing layer. Command handlers = route handlers May 2, 2015 at 19:53
  • The application layer isn't the external interface to the outside world, but rather is intended to be the single interface used by one or more "outside world" facing interfaces (e.g. Web sites, Web services, various Desktop GUI technologies, console/command line interfaces, etc.). When your application has multiple external interfaces, it's best for them to all communicate with the same interface-agnostic layer. This is why I stated that it really boils down to your need to reuse the application logic. May 8, 2015 at 0:34
  • For further discussion of this topic, I would highly recommend watching Robert Martin's "Architecture: The Lost Years" presentation available here. May 8, 2015 at 0:48
1

Well.. main idea of CQRS to separate read and write operations. You might use of this pattern for one main reason,

The change that CQRS introduces is to split that conceptual model into separate models for update and display - Martin Fowler

So if you have two of these models to maintain, it would be very hard not to use commands, command handlers and so on.

But since you think you can get rid of those and move the logic to controllers (of course not the domain logic), then probably you are not actually using CQRS, and probably you should not use it if you don't need to.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.