Je gère actuellement une bibliothèque qui a beaucoup d'utilité publique, et j'avais une question sur le versioning sémantique . Je veux refactoriser une partie assez importante de la bibliothèque qui est implémentée incorrectement - et a toujours été implémentée incorrectement. Mais cela signifierait des modifications de l'API publique, ce qui est une décision majeure.
Le changement que je veux faire tourne autour de la façon dont les itérateurs sont utilisés. Actuellement, les utilisateurs doivent faire ceci:
while ($element = $iterator->next()) {
// ...
}
Ce qui est incorrect, du moins dans l' interface Iterator native de PHP . Je veux remplacer par ceci:
while ($iterator->valid()) {
$element = $iterator->current();
// ...
$iterator->next();
}
ce qui est analogue à:
foreach ($iterator as $element) {
// ...
}
Si vous regardez le guide de Tom sur le versioning sémantique, il déclare clairement que toute modification de l'API publique (c'est-à-dire celles qui ne sont pas rétrocompatibles), devrait justifier une version majeure. La bibliothèque passerait donc de 1.7.3 à 2.0.0, ce qui est pour moi un pas trop loin. Nous ne parlons que d'une fonctionnalité en cours de correction.
J'ai l'intention de publier la version 2.0.0, mais je pensais que c'était lorsque vous avez complètement réécrit la bibliothèque et mis en œuvre de nombreux changements d'API publics. L'introduction de ce refactoring justifie-t-elle une sortie de version majeure? Je ne vois vraiment pas comment cela se passe - je me sens plus à l'aise de le publier en tant que 1.8.0 ou 1.7.4. Quelqu'un a-t-il des conseils?
next()
méthode est utilisée pour récupérer l'élément actuel ET déplacer le pointeur interne vers l'avant. Ce qui est faux.next()
devrait déplacer le pointeur, etcurrent()
est utilisé pour récupérer ...next()
celle qui déplace le pointeur, cela ne rompt vraiment pas la compatibilitéRéponses:
Vous hésitez car vous ne voulez pas faire de versioning sémantique, vous voulez faire du "versioning supporting versioning". Vous vous attendez à ce qu'un numéro de version "2.0" indique au monde que vous avez maintenant un tas de nouvelles fonctionnalités intéressantes, pas que vous ayez changé l'API. C'est ok (de nombreux éditeurs de logiciels et / ou développeurs le font). À mon humble avis, vous avez les options suivantes:
next
, ajoutez simplement les fonctionsvalid
etcurrent
). Ensuite, vous pouvez utiliser "1.8.0" comme numéro de version suivant. Si vous pensez que changer le comportement denext
est vraiment important, faites-le dans 2.0.0.la source
next()
de continuer à faire ce qu'elle fait. Pour implémenter correctement la fonctionnalité, il doit faire quelque chose de différent. Donc, si je le rend rétrocompatible - la nouvelle fonctionnalité / correction sera également erronée et sapera tout le point du changement.next()
méthode pour faire toutes les nouvelles fonctionnalités, plus ce qui était nécessaire pour rendre la compatibilité descendante. C'est un peu horrible de devoir ternir de nouvelles fonctionnalités comme celle-ci, mais bon ho.Tenez-vous au guide de Tom pour le versioning sémantique.
Toute modification importante d'une API publique doit être effectuée à l'un des deux points:
Soit dit en passant, mon vote est le premier. Mais je reconnais que cela ne convient qu'aux choses insignifiantes.
Le problème est de maintenir la compatibilité descendante et de vous assurer de ne pas casser les choses pour les utilisateurs précédents de votre API.
En substance, vous créez une erreur d'indexation pour vos utilisateurs qui ne connaissent pas la modification. Forcer une modification comme celle-ci oblige tous vos utilisateurs à effectuer les opérations suivantes:
Cela peut potentiellement demander beaucoup d'efforts, surtout si l'on considère le peu de projets qui ont des cas de test en place afin de valider des changements comme celui-ci. La quantité d'efforts augmente lorsque vous considérez le nombre d'utilisateurs en aval de vos utilisateurs qui devront également mettre à jour leurs installations.
Pour quelque chose d'aussi petit, je le laisserais partir et ne m'embêterais pas avec.
Si cela vous dérange vraiment (ce qui semble ou si vous ne l'auriez pas demandé), je ferais ce qui suit.
Release Notes
avance de la diffusion du changementEt puis soyez patient car il faudra un certain temps pour accumuler d'autres éléments qui justifient la mise à niveau du numéro de version vers une nouvelle version majeure. La notification avancée (partie 3) vous donne le temps de recevoir les commentaires des utilisateurs finaux pour savoir à quel point l'impact de ce changement va être.
Une solution alternative consiste à ajouter une nouvelle fonction qui fonctionne comme vous le souhaitez.
Si vous l'avez, vous devez
foo()
créerfooCorrect()
afin de fournir le correctif, mais aussi de préserver pleinement la compatibilité descendante. Et à un moment donné, vous pouvez déconseillerfoo()
de faire savoir aux autres de ne pas l'utiliser.Le défi est que vous trouverez quelque chose d'autre dans
fooCorrect()
lequel nécessite une mise à jour et que vous vous retrouvez avecfooCorrectedCorrect()
ou un autre non-sens stupide.Si vous voulez vraiment que cela soit corrigé maintenant, cette approche alternative est probablement la meilleure solution. Soyez conscient et méfiez-vous de créer de nombreuses fonctions supplémentaires de cette façon car cela rend l'API plus difficile à travailler. Et cette prise de conscience peut être suffisante pour éviter le pire de ces types de problèmes.
Mais cela pourrait être l'approche "la moins mauvaise" à considérer pour quelque chose de petit.
la source
next()
nonnextCorrect()
). Je vais voir si je peux modifier next () afin qu'il soit rétrocompatible ET fonctionne lors de la mise en œuvre de l'Iterator
interface.