Partage d'objets DTO entre microservices

15

TL; DR - Est-il possible de partager une bibliothèque POJO entre les services?

Généralement, nous aimons garder le partage entre services strictement limité à aucun si possible. Il y a eu un débat sur la question de savoir si le service qui partage des données devrait fournir une bibliothèque cliente à utiliser par les clients. Le client-lib est généralement facultatif pour un client du service à utiliser et peut consommer l'API comme bon lui semble, que ce soit pour utiliser le client-lib, ou utiliser un autre langage et utiliser les aspects généraux de la bibliothèque et autres.

Dans mon cas - je considère un service qui crée un objet de données. Supposons que cet objet soit un PET. Ce n'est PAS l'entité de base de données, mais strictement un POJO qui représente implicitement les données sous-jacentes. Ce POJO est ce que l'API a défini. Supposons: Animal de compagnie - âge, poids, nom, propriétaire, adresse, espèce, etc.

Service 1 - PetKeeper: Il générera un animal de compagnie pour une raison quelconque et conservera toutes les données et doit référencer ce service pour obtenir l'animal de compagnie, ou apporter des modifications à l'animal de compagnie, disons que le nom change, ou le changement d'adresse doit être effectué via un Appel API à ce service.

Service 2 - PetAccessor: Ce service rassemble l'animal et effectue des contrôles de validation

Service 3,4 - Plus d'appels de service intermédiaires

Service 5 - Interface utilisateur

Ce sont très arbitraires mais le point est simple. L'interface utilisateur ou un service orienté utilisateur souhaite présenter en quelque sorte cet objet "PET". Il doit appeler via une API un service, qui appelle un service, qui appelle un service, etc. jusqu'à ce qu'il atteigne le service qui rassemble les informations requises et recommence le relais. Enfin, le service d'interface utilisateur a l'objet PET à afficher.

C'est assez courant - mais avec notre mentalité absolue, nous avons dupliqué l'objet PET dans chaque service. Le principe SEC (ne vous répétez pas) s'applique uniquement au code INTÉRIEUR d'un service et ne s'applique pas à tous les services, mais le point est toujours là. Et si nous ajoutons un champ ... nous devons modifier 5 services du POJO dans chacun.

--OU-- Nous pouvons fournir une bibliothèque Pet-Objects qui contient certains des pojo de l'API et chaque service peut importer / dépendance sur la bibliothèque. Il n'y a aucune dépendance sur le (s) service (s) eux-mêmes, mais uniquement sur la bibliothèque générale. J'aime cette idée pour que chaque service ait le même type d'objet et les mises à jour soient plus faciles. Mais je suis préoccupé par les objets divins.

Quels sont les avantages et les inconvénients - quel est le meilleur design? Qu'avez-vous fait pour transmettre des données entre les services afin de minimiser la répétition des mêmes classes POJO tout en restant découplé?

Aerith
la source
@DaiKaixian: Vous ne suggérez sûrement pas que le PO va avec un objet divin, n'est-ce pas? Cela est couramment considéré comme un anti-modèle.
Makoto
Je suis d'accord avec la réponse de @javaguy.
Et je veux aussi dire que vous pouvez considérer le modèle de visiteur. en.wikipedia.org/wiki/Visitor_pattern . Créez tout le champ et le setter / getter dans un POJO, et partagez-le entre les microservices.Si vous souhaitez effectuer une opération sur le POJO dans différents microservices, écrivez une VisitorClass.
Merci. Mon hésitation à avoir cette «bibliothèque commune» est qu'elle va grandir. Et il y aura des objets là-dedans que seuls les services 1 & 3 se soucient, ou 2 & 4, ou tous, ou toute combinaison de ceux-ci. Un type de package de bibliothèque DTO général qui contient tous les DTO, que j'utilise un modèle de vistor ou un simple DTO POJO ou autre. Est-ce acceptable d'inclure tous ces objets mais d'essayer de le maintenir le mieux possible? Au moins, les objets sont fournis à tous ceux qui en ont besoin S'ils souhaitent les utiliser ...

Réponses:

5

Quel est le meilleur design?

