Section 4 of 5
Clean Architecture
🎯 What You'll Learn
- What is Clean Architecture
- Layers and dependencies
- Domain layer
- Application layer
- Infrastructure layer
What is Clean Architecture?
Clean Architecture organizes code into layers with dependencies pointing inward, keeping business logic independent of frameworks and infrastructure.
Layers
| Layer | Responsibility | Dependencies |
|---|---|---|
| Domain | Business entities and rules | None |
| Application | Use cases and business logic | Domain |
| Infrastructure | Data access, external services | Application, Domain |
| Presentation | UI, API controllers | Application |
Project Structure
Solution Structure
Text
InvenTrack/
├── InvenTrack.Domain/
│ ├── Entities/
│ │ ├── Product.cs
│ │ ├── Order.cs
│ ├── Interfaces/
│ │ ├── IProductRepository.cs
├── InvenTrack.Application/
│ ├── Services/
│ │ ├── ProductService.cs
│ ├── DTOs/
│ │ ├── ProductDto.cs
├── InvenTrack.Infrastructure/
│ ├── Data/
│ │ ├── InvenTrackDbContext.cs
│ ├── Repositories/
│ │ ├── ProductRepository.cs
├── InvenTrack.Web/
│ ├── Controllers/
│ │ ├── ProductsController.cs
Domain Layer
Domain/Entities/Product.cs
C#
namespace InvenTrack.Domain.Entities;
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public int Quantity { get; set; }
public bool IsLowStock() => Quantity < 10;
}
Domain/Interfaces/IProductRepository.cs
C#
namespace InvenTrack.Domain.Interfaces;
public interface IProductRepository
{
Task<Product> GetByIdAsync(int id);
Task<IEnumerable<Product>> GetAllAsync();
Task AddAsync(Product product);
}
Application Layer
Application/DTOs/ProductDto.cs
C#
namespace InvenTrack.Application.DTOs;
public class ProductDto
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
Application/Services/ProductService.cs
C#
namespace InvenTrack.Application.Services;
public class ProductService
{
private readonly IProductRepository _repository;
public ProductService(IProductRepository repository)
{
_repository = repository;
}
public async Task<IEnumerable<ProductDto>> GetAllProductsAsync()
{
var products = await _repository.GetAllAsync();
return products.Select(p => new ProductDto
{
Id = p.Id,
Name = p.Name,
Price = p.Price
});
}
}
Infrastructure Layer
Infrastructure/Repositories/ProductRepository.cs
C#
namespace InvenTrack.Infrastructure.Repositories;
public class ProductRepository : IProductRepository
{
private readonly InvenTrackDbContext _context;
public ProductRepository(InvenTrackDbContext context)
{
_context = context;
}
public async Task<Product> GetByIdAsync(int id)
{
return await _context.Products.FindAsync(id);
}
}
Presentation Layer
Web/Controllers/ProductsController.cs
C#
namespace InvenTrack.Web.Controllers;
public class ProductsController : Controller
{
private readonly ProductService _productService;
public ProductsController(ProductService productService)
{
_productService = productService;
}
[HttpGet]
public async Task<IActionResult> Index()
{
var products = await _productService.GetAllProductsAsync();
return View(products);
}
}
Key Takeaways
- Clean Architecture: Layers with inward dependencies
- Domain: Business entities and interfaces (no dependencies)
- Application: Use cases and DTOs (depends on Domain)
- Infrastructure: Data access (depends on Domain)
- Presentation: UI/API (depends on Application)
- Benefits: Testable, maintainable, framework-independent