J'essaie d'obtenir un avis pour mes listes de pros/Infers sur la manière de structurer les engagements qui sont sortis d'une discussion à mon travail.
Voici le scénario:
Ma société dispose des règles suivantes strictement forcées:
La question est donc de savoir comment structurer les engagements pour ces 3 choses. (Refactoring, caractéristique X et test de la fonctionnalité X) Mon collègue m'a référé à cet autre article mais il ne semble pas aborder la partie refactorisée. (Je suis d'accord sans la source de refactorisation et le test devraient être dans un commettre) L'article parle de "Breaker Git Bisect" et "en veillant à ce que chaque commit compile/passe "mais nos règles strictes couvrent déjà cela. L'autre autre argument qu'ils donnent est le "code logiquement connexe maintenu ensemble" qui semble un peu philosophique pour moi.
Je vois 3 façons de procéder. J'espère que vous pouvez soit a) ajouter à lui b) commentez pourquoi l'un des pro/contre existants n'est pas important et doit être supprimé de la liste.
Méthode 1 (un commit): Comprend une fonctionnalité X, Test pour la fonctionnalité X et Refactoring
avantages:
les inconvénients:
Méthode 2 (deux commits): une inclut la fonction X, puis deux inclut le refactoring et le test pour la fonctionnalité X
avantages:
les inconvénients:
Méthode 3 (deux commits): une inclut le refactoring, deux inclut la fonction X et Test pour la fonctionnalité X
avantages:
les inconvénients:
Donc, en fonction de tout cela, je suis penché vers 3. Avoir la couverture de test automatisée est une grosse victoire (et ce qui m'a démarré dans ce trou de lapin en premier lieu). Mais peut-être que l'un de vous a des avantages/inconvénients que j'ai manqués? Ou peut-être qu'il y a une 4ème options?
Lorsque vous travaillez sur le code existant, il est courant que vous devez refactoriser le code avant de pouvoir implémenter votre fonctionnalité.
Ceci est le mantra de Kent Beck: "Effectuez le changement facile (AVERTISSEMENT: Cela peut être difficile), puis effectuez le changement facile"
Pour ce faire, je recommande généralement de faire des petits commits fréquents. Prenez des petits pas. Refacteur progressivement:
Chaque refactoring ne change pas la manière dont le code fonctionne, mais comment cela est mis en œuvre. Ce n'est pas "difficile à examiner" car les deux implémentations sont également valables. Mais la nouvelle mise en œuvre facilitera le changement de changement.
Enfin, écrivez le test et faites-le passer. Il devrait être relativement court et au point. Cela facilite également la lecture de la société.
donc j'irais aussi pour la 3ème option. Peut-être que j'aurais même plusieurs commits de refactorisation. Ou je les écrases dans l'un avant de pousser cela pour examen, donc il n'y en a qu'un. Ou peut-être que je ferais un premier PR qui ne fait que refactoring, puis une seconde qui n'est que la fonctionnalité. Cela dépend vraiment de la quantité de refactoring (garder votre PRS Short) et vos conventions de votre équipe!
Si la seule valeur du refactoring est à tester et que le test est dans un futur commettre, vous devez aller de retour entre les deux pour comprendre pourquoi cela a été fait et si cela aurait pu être fait mieux
Pour résoudre ce problème, vous devez obtenir votre équipe à l'aise dans cette approche: le refacteur d'abord, puis implémentez la fonctionnalité.
Je vous suggérerais de discuter avec vos collègues et de l'essayer. Je vous recommanderais également d'essayer de Pratiquez "Over-commettant" pour vous permettre de faire des commentaires plus petits. C'est une compétence utile pour avoir lorsque le code est délicat, c'est donc un excellent exercice à faire lorsque le code n'est pas!
En tout cas, je pense que vous avez une discussion en bonne santé avec vos collègues. Vous trouverez sans doute ce qui fonctionne pour votre équipe!
Allez avec 3 - mais mentionnez la raison du refactoring clairement dans le message de validation. Puis personne ne doit deviner pourquoi vous l'avez fait.
Tout refactoring qui touche de nombreux fichiers sera toujours plus difficile à examiner que celui qui ne touche que quelques-uns, ce qui ne fait aucune différence si vous le faites au début, au milieu ou à la fin du cycle de développement. Mais lorsque vous mélangez de gros refacteurs et nouvelles fonctionnalités d'un commettre, qui devient vraiment difficile à examiner, de sorte que cette méthode des règles 1.
Méthode 2 a l'inconvénient que vous n'aurez aucune chance de faire de TDD pour la nouvelle fonctionnalité X. Et après avoir été ajoutée X sans aucun test d'unité, il existe un certain risque d'oublier les tests par la suite, car l'effort supplémentaire de requérant Un refactoring important avant d'être en mesure d'ajouter des tests d'unité peut ne pas sembler la peine (ce qui est probablement une erreur, mais vous devrez peut-être expliquer cela à vos supérieurs).
De plus, je recommanderais
pour vous assurer d'avoir suffisamment de tests en place avant de commencer (pas nécessairement des tests unitaires) qui vous donnent confiance, le refactoring ne brise rien. Sinon, prenez auparavant le temps d'ajouter de tels tests.
pour vous assurer qu'une fois que vous avez terminé des tests d'unité X +, vous passez en revue le code par vous-même et vérifiez si le refactoring que vous avez fait au préalable atteint ses objectifs et si le code est vraiment dans un état propre maintenant. Sinon, ajoutez un refactoring supplémentaire/nettoyage étape par la suite.
Le refactoring avant que la nouvelle fonctionnalité soit votre choix (méthode numéro 3), bien que je envisageais certainement de refactoriser plusieurs fois avant la nouvelle fonctionnalité. Si vous le pouvez, je recommanderais de casser votre refactoring dans des engagements individuels.
Bien que les grands engagements sont parfois inévitables (surtout avec le code plus âgé), plus le meilleur est le meilleur.
Comportements de refacteur en créant les sous-routines d'abord, quelques-uns ou un à la fois, modifiant les appelants, quelques-uns ou un à la fois, pour arrêter de réaliser ce comportement par code interne et appeler le sous-programme. Test de suites pour comparer les comportements avant et après peut être ajouté si le nom de l'appelant est modifié afin qu'ils existent tous deux à une révision pour des tests de comparaison, puis le code de code et le test de comparaison obsolescent peut être supprimé dans une autre version, en annulation du nouveau code à la version. Vieux nom afin que ses appelants ne doivent pas nécessairement être modifiés.
Une bonne couverture de test est bien sûr extrêmement importante: tous les cas étranges, exceptions, nulls, négatifs, diviser par zéro, nan, erreurs, bords et cas de centre de toutes sortes.
la méthode 3 est la plus courante, car
vous développez un incrément de fonctionnalité et aucun incrément de fonctionnalité ne doit être possibilibile sans ses tests associés. Lorsque je tire une branche, la première chose que je fais est de regarder des tests pour trouver des exemples d'utilisation des API nouvellement développées. Ce commit est autoconstissant et documenté par le test
Une fois que vous êtes en mesure de fournir un code de travail avec une nouvelle fonctionnalité à votre équipe, vous êtes prêt à refacturer le code. Le refactoring devrait être fait avec très peu de pas, sans casser aucun test. Les changements de rupture devraient arriver de la manière la plus sûre
Cette partie est ce que j'appelle "étendre, remplacer, supprimer"
supposons que vous ayez
public void executeBadCode(String what , String why) { ... }
et votre refactoring implique un changement de rupture telle que introduire un objet de paramètre.
donc, vous ajoutez une méthode
public void excuteBadCode(BadParams b) {
executeBadCode(b.what() , b.why());
}
avec son test d'unité. Vous allez commettre spécifiquement que c'est un refactoring. par exemple. [refact] Introduction de la surcharge d'objets de paramètre pour la méthode ExecuteBadCode ()
Maintenant, je remplace tous les usages de la fonction précédente. Je le ferai un à l'heure, en faisant une seule commission par substitution dans une classe/fichier, ainsi que des modifications potentielles ou des ajouts dans des tests associés
Enfin, je retire la méthode ancienne déplaçant son corps dans le nouveau et en veillant à ce qu'il n'y ait aucune référence dans le code.
De cette manière, chaque développeur pourrait choisir une version de travail de votre code, peut l'examiner et peut comparer avec la précédente, détectant facilement le changement significatif.