Temps de lecture estimé : 3 minutes
Il existe une diversité de systèmes de numérotation des logiciels, du plus simple (n+1) au plus exotique (suivant les décimales de Pi).
Dans le lot, semver
décrit une numérotation en trinôme M.m.p
où M représente des changements non rétro-compatibles, m représente des changements rétrocompatibles et p représente des correctifs. Puisque chaque système vise à bien communiquer aux consommateurs, semver semble la solution parfaite.
Semble seulement, car en fait cet idéal de communication parfaite n’est pas atteint ; le problème est la nature d’un changement rétro-incompatible. Dans la théorie, une rupture de compatibilité est simple : il s’agit d’une possibilité enlevée au consommateur.
Alors soyons clairs, j’adore semver parce que les informations qu’il transmet sont les plus utiles dans une relation « fournisseur -> consommateur », mais je crois que les consommateurs que nous sommes ne pouvons pas plus faire confiance à ce système de numérotation qu’à n’importe quel autre.
Pourquoi ? Parce que la pratique peut être largement éloignée de la théorie pour plusieurs raisons possibles :
NB: Ce dernier cas peut paraître absurde, il est pourtant arrivé aux images Docker MySQL 8.0 et 5.7 en juillet 2022. Sur une même version, les mainteneurs ont changé le système socle de Debian vers Oracle, créant de fait une rupture de compatibilité dans toutes les images filles.
Ce qui s’est passé ici est symptomatique de l’absence de norme de numérotation autour de la nouvelle sémantique de l’application : désormais dockerisée, que numérote-t-on ? Juste l’application ? L’ensemble application / infra ?
Ces trois situations le montrent, la prise de décision humaine est sujette à erreur et cette erreur fait perdre à semver la force de son système de numérotation sur tous les autres.
Aujourd’hui, nous utilisons massivement des gestionnaires de dépendances dédiés pour nos applications : composer, npm, gem, pub, etc. D’une certaine façon, ces gestionnaires de dépendances sont un peu responsables de la popularité de semver… et de son mésusage.
En effet, tous supportent l’opérateur de plage « ^ », permettant les mises à jour satisfaisant : >= M.m.p && < (M+1)
. Pire, composer et npm vont jusqu’à le recommander.
Ce positionnement fait semblant d’ignorer les écueils que nous avons vus plus tôt et c’est un vrai problème.
Il y a deux faits importants :
Pour éviter que les dangers se propagent comme une boule de neige, vous devez gérer le cycle de vie de vos dépendances comme vous géreriez votre propre code : chaque mise à jour doit faire l’objet de test pour éviter les régressions.
En tout premier lieu, il est donc nécessaire d’épingler le plus précisément possible les versions de dépendances. Les patches étant mieux compris que les différences rétro-compatibles / rétro-incompatibles, l’opérateur pessimiste « ~ » peut être un bon compromis (équivalent à >= M.m.p && < M.(m+1)
).
Ensuite, puisque vous devez également prévenir l’excès inverse consistant à ne plus mettre à jour les dépendances, vous pouvez vous appuyer sur des outils surveillant vos dépendances ; les plus évolués vont jusqu’à créer des PRs / MRs pour vous :
Sources :
Ce billet vous a plu ? Partagez-le sur les réseaux…
… Ou inscrivez-vous à la newsletter pour ne manquer aucun article (Si vous ne voyez pas le formulaire, désactivez temporairement uBlock).