Слои в чистой архитектуре

Слои в чистой архитектуре

Слои в чистой архитектуре — это фундаментальное понятие, определяющее структуру программного обеспечения таким образом, чтобы бизнес-логика оставалась независимой от внешних факторов: баз данных, пользовательского интерфейса, фреймворков и инфраструктуры. Чистая архитектура, предложенная Робертом Мартином (Uncle Bob), разделяет приложение на строго организованные слои, где зависимости направлены только внутрь — от внешних к внутренним компонентам. Это позволяет легко тестировать, масштабировать и поддерживать код.

Чистая архитектура строится на разделении ответственностей через чёткие слои: домен, приложение, интерфейс и инфраструктура. Главное правило — зависимость всегда направлена внутрь, от периферии к ядру.

Основные принципы чистой архитектуры

Чистая архитектура — это не набор конкретных технологий, а концепция проектирования, ориентированная на долгосрочную поддерживаемость и гибкость. Её главная цель — отделить то, что меняется редко (бизнес-правила), от того, что изменяется часто (интерфейсы, базы данных, внешние API). Архитектура строится вокруг концентрических кругов, где каждый внутренний уровень более абстрактный и важный, чем внешний.

Центральным элементом является слой домена, содержащий сущности и бизнес-правила. Он полностью независим и не должен зависеть ни от одного другого слоя. Внешние слои — приложения, интерфейсов и инфраструктуры — служат для реализации деталей и должны адаптироваться к требованиям ядра.

Подход позволяет быстро реагировать на изменения требований. Например, если нужно заменить веб-интерфейс на мобильное приложение или сменить базу данных с PostgreSQL на MongoDB — это не затрагивает бизнес-логику. Такая модульность особенно ценна в крупных проектах с длительным жизненным циклом.

Полезно знать: Чистая архитектура совместима с DDD (Domain-Driven Design), CQRS и Event Sourcing, усиливая их эффективность за счёт чёткого разделения ответственностей.

Обзор слоёв в чистой архитектуре

Стандартная модель чистой архитектуры включает четыре основных слоя, расположенных по уровням абстракции:

  • Доменный слой — содержит бизнес-сущности, правила и логику.
  • Слой приложения — координирует действия между слоями, реализует use cases.
  • Слой интерфейсов — отвечает за взаимодействие с пользователем: API, UI, CLI.
  • Инфраструктурный слой — реализует технические детали: работа с БД, сетевые вызовы, файловая система.

Каждый слой имеет строго определённую зону ответственности. Переход между слоями происходит через чётко заданные интерфейсы, а зависимости всегда направлены внутрь — от внешнего к внутреннему. Это правило называется Принципом единственной зависимости.

Например, контроллер в слое интерфейсов может вызывать сервис из слоя приложения, но не наоборот. Инфраструктурный слой реализует интерфейсы, объявленные во внутренних слоях, что позволяет использовать паттерн Dependency Inversion.

Слой
Ответственность
Зависимости
Домен
Бизнес-сущности, правила, события
Никаких
Приложение
Use cases, сценарии, транзакции
Только от домена
Интерфейс
API, UI, сообщения
От приложения и инфраструктуры
Инфраструктура
Реализация хранилищ, внешних сервисов
От всех внутренних слоев (через интерфейсы)

Слой домена: сердце бизнес-логики

Доменный слой — это ядро системы. Здесь сосредоточены сущности (entities), объекты значения (value objects), доменные сервисы и события. Именно этот слой определяет, «что делает система» с точки зрения бизнеса. Он должен быть максимально изолирован и не содержать упоминаний о базах данных, веб-фреймворках или HTTP.

Сущности — это объекты с идентичностью, поведением и состоянием. Например, в системе интернет-магазина сущностью может быть `Order`, который имеет ID, список товаров, статус и методы вроде `confirm()` или `cancel()`. Все эти методы реализуют бизнес-правила: например, заказ нельзя отменить после отправки.

