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.