Comment gérer un refactoring qui prend plus de temps qu'un sprint?

49

Je travaille avec une base de code de plus de 500 000 lignes de code. Il a sérieusement besoin de refactoring. Des efforts de refactorisation ont été identifiés et prendront plus de temps que le sprint normal de deux semaines. Celles-ci ne peuvent pas être divisées en tâches plus petites, comme je l'ai vu suggéré dans d'autres réponses de ce site. Le produit doit fonctionner à la fin de l'itération et une refactorisation partielle laissera le système dans un état inutilisable, car la dépendance entre les éléments est horrible. Alors, quelle serait la meilleure façon d’aborder cet obstacle? Encore une fois, je le mentionne, le décomposer en plus petits éléments n’est pas une option, cela a déjà été fait.

Mise à jour: Les gens semblent avoir besoin d'une explication sur la raison pour laquelle cela ne peut pas être intégré dans un sprint de 2 semaines. Un sprint implique plus que la simple écriture de code. Nous avons une politique de non-code sans tests. Cette politique n'existait pas toujours et une grande partie de la base de code ne les avait pas. De plus, certains de nos tests d'intégration sont toujours des tests manuels. Le problème n'est pas que le refactoring lui-même est si grand. C’est avec le fait que de petits changements ont un effet sur de nombreuses parties du système et nous devons nous assurer que ces parties fonctionnent toujours correctement.

Nous ne pouvons pas retarder ou prolonger un sprint car nous avons des correctifs mensuels. Par conséquent, cette modification qui s’étend au-delà d’un sprint ne peut pas empêcher l’autre travail d’être ajouté au correctif.

Refactoring vs Refonte: Le simple fait que notre processus de développement ne soit pas assez efficace pour gérer ce refactoring dans un cycle de deux semaines ne justifie pas de le renommer en une refonte. J'aimerais croire qu'à l'avenir, nous pourrions accomplir exactement la même tâche dans un cycle de deux semaines à mesure que notre processus s'améliorera. Le code en question ici n'a pas dû changer depuis très longtemps et est assez stable. Maintenant que la direction de la société devient de plus en plus adaptable au changement, nous souhaitons que cette partie de la base de code soit aussi adaptable que le reste. Ce qui nécessite de le refactoriser. Sur la base des réponses fournies ici, il devient évident qu’il manque un échafaudage pour que ce refactoring puisse fonctionner dans les délais impartis pour les sprints normaux.

Répondre:

Je vais faire l'approche de fusion et de succursale que Corbin March a suggérée pour la première fois afin que nous puissions en apprendre davantage sur ces problèmes et sur la façon d'identifier les tests manquants. Je pense que pour aller de l'avant, nous devrions adopter l'approche suggérée par Buhb, qui consiste à identifier les zones manquant de tests et les mettre en œuvre en premier, puis procéder à la refactorisation. Cela nous permettra de nous en tenir à notre cycle normal de sprint de deux semaines, comme beaucoup l'ont dit ici, cela devrait toujours être le cas pour la refactorisation.

Charles Lambert
la source
23
En passant, il s’agit par définition d’une refonte à grande échelle et non de refactoring . J'espère que vous ne prendrez pas ça pour du piquant - IMHO, il est important d'utiliser une terminologie claire pour éviter les problèmes de communication :-)
Péter Török
9
@ Charles, "Le refactoring est généralement effectué par petites étapes. Après chaque étape, il vous reste un système en fonctionnement qui n'a pas changé de fonctionnalité. " Citation tirée de la page que j'ai liée ci-dessus.
Péter Török
2
@Charles: le refactoring peut toujours être effectué de manière incrémentielle, tout en maintenant le système en fonctionnement. placez un gros commentaire "Refactoring en cours" en haut de la classe, du package ou du module en cours de refactorisation, et créez les parties une par une. Si vous coupez une version intermédiaire pendant que le modèle objet est en transition, c'est bien.
Sean McMillan
7
Si vous effectuez des opérations d'une telle ampleur qu'il vous est impossible de disposer d'un élément de code fonctionnel de manière régulière, c'est la définition même du moment où la refactorisation devient une refonte. S'il vous plaît, ne vous fâchez pas contre les gens qui vous ont appelé pour votre mauvaise utilisation du mot. Il n'y a rien de mal à poser des questions sur la refonte. Les commentateurs essaient simplement d'indiquer que vous n'obtiendrez pas les réponses que vous souhaitez, car vous en abusez, ce qui est déjà arrivé.
jprete
5
Je sais que c'est un peu en dehors du sujet, mais vous m'avez vraiment laissé curieux de savoir quelles circonstances rendent impossible la refactorisation par petites étapes. S'il vous plaît partager un peu plus de fond à ce sujet.
Buhb