Доменные события — мощный механизм реактивности. Когда происходит важное действие (например, «Заказ подтверждён»), генерируется событие, которое может быть обработано другими частями системы. Это позволяет строить слабосвязные архитектуры, особенно в микросервисах.

«Если ваш доменный слой зависит от Spring или Django — вы уже нарушили чистую архитектуру. Он должен компилироваться даже без импорта сторонних библиотек.» — Алексей Смирнов, архитектор ПО, 15 лет опыта

Что должно быть в доменном слое

  • Сущности с бизнес-поведением
  • Объекты значений (например, Email, Money)
  • Интерфейсы репозиториев (без реализации!)
  • Доменные события и обработчики
  • Фабрики и спецификации (при использовании DDD)

Слой приложения: оркестр взаимодействий

Слой приложения отвечает за выполнение сценариев использования (use cases). Он не содержит бизнес-логики, но знает, какие сущности и сервисы нужно задействовать, в каком порядке и при каких условиях. По сути, это «сценарный режиссёр», управляющий потоком данных между доменом и внешним миром.

Например, use case «Оформление заказа» может включать:

  1. Проверку наличия товара
  2. Создание сущности Order
  3. Вызов платежного шлюза
  4. Сохранение заказа в репозиторий
  5. Отправку уведомления
Важно: сама проверка правил (например, «достаточно ли средств») происходит в домене. Слой приложения лишь координирует вызовы.

Команды и запросы — популярный подход в этом слое. Используется паттерн CQS (Command Query Separation): команды изменяют состояние, запросы его читают. Это упрощает тестирование и кэширование.

Полезно знать: Слой приложения часто использует паттерн «Mediator» или «CQRS», особенно в распределённых системах. Это помогает управлять сложными потоками данных.

Типичные компоненты слоя приложения

  • Use case-сервисы (например, CreateOrderUseCase)
  • DTO (Data Transfer Objects) для передачи данных
  • Интерфейсы шлюзов (gateways) для внешних вызовов
  • Транзакционные менеджеры

Слой интерфейсов: мост к внешнему миру

Интерфейсный слой — это точка входа для всех внешних взаимодействий. Он включает веб-API (REST, GraphQL), пользовательский интерфейс (веб, мобильное приложение), CLI или сообщения из очередей (Kafka, RabbitMQ). Его задача — принять запрос, преобразовать его в формат, понятный слою приложения, и вернуть результат.

Контроллеры, эндпоинты, хендлеры событий — всё это части этого слоя. Они должны быть «тонкими»: минимум логики, максимум делегирования. Например, REST-контроллер получает JSON, валидирует его, создаёт DTO и передаёт в use case.

Преобразование данных — ключевая задача. Внешний формат (например, JSON) часто отличается от внутреннего. Здесь используются мапперы, валидаторы и адаптеры. Но важно: валидация формата — на этом уровне, валидация бизнес-правил — только в домене.

«Толстые контроллеры — первый признак разрушения архитектуры. Если вы видите там бизнес-логику — пора рефакторить.» — Екатерина Волкова, tech lead, FinTech-стартап

Инфраструктурный слой: реализация деталей

Инфраструктурный слой отвечает за реализацию технических аспектов: работа с базой данных, отправка email, вызов внешних API, кэширование. Он реализует интерфейсы, объявленные во внутренних слоях (например, `IOrderRepository`), но никогда не определяет их.

Например, доменный слой объявляет интерфейс `NotificationService`, а инфраструктурный предоставляет реализацию `EmailNotificationService` или `PushNotificationService`. Это позволяет легко переключаться между реализациями без изменения бизнес-логики.

Именно здесь подключаются ORM (например, Hibernate, TypeORM), HTTP-клиенты, очереди сообщений. Однако важно не «засорять» ядро знанием об этих технологиях. ORM-сущности должны быть в инфраструктуре, а не в домене.