Vous pouvez réutiliser le même objet Pet DTO parmi les services backend (qui traitent la logique métier typique), mais en ce qui concerne le niveau de présentation (interface utilisateur), il est généralement recommandé d'utiliser un FormBean (un bean différent avec des champs ajoutés). pour la logique de présentation) afin qu'il y ait une séparation claire entre la logique de présentation et la logique métier .

Cela est nécessaire car les services doivent être réutilisables et un seul service peut être exposé / réutilisé par plusieurs points de terminaison différents (comme le frontend ou pourrait être un service Web différent, etc.) et chacun de ces points de terminaison peut nécessiter des champs supplémentaires qui seront remplis par les contrôleurs ou couches respectifs (comme les adaptateurs) au-dessus des services.

Qu'avez-vous fait pour transmettre des données entre les services afin de minimiser la répétition des mêmes classes POJO tout en restant découplé?

Si vous utilisez un seul bean entre les niveaux métier et Web, vous couplez étroitement la logique de présentation avec la logique métier, ce qui n'est pas une bonne pratique et vous finirez par modifier les services pour une exigence dans le frontend (comme par exemple, un format de date différent à afficher dans l'interface utilisateur). De plus, pour effectuer ce processus de remplissage / copie des données sur les beans (comme DTO vers FormBean ou Viceversa), vous pouvez utiliser des bibliothèques comme Apache BeanUtils.copyProperties() ou Dozer pour éviter le code passe-partout .

développeur
la source
Je suis d'accord que la couche de présentation devrait probablement désérialiser la charge utile entrante en tant que bean de présentation avec différents attributs selon les besoins. Mais en général, est-il acceptable de réutiliser les mêmes objets DTO dans tous les services backend? Nous essayons généralement de séparer ces packages DTO en packages plus petits pour les quelques services qui en ont besoin. Je suis fatigué d'avoir un tiroir indésirable d'un package de bibliothèque DTO qui a des DTO pour plus de 75 microservices dont tous les services dépendent. À moins que ce soit correct car ce ne sont que des objets DTO qui sont facultatifs en premier lieu?
Oui, vous pouvez évidemment réutiliser le même objet DTO sur tous les mêmes types de services backend comme le vôtre PetServicespour éviter la duplication. Mais mon point n'est pas de coupler étroitement backend et frontend, c'est tout.
développeur
4

Si le DTO représente la même entité commerciale dans tous les microservices, il ne devrait y avoir qu'une seule classe, partagée entre les services. Il n'est (presque) jamais correct d'avoir du code en double pour le même objet.

Jim Garrison
la source
3
Le partage des DTO entre les microservices est un cauchemar. "Est-ce que cette version a déjà ce champ? Hm peut-être?" Vous vous retrouverez avec un vrai gâchis après un certain temps. Le code dupliqué est bon dans ce cas.
Mejmo
1

La façon dont je prévois de le faire maintenant, c'est que chaque service ne regroupe que des DTO et les place dans Nexus en tant que lib jar. Quand un autre service en aura besoin, il obtiendra ces librairies DTO comme dépendance dans manve / gradle. Si la nouvelle version de DTO est publiée sur un service, c'est bien tant que l'ancienne version est également prise en charge en même temps, alors ne brisez pas la compatibilité ascendante, le versioning, etc. De plus, pour éviter la dépendance à la circulation, il est préférable de séparer le service de l'emballage dto

Maintenant, regardez backend-to-frontend et vice versa, je ne suis pas d'accord avec les commentaires précédents selon lesquels l'interface utilisateur en tant que couche de présentation est différente. CE N'EST PAS!!! L'interface utilisateur n'est qu'un autre microservice qui consomme et produit également des événements.

Direction backend vers frontend Ce que je fais est de convertir POJO (dtos) en interfaces Typescript et de les empaqueter en NPM et de les charger dans Nexus également. Le projet basé sur UI nodejs consomme et utilise ensuite ceux-ci. C'est un service de façon à l'interface utilisateur.

Direction front-end-backend Pour l'interface utilisateur aux événements de la couche de service, je convertis les interfaces Typescript et les convertis en POJO (dtos), les empaquette sous forme de jar et les télécharge sur Nexus (ou un certain repo) sous forme de jar à consommer par les services backend.

Ces processus sont facilement gérés par les processus CI (Travis, Gitlab CI, etc.)

Tous les commentaires sur cette approche sont les bienvenus.

kensai
la source