Réponses:

14

Si vous avez le luxe de retarder la refactorisation, je suggère de concentrer les itérations à venir sur l'ajout de tests unitaires et de tests d'intégration automatisés au point où vous pouvez facilement refactoriser la base de code, puis refactoriser en un seul sprint.

Buhb
la source
68

Ma suggestion:

  1. Créer une branche
  2. Fusionnez tous les jours du tronc vers votre branche et résolvez les conflits.
  3. Travailler jusqu'à ce que ce soit fait. Votre branche peut être en dehors du développement de base pour plusieurs sprints.
  4. Fusionner vers le tronc.

Il ne fait aucun doute que la situation deviendra probablement laide. Je ne t'envie pas. D'après mon expérience, lorsque vous modifiez radicalement un projet, il est plus facile de fusionner le développement en cours dans le nouveau paradigme, plutôt que de fusionner le nouveau paradigme dans un tronc désormais modifié une fois que tout est terminé. Mais ça va faire mal.

Corbin March
la source
1
Nous avons discuté de l’utilisation de cette approche, et si aucune autre idée n’a été formulée avant de l’aborder, c’est ce que nous prévoyons de faire.
Charles Lambert
3
Je crains fort que vous ne perdiez pas vos frais généraux entre le tronc et la succursale si vous souhaitez effectuer une refactorisation aussi approfondie.
Giorgio
Dans la plupart des cas (espérons-le), ces modifications fusionnées n'affecteront pas le code en question ici. Cela ne me dérangerait pas de prolonger la chronologie de ce changement si cela garantissait un résultat fiable.
Charles Lambert
1
Compte tenu de la volatilité que votre présentation semble suggérer, vous devriez peut-être envisager Git , car cela facilite ce type de ramification et de fusion spéculatives.
John Tobler
1
@Giorgio: Moi aussi, la fusion quotidienne semble un peu paranoïaque, mais cela dépend vraiment de la taille de l'équipe. Plus il y a de personnes, plus il y a de changements et plus vous devez fusionner fréquemment. Quotidien semble être la limite inférieure si vous voulez avoir le temps de travailler.
Matthieu M.
40

Toutes les tâches ne peuvent pas être accomplies dans un sprint (artificiel) de 2 semaines, le bon sens est donc nécessaire. S'il n'est plus possible de le décomposer et qu'il faut le faire, continuez et agissez. Le processus n’est pas plus important que le résultat final et doit être considéré comme une directive plutôt que comme une loi à ne jamais être violée.

Chris Card
la source
3
Votre réponse est une très bonne information sur le sujet. Je suis ici pour "faire et faire" comme vous dites. J'ai posé la question dans l'espoir d'obtenir des informations qui me permettraient de proposer un processus parallèle, ou de modifier le processus en cours pour résoudre ma situation actuelle. J'ai besoin de quelque chose à dire aux développeurs afin qu'ils disposent de directives dans lesquelles travailler, car cela se produira au moins deux fois de plus.
Charles Lambert
+1 pour "Le processus n'est pas plus important que le résultat final et doit être considéré comme une directive plutôt que comme une loi à ne jamais être enfreinte." - Les gens semblent vraiment oublier ça.
Bjarke Freund-Hansen
32

Il suffit de faire un sprint de 3, 4 ou 5 semaines. On s'en fout? Vous êtes évidemment convaincu que rien ne peut être fait dans un délai plus court, alors arrêtez de vous battre.

Il suffit de ne pas en parler à la Royal Society of Blind Agile Adherance.

JeffO
la source
semble que pour des raisons d’organisation (correctifs mensuels), les sprints de 2 semaines sont assez difficiles à changer.
Steve Bennett
10

Je recommande de commencer avec le livre Working Effectively with Legacy Code , de Michael Feathers. Il couvre une variété de techniques pour réduire la portée des changements de style refactoring.

ségrégation
la source
Un bon livre, c'est sûr, mais je ne pense pas qu'il couvre la refactorisation par fractionnement sur plusieurs sprints.
Adam Lear
4
Je vais lui donner un +1 parce que c'est probablement le meilleur livre pour commencer lorsque vous commencez à apprendre, comme le titre le dit, à travailler efficacement avec le code hérité. Cela concerne tout le monde qui pourrait poser cette question et ne pas comprendre en quoi consiste la division des choses en plusieurs étapes.
Charles Lambert
@Anna - alors vous voudrez peut-être (re) lire le chapitre 25, qui parle de techniques pour casser les sortes de couplages qui empêchent de petits changements.
Kdgregory
@kdgregory Fair assez. :) Vous pensez ajouter cela à votre réponse pour la rendre plus géniale?
Adam Lear
7