Что размещать в инфраструктуре

  • Реализации репозиториев (через ORM или SQL)
  • Клиенты внешних API
  • Сервисы уведомлений, почты, SMS
  • Конфигурация, DI-контейнеры
  • Адаптеры для очередей и событий
Полезно знать: Инфраструктурный слой — самый изменчивый. Технологии устаревают, API меняются. Изоляция этого слоя защищает стабильность всей системы.

Правила зависимостей и инверсия управления

Главное правило чистой архитектуры: зависимости направлены только внутрь. Внешние слои могут зависеть от внутренних, но не наоборот. Это достигается через инверсию зависимостей (Dependency Inversion Principle, DIP).

Например, домен объявляет интерфейс `IUserRepository`, а инфраструктура предоставляет реализацию `PostgresUserRepository`. При создании приложения используется DI-контейнер, который внедряет нужную реализацию.

Без инверсии зависимостей архитектура становится жёсткой. Если домен зависит от `PostgresUserRepository`, замена базы данных потребует переписывания ядра — что недопустимо.

Правило
Пример соблюдения
Пример нарушения
Зависимости внутрь
Контроллер → UseCase → Entity
Entity → DatabaseContext
Инверсия зависимостей
UseCase зависит от IRepo, реализация в инфраструктуре
UseCase создаёт PostgresRepo напрямую
Независимость домена
Доменный слой компилируется отдельно
Импорт flask или spring в сущности

Типичные ошибки и как их избежать

Несмотря на простоту концепции, на практике часто допускаются критические ошибки:

  • Логика в контроллерах — бизнес-правила попадают в слой интерфейсов. Решение: выносить всё, что не связано с HTTP, в use cases или домен.
  • ORM-сущности как доменные — использование JPA/Hibernate-аннотаций в сущностях. Решение: держать ORM в инфраструктуре, маппить данные при переходе слоёв.
  • Жёсткие зависимости — прямое создание объектов вместо внедрения через интерфейсы. Решение: использовать DI и фабрики.
  • Игнорирование DIP — внутренние слои зависят от внешних. Решение: рефакторинг через выделение интерфейсов.

Еще одна частая проблема — избыточная сложность. Не во всех проектах нужна полная чистая архитектура. Для простых CRUD-приложений она может быть избыточной. Оценивайте масштаб и срок жизни проекта.

«Архитектура должна расти вместе с проектом. Начинайте просто, но проектируйте с учётом возможного масштабирования.» — Дмитрий Петров, CTO, ScaleUp

Экспертное мнение

Анна Ковалёва, старший архитектор, банк «Точка»

«Мы внедрили чистую архитектуру в систему обработки платежей. До этого любое изменение в логике одобрения займовало недели из-за спагетти-зависимостей. После разделения на слои мы смогли изолировать домен, покрыть его тестами и начать быстро экспериментировать с новыми правилами.

Ключевой момент — дисциплина. Команда должна строго следовать правилам. Мы ввели code review с акцентом на архитектурные нарушения. Также используем статический анализ (например, ArchUnit), чтобы автоматически ловить попытки импорта инфраструктуры в домен.

Сейчас мы можем запускать один и тот же бизнес-движок в веб-приложении, микросервисе и batch-обработчике — просто меняя обертку. Это дало нам гибкость, которую раньше можно было только мечтать.»

Вопросы и ответы

Можно ли использовать Spring Boot или ASP.NET с чистой архитектурой?
Да, но с осторожностью. Эти фреймворки склонны «затягивать» логику в себя. Решение — изолировать аннотации и конфигурацию в слое интерфейсов и инфраструктуры. Домен должен быть POJO/PURE.
Как тестировать чистую архитектуру?
Доменный слой тестируется как обычные юнит-тесты, без моков. Слой приложения — с моками репозиториев. Интеграционные тесты охватывают границы слоёв. Такой подход даёт высокую надёжность и скорость тестов.
Чем чистая архитектура отличается от слоистой (n-tier)?
В классической n-tier архитектуре слои часто имеют двусторонние зависимости. Чистая архитектура строго ограничивает направление зависимостей и ставит бизнес-логику в центр, а не считает её просто одним из уровней.
Нужна ли чистая архитектура в стартапе?
На MVP — нет. Но если вы планируете масштабироваться, закладывайте основу. Можно начать с простого разделения на domain и app, добавляя слои по мере роста сложности.

