Рис. 3.2. В микросервисах представляются вложенные ограниченные контексты, скрытые внутри товарного склада
Рис. 3.3. Ограниченные контексты внутри товарного склада, выскочившие на свои собственные контексты самого верхнего уровня
В общем, какого-либо непреложного правила о том, какой из подходов имеет больший смысл, просто не существует. Но выбор подхода с вложенными контекстами, а не подхода с полным отделением должен основываться на структуре вашей организации. Если выполнение заказов, управление запасами и получение товаров управляются разными командами, то они, по-видимому, заслуживают своего статуса микросервисов самого верхнего уровня. Если же все они управляются одной командой, больше смысла будет в модели с вложениями. Все дело во взаимосвязанности организационных структур и архитектуры программного продукта, которая рассматривается ближе к концу книги, в главе 10.
Еще одной причиной, по которой нужно отдавать предпочтение подходу с использованием вложений, может быть разбиение архитектуры на части с целью упрощения тестирования. Например, при тестировании сервисов, использующих товарный склад, не нужно будет ставить заглушки на каждый сервис внутри контекста товарного склада, как при более приблизительном API. Это также может дать вам единицу изолированности при рассмотрении более масштабных тестов. К примеру, я могу принять решение об использовании сквозных тестов при запуске всех сервисов внутри контекста товарного склада, но для всех других сотрудничающих компонентов системы могу их заглушить. Более подробно тестирование и изоляция будут рассматриваться в главе 7.
Изменения, реализуемые в нашей системе, зачастую относятся к изменениям, требующимся бизнесу, чтобы определить поведение системы. Мы изменяем функциональность, то есть возможности, которые раскрываются для наших потребителей. Если наши системы прошли декомпозицию по ограниченным контекстам, представляющим область, изменения, которые нужно произвести, скорее всего, должны быть изолированы одной отдельно взятой границей микросервиса. Это сократит количество мест, в которые нужно вносить изменение, и позволит быстро развернуть это изменение.
Важно также продумать обмен данными между этими микросервисами с точки зрения одних и тех же бизнес-концепций. Моделирование программного продукта относительно вашей области бизнеса не должно останавливаться на замысле ограниченных контекстов. Одинаковые понятия и идеи, совместно используемые отделами вашей организации, должны быть отображены в интерфейсах. Было бы полезно продумать формы, отправляемые между этими микросервисами, почти так же, как и формы, отправляемые в пределах всей организации.
Полезно было бы взглянуть на то, что может пойти не так, когда сервисы смоделированы неправильно. В недавнем прошлом я с рядом коллег работал с клиентом из Калифорнии, помогая компании внедрить несколько инструкций по очищению кода и приближению к автоматизированному тестированию. Начали мы с самого легкодоступного — декомпозиции сервиса и тут заметили нечто более тревожное. Я не могу вдаваться в подробности того, чем занималось приложение, но оно относилось к категории общедоступных и имело обширную глобальную клиентскую базу.
Команда и система разрослись. Изначально в представлении отдельно взятого человека система вбирала в себя все больше и больше функций и у нее становилось все больше и больше пользователей. В конце концов организация решила увеличить штат команды — создать новую группу разработчиков, находящуюся в Бразилии, и переложить на нее часть работы. Система подверглась разбиению, причем одна половина приложения, по существу, утратила конкретное «гражданство» и стала представлять собой общедоступный сайт (рис. 3.4). Другая половина системы стала простым интерфейсом удаленного вызова процедуры (Remote Procedure Call (RPC)) в отношении хранилища данных. Представьте, что вы, по сути, берете в своем исходном коде уровень хранилища данных и превращаете его в отдельный сервис.