Quand refactoriser

32

J'ai lu la majeure partie du livre de refonte de Fowler et j'ai refactorisé de nombreuses applications dans mon passé, petits et grands.

L'une des choses les plus difficiles à apprendre est «quand» refactoriser. J'ai tendance à le faire sur la base d'une intuition qui m'a remarquablement bien servi dans le passé. Cependant, lors de discussions avec les gens sur la question de savoir si un morceau de code doit être laissé seul ou refactorisé en ce moment, il est difficile de s'en tenir à la «vérification de l'intestin».

Je pense qu'il devrait y avoir des approches plus rigoureuses à ce sujet, mais je ne suis pas sûr de ce qu'elles sont.

Je comprends les "odeurs de code", le refactor rouge-vert et d'autres pensées, mais souvent je pense que le meilleur moment pour refactoriser n'est pas la première fois que vous écrivez le code, mais la deuxième ou la troisième fois que vous utilisez le code et réalisez qu'il s'agit en fait d'un problème et qu'il est réellement utilisé.

Hortitude
la source
2
Essentiellement, vous demandez la même chose que ceci: programmers.stackexchange.com/questions/6268/… . Sauf que votre seuil d'action est plus bas, car le coût et le risque sont plus bas, non?
S.Lott

Réponses:

22

Refactoriser lorsque le coût de refactoring est inférieur au coût de non refactoring.

Mesurez le «coût» comme vous le pouvez. Par exemple, le code est-il si mal implémenté que des bugs insignifiants coûtent des heures ou des jours à corriger? Le refactoring vous permettra-t-il de gagner plus de clients, d'augmenter la capacité ou d'améliorer les performances et ainsi de rendre vos clients existants plus heureux?

Bryan Oakley
la source
court et parfait
ZJR
8
En d'autres termes: "ça vaut la peine de refactoriser quand ça vaut la peine de refactoriser". Duh. Eh bien, ce n'est pas vraiment une réponse, n'est-ce pas :) Measure "cost" however you can.- OK, comment? N'est-ce pas l'essentiel de la question? Quelle perspective temporelle faut-il appliquer pour mesurer ce coût?
Konrad Morawski
2
@Morawski: non, c'est une paraphrase incorrecte. J'ai dit que cela valait la peine de refactoriser si la valeur reçue du refactoring est supérieure au coût du refactoring. Ce n'est pas la même chose que de dire "ça vaut le coup de refactoriser quand ça vaut le coup de refactoriser". Calculez le coût de la refactorisation. Calculez le coût de la non refactorisation. Lequel est plus gros?
Bryan Oakley
@BryanOakley: le problème est que vous ne pouvez pas "calculer" ces coûts. Vous pouvez au mieux les estimer, ce qui est vraiment difficile à faire en ce qui concerne le coût de la non-refactorisation . Quel multiplicateur de coût de maintenance appliquez-vous à la version non refacturée vs à la version refactorisée? Comment savez-vous si le code en question devra être conservé ou modifié? Comment estimez-vous le nombre de bugs qu'il va générer? En fin de compte, je suppose que nous faisons tous inconsciemment ce genre d'estimations dans le cadre de notre processus de décision lorsque nous pensons à la refactorisation, mais il n'y a aucune précision à en attendre.
guillaume31
1
@ ian31: vrai, vous ne pouvez pas calculer de valeurs, et le mieux que vous puissiez faire est d'estimer. Pourtant, c'est la seule façon vraiment valable de décider de refactoriser ou non, en supposant que vous avez un temps et des ressources limités. Vous devez décider si le refactoriste en vaut la peine. La façon dont vous définissez la «valeur» est une science très inexacte. Le fait est que vous ne devriez pas refactoriser un sentiment d'intestin - il devrait y avoir une bonne raison de refactoriser autre que "Je veux que le code soit plus joli".
Bryan Oakley
12

  1. La complexité cyclomatique de la fonction est-elle inférieure à 5?
  2. Avez-vous complètement compris ce qu'était la complexité cyclomatique sans suivre ce lien?
  3. Avez-vous un test automatisé ou un cas de test documenté pour chaque chemin à travers la fonction?
  4. Tous les cas de test existants réussissent-ils?
  5. Pouvez-vous m'expliquer la fonction et tous ses cas marginaux en moins d'une minute?
  6. Sinon, que diriez-vous de 5 minutes?
  7. 10 minutes?
  8. Y a-t-il moins de 100 lignes de code dans la fonction (y compris les commentaires)?
  9. Pouvez-vous trouver deux autres développeurs qui conviennent que ce code est exempt d'erreurs simplement par inspection visuelle?
  10. Cette fonction est-elle utilisée à un seul endroit?
  11. La fonction atteint-elle ses objectifs de performances (temps / mémoire / CPU)?

Notation