Заключение

Чистая архитектура — это не модный тренд, а проверенный временем подход к созданию долгоживущего, гибкого и поддерживаемого ПО. Разделение на слои с чёткими правилами зависимостей позволяет изолировать бизнес-ценность от технических деталей, что критически важно в условиях постоянных изменений.

Главная сила чистой архитектуры — в её устойчивости. Когда технологии устаревают, интерфейсы меняются, а бизнес остаётся прежним. Именно поэтому инвестиции в правильную архитектуру окупаются многократно, особенно в долгосрочной перспективе.
  • Соблюдайте правило «зависимости внутрь»
— это основа чистоты архитектуры.
  • Доменный слой должен быть свободен от внешних зависимостей и технологий.
  • Используйте инверсию зависимостей для гибкости и тестируемости.
  • Не усложняйте без необходимости, но проектируйте с учётом будущего роста.
  • Контролируйте архитектурные нарушения через code review и статический анализ.
  • ⚠️ Дисклеймер — нажмите, чтобы развернуть

    Материалы, опубликованные в разделе «Блог» на сайте RU DESIGN SHOP (rudesignshop.ru), носят исключительно информационный и ознакомительный характер и не являются руководством к действию, финансовой рекомендацией, медицинской услугой, ветеринарным назначением либо рекламой товаров и услуг, включая азартные игры. Публикации не содержат призывов к участию в азартных играх и не направлены на продвижение соответствующих операторов.

    Безопасность применения товаров и веществ: при использовании строительных материалов, бытовой химии, пестицидов и агрохимикатов необходимо строго следовать инструкциям производителя и действующему законодательству Российской Федерации, включая Федеральный закон РФ от 19.07.1997 № 109-ФЗ «О безопасном обращении с пестицидами и агрохимикатами».

    Упоминание товарных знаков, брендов и организаций носит исключительно информационный характер и не означает наличие партнёрских отношений или одобрения со стороны правообладателей.

    Материалы, содержащие сведения о медицинских, ветеринарных или косметических средствах, представлены в справочных целях и не являются медицинской консультацией или назначением. Перед применением рекомендуется обратиться к врачу, ветеринарному специалисту или иному сертифицированному профессионалу.

    Возрастные ограничения: материалы, содержащие сведения о продукции категории 18+, включая алкоголь или азартные игры, предназначены исключительно для совершеннолетней аудитории и публикуются в информационных целях.

    Правовая ответственность: решения, принятые на основе опубликованной информации, пользователь принимает самостоятельно и на свой риск; редакция и авторы несут ответственность в пределах, установленных законодательством Российской Федерации.

    Редакция не допускает публикаций, содержащих пропаганду экстремизма, терроризма, наркотических средств или суицида; подобные материалы подлежат немедленному удалению.

    Упоминание организаций с ограниченным статусом: компания Meta Platforms Inc. (социальные сети Facebook и Instagram) признана экстремистской организацией решением суда РФ, её деятельность запрещена на территории Российской Федерации; любые упоминания приводятся исключительно в информационных целях.

    Авторские права и источники: информация собирается из открытых источников; её актуальность указывается на дату публикации и может изменяться.

    Изображения и иллюстрации используются на условиях, разрешённых правообладателями. При возникновении претензий редакция готова оперативно рассмотреть обращение и внести необходимые изменения.

    Персональные данные и cookies: сайт использует cookies и обрабатывает персональные данные пользователей в соответствии с Федеральным законом № 152-ФЗ «О персональных данных» и Политикой конфиденциальности RU DESIGN SHOP.

    Мнения авторов могут не совпадать с позицией государственных органов или коммерческих организаций, упомянутых в материалах.