Introduction

Clean Architecture is a design approach that helps you build scalable, maintainable, and testable applications. It separates your code into clear layers so that business logic stays independent from frameworks, databases, and UI.

In modern .NET 10 applications, Clean Architecture is widely used for building enterprise-level APIs, microservices, and modular systems. In this article, you will learn how to implement Clean Architecture step by step using a layered folder structure with practical examples in simple, easy-to-understand language.

What is Clean Architecture?

Clean Architecture is a software design principle introduced to keep your core business logic independent of external concerns like databases, UI, and frameworks.

The main idea is:

This ensures your application remains flexible and easy to change.

Core Principles of Clean Architecture

1. Separation of Concerns

Each layer has a specific responsibility.

2. Dependency Rule

Dependencies always point inward.

3. Testability

You can test business logic without database or UI.

4. Maintainability

Changes in one layer do not affect others.

Clean Architecture Layers in .NET 10

A typical Clean Architecture solution contains the following layers:

1. Domain Layer (Core)

This is the heart of your application.

Contains:

Example:

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

2. Application Layer

This layer contains business use cases.

Contains:

Example:

public interface IProductRepository
{
    Task<Product> GetByIdAsync(int id);
}

3. Infrastructure Layer

This layer handles external concerns.

Contains:

Example:

public class ProductRepository : IProductRepository
{
    private readonly AppDbContext _context;

    public ProductRepository(AppDbContext context)
    {
        _context = context;
    }

    public async Task<Product> GetByIdAsync(int id)
    {
        return await _context.Products.FindAsync(id);
    }
}

4. Presentation Layer (API)

This is the entry point of your application.

Contains:

Example:

app.MapGet("/products/{id}", async (int id, IProductRepository repo) =>
{
    var product = await repo.GetByIdAsync(id);
    return product is not null ? Results.Ok(product) : Results.NotFound();
});

Recommended Folder Structure in .NET 10

Here is a clean and scalable folder structure:

Solution
│
├── Domain
│   ├── Entities
│   ├── ValueObjects
│   └── Interfaces
│
├── Application
│   ├── Interfaces
│   ├── Services
│   └── DTOs
│
├── Infrastructure
│   ├── Data
│   ├── Repositories
│   └── Services
│
├── Presentation (API)
│   ├── Endpoints
│   └── Middleware
│
└── Shared (Optional)

Step-by-Step Implementation in .NET 10

Step 1: Create Solution

dotnet new sln -n CleanArchitectureDemo

Step 2: Create Projects

dotnet new classlib -n Domain
dotnet new classlib -n Application
dotnet new classlib -n Infrastructure
dotnet new webapi -n Presentation

Step 3: Add Project References

Step 4: Add Dependency Injection

builder.Services.AddScoped<IProductRepository, ProductRepository>();

Step 5: Configure Database

builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseSqlServer(connectionString));

Step 6: Implement Use Case

public class GetProductService
{
    private readonly IProductRepository _repo;

    public GetProductService(IProductRepository repo)
    {
        _repo = repo;
    }

    public async Task<Product> Execute(int id)
    {
        return await _repo.GetByIdAsync(id);
    }
}

Step 7: Use in API

app.MapGet("/products/{id}", async (int id, GetProductService service) =>
{
    var result = await service.Execute(id);
    return Results.Ok(result);
});

Benefits of Clean Architecture in .NET 10

Common Mistakes to Avoid

Real-World Example

In an e-commerce system:

This structure allows easy scaling and feature additions.

Conclusion

Implementing Clean Architecture in .NET 10 helps you build modern, scalable, and maintainable applications. By separating concerns and following proper layering, you can create systems that are easy to test, extend, and manage.

Start with a simple structure, follow best practices, and gradually improve your architecture as your application grows.