
Alors, à quel point cela peut-il être difficile de versionner une API ? La vérité est que ce n'est pas si compliqué, mais ce qui est difficile, c'est de maintenir un semblant de bon sens en évitant de se perdre dans un nombre vertigineux de versions et de sous-versions appliquées à des dizaines de points de terminaison d'API avec des compatibilités floues.
Business in a box.
Découvrez nos solutions.
Parlez à notre équipe de vente
Breaking Changes Mauvais! API Versioning Bon!
Comme toute personne qui a construit ou utilise régulièrement une API le réalise tôt ou tard, les changements incompatibles sont très mauvais et peuvent être une tache très sérieuse sur une API autrement utile. Un changement incompatible est une modification du comportement d'une API qui peut casser l'intégration d'un utilisateur et entraîner beaucoup de frustration et une perte de confiance entre le fournisseur d'API et l'utilisateur. Les changements incompatibles requièrent que les utilisateurs soient prévenus à l'avance (avec des excuses adéquates) plutôt qu'un changement qui apparaît simplement, comme une nouvelle fonctionnalité plaisante. La façon d'éviter cette frustration est de versionner une API avec l’assurance du propriétaire de l'API qu'il n'y aura pas de changements surprenants introduits dans une version unique.
Alors, à quel point peut-il être difficile de versionner une API? La vérité, c'est que ce n'est pas difficile, mais ce qui est compliqué, c'est de maintenir une certaine raison en ne sombrant pas inutilement dans un vertige de nombreuses versions et sous-versions appliquées à travers des dizaines de points de terminaison d'API aux compatibilités peu claires.
Nous avons introduit v1 de l'API il y a trois ans et nous ne réalisions pas qu'elle serait en vigueur jusqu'à ce jour. Alors comment avons-nous continué à fournir la meilleure API de livraison d'emails depuis plus de deux ans tout en maintenant la même version d'API? Bien qu'il y ait de nombreux avis différents sur la façon de versionner les API REST, j'espère que l'histoire de notre modeste mais puissante v1 pourrait vous guider sur votre chemin vers l'éveil au versionnement d'API.
REST is Best
API Governance
Avec une convention de version sélectionnée, nous avions plus de questions. Quand devrions-nous augmenter la version ? Qu'est-ce qu'un changement majeur ? Devons-nous remonter la version de toute l'API ou seulement de certains points de terminaison ? Chez SparkPost, nous avons plusieurs équipes travaillant sur différentes parties de notre API. Au sein de ces équipes, les gens travaillent sur différents points de terminaison à différents moments. Par conséquent, il est très important que notre API soit cohérente dans l'utilisation des conventions. Cela était plus important que la gestion des versions.
Nous avons établi un groupe de gouvernance comprenant des ingénieurs représentant chaque équipe, un membre de l'équipe de gestion des produits et notre CTO. Ce groupe est responsable de l'établissement, de la documentation et de l'application de nos conventions API à travers toutes les équipes. Un canal de gouvernance API Slack est également utile pour des débats animés sur le sujet.
Le groupe de gouvernance a identifié plusieurs moyens par lesquels des changements peuvent être introduits dans l'API, bénéfiques pour l'utilisateur et ne constituant pas un changement majeur. Ceux-ci incluent :
Une nouvelle ressource ou point de terminaison API
Un nouveau paramètre optionnel
Un changement à un point de terminaison API non public
Une nouvelle clé optionnelle dans le corps des requêtes POST en JSON
Une nouvelle clé retournée dans le corps de réponse JSON
Inversement, un changement majeur inclut tout ce qui pourrait briser l'intégration d'un utilisateur, tel que :
Un nouveau paramètre requis
Une nouvelle clé requise dans les corps de requêtes POST
La suppression d'un point de terminaison existant
La suppression d'une méthode de requête de point de terminaison existant
Un comportement interne matériellement différent d'un appel API – comme un changement du comportement par défaut.
The Big 1.0
Comme nous avons documenté et discuté de ces conventions, nous sommes également parvenus à la conclusion qu’il était dans l’intérêt de tout le monde (y compris le nôtre !) d’éviter d’apporter des changements cassants à l’API, car gérer plusieurs versions ajoute pas mal de surcharge. Nous avons décidé qu’il y avait quelques éléments que nous devrions corriger dans notre API avant de nous engager à la « v1 ».
L’envoi d’un simple email nécessitait beaucoup trop d'efforts. Pour « garder les choses simples », nous avons mis à jour le corps de la demande POST afin de garantir que les cas d’utilisation simples et complexes soient pris en charge. Le nouveau format était également plus pérenne. Deuxièmement, nous avons résolu un problème avec le point de terminaison Metrics. Ce point de terminaison utilisait un paramètre « group_by » qui modifiait le format du corps de réponse GET de sorte que la première clé serait la valeur du group by. Cela ne semblait pas très RESTful, nous avons donc divisé chaque group by en un point de terminaison séparé. Enfin, nous avons audité chaque point de terminaison et apporté des modifications mineures ici et là pour nous assurer qu'ils étaient conformes aux normes.
Documentation Précise
Il est important d'avoir une documentation API précise et utilisable pour éviter les changements disruptifs, qu'ils soient délibérés ou non. Nous avons décidé d'utiliser une approche simple de documentation API en utilisant un langage Markdown appelé API Blueprint et managér nos docs dans Github. Notre communauté contribue et améliore ces documents open source. Nous maintenons également un ensemble non public de documents dans Github pour des APIs internes et des endpoints.
Initialement, nous avons publié nos documents sur Apiary, un excellent outil pour prototyper et publier des documents API. Cependant, intégrer Apiary dans notre site web ne fonctionne pas sur les appareils mobiles, nous utilisons donc maintenant Jekyll pour générer des documents statiques à la place. Nos derniers SparkPost API docs se chargent rapidement et fonctionnent bien sur les appareils mobiles, ce qui est important pour les développeurs qui ne sont pas toujours assis à leur ordinateur.
Séparer le déploiement de la sortie
Nous avons appris très tôt l'astuce précieuse de séparer un déploiement d'une mise en production. De cette façon, il est possible de déployer fréquemment des modifications lorsqu'elles sont prêtes par le biais de la livraison continue et du déploiement, mais nous ne les annonçons pas toujours publiquement ou ne les documentons pas toujours en même temps. Il n'est pas rare que nous déployions un nouvel endpoint d'API ou une amélioration d'un endpoint d'API existant et l'utilisions depuis l'interface utilisateur ou avec des outils internes avant de le documenter et de le prendre en charge publiquement. Ainsi, nous pouvons y apporter quelques ajustements pour l'améliorer en termes d'utilisabilité ou de conformité aux normes sans avoir à craindre d'introduire un changement majeur redouté. Une fois que nous sommes satisfaits du changement, nous l'ajoutons à notre documentation publique.
Doh !
Il est juste d'admettre qu'il y a eu des moments où nous n'avons pas respecté nos idéaux de « aucun changement de rupture » et qu'il vaut la peine d'apprendre de ceux-ci. À une occasion, nous avons décidé qu'il serait préférable pour les utilisateurs si une certaine propriété était définie par défaut sur true au lieu de false. Après avoir déployé le changement, nous avons reçu plusieurs plaintes d'utilisateurs car le comportement avait changé de manière inattendue. Nous avons annulé le changement et ajouté un paramètre au niveau du compte – une approche beaucoup plus conviviale assurément.
Parfois, nous sommes tentés d'introduire des changements de rupture à la suite de corrections de bugs. Cependant, nous avons décidé de laisser ces particularités telles qu'elles sont plutôt que de risquer de casser les intégrations des clients pour le bien de la cohérence.
Il y a des cas rares où nous avons pris la décision sérieuse de faire un changement de rupture – comme l'abandon d'une ressource ou méthode API – dans l'intérêt de la communauté des utilisateurs au sens large et seulement après avoir confirmé qu'il y a peu ou pas d'impact pour les utilisateurs. Par exemple, nous avons délibérément choisi de modifier le comportement de réponse de l'API de suppression mais seulement après avoir soigneusement pesé les avantages et les impacts pour la communauté et communiqué soigneusement le changement à nos utilisateurs. Cependant, nous ne ferions jamais un changement qui a une possibilité, même lointaine, d'impacter directement l'envoi d'un email de production d'un utilisateur.