Программная архитектура и слои
Программная архитектура отвечает на вопрос, как устроена программная часть информационной системы. На этом уровне появляются модули, классы, интерфейсы, сервисы, зависимости и правила их взаимодействия.
Важно не смешивать программную архитектуру с системной. Программная архитектура говорит о внутренней организации ПО: какие части есть в программе и как они зависят друг от друга. Системная архитектура говорит о размещении: где работают клиент, сервер, база данных, внешние системы и среды выполнения.
Для учебной модели удобно использовать простую слоистую структуру. Она не требует углубления в DDD, Clean Architecture или конкретный backend-фреймворк, но помогает не смешивать ответственности.
Типовые слои:
- presentation layer: взаимодействие с пользователем или внешним клиентом;
- application layer: сценарии приложения и координация пользовательских целей;
- domain/model layer: предметная модель и бизнес-правила;
- infrastructure/data access layer: хранение, файлы, внешние сервисы, сетевые интеграции.
Главное правило слоистой модели — контролировать зависимости. Пользовательский интерфейс или контроллер может обращаться к application layer. Application layer координирует сценарий и использует предметную модель. Infrastructure layer реализует технические детали хранения и интеграции. Предметная модель не должна напрямую зависеть от базы данных, HTTP-клиента, файловой системы или UI.
Типовые роли классов:
| Роль | Ответственность |
|---|---|
| Controller | принять внешнее действие и передать его дальше |
| ApplicationService | скоординировать сценарий приложения |
| DomainService | выполнить предметную операцию, если она не принадлежит одному объекту |
| Repository | скрыть способ загрузки и сохранения объектов |
| DTO | перенести данные через границу слоя или интерфейса |
| Mapper | преобразовать одну техническую форму данных в другую |
| Gateway / Adapter | изолировать внешнюю систему |
| Entity / Model | представить предметный объект в технической модели |
Например, в сценарии оформления заказа контроллер может принять команду от клиента и передать её в сервис приложения. Сервис приложения загружает данные через репозиторий, вызывает операции предметных объектов, проверяет правила и сохраняет результат. Если нужно обратиться к платёжной системе, приложение работает не напрямую с конкретным API, а через шлюз или адаптер.
Слоистая архитектура полезна только тогда, когда у слоёв есть разные причины для изменения. Интерфейс может меняться из-за требований пользователей. Application layer меняется из-за сценариев. Domain/model layer меняется из-за предметных правил. Infrastructure layer меняется из-за базы данных, внешних сервисов и технологий.
Слои не равны папкам. Папки помогают организовать код, но архитектурный смысл появляется только тогда, когда зависимости между классами соответствуют выбранным ролям. Если контроллер сам проверяет бизнес-правила, формирует SQL и вызывает внешний сервис, слоистая архитектура фактически отсутствует.
Допустимость зависимости можно проверять простым вопросом: станет ли предметная логика зависеть от технической детали? Если правило отмены заказа зависит от HTTP-клиента или SQL-запроса, зависимость выбрана плохо. Если сервис приложения зависит от интерфейса репозитория или шлюза, это нормальный способ скрыть инфраструктуру за абстракцией.
В технической диаграмме классов слои должны быть видны не только названиями пакетов, но и направлением связей. Иначе слоистость остаётся декларацией.