My Current Approach (Controller-Oriented Orchestration)
- DTO validation by param decorators (using zod with a custom interceptor)
- The controller injects all necessary services and coordinates between them to perform the task.
- No other service or controller depends on the controller, eliminating the risk of circular dependencies.
Pros:
- Clean and flat dependency graph.
- Services remain small, focused, and independent.
- Avoids circular dependencies entirely.
Cons:
- Potential code duplication if the same orchestration logic is needed across multiple controllers or entry points, though in my experience, this hasn’t really happened.
CTO's Preferred Approach (Service-Oriented Orchestration)
My CTO recommends moving orchestration into the service layer. The controller should only:
- Handle request validation/parsing.
- Pass DTOs to a service.
- Let the service handle coordination between other services.
Pros:
- Encourages service reusability across controllers, other services, and consumers.
- Keeps controllers thin and focused on HTTP concerns.
Cons:
- Risk of cyclic dependencies - e.g., ServiceA calls ServiceB, and ServiceB also needs to call ServiceA.