Чистая архитектура
Чистая архитектура (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-го слоя).