- Les décisions de nommage et de modélisation des ressources API constituent la partie la plus difficile et la plus importante de la conception d’API. Les ressources façonnent le modèle mental que les utilisateurs se font du fonctionnement et des fonctionnalités du produit.
- L’équipe d’Increase s’appuie sur le principe de « aucune abstraction » pour guider la conception de ses API.
L’approche de Stripe en matière de conception d’API
- Une grande partie de l’équipe de Stripe a auparavant travaillé chez Stripe, et prend en compte les valeurs qui ont fait le succès de la conception d’API de Stripe.
- Stripe excelle à extraire les fonctions essentielles de domaines complexes sous forme d’abstractions que les utilisateurs peuvent facilement comprendre et utiliser. (Ex. :
PaymentIntent, qui abstrait les différences entre Visa et Mastercard)
- La plupart des utilisateurs de Stripe sont de jeunes startups qui développent des produits sans lien avec les paiements, et n’ont pas besoin de connaître les détails des cartes bancaires. Ils veulent intégrer Stripe rapidement et se concentrer sur le développement de leur produit.
Les utilisateurs d’Increase et le principe de conception d’API
- À l’inverse, les utilisateurs d’Increase ont une connaissance approfondie des réseaux de paiement, et choisissent Increase précisément pour sa connexion directe aux réseaux et la profondeur de son intégration.
- Ils veulent savoir exactement quand la fenêtre FedACH se ferme et à quel moment un virement est émis, et comprennent que, dans un virement ACH, différents paramètres de code SEC peuvent influer sur le délai de retour.
- Toute tentative de masquer la complexité fondamentale de ces réseaux ne fait qu’irriter les utilisateurs au lieu de leur simplifier la vie.
- C’est à travers les échanges avec les premiers utilisateurs que le principe de « aucune abstraction » a été formulé et appliqué à la conception de l’API.
L’impact du principe de « aucune abstraction » sur la conception de l’API
- Utiliser la terminologie réellement employée : au lieu d’inventer leurs propres noms pour les ressources et propriétés API, ils reprennent le vocabulaire du réseau sous-jacent. (Ex. : les paramètres des virements ACH utilisent les noms de champs de la spécification Nacha)
- Immutabilité : en prenant les événements réels comme modèle, davantage de ressources API deviennent immuables. Il est efficace de regrouper des ensembles de ressources immuables sous forme d’objets de cycle de vie à machine d’états. (Ex. : le champ
status de l’objet ach_transfer et plusieurs sous-objets immuables créés en fonction du cycle de vie du transfert)
- Séparer les ressources par cas d’usage : lorsque l’ensemble des actions possibles diffère fortement selon l’instance d’une ressource, celle-ci est divisée en plusieurs ressources. (Ex. : les virements ACH sortants et les virements ACH entrants sont séparés en ressources distinctes)
Respect de cette approche par l’équipe d’ingénierie
- L’équipe d’ingénierie s’est engagée à respecter cette approche.
- Lorsqu’on conçoit une API complexe pendant plusieurs années, il faut constamment prendre de petites décisions incrémentales. S’engager à l’avance à respecter des principes fondamentaux réduit la charge cognitive liée à ces décisions.
- Par exemple, pour le champ Input Message Accountability Data requis lors d’un transfert vers la Réserve fédérale, une API très abstraite amènerait à réfléchir à une manière de renommer ce champ de façon « conviviale », tandis que chez Increase, l’ingénieur le nomme simplement
input_message_accountability_data et passe à la suite.
L’avis de GN⁺
- Le niveau d’abstraction d’une API peut varier selon le niveau d’expérience du développeur dans le domaine du produit concerné et l’énergie qu’il est prêt à consacrer à l’intégration. Il est donc important, lors de la conception d’une API, de réfléchir au niveau d’abstraction approprié pour les développeurs qui vont l’intégrer.
- Si l’on construit une API avec un haut niveau d’abstraction, il faut bien réfléchir avant d’ajouter de nouvelles fonctionnalités. À l’inverse, si l’on construit une API avec un faible niveau d’abstraction, il faut rester cohérent avec ce choix et résister à la tentation d’ajouter des abstractions.
- Reprendre tels quels les termes du réseau ou du protocole sous-jacent peut aider les développeurs à comprendre l’underlying system, mais cela peut aussi constituer une barrière à l’entrée pour ceux qui le découvrent. Il semble donc important de bien soigner les annotations et la documentation.
- Utiliser des objets immuables dans la conception d’une API peut être efficace pour préserver la cohérence des données et éviter les side effects. Mais cela peut aussi devenir contraignant lorsqu’une mise à jour des données est nécessaire, il faut donc bien évaluer les trade-offs.
- Séparer les ressources selon les cas d’usage peut accroître la complexité de l’API, mais améliorer sa prévisibilité à long terme. En revanche, si la granularité devient excessive, l’utilisabilité peut en pâtir ; il est donc important de trouver le bon niveau.
1 commentaires
Commentaire Hacker News
Il est préférable de proposer à la fois une API de bas niveau et une API de haut niveau
J’ai apprécié le passage expliquant pourquoi Increase a choisi une approche différente
La véritable force de Stripe, c’est de bien connaître ses clients et de leur offrir la simplicité qu’ils recherchent
Cela ressemble au patron de conception de la "langue omniprésente (Ubiquitous Language)" du Domain-Driven Design, dans lequel l’implémentation utilise les mêmes termes que ceux employés par les experts métier
Il faut utiliser un langage que les experts métier peuvent comprendre
Sans une abstraction comme POSIX, les applications devraient écrire des adaptateurs pour tous les systèmes de fichiers pris en charge
Il est dit qu’une partie de la structure de l’API est construite en correspondance 1:1 à partir de spécifications contrôlées de l’extérieur
Un point difficile à modéliser proprement dans une API de paiement est que les schémas de paiement représentent différemment les rôles du payeur et du bénéficiaire lors d’un remboursement