Пример многоуровневой архитектуры и анализ паттерна
Чтобы проиллюстрировать работу многоуровневой архитектуры, рассмотрим запрос бизнес-пользователя на получение информации о клиенте для конкретного человека, как показано на рис. 1-4. Черными стрелками показан запрос, идущий вниз к базе данных для получения данных о клиенте, а красными стрелками - ответ, идущий вверх к экрану для отображения данных. В данном примере информация о клиенте состоит как из данных о клиенте, так и из данных о заказах (заказах, сделанных клиентом).
Экран клиента отвечает за прием запроса и отображение информации о клиенте. Он не знает, где находятся эти данные, как они извлекаются и сколько таблиц базы данных необходимо запросить для получения информации. Получив запрос на получение информации о клиенте для конкретного лица, клиентский экран передает его в модуль делегата клиента. Этот модуль отвечает за то, чтобы знать, какие модули бизнес-уровня могут обработать этот запрос, а также как добраться до этого модуля и какие данные ему нужны (контракт). Объект customer на бизнес-уровне отвечает за агрегирование всей информации, необходимой для выполнения запроса (в данном случае для получения информации о клиенте). Этот модуль обращается к модулю customer dao (объект доступа к данным) на уровне персистентности для получения данных о клиенте, а также к модулю order dao для получения информации о заказе. Эти модули, в свою очередь, выполняют SQL-запросы для получения соответствующих данных и передают их обратно объекту customer на бизнес-уровне. Получив данные, объект customer агрегирует их и передает делегату customer, который затем передает эти данные на экран customer для представления пользователю.
С точки зрения технологии существуют буквально десятки способов реализации этих модулей. Например, на платформе Java экран клиента может представлять собой экран (JSF) Java Server Faces, соединенный с делегатом клиента в качестве компонента управляемого боба. Объект клиента на бизнес-уровне может быть локальным бобом Spring или удаленным бобом EJB3. Объекты доступа к данным, показанные в предыдущем примере, могут быть реализованы в виде простых POJO (Plain Old Java Objects), файлов MyBatis XML Mapper или даже объектов, инкапсулирующих необработанные вызовы JDBC или запросы Hibernate. С точки зрения платформы Microsoft, экран клиента может представлять собой модуль ASP (active server pages), использующий фреймворк .NET для доступа к модулям C# на бизнес-уровне, причем модули доступа к данным клиента и заказа могут быть реализованы как ADO (ActiveX Data Objects).
Соображения
Модель многоуровневой архитектуры является надежной моделью общего назначения, что делает ее хорошей отправной точкой для большинства приложений, особенно если вы не уверены в том, какая архитектура лучше всего подходит для вашего приложения. Однако при выборе этого паттерна есть несколько моментов, которые следует учитывать с точки зрения архитектуры.
Прежде всего, следует обратить внимание на так называемый "антипаттерн архитектурной воронки". Этот антипаттерн описывает ситуацию, когда запросы проходят через несколько уровней архитектуры как простая сквозная обработка с небольшим количеством логических операций на каждом уровне или вообще без них. Например, предположим, что презентационный уровень отвечает на запрос пользователя на получение данных о клиенте. Презентационный уровень передает запрос на бизнес-уровень, который просто передает запрос на уровень постоянства, который затем выполняет простой SQL-вызов на уровень базы данных для получения данных о клиенте. Затем данные передаются обратно по стеку без какой-либо дополнительной обработки или логики для агрегирования, вычисления или преобразования данных.
В каждой многоуровневой архитектуре есть как минимум несколько сценариев, которые попадают в антипаттерн "архитектурная воронка". Главное, однако, проанализировать процент запросов, попадающих в эту категорию. Правило 80-20 обычно является хорошей практикой, позволяющей определить, сталкиваетесь ли вы с проблемой "архитектурной воронки". Обычно около 20% запросов представляют собой простую сквозную обработку, а 80% запросов имеют определенную бизнес-логику, связанную с запросом. Однако если вы обнаружите, что это соотношение обратное и большинство запросов представляют собой простую сквозную обработку, вам следует рассмотреть возможность сделать некоторые слои архитектуры открытыми, не забывая при этом, что контролировать изменения будет сложнее из-за отсутствия изоляции слоев.
Еще один момент, связанный со слоистой архитектурой, заключается в том, что она склонна к созданию монолитных приложений, даже если разделить презентационный и бизнес-уровни на отдельные развертываемые блоки. Хотя для некоторых приложений это может и не представлять проблемы, но с точки зрения развертывания, общей устойчивости и надежности, производительности и масштабируемости это создает некоторые потенциальные проблемы.
Анализ паттерна
В следующей таблице приведен рейтинг и анализ общих характеристик архитектуры для паттерна многоуровневой архитектуры. Оценка каждой характеристики основывается на естественной тенденции развития данной характеристики как возможности на основе типичной реализации паттерна, а также на том, чем данный паттерн известен в целом.
Общая маневренность
Анализ: Общая гибкость - это способность быстро реагировать на постоянно меняющуюся среду. Хотя изменения можно изолировать с помощью слоев изоляции данного паттерна, все же вносить изменения в этот архитектурный паттерн очень сложно и долго из-за монолитности большинства реализаций, а также из-за тесной связи компонентов, обычно присущей этому паттерну.
Простота развертывания
Анализ: В зависимости от способа реализации данного паттерна развертывание может стать проблемой, особенно для крупных приложений. Одно небольшое изменение в компоненте может потребовать переразвертывания всего приложения (или значительной его части), что приводит к необходимости планирования, планирования и выполнения развертывания в нерабочее время или в выходные дни.
В связи с этим данный паттерн не очень легко поддается конвейеру непрерывной доставки, что еще больше снижает общий рейтинг развертывания.
Тестируемость
Анализ: Поскольку компоненты относятся к определенным уровням архитектуры, другие уровни могут быть имитированы или заглушены, что делает данный паттерн относительно простым для тестирования. Разработчик может имитировать презентационный компонент или экран, чтобы изолировать тестирование внутри бизнес-компонента, а также имитировать бизнес-слой для тестирования определенной функциональности экрана.
Производительность
Анализ: Несмотря на то, что некоторые многоуровневые архитектуры могут работать хорошо, этот паттерн не подходит для высокопроизводительных приложений из-за неэффективности, связанной с необходимостью проходить через несколько уровней архитектуры для выполнения бизнес-запроса.
Масштабируемость
Анализ: Из-за тенденции к тесному соединению и монолитности приложений, построенных с использованием данного паттерна, их масштабирование обычно затруднено. Масштабировать многослойную архитектуру можно путем разделения слоев на отдельные физические развертывания или тиражирования всего приложения на несколько узлов, но в целом гранулярность слишком широка, что делает масштабирование дорогим.
Простота разработки
Анализ: Простота разработки получила относительно высокий балл, в основном потому, что этот паттерн хорошо известен и не является слишком сложным для реализации. Поскольку большинство компаний разрабатывают приложения, разделяя наборы навыков по уровням (презентация, бизнес, база данных), этот паттерн становится естественным выбором для разработки большинства бизнес-приложений. Связь между коммуникационной и организационной структурой компании и тем, как она разрабатывает программное обеспечение, описывается так называемым законом Конвея. Для получения более подробной информации об этой интересной взаимосвязи можно набрать в Google "Conway's law".
Перевод книги "Software Architecture Patterns".