Карта / Архитектура / Чистая архитектура

Чистая архитектура

Чистая архитектура (Clean Architecture, Robert Martin) — подход, при котором бизнес-логика не зависит ни от чего внешнего: ни от Spring, ни от JPA, ни от базы данных, ни от HTTP. Всё это — детали, которые можно заменить, не трогая ядро.

Главная идея — правило зависимостей: зависимости идут только внутрь. Внешние слои знают о внутренних, но не наоборот.

┌────────────────────────────────────────┐
│  Frameworks & Drivers                  │  Spring Boot, JPA, HTTP
│  ┌────────────────────────────────┐    │
│  │  Interface Adapters            │    │  Controllers, Repository impl
│  │  ┌──────────────────────────┐  │    │
│  │  │  Application / Use Cases │  │    │  Сценарии использования
│  │  │  ┌──────────────────┐    │  │    │
│  │  │  │  Domain / Entities│    │  │    │  Чистые бизнес-объекты, правила
│  │  │  └──────────────────┘    │  │    │
│  │  └──────────────────────────┘  │    │
│  └────────────────────────────────┘    │
└────────────────────────────────────────┘

Domain — бизнес-сущности и правила без каких-либо фреймворков. Обычный Java-класс, никакого @Entity.

Use Case — сценарий (RegisterUser, PlaceOrder). Знает о Domain, но не о Spring и не о БД.

Adapters — переводчики: Controller переводит HTTP в UseCase, Repository-реализация переводит UseCase в SQL.

Копнуть глубже

Dependency Inversion для разворота зависимостей. Чтобы Use Case не зависел от JPA, вводится интерфейс репозитория в слое Use Case (не в слое данных):

// Во внутреннем слое — интерфейс
package com.app.domain.port;
public interface UserRepository {
    User findById(Long id);
}

// Во внешнем слое — реализация через JPA
package com.app.infra.persistence;
@Repository
public class JpaUserRepository implements UserRepository {
    private final SpringDataUserRepo repo;
    public User findById(Long id) { return repo.findById(id).map(Mapper::toDomain)...; }
}

Теперь Use Case зависит от абстракции, а не от Spring Data — можно подменить реализацию без изменения бизнес-логики.

Hexagonal Architecture (Ports & Adapters) — другое название той же идеи. «Порты» — интерфейсы на границах ядра (входящие: что система умеет делать; исходящие: что ей нужно). «Адаптеры» — реализации этих интерфейсов для конкретных технологий. Termинология разная, суть одна.

Когда применять. Чистая архитектура добавляет сложность: больше классов, больше маппинга. Для простого CRUD-сервиса (контроллер → сервис → репозиторий) это оверинжиниринг. Оправдана, когда: сложная бизнес-логика, которую нужно тестировать без Spring; планируется замена инфраструктуры (PostgreSQL → Cassandra); команда большая и нужны чёткие границы модулей.

🎤 Закрыл тему, если можешь объяснить:
• главный принцип чистой архитектуры — правило зависимостей;
• чем чистая архитектура отличается от слоистой и когда она оправдана (если дошёл до 2-го слоя).