Clean Architecture is a software design philosophy that separates the elements of a design into ring levels. The foundational rule is simple:
Dependencies can only point inward. Outer layers depend on inner layers, never the reverse.
This concept was introduced by Robert C. Martin (Uncle Bob) in his influential 2012 article The Clean Architecture. He also published the book Clean Architecture: A Craftsman's Guide to Software Structure and Design, which expands on these principles in depth.
This constraint is what gives Clean Architecture its power. It keeps your business logic free of framework concerns, makes the application independently testable, and means you can swap out infrastructure (databases, APIs, message queues) without touching your domain.
This template is based primarily on the practical .NET application of Clean Architecture by Milan Jovanović - Software Architect and Microsoft MVP.
Robert C. Martin's original diagram visualises the architecture as concentric rings, with the innermost ring containing the most stable business rules and each outer ring adding layers of detail and infrastructure concerns.
The four circles represent:
- Entities (innermost) - Enterprise-wide business rules that remain true regardless of which application uses them
- Use Cases - Application-specific business logic that orchestrates data flow with Entities
- Interface Adapters - Controllers, Gateways, Presenters that convert data between the application and external systems (web, database, etc.)
- Frameworks & Drivers (outermost) - Web frameworks, databases, and other external libraries kept at arm's length
Uncle Bob's foundational principle: "source code dependencies can only point inward." Nothing in an inner circle can know anything about something in an outer circle.
Read The Clean Architecture - the original article that started it all.
This solution is split into four projects, each representing one layer:
The innermost ring. It has no dependencies on any other project in the solution.
Contains:
- Entities - objects with identity and lifecycle
- Value Objects - immutable descriptors with no identity
- Domain Events - things that happened in the domain
- Repository interfaces - abstractions over data access (implementations live in Infrastructure)
- Domain exceptions - business rule violations
This is where your business rules live. If you can describe a rule without mentioning a database or an HTTP request, it belongs here.
Sits directly above Domain. Acts as an orchestrator - it coordinates domain objects to fulfil use cases, but contains no business rules itself.
Contains:
- Commands and Queries (CQRS) - one class per use case
- Command/Query handlers - the logic that executes each use case
- Abstractions - interfaces for things the Application layer needs but does not implement (email, storage, messaging)
- Pipeline behaviours - cross-cutting concerns like logging and validation
The Application layer depends on Domain. It never depends on Infrastructure or Presentation.
Implements the abstractions defined by the Application layer. Everything that talks to the outside world lives here.
Contains:
- Database access and configuration
- External service clients (email, blob storage, message brokers)
- Background jobs
- Authentication integrations
Infrastructure depends on both Domain and Application but is never referenced by them.
The entry point to the system - the presentation project. In this solution that is Web.Mvc.
Contains:
- Controllers - typical MVC controller patterns
- Middleware - request pipeline concerns
- Error handling - exception handling and mapping
Resultfailures to HTTP problem details - Authentication configuration
- Style - a dedicated scss file for and named after each component
The Presentation layer depends on Application (to send commands/queries) but should not reference Infrastructure directly.
Domain ← Application ← Infrastructure
↑
Presentation
The arrows show the direction of allowed dependencies. No arrow ever points toward Infrastructure from the inner layers.
These rules are enforced by the tests in tests/SchoolAccount.ArchitectureTests.
| Layer | Project |
|---|---|
| Domain | SchoolAccount.Domain |
| Application | SchoolAccount.Application |
| Infrastructure | SchoolAccount.Infrastructure |
| Presentation | SchoolAccount.Web.Mvc |
| Shared kernel | SchoolAccount.SharedKernel |
SchoolAccount.SharedKernel contains primitives used across all layers (Result<T>, Error, ValidationError, IDateTimeProvider)
and sits outside the ring model - it has no dependencies itself and can be referenced by any layer.
The Application layer organises features using package by feature under src/SchoolAccount.Application/, with each use case in
its own folder.
- The Clean Architecture (2012) - Robert C. Martin's foundational article
- Clean Architecture: A Craftsman's Guide to Software Structure and Design - Robert C. Martin's comprehensive book
- Clean Architecture in .NET - Complete Guide - Milan Jovanović
- How To Approach Clean Architecture Folder Structure - Milan Jovanović
- Clean Architecture: The Missing Chapter - Milan Jovanović
- Pragmatic Clean Architecture course - Milan Jovanović