Udostępnianie obiektów DTO między mikrousługami

15

TL; DR - Czy można współdzielić bibliotekę POJO między usługami?

Zasadniczo chcemy, aby dzielenie między usługami było ściśle ograniczone do żadnego, jeśli to możliwe. Odbyła się dyskusja, czy usługa udostępniająca dane powinna zapewniać bibliotekę klienta do użytku przez klientów. Klient-lib jest ogólnie opcjonalny dla klienta usługi i może korzystać z interfejsu API, jakkolwiek mu się podoba, czy używać klienta-lib, czy używać alternatywnego języka i korzystać z ogólnych aspektów biblioteki i tym podobnych.

W moim przypadku - uważam usługę, która tworzy obiekt danych. Załóżmy, że ten obiekt to PET. NIE jest to jednostka bazy danych, ale ściśle POJO, która pośrednio reprezentuje dane bazowe. To POJO zdefiniowało API. Załóżmy: zwierzę domowe - wiek, waga, imię, właściciel, adres, gatunek itp.

Usługa 1 - PetKeeper: Generuje zwierzaka z dowolnego powodu i zachowuje wszystkie dane i musi odwoływać się do tej usługi, aby uzyskać zwierzaka lub wprowadzić zmiany w zwierzaku, powiedzmy, że zmiana imienia lub zmiana adresu musi zostać wykonana za pomocą Wywołanie interfejsu API do tej usługi.

Usługa 2 - PetAccessor: Ta usługa zbiera zwierzaka i wykonuje kontrole walidacyjne

Usługa 3,4 - Więcej pośrednich połączeń serwisowych

Usługa 5 - interfejs użytkownika

Są to bardzo arbitralne, ale sprawa jest prosta. Interfejs użytkownika lub jakaś usługa skierowana do użytkownika chce w jakiś sposób przedstawić ten obiekt „PET”. Musi wywoływać za pośrednictwem interfejsu API usługę, która wywołuje usługę, która wywołuje usługę itp., Dopóki nie dotrze do usługi, która zbiera wymagane informacje i rozpoczyna przekazywanie z powrotem. Wreszcie usługa interfejsu użytkownika ma obiekt PET do wyświetlenia.

Jest to dość powszechne - ale przy naszej absolutnej mentalności duplikowaliśmy obiekt PET w każdej usłudze. Zasada DRY (nie powtarzaj się) dotyczy tylko kodu WEWNĄTRZ usługi i nie dotyczy wszystkich usług, ale kwestia nadal istnieje. Co jeśli dodamy pole ... musimy zmodyfikować po 5 usług POJO w każdym.

--LUB - Możemy zapewnić bibliotekę obiektów-zwierząt domowych, która zawiera niektóre pojęcia z interfejsu API, a każda usługa może importować / zależeć od biblioteki. Nie ma zależności od samych usług, ale tylko od biblioteki ogólnej. Podoba mi się ten pomysł, dzięki czemu każda usługa ma ten sam typ obiektu, a aktualizacje są łatwiejsze. Ale martwię się o Boskie Przedmioty.

Jakie są zalety / wady - jaki jest najlepszy projekt? Co zrobiłeś, aby przesyłać dane między usługami, aby zminimalizować powtarzanie tych samych klas POJO, jednocześnie pozostając rozłączonym?

Aerith
źródło
@DaiKaixian: Z pewnością nie sugerujesz, że PO idzie z przedmiotem Boga, prawda? Jest to rutynowo uważane za anty-wzór.
Makoto
Zgadzam się z odpowiedzią @javaguy.
Chcę też powiedzieć, że możesz wziąć pod uwagę wzór odwiedzin. en.wikipedia.org/wiki/Visitor_pattern . Zrób całe pole i setter / getter w POJO i udostępnij je między mikrousługami. Jeśli chcesz wykonać operację na POJO w innej mikrousługie, napisz trochę VisitorClass.
Dzięki. Moje wahanie związane z posiadaniem „wspólnej biblioteki” polega na tym, że będzie się ona powiększać. Będą tam obiekty, o które dbają tylko usługi 1 i 3, 2 i 4, wszystkie lub dowolna ich kombinacja. Rodzaj ogólnego pakietu bibliotek DTO, który ma wszystkie DTO, niezależnie od tego, czy używam wzorca Vistora, czy zwykłego DTO POJO, czy czegoś innego. Czy to dopuszczalne, aby uwzględnić wszystkie te obiekty, ale starać się zachować je jak najlepiej? Przynajmniej przedmioty są dostarczane tym, którzy ich potrzebują, JEŻELI chcą ich użyć ...

Odpowiedzi:

5

Jaki jest najlepszy projekt?

