Глава 9. Представление бизнес-логики 159
Несмотря на сказанное выше, обязанности приложения по обработке вариантов ис-
пользования никак нельзя назвать банальными. Создание, обновление или удаление в
приложении объекта домена, не говоря уже о проверке правильности его содержимого,
требует отправки уведомлений пользователям или другим интефированным приложени-
ям. Координацией откликов и отправлением их в рамках атомарных транзакций и зани-
маются операции слоя служб.
К сожалению, определить, в какие абстракции слоя служб необходимо сфуппировать
родственные операции, далеко не просто. Универсального рецепта для решения этой
проблемы не существует. Небольшому приложению вполне может хватить одной абст-
ракции, названной по имени самого приложения. Более крупные приложения обычно
разбиваются на несколько подсистем, каждая из которых включает в себя вертикальный
срез всех имеющихся архитектурных слоев. В этом случае я предпочитаю создавать по
одной одноименной абстракции для каждой подсистемы. В качестве альтернатив можно
предложить создание абстракций, отражающих основные составляющие модели пред-
метной области, если таковые отличаются от подсистем (например, ContractService,
ProductsService) или абстракций, названных в соответствии с типами поведения
(например, RecognitionServi.ee).
ОСОБЕННОСТИ JAVA-РЕАЛИЗАЦИИ
Оба подхода, упомянутых в предыдущем разделе, — создание интерфейса
доступа к домену и построение сценария операции — допускают реализацию
класса слоя служб в виде объекта POJO или же компонента сеанса, не имею-
щего состояний. К сожалению, какое бы решение вы не выбрали, вам обяза-
тельно придется чем-то пожертвовать — либо простотой тестирования, либо
легкостью управления транзакциями. Так, объекты POJO легче тестировать,
поскольку для их функционирования не нужны EJB-контейнеры. С другой
стороны, слою служб, реализованному в виде объекта POJO, будет труднее
работать со службами распределенных транзакций, управляемых на уровне
контейнера, особенно при обмене данными между разными службами. Компо-
ненты сеанса, напротив, хорошо справляются с распределенными транзакция-
ми, управляемыми на уровне контейнера, однако могут быть протестированы и
запущены только при наличии EJB-контейнера. Проще говоря, из двух зол
приходится выбирать меньшее.
Я предпочитаю реализовать слой служб с использованием локальных интер-
фейсов и сценария операции в виде компонентов сеанса EJB 2.0, обращающих-
ся за логикой домена к классам объектов домена POJO. Что ни говори, а слой
служб очень удобно реализовать в виде компонента сеанса, не меняющего со-
стояния, потому что в EJB предусмотрена поддержка распределенных транзак-
ций, управляемых на уровне контейнера. Кроме того, с помощью локальных
интерфейсов, появившихся в EJB 2.0, слой служб может использовать весьма
ценные службы транзакций и в то же время избежать всех неприятностей, свя-
занных с вопросами распределения объектов.
Говоря о Java, хочу обратить ваше внимание на отличие слоя служб от
интерфейса доступа посредством компонентов сеанса (Session Facade) — типового
решения для J2EE, описанного в [3, 28]. Разработчики интерфейса доступа по-
средством компонентов сеанса намеревались избежать падения производитель-
ности, связанной с чрезмерным количеством удаленных вызовов компонентов