Additionnez les réponses «non» ci-dessus:

  • 0-1 - Pourquoi pensez-vous même à refactoriser cela? Vous voulez probablement simplement renommer des variables parce que vous n'aimez pas la convention de dénomination du développeur précédent
  • 2-5 - Cela pourrait nécessiter un petit ajustement, mais je ne tiendrais pas une version de production pour quelque chose dans cette gamme
  • 6-8 - OK, nous devons probablement résoudre ce problème ... Il est probable que nous allons continuer à revoir cela et / ou nous ne savons pas vraiment ce qu'il fait. Toujours sur la clôture, mais c'est très suspect
  • 9+ - Ceci est un candidat de choix pour le refactoring. (Remarque, l'écriture de cas de test est une forme de refactoring)

http://mikemainguy.blogspot.com/2013/05/when-to-refactor-code.html

Mainguy
la source
4
# 2 semble très snob et est en fait inutile pour évaluer le code . # 3 & # 4 toutes les entreprises n'utilisent pas de tests unitaires. # 8 Évitez les commentaires dans la mesure du possible et 100 lignes sont trop élevées. J'ai 1 grand écran large en mode portrait et je serais à peine capable de voir toute la fonction à la fois. S'il s'agit de plus de 15 lignes de code réel, il devrait déjà y avoir une raison solide pour que vous le conserviez ainsi. C'est une bonne approche pratique d'avoir une liste de contrôle, mais trop de points ici sont simplement constitués ou utilisent des valeurs aléatoires sans aucun raisonnement.
R. Schmitz
8

Lorsque votre instinct vous dit que vous devriez probablement faire un peu de refactoring, c'est probablement votre instinct qui vous dit un peu tard que vous retardez quelque chose d'important depuis trop longtemps.

Je comprends les "odeurs de code", le refactor rouge-vert et d'autres pensées, mais souvent je pense que le meilleur moment pour refactoriser n'est pas la première fois que vous écrivez le code, mais la deuxième ou la troisième fois que vous utilisez le code et réalisez qu'il s'agit en fait d'un problème et qu'il est réellement utilisé.

Il existe effectivement deux niveaux de refactoring. Le premier est les problèmes évidents qui apparaissent lorsque vous codez pour la première fois. Ce sont les petites optimisations qui vous coûtent très peu à faire dès le départ. Des choses comme garder vos méthodes et vos classes petites et adhérer à DRY et SRP. Ensuite, vous avez l'étape supplémentaire de traiter les défauts majeurs de votre conception, qui peuvent ne pas être immédiatement apparents jusqu'à ce que votre code ait quelques kilomètres en dessous. C'est de ce deuxième niveau que vous parlez, et pourtant pour vous assurer que la refactorisation ultérieure ne soit pas trop coûteuse, vous devez avoir déjà écrit votre code de telle manière que l'effort que vous envisagez plus tard soit rendu plus facile et moins coûteux, ce qui signifie faire une refactorisation précoce.

Comme Jeff l'a mentionné dans sa réponse, «le temps c'est de l'argent» , en particulier dans les entreprises où la charge de travail est élevée et les risques encore plus élevés. Le temps passé à l'avant pour s'assurer que le code est dans son meilleur état possible est un gain de temps plus tard, lorsque démêler ce qui aurait dû être une refactorisation facile se révèle être une opération majeure.

Lors de l'écriture d'un logiciel, chaque instant passé à améliorer votre code est un gain de temps plus tard, lorsque vous en aurez vraiment besoin. Plus vous refactorisez tôt, plus vos modifications ultérieures seront claires. C'est comme faire un acompte en dollars d'aujourd'hui contre une future dette technique qui sera en dollars gonflés de demain.

Dans tous les cas, le refactoring ne devrait pas être une tâche que vous remettez à un avenir mystérieux lorsque le logiciel est déjà complet et stable, car il augmente vos risques plus tard lorsque les enjeux sont beaucoup plus élevés et le produit beaucoup plus difficile à changer. La refactorisation devrait faire partie de vos activités quotidiennes, et c'est l'essence de la philosophie Red-Green-Refactor que vous avez mentionnée.

S.Robins
la source
2

Je pense que votre question peut être répondue différemment par chaque développeur et même par la direction en charge de la programmation.

Ma préférence personnelle est, chaque fois que j'apprends quelque chose de nouveau ou améliore mes meilleures pratiques, je refactorise le code que je peux - j'aime garder mon code à la norme dès que j'apprends quelle était la meilleure norme à utiliser pour cette situation. Je suis autorisé à le faire car c'est une petite entreprise qui utilise le même logiciel pendant de longues périodes.

Dans une plus grande entreprise de développement de logiciels où le temps c'est de l'argent, il peut être juste de commencer à concevoir avec les meilleures pratiques que vous avez apprises à partir de maintenant, ne vous inquiétez pas de la refactorisation jusqu'à la version 2 de ce logiciel spécifique?

Je pense qu'enseigner quand refactoriser dépend vraiment de l'entreprise dans laquelle vous vous trouvez actuellement.

Jeff
la source
2

"Quand refaçonner?"

Réponse courte: chaque fois que vous rencontrez du code qui sent mauvais ou qui pourrait être amélioré ( règle du scoutisme )

En pratique, cela se produit:

  • Si vous pratiquez TDD, systématiquement pendant l'étape Refactor du cycle TDD, c'est-à-dire une fois que votre test est vert et avant de commencer à écrire un nouveau test.
  • À la suite d'une révision du code
  • Lors de la reprise du code hérité
  • Lors de la consommation de code qui semble maladroitement conçu
  • etc.
guillaume31
la source
J'ai l'impression que cela dit simplement "Vous devriez refactoriser" sans répondre à la partie la plus difficile: "Je pense qu'il devrait y avoir des approches plus rigoureuses à cela, mais je ne suis pas sûr de ce qu'elles sont."
Hortitude
Je ne sais pas quoi dire, sauf ressentir ce qui est pénible à entretenir, renifler les odeurs de code et utiliser votre expérience. Je doute qu'il y aura jamais une méthode définitive et établie qui vous dira quand et quoi refactoriser si c'est ce que vous recherchez.
guillaume31
1

Quand j'ai appris pour la première fois le refactoring, mon mentor m'a dit: "Faites-le deux fois, tenez votre nez. Faites-le trois fois. Refactor." (Merci, Josh!) Pour être précis, ce qu'il disait, c'est que lorsque vous êtes sur le point d'écrire le même bloc de code pour la troisième fois (ou même un modèle de code similaire), c'est le moment de refactoriser. J'ai suivi cela pendant les 10 dernières années, et j'ai trouvé que c'était une règle empirique suffisamment solide.

L'utilisation d'Eclipse, ou d'un IDE similaire qui prend en charge la refactorisation, réduit l'effort de refactorisation. Le support IDE rend plus probable que vous refactoriserez dès que vous frapperez la "troisième fois" (ou voyez le besoin), au lieu de le voir comme un effort supplémentaire.

Aussi - TDD est d'une grande aide ici aussi, car vous pouvez continuer à exécuter vos tests en tant que refactor, et savoir que vous n'avez rien cassé.

Sam Goldberg
la source
1

Le refactoring par sa définition est un processus. Cela implique que vous ne devez pas vous efforcer de trouver du temps libre pour effectuer la tâche de rafactoring, mais que vous devez continuer à refactoriser tout le temps lorsque vous rencontrez du code qui pourrait être mieux écrit.

Personnellement, j'aime écrire des prototypes évolutifs, le dire plus simplement: du code qui fonctionne, puis refactoriser ceux-ci jusqu'à ce qu'ils répondent aux normes de codage attendues. Un autre bon exemple est l'ajout de fonctionnalités supplémentaires et la refactorisation du code existant pour permettre sa réutilisation.

0lukasz0
la source
1

Au cours de mes 20 années de programmation, voici la seule règle empirique à laquelle j'ai réellement vu du travail, à laquelle les gens peuvent se tenir et que les gestionnaires accordent du temps. (Le refactoring est comme un régime: bien sûr, "calories entrantes / calories sortantes" est la formule pour perdre du poids, mais cela ne se traduit pas par un régime alimentaire auquel les gens se conformeront.) Et donc:

Refactorisez continuellement, pendant que vous travaillez. Utilisez le développement piloté par les tests pour avoir plusieurs cycles de refactorisation rouge-vert tout au long de la journée. Refactorisez uniquement les parties du code que vous avez touchées.

Une fois que vous êtes plus sûr de vous, vous pouvez varier de ce régime.

Dogweather
la source
1

Je pense que cela dépend des exigences du maître d'ouvrage et du gars qui répond de la qualité du code. Vous ne pouvez tout simplement pas décider seul, lorsque l'argent de quelqu'un d'autre est remis en question.

Quant aux raisons techniques, il y en a plusieurs.

  • Si vous avez un bogue dans le code, cela signifie que cet endroit est mal compris et il est TRÈS probable que davantage d'erreurs pourraient être cachées ici et il y aura sûrement de gros problèmes avec toute tentative de développement des parties connectées du code. Donc, cet endroit doit être vérifié pour une éventuelle refactorisation.
  • Une autre raison est lorsque vous ajoutez ou modifiez une fonctionnalité et que l'ancien code est très peu pratique pour changer / ajouter et que les modifications / ajouts ultérieurs sont hautement possibles. Bien sûr, vous devez équilibrer le coût.
  • La raison la plus grave est peut-être lorsque vous modifiez le code et qu'il n'est pas testable.
Gangnus
la source
En tant que Scrum Master, nous avons eu un développeur qui a constamment soutenu que chaque histoire de la taille de l'équipe était plus grande que ce que l'équipe pensait, et a réalisé qu'il voulait refactoriser chaque morceau de code qu'il rencontrait. Ainsi, une histoire en 3 points était toujours un 8 pour lui. De toute évidence, cela a gâché la livraison de la valeur. Donc, d'une manière ou d'une autre, il faut savoir quand refactoriser et comment prendre la décision. Juste ma pensée, à partir de cette expérience (et de quelques autres).
Curtis Reed