The document proposes adding a "Service Mediator" pattern to the traditional MVC pattern to reduce dependency bloat in controllers. It describes the typical workflow of a controller handling a request by interacting with domain services and mapping responses. To address this, the author suggests an MVCM pattern where a Service Mediator encapsulates how controllers interact with services, promoting loose coupling. The document demonstrates this pattern in ASP.NET Core using MediatR to delegate requests from controllers to self-contained "Features" through a mediator, diminishing controller logic and improving testability.
2. About Myself
• Principal Consultant at Cardinal Solutions
• Over 18 years in the software development industry
• Front-end, .NET, App Modernization
• New found passion:
• containerization & orchestration / infrastructure automation
• The terminal! LOL
3. What we’ll cover tonight
• Review our favorite pattern: MVC
• Our current approach to passing and interacting with dependencies
• How we’re shrinking our controllers
• Typical controller workflow
• Finding a solution
• Implementing our solution
• Benefits
4. By now we should know what MVC is…
https://en.wikipedia.org/wiki/Model-view-controller
5. Passing Dependencies to Controllers
• Controllers can start easy
• Additional dependencies added overtime
• Easy to bloat controller logic with business logic
• Controller is aware of domain services
• Unit test controller to ensure proper dependency communication
Does the controller need to be aware of our dependencies?
6. Strategies to mitigate dependency bloat
• Not worry about it for simple projects
• Separate concerns, AOP
• Apply SOLID principles
• Service layer/domain services (DDD)
• Custom solutions
7. Typical Controller Workflow:
CustomerOrdersController
POST, CustomerOrderDto (aka ViewModel)
1. Client requests an endpoint: /api/customers/abc/orders
2. Controller processes DTO on action AddCustomerOrder()
3. DTO converted to a domain object
4. Domain object delegated to a domain service
5. Controller gets response from delegated domain service
6. Additional fluff occurs..
7. Controller converts response to another DTO
8. Controller returns the DTO/View to client
8. What’s the problem?
• The controller is doing to much churning
• Without a mapping layer, controller responsible for mapping
• Custom solutions can be created: services, helpers, “managers”, etc.
• Too much repetition: similar solutions for other controllers or actions
• Single responsibility
9. Summarizing the Workflow
• A request of a given type is made
• A service handles the request, but you have to know what that
service is
• The service returns a response
• The response is transformed for client use and returned
• Keywords: request of a given type, handle, response
The outline above is a pattern
12. The Mediator Pattern
GoF Behavioral Design Pattern
“Define an object that encapsulates
how a set of objects interact… promotes
loose coupling by keeping objects from
referring to each other explicitly, and it
lets you vary their interaction
independently.”
https://www.dofactory.com/net/mediator-design-pattern
http://codepumpkin.com/mediator-design-pattern/
14. Benefits
• Loose coupling between dependencies
• Controller bloat diminished greatly
• Each controller action responsible for delegating to mediator
• Controller reacts to the response from the mediator
• Well, you still need a mapping layer
• Unit testing controllers is easier
• Controller action parameters encapsulated into a DTO
• Behaviors segregated into self-documenting “Features”