fix issues in core
This commit is contained in:
206
docs/architecture/ADAPTERS.md
Normal file
206
docs/architecture/ADAPTERS.md
Normal file
@@ -0,0 +1,206 @@
|
||||
Delivery Adapters vs App Code (Strict Clean Architecture)
|
||||
|
||||
This document clarifies where Controllers live, why they are adapters, and how to structure them cleanly in large systems.
|
||||
|
||||
It resolves the common confusion between:
|
||||
• architectural role (what something is)
|
||||
• physical placement (where something lives in the repo)
|
||||
|
||||
This document is framework-agnostic in its principles and feature-based in its structure.
|
||||
|
||||
⸻
|
||||
|
||||
1. Clean Architecture Layers (Authoritative)
|
||||
|
||||
Clean Architecture defines roles, not folders.
|
||||
|
||||
ENTITIES
|
||||
USE CASES
|
||||
INTERFACE ADAPTERS
|
||||
FRAMEWORKS & DRIVERS
|
||||
|
||||
Everything that follows maps code to these roles.
|
||||
|
||||
⸻
|
||||
|
||||
2. What a Controller Is (Architecturally)
|
||||
|
||||
A Controller is an Interface Adapter.
|
||||
|
||||
Why:
|
||||
• It receives external input (HTTP)
|
||||
• It translates that input into Use Case input
|
||||
• It invokes a Use Case
|
||||
• It performs no business logic
|
||||
|
||||
By definition:
|
||||
|
||||
Anything that translates between external input and the application boundary is an adapter.
|
||||
|
||||
So:
|
||||
|
||||
✅ Controllers are Interface Adapters
|
||||
|
||||
⸻
|
||||
|
||||
3. Why Controllers Do NOT Live in adapters/
|
||||
|
||||
Although Controllers are adapters by role, they are also:
|
||||
• Framework-specific
|
||||
• Delivery-specific
|
||||
• Not reusable outside their app
|
||||
|
||||
They:
|
||||
• use routing decorators
|
||||
• depend on HTTP concepts
|
||||
• depend on a specific framework
|
||||
|
||||
Therefore:
|
||||
|
||||
Controllers belong to the delivery application, not to shared adapters.
|
||||
|
||||
⸻
|
||||
|
||||
4. Adapter vs App — The Key Distinction
|
||||
|
||||
Concept Meaning
|
||||
Adapter Architectural role (translator)
|
||||
App Delivery mechanism (HTTP, UI, CLI)
|
||||
|
||||
“Adapter” answers what it does.
|
||||
“App” answers where it runs.
|
||||
|
||||
Both are correct at the same time.
|
||||
|
||||
⸻
|
||||
|
||||
5. Feature-Based Structure (Mandatory for Scale)
|
||||
|
||||
Flat technical folders do not scale.
|
||||
|
||||
Everything is organized by feature / bounded context.
|
||||
|
||||
⸻
|
||||
|
||||
6. Canonical Project Structure (Strict)
|
||||
|
||||
Root
|
||||
|
||||
core/ # Application + Domain (pure)
|
||||
adapters/ # Reusable infrastructure adapters
|
||||
apps/ # Delivery applications
|
||||
|
||||
|
||||
⸻
|
||||
|
||||
Core (Feature-Based)
|
||||
|
||||
core/
|
||||
└── racing/
|
||||
├── domain/
|
||||
│ ├── entities/
|
||||
│ ├── value-objects/
|
||||
│ └── services/
|
||||
└── application/
|
||||
├── use-cases/
|
||||
├── inputs/
|
||||
├── results/
|
||||
└── ports/
|
||||
├── gateways/
|
||||
└── output/
|
||||
|
||||
• No framework imports
|
||||
• No DTOs
|
||||
• No controllers
|
||||
|
||||
⸻
|
||||
|
||||
Reusable Adapters (Framework-Agnostic Implementations)
|
||||
|
||||
adapters/
|
||||
└── racing/
|
||||
├── persistence/
|
||||
│ ├── TypeOrmRaceRepository.ts
|
||||
│ └── TypeOrmDriverRepository.ts
|
||||
├── presentation/
|
||||
│ └── presenters/
|
||||
│ └── GetDashboardOverviewPresenter.ts
|
||||
├── messaging/
|
||||
│ └── EventPublisher.ts
|
||||
└── logging/
|
||||
└── StructuredLogger.ts
|
||||
|
||||
These adapters:
|
||||
• implement Core ports
|
||||
• are reusable across apps
|
||||
• do not depend on routing or UI
|
||||
|
||||
⸻
|
||||
|
||||
API App (Delivery Application)
|
||||
|
||||
apps/api/
|
||||
└── racing/
|
||||
├── controllers/
|
||||
│ └── DashboardController.ts
|
||||
├── services/
|
||||
│ └── DashboardApplicationService.ts
|
||||
├── dto/
|
||||
│ └── DashboardOverviewResponseDto.ts
|
||||
└── module.ts
|
||||
|
||||
Responsibilities:
|
||||
• Controllers translate HTTP → Input
|
||||
• Application Services orchestrate Use Case + Presenter
|
||||
• DTOs represent HTTP contracts
|
||||
• Module wires dependencies
|
||||
|
||||
⸻
|
||||
|
||||
7. Responsibilities by Layer (No Overlap)
|
||||
|
||||
Controllers
|
||||
• HTTP only
|
||||
• No business logic
|
||||
• No mapping logic
|
||||
• Call Application Services only
|
||||
|
||||
Application Services (API)
|
||||
• Instantiate Output Adapters
|
||||
• Invoke Use Cases
|
||||
• Return response DTOs
|
||||
|
||||
Presenters
|
||||
• Implement Output Ports
|
||||
• Map Result → DTO/ViewModel
|
||||
• Hold state per execution
|
||||
|
||||
⸻
|
||||
|
||||
8. Forbidden Patterns
|
||||
|
||||
❌ Controllers inside adapters/
|
||||
❌ Use Cases inside apps/api
|
||||
❌ DTOs inside core
|
||||
❌ Controllers calling Use Cases directly
|
||||
❌ Business logic in Controllers or Services
|
||||
|
||||
⸻
|
||||
|
||||
9. Final Mental Model
|
||||
|
||||
Controllers are adapters by responsibility.
|
||||
Apps define where adapters live.
|
||||
|
||||
This separation allows:
|
||||
• strict Clean Architecture
|
||||
• multiple delivery mechanisms
|
||||
• feature-level scalability
|
||||
|
||||
⸻
|
||||
|
||||
10. One-Line Summary
|
||||
|
||||
Controller = Adapter (role), App = Delivery (location).
|
||||
|
||||
This document is the authoritative reference for controller placement and adapter roles.
|
||||
Reference in New Issue
Block a user