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