TL; DR. Можно ли делиться библиотекой POJO между службами?
Как правило, нам нравится строго ограничивать обмен между службами, если это возможно. Были некоторые споры о том, должна ли служба, предоставляющая данные, предоставлять клиентскую библиотеку для использования клиентами. Клиент-библиотека обычно необязательна для использования клиентом службы и может использовать API, как им угодно, использовать ли клиент-библиотеку или использовать альтернативный язык и использовать общие аспекты библиотеки и тому подобное.
В моем случае - я рассматриваю сервис, который создает объект данных. Давайте предположим, что этот объект является ПЭТ. Это не объект базы данных, а строго POJO, который неявно представляет базовые данные. Этот POJO - это то, что определил API. Предположим: домашнее животное - возраст, вес, имя, владелец, адрес, вид и т. Д.
Сервис 1 - PetKeeper: он будет генерировать питомца по любой причине и сохранит все данные и должен ссылаться на эту услугу для получения питомца или внесения изменений в питомца, скажем, изменение имени или изменение адреса должно быть выполнено через API вызов этого сервиса.
Служба 2 - PetAccessor: эта служба собирает питомца и делает проверки
Сервис 3,4 - Дополнительные промежуточные сервисные звонки
Сервис 5 - Интерфейс пользователя
Это очень произвольно, но суть проста. Пользовательский интерфейс или какой-либо пользовательский сервис желает каким-то образом представить этот объект «PET». Он должен вызывать через API сервис, который вызывает сервис, который вызывает сервис и т. Д., Пока он не достигнет сервиса, который собирает необходимую информацию и запускает ретрансляцию. Наконец, у сервиса UI есть объект PET для отображения.
Это довольно часто - но с нашим абсолютным менталитетом мы дублировали объект PET в каждом сервисе. Принцип СУХОЙ (не повторяйся) применим только к коду ВНУТРИ услуги и не распространяется на другие службы, но суть все еще в силе. Что если мы добавим поле ... мы должны изменить 5 сервисов POJO в каждом.
--OR-- Мы можем предоставить Pet-Objects-Library, которая содержит некоторые pojo из API, и каждый сервис может импортировать / зависеть от библиотеки. Нет зависимости от самих сервисов, но есть только общая библиотека. Мне нравится эта идея, так что каждый сервис имеет один и тот же тип объекта, и обновления проще. Но я беспокоюсь о Боге-объектах.
Какие плюсы / минусы - какой дизайн лучший? Что вы сделали для передачи данных между сервисами, чтобы минимизировать повторение тех же классов POJO, оставаясь при этом не связанными?
источник
Ответы:
Вы можете повторно использовать один и тот же объект
Pet
DTO среди внутренних сервисов (которые обрабатывают типичную бизнес-логику), но когда дело доходит до уровня представления (пользовательский интерфейс), обычно рекомендуется использовать FormBean (другой компонент с добавленными полями). для логики представления), чтобы было четкое разделение между логикой представления и бизнес-логикой .Это необходимо, потому что сервисы должны быть многократно используемыми, и один сервис может быть доступен / повторно использоваться несколькими / разными конечными точками (например, внешним интерфейсом или может быть другим веб-сервисом и т. Д.), И каждая из этих конечных точек может требовать дополнительных полей, которые будут заполнены соответствующие контроллеры или уровни (например, адаптеры) над сервисами.
Если вы используете один компонент между бизнес-уровнями и веб-уровнями, то вы тесно связываете логику представления с бизнес-логикой, что не является хорошей практикой, и в итоге вы меняете службы для требований во внешнем интерфейсе (как, например, другой формат даты). быть показано в пользовательском интерфейсе). Кроме того, чтобы сделать этот процесс заполнения / копирования данных между компонентами (такими как DTO в FormBean или Viceversa), вы можете использовать библиотеки, такие как Apache
BeanUtils.copyProperties()
или Dozer, чтобы избежать шаблонного кода .источник
PetServices
во избежание дублирования. Но моя точка зрения не в том, чтобы тесно связывать бэкэнд и фронтэнд, вот и все.Если DTO представляет один и тот же бизнес-объект во всех микросервисах, то должен быть только один класс, совместно используемый службами. (Почти) никогда не правильно иметь дублированный код для одного и того же объекта.
источник
Способ, которым я планирую сделать это сейчас, заключается в том, что каждый сервис упаковывает только DTO и помещает их в Nexus как jar lib. Когда другие сервисы нуждаются в них, они получают DTO lib (s) в качестве зависимости в manve / gradle. Если новая версия DTO выпущена на одном сервисе, это нормально, если одновременно поддерживается и старая версия, поэтому не нарушайте обратную совместимость, управление версиями и т. Д., Так что это область backend-to-backend. Также для предотвращения циркулярной зависимости лучше отделить сервис от dto-упаковки
Теперь посмотрим на бэкэнд-интерфейс, и наоборот, я не согласен с предыдущими комментариями о том, что пользовательский интерфейс как уровень представления отличается. НЕ ТО!!! Интерфейс для меня - это просто еще один микросервис, который также потребляет и генерирует события.
Направление от бэкенда к внешнему интерфейсу Что я делаю, так это конвертирую POJO (dtos) в интерфейсы Typescript, упаковываю в NPM и загружаю их в Nexus. Затем проект, основанный на UI nodejs, использует и использует их. Это способ обслуживания пользовательского интерфейса.
Направление от внешнего интерфейса к внутреннему Для событий пользовательского интерфейса на уровне сервисов я конвертирую интерфейсы Typescript и преобразую их в POJO (dtos), упаковываю как jar и загружаю в Nexus (или некоторое хранилище) в виде jar для использования бэкэнд-сервисами.
Эти процессы легко обрабатываются процессами CI (Travis, Gitlab CI и т. Д.)
Любые комментарии к этому подходу приветствуются.
источник