Możesz ponownie użyć tego samego obiektu Pet DTO wśród usług zaplecza (które przetwarzają typową logikę biznesową), ale jeśli chodzi o warstwę prezentacji (interfejs użytkownika), ogólnie dobrą praktyką jest użycie FormBean (innej fasoli z dodanymi polami) dla logiki prezentacji), dzięki czemu będzie wyraźne oddzielenie logiki prezentacji od logiki biznesowej .

Jest to wymagane, ponieważ usługi powinny być wielokrotnego użytku, a pojedyncza usługa może być ujawniona / ponownie wykorzystana przez wiele / różnych punktów końcowych (takich jak interfejs użytkownika lub może to być inna usługa internetowa itp.), A każdy z tych punktów końcowych może wymagać dodatkowych pól, które zostaną wypełnione przez odpowiednie Kontrolery lub warstwy (takie jak adaptery) nad usługami.

Co zrobiłeś, aby przesyłać dane między usługami, aby zminimalizować powtarzanie tych samych klas POJO, jednocześnie pozostając rozłączonym?

Jeśli używasz pojedynczego komponentu bean między warstwami biznesowymi i sieciowymi, to ściśle łączysz logikę prezentacji z logiką biznesową, co nie jest dobrą praktyką, i ostatecznie zmienisz usługi dla wymagań w interfejsie użytkownika (np. Inny format daty do wyświetlenia w interfejsie użytkownika). Ponadto, aby ten proces zapełniania / kopiowania danych między komponentami bean (np. DTO do FormBean lub Viceversa), można użyć bibliotek takich jak Apache BeanUtils.copyProperties() lub Dozer, aby uniknąć kodu płyty zbiorczej .

deweloper
źródło
Zgadzam się, że warstwa prezentacji powinna prawdopodobnie dokonać deserializacji przychodzącego ładunku jako fasola prezentacji z różnymi atrybutami w razie potrzeby. Ale ogólnie, czy można ponownie używać tego samego obiektu DTO we wszystkich usługach zaplecza? Zasadniczo staramy się rozdzielić te pakiety DTO na mniejsze pakiety tylko dla kilku usług, które ich potrzebują. Mam dość szuflady pakietu biblioteki DTO, który zawiera DTO dla ponad 75 mikrousług, od których zależą wszystkie usługi. Chyba że to w porządku, ponieważ to tylko obiekty DTO są opcjonalne?
Tak, oczywiście możesz ponownie użyć tego samego obiektu DTO we wszystkich usługach zaplecza, takich jak Twoja, PetServicesaby uniknąć powielania. Ale moim celem nie jest ścisłe połączenie zaplecza i interfejsu, to wszystko.
programista
4

Jeśli DTO reprezentuje ten sam podmiot gospodarczy we wszystkich mikrousługach, powinna istnieć tylko jedna klasa, dzielona między usługi. Duplikat kodu dla tego samego obiektu (prawie) nigdy nie jest poprawny.

Jim Garrison
źródło
3
Udostępnianie DTO między mikrousługami to koszmar. „Czy ta wersja ma już to pole? Może Hm?” Po pewnym czasie skończy się prawdziwy bałagan. W tym przypadku dobry jest powielony kod.
Mejmo
1

Teraz planuję to zrobić tak, że każda usługa pakuje tylko DTO i umieszcza je w Nexusie jako jar lib. Gdy inne usługi będą tego potrzebować, dostaną te DTO lib (s) jako zależność w manve / gradle. Jeśli nowa wersja DTO zostanie wydana w jednej usłudze, będzie obowiązywać, dopóki stara wersja będzie również obsługiwana w tym samym czasie, więc nie naruszaj kompatybilności wstecznej, wersjonowania itp., Więc jest to obszar backend-to-backend. Aby zapobiec uzależnieniu od sieci, lepiej jest oddzielić usługę od pakowania Dto

Teraz spójrz na backend-to-frontend i vice versa Nie zgadzam się z poprzednimi komentarzami, że interfejs użytkownika jako warstwa prezentacji jest inna. NIE JEST!!! Interfejs użytkownika jest dla mnie kolejną mikrousługą, która również zużywa i wytwarza zdarzenia.

Kierunek backend-to-frontend To, co robię, to konwersja POJO (dtos) na interfejsy maszynopisu i pakowanie w NPM i ładowanie ich również do Nexusa. Projekt oparty na interfejsie użytkownika nodejs następnie je wykorzystuje i wykorzystuje. Jest to sposób obsługi interfejsu użytkownika.

Kierunek frontend -backend Aby interfejs użytkownika obsługiwał zdarzenia warstwy, konwertuję interfejsy maszynopisu i konwertuję je na POJO (dtos), pakuję jako jar i przesyłam do Nexusa (lub repozytorium) w postaci jar przeznaczonej do użytku przez usługi backendu.

Procesy te są łatwo obsługiwane przez procesy CI (Travis, Gitlab CI itp.)

Wszelkie uwagi dotyczące tego podejścia są mile widziane.

kensai
źródło