Gestion des versions API chez Monite
Nous aimons tous avoir de nouveaux outils brillants, mais détestons la corvée de les mettre à jour constamment. Cela s'applique à tout : les systèmes d'exploitation, les applications, les API, les packages Linux. C'est douloureux lorsque notre code cesse de fonctionner à cause d'une mise à jour et c'est doublement douloureux lorsque la mise à jour n'a même pas été initiée par nous.
Dans le développement d'API Web, vous risquez constamment de casser le code de vos utilisateurs à chaque nouvelle mise à jour. Si votre produit est une API, alors ces mises à jour seront terrifiantes à chaque fois. Les principaux produits de Monite sont notre API et notre SDK en marque blanche. Nous sommes une entreprise axée sur les API, nous prenons donc grand soin de maintenir notre API stable et facile à utiliser. Par conséquent, le problème des modifications interrompues figure en tête de notre liste de priorités.
Une solution courante consiste à émettre des avertissements de dépréciation à vos clients et à publier rarement les modifications importantes. Du coup, vos versions peuvent désormais prendre des mois et certaines fonctionnalités doivent rester cachées, voire non fusionnées, jusqu'à chaque version suivante. Cela ralentit votre développement et oblige vos utilisateurs à mettre à jour leur intégration tous les quelques mois.
Si vous publiez plus rapidement, vos utilisateurs vont devoir mettre à jour leur intégration trop souvent. Si vous allongez le délai entre les versions, votre entreprise évoluera plus lentement. Plus vous le rendrez gênant pour les utilisateurs, plus cela sera pratique pour vous, et vice versa. Ce n’est certainement pas un scénario optimal. Nous voulions avancer à notre rythme sans rien casser pour les clients existants, ce qui serait impossible avec une approche de dépréciation régulière. C'est pourquoi nous avons choisi une solution alternative : le Versionnage API.
C'est une idée assez simple : publier toutes les modifications importantes à tout moment mais les masquer sous une nouvelle version de l'API. Il vous offre le meilleur des deux mondes : les utilisateurs ne verront pas leurs intégrations systématiquement interrompues et vous pourrez vous déplacer à la vitesse que vous souhaitez. Les utilisateurs migreront quand ils le souhaitent, sans aucune pression.
Compte tenu de la simplicité de l'idée, elle semble parfaite pour toute entreprise. C’est ce que l’on s’attend à lire dans un blog d’ingénierie typique. Malheureusement, ce n'est pas si simple.
Attention au prix
Le contrôle de version des API est difficile, très difficile. Sa simplicité illusoire disparaît rapidement une fois que vous commencez à la mettre en œuvre. Malheureusement, Internet ne vous prévient jamais vraiment car il existe étonnamment peu de ressources sur le sujet. La majorité absolue d'entre eux discutent de l'endroit où placer la version de l'API, mais seuls quelques rares articles tentent de répondre : "Comment pouvons-nous l'implémenter ?". Les plus courants sont :
- mettre différentes versions de la même application Web dans des déploiements distincts
- copier des itinéraires uniques qui ont changé entre les versions
- copier l'intégralité de l'application versionnée pour chaque version
Les déploiements séparés peuvent devenir très coûteux et difficiles à prendre en charge, la copie de routes uniques ne s'adapte pas très bien aux changements importants, et la copie de l'application entière crée tellement de code supplémentaire que vous commencerez à vous noyer dedans après seulement quelques versions.
Même si vous essayez de choisir le moins cher, le fardeau du versioning vous rattrapera bientôt. Au début, cela semblera simple : ajoutez un autre schéma ici, une autre branche de logique métier là, et dupliquez quelques routes à la fin. Mais avec suffisamment de versions, votre logique métier deviendra rapidement ingérable, beaucoup de vos développeurs confondront les versions d'application et les versions d'API, et commenceront à versionner les données dans votre base de données, et votre application deviendra impossible à maintenir.
Vous pourriez espérer ne jamais avoir plus de deux ou trois versions d'API en même temps ; que vous pourrez supprimer les anciennes versions tous les quelques mois. C’est vrai si vous ne prenez en charge qu’un petit nombre de consommateurs internes. Mais les clients extérieurs à votre organisation n’apprécieront pas l’expérience d’être obligés d’effectuer une mise à niveau tous les quelques mois.
La gestion des versions des API peut rapidement devenir l'un des éléments les plus coûteux de votre infrastructure. Il est donc essentiel d'effectuer des recherches assidues au préalable. Si vous ne prenez en charge que les consommateurs internes, vous aurez peut-être plus de facilité avec quelque chose comme GraphQL, mais cela peut rapidement devenir aussi coûteux que la gestion des versions.
Si vous êtes une startup, il serait sage de reporter la gestion des versions de l'API jusqu'aux étapes ultérieures de votre développement, lorsque vous disposez des ressources nécessaires pour le faire correctement. D’ici là, les dépréciations et les stratégies de changement additives pourraient suffire. Votre API n'aura pas toujours fière allure, mais au moins vous économiserez beaucoup d'argent en évitant le versioning explicite.
Comment implémentons-nous le versioning de l'API ?
Après quelques essais et de nombreuses erreurs, nous étions à la croisée des chemins : nos précédentes approches de versionnement que nous avons mentionnées ci-dessus étaient trop coûteuses à maintenir. À la suite de nos difficultés, j'ai élaboré la liste suivante d'exigences qui seraient requises pour un cadre de gestion de versions parfait :
- "Maintenir un grand nombre de versions est facile" pour s'assurer que le versioning ne ralentit pas le développement de nos fonctionnalités
- "Supprimer les anciennes versions est facile" pour être sûr que nous pouvons nettoyer notre base de code sans efforts
- "Créer de nouvelles versions n'est pas trop facile" pour nous assurer que nos développeurs sont toujours incités à essayer de résoudre les problèmes sans versions.
- "Maintenir un journal des modifications entre les versions est facile" pour garantir que nous et nos clients pouvons toujours être sûrs des réelles différences entre les versions
Malheureusement, il n'existait que peu ou pas d'alternatives à nos approches existantes. C'est à ce moment-là qu'une idée folle m'est venue à l'esprit : et si nous essayions de créer quelque chose de sophistiqué, quelque chose de parfait pour le travail - quelque chose comme la gestion des versions de l'API de Stripe ?
Grâce à d'innombrables expériences, nous disposons désormais de Cadwyn : un framework de gestion de versions d'API open source qui non seulement implémente l'approche de Stripe, mais s'appuie également de manière significative sur celle-ci. Nous parlerons de sa mise en œuvre Fastapi et Pydantic, mais les principes fondamentaux sont indépendants du langage et du framework.
Comment fonctionne Cadwyn
Modifications de versions
Le problème de toutes les autres approches de gestion des versions est que nous dupliquons trop. Pourquoi devrions-nous dupliquer l'intégralité de l'itinéraire, du contrôleur ou même de l'application alors que seule une infime partie de notre contrat a été rompue ?
Avec Cadwyn, chaque fois que les responsables de l'API ont besoin de créer une nouvelle version, ils appliquent les dernières modifications à leurs derniers schémas, modèles et logique métier. Ensuite, ils créent un changement de version : une classe qui encapsule toutes les différences entre la nouvelle version et une version antérieure.
Par exemple, disons qu'auparavant nos clients pouvaient créer un utilisateur avec une adresse mais que maintenant nous aimerions leur permettre de spécifier plusieurs adresses au lieu d'une seule. Le changement de version ressemblerait à ceci :
class ChangeUserAddressToAList(VersionChange): description = ( "Renamed `User.address` to `User.addresses` and " "changed its type to an array of strings" ) instructions_to_migrate_to_previous_version = ( schema(User).field("addresses").didnt_exist, schema(User).field("address").existed_as(type=str), ) @convert_request_to_next_version_for(UserCreateRequest) def change_address_to_multiple_items(request): request.body["addresses"] = [request.body.pop("address")] @convert_response_to_previous_version_for(UserResource) def change_addresses_to_single_item(response): response.body["address"] = response.body.pop("addresses")[0]
instructions_to_migrate_to_previous_version sont utilisées par Cadwyn pour générer du code pour les anciennes versions API des schémas et les deux fonctions de conversion sont l'astuce qui nous permet de maintenir autant de versions que nous le souhaiterions. Le processus ressemble au suivant :
- Cadwyn convertit toutes les demandes des utilisateurs des anciennes versions de l'API vers la dernière version de l'API à l'aide du convertisseur change_address_to_multiple_items et les redirige vers notre logique métier.
- La logique métier, ses réponses API et ses modèles de base de données sont toujours adaptés à la dernière version de l'API (bien sûr, elle doit toujours prendre en charge les anciennes fonctionnalités même si elles ont été supprimées dans les nouvelles versions)
- Une fois que la logique métier a produit la réponse, Cadwyn la convertit vers l'ancienne version de l'API utilisée actuellement par le demandeur client à l'aide du convertisseur change_addresses_to_single_item.
Une fois que nos responsables de l'API ont créé le changement de version, ils doivent l'ajouter à notre VersionBundle pour indiquer à Cadwyn que ce VersionChange sera inclus dans certaines versions :
VersionBundle( Version( date(2023, 4, 27), ChangeUserAddressToAList ), Version( date(2023, 4, 12), CollapseUserAvatarInfoIntoAnID, MakeUserSurnameRequired, ), Version(date(2023, 3, 15)), )
Ça y est : nous avons ajouté un changement radical mais notre logique métier ne gère qu'une seule version : la dernière. Même après avoir ajouté des dizaines de versions d'API, notre logique métier sera toujours exempte de logique de version, de renommage constant, de si et de convertisseurs de données.
Chaînage de versions
Les changements de version dépendent de l'interface publique de l'API et nous n'ajoutons presque jamais de modifications majeures aux versions d'API existantes. Cela signifie qu'une fois que nous aurons publié la version, elle ne sera pas cassée.
Étant donné que les changements de version décrivent les modifications majeures au sein des versions et qu'il n'y a pas de modifications majeures dans les anciennes versions, nous pouvons être sûrs que nos modifications de version sont complètement immuables – elles n'auront jamais de raison de changer. Les entités immuables sont beaucoup plus faciles à maintenir que si elles faisaient partie de la logique métier, car elles sont en constante évolution. Les changements de version sont également appliqués les uns après les autres, formant une chaîne de transformateurs entre les versions qui peuvent migrer toute demande vers une version plus récente et toute réponse vers une version plus ancienne.
Effets secondaires
Les contrats API sont bien plus complexes que de simples schémas et champs. Ils comprennent tous les points de terminaison, les codes d'état, les erreurs, les messages d'erreur et même les comportements de logique métier. Cadwyn utilise le même DSL que nous avons décrit ci-dessus pour gérer les points de terminaison et les codes d'état, mais les erreurs et les comportements de la logique métier sont une autre histoire : ils sont impossibles à décrire à l'aide d'un DSL, ils doivent être intégrés dans la logique métier.
This makes such version changes much more expensive to maintain than all others because they affect business logic. We call this property a "side effect" and we try to avoid them at all costs because of their maintenance burden. All version changes that want to modify business logic will need to be marked as having side effects. It will serve as a way to know which version changes are "dangerous":
class RequireCompanyAttachedForPayment(VersionChangeWithSideEffects): description = ( "User must now have a company_id in their account " "if they want to make new payments" )
It will also allow API maintainers to check that the client request uses an API version that includes this side effect:
if RequireCompanyToBeAttachedForPayment.is_applied: validate_company_id_is_attached(user)
No silver bullets
Cadwyn has many benefits: It greatly reduces the burden on our developers and can be integrated into our infrastructure to automatically generate the changelog and improve our API docs.
However, the burden of versioning still exists and even a sophisticated framework is not a silver bullet. We do our best to only use API versioning when absolutely necessary. We also try to make our API correct on the first try by having a special "API Council". All significant API changes are reviewed there by our best developers, testers, and tech writers before any implementation gets moving.
Special thanks to Brandur Leach for his API versioning article at Stripe and for the help he extended to me when I implemented Cadwyn: it would not be possible without his help.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds











