Обмін об'єктами DTO між мікросервісами


15

TL; DR - Чи нормально поділитися бібліотекою POJO між службами?

Як правило, ми хочемо тримати обмін між службами суворо обмеженим, якщо це неможливо. Були певні дискусії щодо того, чи повинна служба, яка обмінюється даними, надавати клієнтську бібліотеку для клієнтів. Client-lib, як правило, необов’язковий для того, щоб клієнт сервісу міг користуватися і може споживати API, однак вони бажають, будь то клієнт-lib, або використовують альтернативну мову та використовують загальні аспекти бібліотеки тощо.

У моєму випадку - я вважаю службу, яка створює об’єкт даних. Припустимо, що цей об’єкт є ПЕТ. Основними даними не є об'єкт бази даних, а суто POJO. Цей POJO - це те, що визначено в API. Припустимо: домашні тварини - вік, вага, ім'я, власник, адреса, види тощо.

Сервіс 1 - PetKeeper: Він з будь-якої причини генерує домашнього улюбленця та зберігатиме всі дані, і повинен посилатися на цю послугу, щоб отримати домашнього улюбленця або внести зміни до Улюбленця, скажімо, змінити ім’я або змінити адресу потрібно через Дзвінок API до цієї служби.

Служба 2 - PetAccessor: ця служба збирає домашніх тварин і робить перевірки перевірки

Служба 3,4 - Більше проміжних дзвінків по службі

Сервіс 5 - Інтерфейс користувача

Вони дуже довільні, але справа проста. Користувацький інтерфейс або якась служба, що звертається до користувача, бажають певним чином представити цей об'єкт "PET" Він повинен викликати через API службу, яка викликає службу, яка викликає службу тощо, поки не надійде до служби, яка збирає необхідну інформацію і не розпочне ретрансляцію назад. Нарешті, сервіс інтерфейсу має об’єкт PET для відображення.

Це досить часто - але з нашим абсолютним менталітетом ми копіювали об’єкт PET у кожній службі. Принцип DRY (не повторюйте себе) застосовується лише до коду INSIDE служби і не застосовується для всіх служб, але справа все ще існує. Що робити, якщо ми додамо поле ... ми повинні змінити 5 служб POJO в кожному.

--OR-- Ми можемо надати бібліотеку Pet-Objects, яка містить частину pojo з API, і кожна служба може імпортувати / залежати від бібліотеки. Існує не залежність від самих служб (служб), а лише загальна бібліотека. Мені подобається ця ідея, тому що в кожній службі є один і той же тип об'єкта, і оновлення простіше. Але мене турбують боги-об’єкти.

Які професіонали / конфесії - який найкращий дизайн? Що ви зробили для передачі даних між службами, щоб мінімізувати повторення тих же класів POJO, а також залишатись роз'єднаними?


Бог-об’єкт? en.wikipedia.org/wiki/God_object

@DaiKaixian: Напевно, ви не пропонуєте, щоб ОП пішла з об'єктом Бога, чи не так? Це звичайно вважається анти-зразком.
Макото

Я згоден з відповіддю @javaguy.

І я також хочу сказати, ви можете розглянути можливість відвідувачів. en.wikipedia.org/wiki/Visitor_pattern . Створіть усе поле та сеттер / геттер у POJO та поділіть його між мікросервісами. Якщо ви хочете виконати якусь операцію над POJO в різних мікросервісах, напишіть трохи VisitorClass.

Спасибі. Моє вагання з цією «спільною бібліотекою» полягає в тому, що вона зростатиме. І там будуть об’єкти, про які піклуються лише послуги 1 і 3, або 2 і 4, або всі, або будь-яка їх комбінація. Тип загального пакету бібліотеки DTO, у якому є всі DTO, чи я використовую шаблон вістора, чи простий DTO POJO чи що ні. Чи прийнятно включати всі ці об'єкти, але намагатися підтримувати їх якнайкраще? Принаймні, об’єкти надаються тим, хто їх потребує, якщо вони хочуть ними користуватися ...

Відповіді:


5

Який найкращий дизайн?

