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

  1. Pure domain: no using Microsoft.EntityFrameworkCore, no web attributes, no DateTime.Now.
  2. Use Cases orchestrate; they do not contain domain rules.
  3. 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