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é?
la source
Réponses:
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.
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 .la source
PetServices
pour éviter la duplication. Mais mon point n'est pas de coupler étroitement backend et frontend, c'est tout.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.
la source
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.
la source