Supposons que vous ayez un grand projet pris en charge par une base d'API. Le projet fournit également une API publique que les utilisateurs finaux (ish) peuvent utiliser.
Parfois, vous devez apporter des modifications à la base d'API qui prend en charge votre projet. Par exemple, vous devez ajouter une fonctionnalité nécessitant une modification de l'API, une nouvelle méthode ou nécessitant la modification de l'un des objets ou du format de l'un de ces objets, transmis vers ou depuis l'API.
En supposant que vous utilisez également ces objets dans votre API publique, les objets publics changeront également chaque fois que vous le ferez, ce qui n'est pas souhaitable car vos clients peuvent compter sur les objets API restant identiques pour que leur code d'analyse fonctionne. (tousser les clients C ++ WSDL ...)
Une solution potentielle consiste donc à mettre à jour l'API. Mais lorsque nous disons «version» de l'API, il semble que cela doit également signifier la version des objets API ainsi que la fourniture d'appels de méthode en double pour chaque signature de méthode modifiée. J'aurais donc un simple vieil objet clr pour chaque version de mon api, ce qui semble encore une fois indésirable. Et même si je fais cela, je ne construirai sûrement pas chaque objet à partir de zéro, car cela aboutirait à de grandes quantités de code dupliqué. Au contraire, l'API est susceptible d'étendre les objets privés que nous utilisons pour notre API de base, mais nous rencontrons ensuite le même problème car des propriétés ajoutées seraient également disponibles dans l'API publique lorsqu'elles ne sont pas censées l'être.
Alors, quel est le bon sens qui est généralement appliqué à cette situation? Je connais de nombreux services publics tels que Git pour Windows maintient une API versionnée, mais j'ai du mal à imaginer une architecture qui prend en charge cela sans de grandes quantités de code en double couvrant les différentes méthodes versionnées et les objets d'entrée / sortie.
Je suis conscient que des processus tels que le versioning sémantique tentent de mettre un certain sens sur le moment où des ruptures d'API publiques devraient se produire. Le problème est plus qu'il semble que beaucoup ou la plupart des changements nécessitent de casser l'API publique si les objets ne sont pas plus séparés, mais je ne vois pas un bon moyen de le faire sans dupliquer le code.
I don't see a good way to do that without duplicating code
- Votre nouvelle API peut toujours appeler des méthodes dans votre ancienne API, ou vice versa.Réponses:
Lors de la maintenance d'une API utilisée par des tiers, il est inévitable que vous deviez apporter des modifications. Le niveau de complexité dépendra du type de changement qui se produit. Ce sont les principaux scénarios qui se présentent:
Ajout de nouvelles fonctionnalités à une API existante
Il s'agit du scénario le plus simple à prendre en charge. L'ajout de nouvelles méthodes à une API ne devrait nécessiter aucune modification des clients existants. Il est sûr de déployer pour les clients qui ont besoin de la nouvelle fonctionnalité car il n'a pas de mises à jour pour un client existant.
Ancienne fonctionnalité déconseillée de l'API
Dans ce scénario, vous devez communiquer aux consommateurs existants de votre API que la fonctionnalité ne sera pas prise en charge à long terme. Jusqu'à ce que vous supprimiez la prise en charge de l'ancienne fonctionnalité (ou jusqu'à ce que tous les clients soient passés à la nouvelle fonctionnalité), vous devez conserver l'ancienne et la nouvelle fonctionnalité d'API en même temps. S'il s'agit d'une bibliothèque fournie, la plupart des langues ont un moyen de marquer les anciennes méthodes comme obsolètes / obsolètes. S'il s'agit d'un service tiers quelconque, il est généralement préférable d'avoir différents points de terminaison pour l'ancienne ou la nouvelle fonctionnalité.
Fonctionnalité existante dans l'API changeant d'une manière ou d'une autre
Ce scénario dépendra du type de changement. Si les paramètres d'entrée n'ont plus besoin d'être utilisés, vous pouvez simplement mettre à jour le service / bibliothèque pour ignorer les données désormais supplémentaires. Dans une bibliothèque, il faudrait que la méthode surchargée appelle en interne la nouvelle méthode qui nécessite moins de paramètres. Dans un service hébergé, le point de terminaison ignore les données supplémentaires et il peut desservir les deux types de clients et exécuter la même logique.
Si la fonctionnalité existante doit ajouter de nouveaux éléments requis, vous devez disposer de deux points de terminaison / méthodes pour votre service / bibliothèque. Jusqu'à la mise à jour des clients, vous devez prendre en charge les deux versions.
d'autres pensées
Rather, the API is likely to extend the private objects we are using for our base API, but then we run into the same problem because added properties would also be available in the public API when they are not supposed to be.
N'exposez pas d'objets privés internes via votre bibliothèque / service. Créez vos propres types et mappez l'implémentation interne. Cela vous permettra d'apporter des modifications internes et de minimiser la quantité de mise à jour que les clients externes doivent faire.
The problem is more that it seems like many or most changes require breaking the public API if the objects aren't more separated, but I don't see a good way to do that without duplicating code.
L'API, qu'il s'agisse d'un service ou d'une bibliothèque, doit être stable au point d'intégration avec les clients. Plus vous prenez de temps pour identifier les entrées et les sorties et les conserver en tant qu'entités distinctes, vous éviterez beaucoup de maux de tête sur la route. Faites en sorte que l'API contracte sa propre entité distincte et mappez-la aux classes qui fournissent le travail réel. Le temps gagné lorsque les implémentations internes changent devrait plus que compenser le temps supplémentaire nécessaire pour définir l'interface supplémentaire.
Ne considérez pas cette étape comme "duplication de code". Bien que similaires, ce sont des entités distinctes qui valent la peine d'être créées. Alors que les modifications de l'API externe nécessitent presque toujours une modification correspondante de l'implémentation interne, les modifications de l'implémentation interne ne doivent pas toujours changer l'API externe.
Exemple
Supposons que vous fournissiez une solution de traitement des paiements. Vous utilisez PaymentProviderA pour effectuer des transactions par carte de crédit. Plus tard, vous obtenez un meilleur taux grâce au processeur de paiement de PaymentProviderB. Si votre API expose les champs de carte de crédit / adresse de facturation de votre type au lieu de la représentation de PaymentProviderA, le changement d'API est 0 car l'interface est restée la même (espérons que de toute façon, si PaymentProviderB nécessite des données qui n'étaient pas requises par PaymentProviderA, vous devez choisir soit soutenir les deux ou garder le pire taux avec PaymentProviderA).
la source