Dans notre boutique, lorsque nous avons d'importantes tâches de refactoring ou de réécriture qui ne peuvent pas être terminées dans une fenêtre d'édition, nous laissons la fonctionnalité telle quelle dans le système. Mais nous commençons avec les nouvelles fonctions lego-block refactorées lorsque le temps le permet. Finalement, nous arrivons à un état où nous avons suffisamment de blocs lego, qu'un sprint donne suffisamment de temps pour brancher les blocs lego dans l'application et l'activer pour les utilisateurs.

De manière plus concise, nous divisons ou retravaillons de grandes fonctions en utilisant de nouveaux noms. Ensuite, à la fin, nous utilisons notre travail renommé, refactoré au lieu du vieux code désagréable.

Amy Anuszewski
la source
C'est une bonne idée, mais cela nécessiterait un haut niveau de communication. Par exemple, lors du codage, si j'identifie une méthode qui n'est utilisée nulle part et qu'elle n'est pas publique, je la supprimerai.
Charles Lambert
5

Consacrez un sprint à déterminer comment maintenir le code en état de fonctionner correctement à mi-refactor. Cela peut prendre la forme de méthodes et de classes, d’emballeurs, d’adaptateurs, etc., obsolètes. Votre refactoring peut rendre le code plus sale pendant un court laps de temps afin d’être plus propre à long terme; c'est bon. À l'heure actuelle, vous dites que cela ne peut pas être fait. Je ne pense pas que ce soit le cas - réfléchissez à ce que serait votre processus si cela pouvait être fait, réfléchissez aux étapes que vous pouvez suivre pour le rendre ainsi. Puis plongez dans.

