Clean Architecture
Organizes code into concentric layers where the domain is the center and nothing from the outside touches it.
Context
You want to isolate business rules from technical details (framework, DB, UI) so that you can change them without rewriting the domain.
Problem
When the domain depends on EF, ASP.NET, or a specific broker, technical changes break business logic.
Solution
Concentric layers following the Dependency Rule: dependencies point inward, never outward.
┌──────────────────────────────────────┐
│ Frameworks & Drivers (Web, EF, MQ) │
│ ┌──────────────────────────────┐ │
│ │ Interface Adapters (DTOs, │ │
│ │ Controllers, Presenters) │ │
│ │ ┌──────────────────────┐ │ │
│ │ │ Use Cases (App) │ │ │
│ │ │ ┌──────────────┐ │ │ │
│ │ │ │ Entities │ │ │ │
│ │ │ └──────────────┘ │ │ │
│ │ └──────────────────────┘ │ │
│ └──────────────────────────────┘ │
└──────────────────────────────────────┘
#Rules
- Pure domain: no
using Microsoft.EntityFrameworkCore, no web attributes, noDateTime.Now. - Use Cases orchestrate; they do not contain domain rules.
- Output interfaces (repositories, services) live in the Application layer; external layers implement them (DI inversion).
#Typical Structure
CSHARP
src/
├── Domain/ ← Entities, VOs, events, rules. ZERO dependencies.
├── Application/ ← Use cases, ports (IRepository, IClock). Depends only on Domain.
├── Infrastructure/ ← EF, HTTP, MQ. Implements Application's ports.
└── Web/ ← ASP.NET. Composes the DI graph.
// Application defines the "port"
public interface IOrderRepository { Task<Order?> GetAsync(Guid id); }
// Infrastructure implements it
public class EfOrderRepository : IOrderRepository { /* ... */ }
// Web registers it
services.AddScoped<IOrderRepository, EfOrderRepository>();When NOT to use it
- Small microservices or scripts: the ceremony kills ROI.
- Teams without the discipline to maintain correct dependencies.
Tradeoffs
| Pro | Con |
|---|---|
| Testable domain without infrastructure | More projects and boilerplate |
| Change EF for Dapper without touching domain | Extra mappings between layers |
| Fits perfectly with DDD | Learning curve |
#architecture #clean #ddd