Глава 2. Организация бизнес-логики 57
представить слой служб в виде промежуточного интерфейса, который только и делает,
что направляет адресуемые ему вызовы к нижележащим объектам. В такой ситуации слой
служб обеспечивает API, ориентированный на определенные варианты использования (use
cases) приложения, и предоставляет удачную возможность включить в код функции-
оболочки, ответственные за управление транзакциями и проверку безопасности.
Другая крайность — в рамках слоя служб представить большую часть логики в виде
сценариев транзакции. Нижележащие объекты домена в этом случае могут быть тривиаль-
ными; если они сосредоточены в модели предметной области, удастся обеспечить их одно-
значное отображение на элементы базы данных и воспользоваться более простым вари-
антом слоя источника данных (скажем, активной записью (Active Record, 182)).
Между двумя указанными полюсами существует вариант, представляющий собой
больше, нежели "смесь" двух подходов: речь идет о модели "контроллер-сущность"
("controller—entity") (ее название обязано своим происхождением одному общеупотреби-
тельному приему, основанному на результатах из [22]). Главная особенность модели за-
ключается в том, что логика, относящаяся к отдельным транзакциям или вариантам ис-
пользования, располагается в соответствующих сценариях транзакции, которые в данном
случае называют контроллерами (или службами). Они выполняют роль входных кон-
троллеров в типовых решениях модель-представление-контроллер (Model View Controller,
347) и контроллер приложения (Application Controller, 397) (вы познакомитесь с ними поз-
же) и поэтому называются также контроллерами вариантов использования (use case control-
ler). Функции, характерные одновременно для нескольких вариантов использования, пе-
редаются объектам-сущностям (entities) домена.
Хотя модель "контроллер—сущность" распространена довольно широко, я отношусь
к ней с прохладцей. Контроллеры вариантов использования, подобные любому сценарию
транзакции, негласно поощряют дублирование фрагментов кода. Моя точка зрения тако-
ва: если вы сказали "а", решив прибегнуть к модели предметной области, то будьте лю-
безны произнести и "б", отведя этому решению доминирующую роль. Единственное
достойное исключение, вероятно, связано с изначальным использованием сценария
транзакции совместно со шлюзом записи данных. В такой ситуации имеет смысл передать
повторяющиеся функции шлюзам записи данных, преобразовав их в простую модель
предметной области с помощью решения активная запись. Впрочем, я бы так не делал
(может быть, к этому меня вынудила бы только необходимость модернизации сущест-
вующего приложения).
Здесь речь не идет о том, что вы никогда не должны использовать объекты служб, со-
держащие бизнес-логику; просто я хочу подчеркнуть, что создавать на их основе фикси-
рованный слой кода необязательно. Процедурные служебные объекты подчас весьма
удобны для представления логики, но я склоняюсь к тому, чтобы применять их только по
мере необходимости, а не в виде архитектурного слоя.
Таким образом, на вашем месте я предпочел бы самый тонкий слой служб, какой
только возможен (если он вообще нужен). Обычно же я добавляю его только тогда, когда
он действительно необходим. Впрочем, мне знакомы хорошие специалисты, которые
всегда применяют слой служб, содержащий взвешенную долю бизнес-логики, так что
этим моим советом вы можете благополучно пренебречь. Рэнди Стаффорд (Randy Staf-
ford) добился впечатляющих успехов на ниве проектирования программного обеспече-
ния, используя модели с "богатым" слоем служб, поэтому я и попросил его написать од-
ноименный раздел этой книги.