Carl Manaster
la source
Nous avons déjà fait tout cela. C’est la raison pour laquelle j’ai clairement indiqué qu’il ne pouvait pas être décomposé.
Charles Lambert
Vraiment? Vous avez passé tout un sprint simplement à planifier comment restructurer votre système sans casser votre système et vous n’avez rien trouvé? J'ai du mal à croire qu'un sprint dédié à la planification ne donne rien; vous avez peut-être besoin de faire appel à un consultant (et non, je n'en suis pas un, je ne cherche pas à obtenir un poste).
Carl Manaster
1
Je n'ai rien dit de la sorte. Je disais que nous avons suivi un processus similaire à ce que vous avez décrit et que nous sommes sortis à l’autre bout avec du code qui ne peut pas être reformé en un seul sprint.
Charles Lambert
J'ai dit: "Consacrez un sprint à trouver comment garder le code en état de fonctionner correctement à mi-refactor." Vous avez dit: "Nous avons déjà fait tout cela." Voulez-vous dire le contraire maintenant? Je suis désolé si cela semble controversé, mais je ne comprends pas.
Carl Manaster
5

+1 sur la réponse de Corbin March, c'est exactement ce que je pensais. On dirait que votre base de code est un peu laide et qu'il faudra plus d'un cycle de sprint pour le nettoyer.
Donc, comme l'a dit Corbin,

  1. branchez-le dans un "projet de refactoring"
  2. tester votre changement de branche
  3. promouvoir votre environnement de test pour les tests d'assurance qualité
  4. fusionnez-le progressivement dans le coffre jusqu'à ce que le refactoring soit terminé.

Je suis sûr que vous n'auriez aucun problème à vendre cela à votre responsable de développement. Si vos PM ont du mal à le voir, expliquez-leur que Rome n'a pas été construite en un jour et nettoie toutes les ordures jetées dans celui de Rome. Les rues ne se feront pas en un jour non plus. La refactorisation prendra un certain temps, mais elle en vaudra la peine en termes de maintenance simplifiée, de mises à jour plus rapides des améliorations, de tickets de production moins élevés et d’accord de niveau de service plus rempli.

bkdraper
la source
1
J'ai toutes les munitions dont j'ai besoin pour convaincre tout le monde. J'ai juste besoin d'un plan officiel pour l'exécuter, quand je le présente. D'après les réponses fournies, il ne fait aucun doute que je proposerai une solution reproductible.
Charles Lambert
4

Bien que la refonte que vous voulez vraiment faire soit une tâche importante, serait-il possible de refactoriser de plus petites pièces pour casser / découpler des dépendances individuelles? Vous savez - en cas de doute, ajoutez l'indirection. Chacun de ces découplages devrait être une tâche plus petite que celle que vous ne pouvez pas accomplir.

Une fois les dépendances supprimées, vous devriez pouvoir diviser les tâches de refactoring restantes pour pouvoir les obtenir dans les sprints.

Matthew Flynn
la source
3

Dans le projet pour lequel je travaille en ce moment, nous utilisons des sprints de 4 semaines. Et parfois, nous ne pouvons pas terminer une user story et nous la redémarrons lors du sprint suivant.

Cependant, à mon humble avis, il devrait être possible de diviser une refactorisation en histoires plus petites pouvant s’inscrire dans un sprint de 4 semaines. Si vous ne parvenez pas à mettre le code dans un état cohérent dans un délai de 4 semaines, j'ai le sentiment que vous réécrivez votre application plutôt que de la refactoriser.

Giorgio
la source
un sprint de 4 semaines devrait le couvrir. Cependant, nous ne pouvons pas arrêter les sprints actuels de 2 semaines en raison de corrections de bugs, etc. Cela devrait donc s'étendre à plus d'un sprint. Ainsi, le noeud de mon problème.
Charles Lambert
Comme je l'ai dit, nous utilisons des sprints de 4 semaines et, si une histoire n'est pas terminée dans 4 semaines, nous la planifions simplement pour le prochain sprint. Pouvez-vous au moins avoir le système dans un état cohérent à la fin d'un sprint de 2 semaines (et continuer ensuite pendant le sprint suivant)?
Giorgio
Etat cohérent non vérifiable .
Charles Lambert
Je dois ajouter ma vague aux efforts déployés par les autres pour espérer que vous trouverez un autre mot à utiliser plutôt que «refactoriser». Le refactoring est bien défini et sa portée est beaucoup plus immédiate et à court terme que la reconfiguration et la reprogrammation massives et fastidieuses que vous devez faire.
John Tobler
2

Je recommande que lorsque certaines tâches prennent plus de temps que le cycle de sprint de 2 semaines, la tâche soit reportée à une date ultérieure. Votre équipe a identifié le besoin de refactorisation et c'est important. Parfois, il n'y a pas d'autre option ... et, oui, ça craint.

Lorsque vient le temps de commencer la refactorisation, vous allez simplement suspendre les sprints normaux. Tu n'as pas le choix. Utilisez le contrôle de version intelligent - branche, refactor, test, fusion. Il y a toujours un moment dans le temps où la refactorisation de grands projets a la priorité sur les fonctionnalités. Si possible, je tenterais également de séparer les préoccupations pour une plus grande flexibilité.

IAbstract
la source
Nous ne pouvons pas le remettre à jamais, et votre réponse ne dit pas comment effectuer le refactoring.
Charles Lambert
@ Charles: 'prévu pour une autre fois.' ;) Je n'ai pas dit annuler le projet.
Résumé de la journée du
2

Ayant récemment examiné le même problème avec une partie de notre base de code (qui est également un peu plus grande), j'espère pouvoir partager quelques informations avec vous. Dans ma situation, la base de code ayant été développée par une autre équipe, aucun des développeurs originaux n’a été impliqué dans cette refactorisation. Mon expérience avec la base de code était d'environ un an et un autre développeur l'a chargé de le faire deux ans plus tard.

Permettez-moi deux petites notes concernant les autres réponses ici:

  • La création de branches vous aidera à établir un terrain de jeu pour vous-même, mais ne fusionnez jamais vos modifications dans le tronc dans un grand ensemble de modifications. Vous allez avoir de graves problèmes avec le reste de l'équipe.
  • Vous devez le faire progressivement, et cela peut être fait. Pas d'excuses. Lisez Travailler efficacement avec les codes existants. Relisez le.
  • Penser que vous pouvez le faire en une seule étape est une erreur. Bien qu'il semble y avoir plus de travail, le faire progressivement est beaucoup plus facile à gérer.

Aller apparemment "hors réservation" pendant deux semaines ou plus ne passera pas inaperçu. Vous devez vous assurer que vous êtes soutenu par la gestion de projet et, plus important encore, par l'équipe. Si l'équipe n'est pas engagée dans cette refactorisation (et cela signifie, faites-le maintenant, pas dans un avenir lointain), vous aurez des problèmes.

Ne le faites pas seul, utilisez la programmation en binôme. Cela ne signifie pas pour autant que vous devez rester assis devant le même clavier tout le temps, mais que vous pouvez gérer des tâches petites et étroites (par exemple, écrire des tests qui capturent le comportement de cette classe) individuellement.

