Ответ
Чистая архитектура (Clean Architecture) — это архитектурный подход, предложенный Робертом Мартином (Дядя Боб), который ставит бизнес-логику и правила предметной области в центр системы, делая их независимыми от внешних деталей: баз данных, фреймворков, UI или внешних сервисов.
Основной принцип — правило зависимостей (Dependency Rule):
Зависимости исходного кода должны быть направлены внутрь, к центру. Внешние слои (механизмы доставки, инфраструктура) зависят от внутренних слоев (бизнес-правила), но не наоборот.
Типичные слои (концентрические круги):
- Entities (Сущности): Ядро. Содержат критичные бизнес-правила и объекты предметной области. Это POCO-классы, не знающие ни о чем внешнем.
- Use Cases (Сценарии использования): Содержат специфичную логику приложения. Они оркестрируют поток данных от/к сущностям, координируя работу репозиториев и других интерфейсов.
- Interface Adapters (Адаптеры интерфейсов): Преобразуют данные между форматами, удобными для Use Cases и внешним миром (например, MVC-контроллеры, ViewModels, репозитории как абстракции).
- Frameworks & Drivers (Фреймворки и драйверы): Внешний слой. Базы данных, веб-фреймворки (ASP.NET Core), UI, файловые системы. Сюда подключаются конкретные реализации.
Пример структуры проекта и кода:
MyApp.Domain/ // Слой Entities (ядерные бизнес-правила)
Entities/
Order.cs
Product.cs
Interfaces/
IRepository.cs // Абстракция объявлена здесь!
MyApp.Application/ // Слой Use Cases
UseCases/
CreateOrderUseCase.cs
Interfaces/
IEmailService.cs // Абстракция объявлена здесь!
MyApp.Infrastructure/ // Слой Frameworks & Drivers (конкретные реализации)
Persistence/
OrderRepository.cs // : IRepository (зависит от Domain!)
Services/
SmtpEmailService.cs // : IEmailService (зависит от Application!)
MyApp.WebApi/ // Слой Interface Adapters & Frameworks
Controllers/
OrderController.cs // Использует CreateOrderUseCase
Код сущности (Domain):
// MyApp.Domain/Entities/Order.cs
namespace MyApp.Domain.Entities;
public class Order // НИКАКИХ ссылок на EF, API и т.д.
{
public int Id { get; private set; }
public decimal TotalAmount { get; private set; }
public OrderStatus Status { get; private set; } = OrderStatus.Pending;
public void ApplyDiscount(decimal discount)
{
if (discount <= 0) throw new ArgumentException("Discount must be positive.");
if (discount >= TotalAmount) throw new InvalidOperationException("Discount exceeds total.");
// Бизнес-правило!
TotalAmount -= discount;
}
public void MarkAsPaid() => Status = OrderStatus.Paid; // Еще одно правило
}
Преимущества:
- Независимость: Бизнес-логика не зависит от выбора базы данных, веб-фреймворка или UI.
- Тестируемость: Ядро можно тестировать изолированно, с моками всех внешних зависимостей.
- Гибкость: Замена внешних компонентов (например, миграция с SQL Server на PostgreSQL) требует изменений только во внешнем слое.
- Долгосрочная поддержка: Четкое разделение ответственности облегчает понимание и развитие кодовой базы.
Недостаток: Большой объем шаблонного кода (boilerplate) и повышенная сложность для маленьких проектов.
Видео-ответы
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