Réponses et citations en référence au billet de Florian. Le texte n’a aucun sens indépendamment.
Note: On parle de version dans l’URL mais d’autres la mettent dans les entêtes de requête. Cela ne change finalement pas grand chose vis à vis de la discussion qui suit.
Ensuite, qu’est-ce qui est versionné ? Il y a l’application, l’interface, les formats de données, et les données elle-même.
Je ne comprends pas. Il y a l’application client, l’application serveur et l’interface entre les deux. S’il y a une interface c’est justement pour que chaque application soit indépendante dans son coin (tant qu’elle respecte l’interface).
Ceux qui me préoccupe dans l’API c’est uniquement le changement de l’interface (le I de API). Après que ce changement soit au niveau du format des données, du protocole, du sens des données ou de quelles données sont renvoyées, cela m’est indifférent : Il y a eu changement, qui nécessite (ou pas) de mettre à jour les applications qui utilisent cette interface.
Et j’ajouterai : Si le changement est rétro-compatible, mon contrat d’interface est respecter, donc finalement je n’ai pas « changé » mon interface du point de vue des applications. Je n’ai même pas besoin de l’annoncer et donc de parler de version. Je ne me préoccuperai donc dans la suite que des versions *incompatibles*.
Mais, dans ce cadre là, à quoi vous sert le numéro de version dans l’URL ? Globalement : à rien. Si ce qui compte est la version de l’application, alors les URLs n’ont pas besoin de version.
Quand tu réfléchis à savoir s’il faut passer de v1 à v1.1 lors d’un changement rétro-compatible tu ne motives pas du tout le pourquoi. Ton application est compatible ? restes en v1.
Mon problème c’est quand tu commences à considérer qu’en conséquence autant faire un /books plutôt qu’un /v1/books.
La question est de savoir ce que tu feras quand tu auras une version incompatible. Si tu as choisi /v1/books tu feras probablement un /v2/books et ce sera compréhensible et simple à gérer pour tout le monde. Si tu n’as pas prévu les versions tu vas avoir un /books et un /v2/books en parallèle, et là pour le coup ça va être clairement confus pour tout le monde.
Crédo perso : Il faut l’éviter le plus longtemps possible mais un jour tu finiras forcément par avoir besoin d’un changement incompatible. Autant le prévoir aujourd’hui.
le numéro de version des URLs n’a ici aucun sens,
Indeed, ce n’est pas son rôle. Le numéro de version (qu’il soit dans l’URL ou ailleurs) est là pour dissocier deux appels et savoir ce que l’API doit répondre. On met habituellement des numéros de version ou des dates parce que c’est plus simple et évite des incompréhensions, mais l’important est juste que l’appel soit différent. Il ne s’agit pas de donner une information ou du sens au client. Les v1 et v2 peuvent tout à fait être remplacés par des GUID opaques et sans aucun sens.
C’est d’ailleurs pour cela que les 1.x ne sont à mon avis pas pertinentes. Elles dénotent des versions mineures, où justement on devrait évoluer de façon rétro-compatible, même si ça coûte un peu plus cher. Et dans ce cas, pourquoi casser les URL ?
La rupture n’a de sens qu’en cas d’incompatibilité, et dans ce cas tu fais simplement une v2. Faire la différence entre v1.2 et v2 dans les URL serait justement faire porter un sens à cette information alors qu’il s’agit juste d’un artifice technique destiné à séparer deux requêtes.
Oui, vous pouvez, mais par expérience, je pense que :
- Cela complique inutilement le développement (augmentation mécanique du nombre de lignes et de tests)
- Les risques et complications sont multipliés par le nombre de versions à gérer
- Vous devrez sans cesse assurer que le nouveau code est capable de gérer toutes les versions, et donc les comportements
- Des soucis de performances peuvent être à prévoir
- Cela réduit considérablement les possibilités d’un changement d’architecture interne
Si l’objet est de dire que maintenir des versions parallèles coûte (plus) cher, alors oui : Il faut effectivement vérifier la compatibilité à chaque changement, maintenir potentiellement plusieurs codes, et en gardant la compatibilité on se contraint forcément à ne pas tout changer en big bang. Tout ceci est un peu indépendant de comment tu gères les versions.
(Par contre je ne vois pas où se situe le problème de performance, gérer deux URL qui pointent au même endroit c’est une problématique très simple sans perte de performance ou maintenance excessive)
Mais c’est un peu une non-question pour moi. Je ne vois que deux alternatives :
- Ne jamais faire de changement, même compatible, auquel cas la question ne se pose pas ;
- Lors du changement remplacer l’ancienne version par la nouvelle et s’assurer que tous les clients migrent exactement au même moment.
Dans tous les autres cas que je conçois (mais je peux en oublier), il faut forcément s’assurer de la compatibilité avec plein de versions, et maintenir cette compatibilité un moment, donc payer les coûts que tu annonces.
Personnellement je n’imagines pas faire quelque chose de parfait au point de ne jamais avoir besoin de le faire évoluer, et de mon expérience je n’envisage pas lancer un changement au même moment que tous les clients.
Suite avec la seconde partie :
Oui, tout dépend toujours du contexte, mais pour le coup avoir un /books/type/novel et un /type/novel plus récent amené à remplacer le précédent est pour moi exactement ce qui est dangereux.
Ce qui est à utiliser n’est pas clair, l’utilisateur va être amené à panacher les versions, avec potentiellement des résultats incohérents, et quand tu auras un historique avec plusieurs migrations de ce type ça sera juste un enfer à maintenir.
Quant aux 301 pour faire passer vers la version suivante, c’est juste « non ». Soit le changement est compatible et dans ce cas on ne parle pas de migration de version (on peut changer l’URL, mais c’est un tout autre sujet), soit on parle de versions incompatibles et il est hors de question de rediriger des robots vers une ressource incompatible qui risque de corrompre des données de son côté. Si je coupe je mets une 410, au moins c’est clair.
Parler d’hypermédia c’est bien, mais là aussi c’est un tout autre sujet. Tu parles de comment découvrir les URL, ça ne réponds pas du tout à la question de comment tu les gères de ton côté. Par contre oui, quand tu passes à la v2 tu passes tout à la v2. Permettre de panacher c’est faire durer ta v1 encore plus longtemps et t’exposer à des effets de bords difficile à identifier pour tes clients. Ta v2 est cohérente en elle-même, si un service de la v1 est utile, il sera dans la v2 (ou alors c’est que tu as décidé de le faire disparaitre). Sans compter que les identifiants ne sont pas forcément les mêmes dans les deux versions.
Et à la fin de ton second billet on arrive à la question que j’avais : entête ou URL ?
Par contre :
- Tu affirmes que le passage par l’entête permet de l’habituer à des mises à jour fréquentes sans en augmenter le risque. Je ne vois absolument pas pourquoi, et cette affirmation n’est pas explicitée.
- Tu dis que ça permet de n’en mettre qu’une partie à jour, mais je ne vois pas ici non plus en quoi le passage par l’entête est plus souple.
Alors vu qu’on a fait des jours de hors sujet, autant que je précise :
- Au niveau technique, est-ce que le passage par l’URL ou par l’entête est pus simple à gérer (à cause ou grâce aux proxy par exemple, ou dans le routage de l’application serveur, ou parce que certains langages/frameworks côté clients sont plus difficile à manipuler dans un cas ou dans l’autre)
- Au niveau humain, est-ce que l’un ou l’autre est plus facile à comprendre, à manipuler, est moins propice aux erreurs, à mettre en oeuvre
- Au niveau architecture, est-ce que passer par des URLs ouvre plus de portes ou au contraire amène des contraintes particulières ?
Et pour tout ça je parle de problèmes ou facilités effectivement rencontrées, pas de littérature ou concepts.
Au final là, je n’ai aucun élément qui me permette de faire mon choix
Laisser un commentaire