Ви можете повторно використовувати той самий об’єкт Pet DTO серед сервісів допоміжного сервісу (які обробляють типову логіку бізнесу), але коли мова заходить про рівень презентації (інтерфейс користувача), як правило, є хорошою практикою використовувати FormBean (інший боб із доданими полями для логіки презентації), щоб відбувся чіткий поділ між логікою презентації та логікою бізнесу .

Це потрібно, тому що послуги повинні бути повторно використані, і одна служба може бути піддана / повторно використана декількома / різними кінцевими точками (наприклад, фронтендом або іншим веб-сервісом тощо), і кожна з цих кінцевих точок може потребувати додаткових полів, які будуть заповнені відповідні контролери або рівні (як адаптери) над службами.

Що ви зробили для передачі даних між службами, щоб мінімізувати повторення тих же класів POJO, а також залишатись роз'єднаними?

Якщо ви використовуєте єдиний квадратик між бізнес-та веб-ярусами, то ви щільно з'єднуєте логіку презентації з логікою бізнесу, що не є хорошою практикою, і ви в кінцевому підсумку зміните послуги для вимоги у Frontend (як, наприклад, інший формат дати) відображатиметься в інтерфейсі користувача). Крім того , щоб зробити цей процес заповнення / копіювання даних через боб (як DTO в компонент форму або навпаки), ви можете використовувати бібліотеки , такі як Apache BeanUtils.copyProperties() або бульдозер , щоб уникнути шаблонного коду .


Я погоджуюсь, що рівень презентації, ймовірно, повинен десеріалізувати вхідний корисний набір у вигляді бобів презентації з різними атрибутами, якщо потрібно. Але взагалі, чи нормально повторно використовувати той самий об’єкт DTO у всіх сервісах, які беруть запуск? Як правило, ми намагаємось розділити ці пакети DTO на менші пакети лише для кількох послуг, які їм потрібні. Я втомився мати якийсь шухлядний пакет бібліотеки DTO, який містить DTO для 75+ мікросервісів, від яких залежать усі служби. Якщо це не нормально, оскільки в першу чергу це просто об'єкти DTO?

Так, ви, очевидно, можете повторно використовувати той самий об’єкт DTO для всіх таких самих сервісів, як ваш, PetServicesщоб уникнути дублювання. Але моя думка не в тому, щоб близько поєднати бекенд і фронтенд, ось і все.
розробник

4

Якщо DTO представляє один і той же суб’єкт господарювання у всіх мікропослугах, то між службами повинен бути лише один клас. Дублювати код для одного і того ж об'єкта (майже) ніколи не правильно.


3
Поділ DTO через мікросервіси - це кошмар. "Чи є в цій версії вже це поле? Гм, можливо?" Через деякий час у вас вийде справжній безлад. Дублюваний код хороший у цьому випадку.
Mejmo

1

То, як я планую це зробити зараз, полягає в тому, що кожен сервіс пакує лише DTO і вводить їх у Nexus як jar lib. Коли потрібні інші сервіси, вони отримають ліги DTO як залежність у manve / gradle. Якщо нова версія DTO випущена на одній службі, її штраф до тих пір, коли стара версія також підтримується одночасно, тому не порушуйте зворотну сумісність, версію тощо. Для запобігання циркуляційної залежності вам краще відокремити послугу від упаковки dto

Тепер погляньте на бекенд-фронт і навпаки, я не погоджуюся з попередніми коментарями, що інтерфейс користувача як шару презентації відрізняється. ЦЕ НЕ ТАК!!! Користувальницький інтерфейс - лише черговий мікросервіс, який також споживає та створює події.

Напрям від «вихідного до фронту», що я роблю, - це перетворити POJO (dtos) в інтерфейси Typescript та пакувати в NPM і завантажити їх також у Nexus. Потім проект, заснований на користувальницькому інтерфейсі, споживає та використовує ці. Це спосіб обслуговування інтерфейсу користувача.

Напрямок "Frontend-to-backkend" Для інтерфейсу інтерфейсу для подій рівня обслуговування я конвертую інтерфейси Typescript і перетворюю їх у POJO (dtos), пакую як jar та завантажую в Nexus (або деякий репо) у вигляді баночки, яку споживають сервіси бекенда.

Ці процеси легко обробляються процесами CI (Travis, Gitlab CI тощо)

Будь-які коментарі до цього підходу вітаються.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.