Трехслойный паттерн корпоративной архитектуры
У крупного бизнеса существуют разные потребности, поэтому в зависимости от условий, которые выдвигает бизнес к проектируемой системе, следует подбирать наиболее оптимальную архитектуру.
В данной лекции мы поговорим про классическое решение, которое используется в случае если бизнес хочет быстро получить работающий прототип системы или готовую систему с низкими требованиями к нагрузке и масштабированию.
Наиболее удачным решением для быстрого прототипирования и развертывания системы является трехслойный монолит. На сегодняшний день практически всегда отдается предпочтение в пользу веб-технологий и уровень представления выполняется в виде тонкого клиента, а базовая часть в виде бэкенда, состоящего из двух слоев - данных и бизнес-логики.
Бизнес-логика
Duration: 10
В предыдущей лекции мы рассмотрели общие варианты реализации слоя представления и слоя данных, в этой лекции я хочу остановиться подробно уровне с бизнес-логикой. В книге "Шаблоны корпоративных приложений" Мартина Фаулера описаны четыре основных паттерна, которые применяются в бизнес-решениях при использовании слоистой архитектуры:
- "Transaction script"
- "Domain model"
- "Table Module"
- "Service Layer"
При реализации данных шаблонов следует придерживаться принципа разделения низкоуровнего доступа к хранилищам данных (БД) и непосредственно самими данными. Изоляция может быть реализована с помощью служебных сервисов, отвечающих за реализацию хранения данных и работы с интерфейсами СУБД.
Я хочу предложить типовую архитектуру монолитного, модульного веб-приложения, соответствующего шаблонам, перечисленным у Фаулера.
С учетом развития SPA и переноса значительной функциональности с сервера на фронт, архитектура фронтенда и бэкенда становятся абсолютно идентичными, за тем исключением, что со стороны бэкенда API выполняет пассивную роль (отвечает на запросы), а на стороне фронтенда активную роль (делает запросы).
Логика приложения: - API - Сервисный уровень - Инфраструктурный уровень
Логика домена: - Бизнес-логика
Transaction script
Duration: 10
> Идея: Способ организации бизнес-логики по процедурам, каждая из которых > обслуживает один запрос, инициируемый слоем представления. > Шаблоны корпоративных приложений. М. Фаулер
Это шаблон является базовым решением в системах, где бизнес-задача может быть представлена одной транзакцией в СУБД. Обычно в таких системах нагрузка на слой бизнес логики минимальна и сводится к проверке входных данных, координации представлений и выработке единого интерфейса.
Частые ошибки: - объединение сценария транзакции и источника данных; - толстый контроллер; - сложная логика, не подходящая к реализации в рамках простой транзакции;
Где может быть реализован "transaction script": - сервис - модель
Варианты реализации: - все сценарии в одном классе; - паттерн "команда".
Недостатки: - большое дублирование кода; - нельзя покрыть сложную логику.
Domain model
Duration: 10
Этот шаблон позволяет построить сложную бизнес-логику, используя классы для представления связей и отношений между сущностями предметной области.
В трехслойной архитектуре не принято выделять отдельный слой для инфраструктурных задач, в отличии от, например, луковой архитектуры. При этом с практической точки зрения подобное разделение делать очень удобно и правильно. Поэтому я разделил слой бизнес-логики на дополнительные уровни, каждый из которых целесообразно представлять в виде модели.
Существует два варианта реализации: - простая - когда одна таблица БД отображается в один класс бизнес-логики - сложная - когда существует сложная иерархия наследования и множество отношений между сущностями;
Допускается комбинация доменной модели и скриптов транзакции. Использование одного паттерна не исключает использование других паттернов.
Частые ошибки: - неверная грануляция - слишком мелкие или слишком крупные классы; - перемешивание бизнес-логики и технических аспектов; - смешивание источников данных и доменных моделей; - представление моделей предметной области в виде сервисов.
В сложных системах бизнес-задачи могут организовывать несколько доменов исполнения, в таком случае каждый домен может быть реализован в виде отдельного модуля, который внутренне построен на базе паттерна "доменная модель".
Варианты реализации: - модели (часто) - сервисы (крайне редко, так как обычно это неудачное решение)
Table module
Duration: 10
> Идея: Объект, охватывающий логику обработки всех записей хранимой > или виртуальной таблицы базы данных. > Шаблоны корпоративных приложений. М. Фаулер
Этот шаблон упрощает процесс проектирования за счет введения простого правила "одна таблица - один класс". Такое упрощение сделано из-за постоянных проблем с поиском правильного места для запросов к БД и отображении результатов этих запросов в доменной модели. Шаблон модуль таблицы изначально проектируется как способ установить связь между БД и сущностями приложения.
Модуль таблицы содержит множество данных и операций над ними. При этом множество данных может быть использована в нескольких класса, реализующих "Table Module", а могут быть жестко связаны с источником данных.
Модуль таблицы может манипулировать данными в том числе через статические методы.
Преимущества: - изоляция логики обработки данных - повторное использование в разрезе разных наборов данных - упрощение разделения ответственности
Недостатки: - не подходит для реализации сложной логики
Варианты реализации: - Сервис
Service layer
Duration: 10
> Идея: Схема определения границ приложения посредством слоя служб, > который устанавливает множество доступных действий и координирует > отклик приложения на каждое действие > Шаблоны корпоративных приложений. М. Фаулер
Слой служб целиком сосредоточен в области "логики приложения", однако задача этого слоя не носит самостоятельной роли. Несмотря на то, что его часто изображают как слой "обертывающий" слой доменной логики, на мой взгляд у этого слоя больше вспомогательные функции.
В рамках сервисного слоя решаются такие задачи как "управление уровнем доступа", "отправка уведомлений", "управление пользовательской сессией" и т.д. Фаулер рассматривает два варианта реализации слоя служб:
- интерфейсы доступа к домену - набор тонких интерфейсов, поверх логики домена
- сценарий операций - более "толстый" слой реализующих логику приложения, но за бизнес-логикой обращаются к слою домена.
Я считаю, что такой подход устарел и на сегодняшний день, мне нравится подход с использованием IoC-контейнера и внедрением зависимостей (DI). В рамках этого решения выделяется слой сервисов, которые могут быть использованы в контроллерах или скриптах транзакций.
Доменная модель не должна ничего знать о сервисах, но сервисы могут знать о доменной модели.