Python est plus facile à apprendre et à utiliser, tandis que C est plus puissant mais complexe. 1. La syntaxe Python est concise et adaptée aux débutants. Le typage dynamique et la gestion automatique de la mémoire le rendent facile à utiliser, mais peuvent entraîner des erreurs d'exécution. 2.C fournit des fonctionnalités de contrôle de bas niveau et avancées, adaptées aux applications haute performance, mais a un seuil d'apprentissage élevé et nécessite une gestion manuelle de la mémoire et de la sécurité.

Pour maximiser l'efficacité de l'apprentissage de Python dans un temps limité, vous pouvez utiliser les modules DateTime, Time et Schedule de Python. 1. Le module DateTime est utilisé pour enregistrer et planifier le temps d'apprentissage. 2. Le module de temps aide à définir l'étude et le temps de repos. 3. Le module de planification organise automatiquement des tâches d'apprentissage hebdomadaires.

Python est meilleur que C dans l'efficacité du développement, mais C est plus élevé dans les performances d'exécution. 1. La syntaxe concise de Python et les bibliothèques riches améliorent l'efficacité du développement. Les caractéristiques de type compilation et le contrôle du matériel de CC améliorent les performances d'exécution. Lorsque vous faites un choix, vous devez peser la vitesse de développement et l'efficacité de l'exécution en fonction des besoins du projet.

