При подходе с использованием хореографического принципа вместо этого можно обязать сервис клиентов выдавать в асинхронной манере события, которые бы оповещали о создании клиента. Затем, как показано на рис. 4.4, сервис электронной почты, сервис обычной почты и банк очков лояльности просто подписались бы на подобные события и реагировали на них соответствующим образом. Этот подход имеет намного более разобщенный характер. Если какому-либо другому сервису потребуется добраться до создания клиента, ему просто нужно будет подписаться на события и выполнять по мере необходимости возложенную на него задачу. Недостатком является то, что явное представление бизнес-процесса, которое показано на рис. 4.2, теперь отражается в нашей системе лишь в неявном виде.
Рис. 4.4. Подход к созданию клиента с использованием хореографического принципа
Это означает необходимость выполнения дополнительной работы, дающей возможность наблюдать и отслеживать надлежащее развитие событий. Например, узнаете ли вы о том, что банк очков лояльности имеет некий изъян и по какой-то причине не завел нужную учетную запись? Одним из предпочитаемых мной подходов является построение системы наблюдения, которая в точности соответствует представлению бизнес-процессов, показанному на рис. 4.2, с последующим отслеживанием того, что делает каждый сервис в качестве независимой единицы. Это позволит замечать случайные исключения, отображаемые на более явное течение процесса. Рассмотренная ранее блок-схема является не побудительной причиной, а всего лишь одной из линз, через которую можно увидеть характер поведения системы.
Вообще-то я понял, что системы, больше тяготеющие к подходу с использованием хореографического принципа, обладают намного более слабой связанностью и большей гибкостью и податливостью к изменениям. Но при этом приходится выполнять дополнительную работу для наблюдения и отслеживания процессов, проходящих через системные границы. Я понял, что системы, обладающие самой сильной приверженностью к использованию оркестрового принципа, получаются слишком хрупкими и требующими более высоких затрат на внесение изменений. Помня об этом, я являюсь стойким приверженцем нацеливания на реализацию системы с использованием хореографического принципа, где каждый сервис обладает достаточным интеллектом для понимания своей роли во всем танце.
Мы можем рассмотреть довольно много факторов. Синхронные вызовы проще, и мы будем осведомлены о том, что все идет намеченным курсом. Если нам нравится семантика «запрос — ответ», но мы имеем дело с долговременными процессами, можем просто инициировать асинхронные запросы и ждать обратных вызовов. В то же время совместная работа с использованием асинхронных событий помогает ввести подход, использующий хореографический принцип, который может привести к созданию намного более разобщенных сервисов, к чему, собственно, мы и стремимся, чтобы обеспечить для своих сервисов независимую разъемность.
Разумеется, никто нам не мешает заняться смешиванием и подгонкой. К тому или иному стилю некоторые технологии могут подходить более естественно. Тем не менее нужно оценить особенности ряда различных технических реализаций, что в дальнейшем поможет сделать правильный выбор.
Для начала обратимся к двум технологиям, которые хорошо подходят для рассмотрения стиля «запрос — ответ»: удаленному вызову процедуры (RPC) и передаче репрезентативного состояния (REST).
Удаленный вызов процедуры является технологией локального вызова, который выполняется где-то на удаленном сервисе. У технологии RPC имеется множество разновидностей. Некоторые из них основаны на применении определенного интерфейса (SOAP, Thrift, Protocol Buffers). Использование отдельного определения интерфейса может облегчить создание клиентских и серверных заглушек для различных технологических стеков, таким образом, к примеру, у меня может быть Java-сервер, выставляющий SOAP-интерфейс, и. NET-клиент, созданный из определения интерфейса на языке описания веб-сервисов (WSDL). Другие технологии вроде Java RMI предусматривают более тесную связанность между клиентом и сервером, требующую, чтобы оба они использовали одинаковую исходную технологию, но при этом исключается необходимость в определении совместно используемого интерфейса. Но все эти технологии имеют одинаковые основные характеристики в том смысле, что они делают локальный вызов, похожий на удаленный вызов.