Faites un refactoring Scratch et traitez-le comme tel. (Une sorte de prototype de refactoring "jetable", le bit "jetable" est important!) Honnêtement, il est peu probable que vous connaissiez toutes les implications de votre refactoring. Une refacturation de grattage vous aidera à certains égards:

  • Vous découvrirez des éléments du système dont vous n'aviez jamais su l'existence.
  • Vous aurez une bien meilleure vision de l'interconnexion des modules
  • Vous découvrirez une nouvelle façon de regrouper votre système en modules, probablement très différente de votre compréhension actuelle. Discutez des idées avec votre partenaire. Essayez de distiller votre nouvelle vue. Rédigez un court livre blanc sur l’architecture (ou dessinez un diagramme) qui indique où sont les choses et où elles devraient logiquement appartenir.

Lorsque vous aurez terminé votre refactoring, j'espère que vous découvrirez que vous ne pouvez pas tout changer. Vous vous sentirez mal, c'est juste un gros bazar et vous ne pouvez pas simplement appuyer sur un bouton et le faire fonctionner. C'est ce qui m'est arrivé, cela pourrait être différent dans votre situation.

Cependant, mon partenaire et moi avions une bien meilleure compréhension de notre système. Nous avons maintenant pu identifier des refactorisations / restructurations individuelles, plus petites (bien que toujours importantes). Nous avons capturé notre vision du système dans un diagramme et l'avons partagé avec l'équipe, ainsi que les éléments de l'arriéré que nous avions créés pour mettre en œuvre cette vision. Forts d'un consensus commun, nous avons décidé des éléments à mettre en œuvre au cours de la prochaine itération.

Une dernière chose qui nous a aidés a été d’utiliser un grand tableau blanc. Il y a trop de choses à garder dans votre tête. Il est extrêmement important que vous preniez des notes. Rédigez vous-même une note de compte rendu à la fin de la journée, décrivant ce que vous avez fait aujourd'hui et que vous voulez faire demain. Cela aide à relaxer les grands moments, et vous avez besoin de temps de détente si vous voulez suivre la tâche. Bonne chance!

Johannes Rudolph
la source
1

Démarrer une fenêtre de maintenance pendant laquelle aucun développement supplémentaire n'est effectué. Effectuez la refonte, puis reprenez les sprints de développement.

Christopher Mahan
la source
0

Nous avons deux types de travaux à portée de main:

  1. Heure de travail
  2. Le génie fonctionne

Refactorisation consiste généralement du premier type de travail, étant donné que beaucoup de méthodes sont déjà connus pour les développeurs comme DRY , SRP , OCP , DI , etc. Ainsi , lorsqu'un projet prend deux mois pour être refactorisé, il faut tout simplement deux mois , il y a aucun moyen de le contourner. Par conséquent, ma suggestion serait de ne pas reformuler le projet initial et de le laisser travailler sur sa situation actuelle. Arrêtez de recevoir les nouvelles demandes et exigences des parties prenantes et du propriétaire du produit . Laissez ensuite l’équipe travailler sur le projet jusqu’à ce qu’il soit restructuré et prêt à partir.

Saeed Neamati
la source
0

Une suggestion qui peut aider: Si vous avez un code non testé tel que vous ne disposez pas de suffisamment de temps pour le refactoriser et le retester au cours du sprint de deux semaines, envisagez tout d’abord d’apporter d’autres modifications mineures non liées au code afin que vous puissiez vous concentrer. sur l'écriture des tests pour le premier sprint ou deux. Peut-être pouvez-vous identifier plusieurs clients non testés du code que vous voulez refactoriser; choisissez un client et apportez quelques modifications utiles à l'entreprise qui vous obligeront à écrire des tests pour ce client. Une fois que vous maîtriserez mieux le code, que vous travaillerez dessus, que vous aurez effectué plus de tests et que vous aurez peut-être effectué quelques modifications mineures contributives, vous serez beaucoup mieux placé pour effectuer la refactorisation et le processus (désormais plus facile). ) tester les deux en une itération.

Une autre approche consiste à copier le code incriminé, à le refactoriser, puis à déplacer les clients un par un vers le nouveau code. Ce travail peut être divisé en plusieurs itérations.

Et n'abandonnez pas: n'acceptez pas qu'une grande refactorisation ne peut pas être décomposée en étapes plus petites. L'approche la plus facile / la plus rapide / la meilleure peut prendre plus de temps qu'une itération. Mais cela ne signifie pas qu'il n'y a aucun moyen de faire des morceaux de la taille d'une itération.

Jeff Grigg
la source