Est-ce suffisant pour apprendre Python pendant deux heures par jour? Cela dépend de vos objectifs et de vos méthodes d'apprentissage. 1) Élaborer un plan d'apprentissage clair, 2) Sélectionnez les ressources et méthodes d'apprentissage appropriées, 3) la pratique et l'examen et la consolidation de la pratique pratique et de l'examen et de la consolidation, et vous pouvez progressivement maîtriser les connaissances de base et les fonctions avancées de Python au cours de cette période.

Python et C ont chacun leurs propres avantages, et le choix doit être basé sur les exigences du projet. 1) Python convient au développement rapide et au traitement des données en raison de sa syntaxe concise et de son typage dynamique. 2) C convient à des performances élevées et à une programmation système en raison de son typage statique et de sa gestion de la mémoire manuelle.

PythonlistSaReparmentofthestandardLibrary, tandis que les coloccules de colocède, tandis que les colocculations pour la base de la Parlementaire, des coloments de forage polyvalent, tandis que la fonctionnalité de la fonctionnalité nettement adressée.

Python excelle dans l'automatisation, les scripts et la gestion des tâches. 1) Automatisation: La sauvegarde du fichier est réalisée via des bibliothèques standard telles que le système d'exploitation et la fermeture. 2) Écriture de script: utilisez la bibliothèque PSUTIL pour surveiller les ressources système. 3) Gestion des tâches: utilisez la bibliothèque de planification pour planifier les tâches. La facilité d'utilisation de Python et la prise en charge de la bibliothèque riche en font l'outil préféré dans ces domaines.

Les applications clés de Python dans le développement Web incluent l'utilisation des cadres Django et Flask, le développement de l'API, l'analyse et la visualisation des données, l'apprentissage automatique et l'IA et l'optimisation des performances. 1. Framework Django et Flask: Django convient au développement rapide d'applications complexes, et Flask convient aux projets petits ou hautement personnalisés. 2. Développement de l'API: Utilisez Flask ou DjangorestFramework pour construire RestulAPI. 3. Analyse et visualisation des données: utilisez Python pour traiter les données et les afficher via l'interface Web. 4. Apprentissage automatique et AI: Python est utilisé pour créer des applications Web intelligentes. 5. Optimisation des performances: optimisée par la programmation, la mise en cache et le code asynchrones
