Le refactoring, qu’est-ce que c’est ?

Par nature, un code épuré contient moins d’erreurs, moins d’instructions inutiles, est globalement mieux structuré et donc plus facile à maintenir avec, potentiellement, des économies à la clé.

Sauf que dans la vraie vie, un débutant non cadré (ou même un développeur aguerri à qui on met la pression), a peu de chance de livrer un code conçu dans les règles de l’art.

De fait, le développement d’un logiciel est un processus complexe, auquel participent souvent plusieurs développeurs. Il est donc fréquent que le code source initial soit retravaillé, modifié et complété de nombreuses fois au cours du cycle de vie du logiciel. Par manque de temps ou de maitrise des bonnes pratiques, le source accumule des lignes de code mal écrites, avec des redondances, des problèmes de nommage, du mélange de français et d’anglais… l’ensemble de ces facteurs nuit au bon fonctionnement du logiciel et participe à sa dégradation en termes de qualité et de performances

On se retrouve avec du code ne respectant aucune norme, avec une documentation périmée, sans commentaire, voire avec du code mort. Chaque bug devient plus délicat à corriger avec des menaces de régression ; chaque ajout de fonctionnalité prend de plus en plus de temps à être mis en œuvre et cela à des conséquences avec des coûts de maintenance et une dette qui augmentent.

La solution face à cette situation est de refactoriser (ou réusiner pour nos amis Québécois). Cela consiste à réorganiser, restructurer et clarifier l’existant tout en garantissant que le comportement global de l’applicatif ne change pas.

 

Refactorer : pourquoi nettoyer le code existant ?

Le refactoring permet de faire le ménage, on parle de ‘clean code’, d’organiser l’amélioration du code voire de réécrire une partie du code qui a déjà été développé, afin de favoriser sa lisibilité et sa clarté pour les autres développeurs mais aussi de faciliter les tests.

Cette action de ‘refactorer’ génère une base de code plus saine, rendant le code lisible pour l’ensemble de l’équipe ou pour tout autre développeur et utilisateur susceptible d’y faire référence.

Désormais, cette pratique fait partie des bases pour apprendre la programmation et prend de plus en plus d’importance.

Lorsque que le code est conçu suivant l’état de l’art, sa lecture ne demande pas d’effort particulier et ainsi, les développeurs ont la capacité de l’analyser plus rapidement et de corriger plus facilement les éventuels bugs, la maintenabilité du logiciel et l’évolutivité s’en trouvent facilitées.

Ce processus est nettement plus efficace en termes de coûts que la réécriture complète du code. Pour le développement itératif de logiciels, comme c’est le cas dans le développement agile, le refactoring fait partie intégrante des étapes de travail, avec des modifications en continu.

 

Réusiner son code : comment s’y prendre ?

On peut découper un refactoring en 4 étapes précises. Les trois premières sont importantes et nécessaires, alors que la dernière est à mettre en œuvre lorsque les 3 premières sont réalisées.

Élimination du code mort

Les méthodes qui ne sont plus utilisées depuis longtemps ou encore les blocs de code laissés en commentaire ‘au cas où’ sont à éliminer. Et cela d’autant plus qu’avec les outils de gestion décentralisée de code source (Git), il est possible de retrouver les anciennes versions. De même les méthodes brouillonnes ou trop longues que personne ne comprend ainsi que les redondances (doublons) doivent être nettoyées.

Normalisation et documentation du code

Le code utile doit être uniforme et bien documenté mais aussi respecter les standards de code. De bonnes conventions adoptées par tous permettent à un développeur de s’y retrouver plus facilement dans un code qu’il découvre pour la première fois. Lorsque des normes de code existent, il est important de s’assurer qu’elles sont appliquées :

  • Assurez-vous que les paramètres et les valeurs de retours indiqués dans la doc correspondent bien à ceux présents dans le code
  • Vérifiez que les explications fournies sont toujours exactes au regard du code
  • Rappelez-vous que la documentation doit dire à quoi sert le code, ce qu’il fait, et non comment il le fait
  • Enfin, ajoutez des commentaires aux endroits les plus complexes du code, pour expliquer comment il fonctionne. Profitez-en pour ajouter les messages de logs qui pourraient manquer. Ils seront précieux le jour où vous aurez besoin de tracer finement l’exécution du programme.

Renommage et harmonisation

Vous aviez un petit projet au départ et il contient aujourd’hui des dizaines de méthodes ? Prenez le temps de les renommer intelligemment. Les méthodes devraient, idéalement, se comprendre rien que par leur nom, sans nécessiter de documentation. Reprenez aussi, si besoin, l’ordre des paramètres pour qu’ils restent logiques d’une méthode à l’autre. Simplicité, logique et harmonie sont les mots d’ordre pour simplifier la maintenance future du logiciel.

La plateforme de compilateurs .NET open source permet d’industrialiser le renommage

La commande refactor Rename peut être utilisée sur n’importe quel identificateur du code (par exemple un nom de classe, un nom de propriété, etc.) pour rechercher toutes les occurrences de cet identificateur et les changer. Pour renommer un symbole, cliquez dessus avec le bouton droit, puis choisissez Renommer…, ou utilisez la combinaison de touches Cmd () + R :

Refactor

Ceci met en évidence le symbole et toutes les références à celui-ci. Quand vous commencez à taper un nouveau nom, il change automatiquement toutes les références figurant dans votre code. Vous pouvez valider vos changements en appuyant sur Entrée :

Refactoring

Amélioration du code

Lorsque les étapes précédentes ont été réalisées de manière exhaustive et que le périmètre applicatif est bien défini, vous pouvez vous attaquer à l’amélioration du code sur des sujets plus ardus comme un algorithme un peu délicat, ou des requêtes complexes sur une base de données. Ne vous lancez pas dans une optimisation si vous en êtes encore aux modifications fonctionnelles.

 

Quand faire une refactorisation ?

C’est la grande question. Faut-il vraiment ralentir les développements et perdre du temps avec ça ? Bien souvent, le client ne voit pas la différence lorsque le code est amélioré, car le fonctionnement reste identique : le gain n’est donc pas évident. La plupart des jeunes développeurs ont tendance à vouloir foncer dans leurs développements, ajouter sans cesse de nouvelles fonctions, sans revenir en arrière. C’est humain, les tâches qui ne se voient pas ou ne font pas avancer le projet fonctionnellement peuvent être considérées comme trop chronophages, être remises à plus tard pour finalement être passées aux oubliettes.

Alors que plus le refactoring intervient tôt, moins il est coûteux en temps et, comme chacun sait, le temps c’est de l’argent.

Chaque période de développement (par exemple un sprint si vous utilisez la méthode Scrum) devrait être immédiatement suivie d’un temps de refactorisation, qui servira à consolider le code qui vient juste d’être réalisé, et à s’assurer que la documentation qui l’accompagne est complète.

En fait, on trouve d’excellentes occasion de faire du refactoring lors :

  • De la correction de bugs
  • De l’ajout d’une nouvelle fonctionnalité
  • Ou pendant les revues de code

Le mieux est de procéder par toutes petites étapes et de tester les modifications apportées au code avec des processus de développement de logiciels, comme le développement piloté par les tests (TDD pour Test Driven Development) ou l’intégration continue (CI pour Continuous Integration). L’intégration continue permet de livrer régulièrement le code pour qu’il soit testé et fusionné dans le référentiel commun. Le fait de surveiller en continu les portions de code livrées permet de résoudre plus tôt, plus souvent et plus rapidement les dysfonctionnements éventuels.

 

Quelles techniques de refactoring ?

Il existe de nombreuses techniques de refactoring. Par exemple :

Développement rouge-vert

Le développement rouge-vert est un pilier du refactoring en continu dans le cadre d’un développement agile de logiciel : rouge, vert, refactorisez.

Le rouge symbolise le premier cycle de tests, avant l’implémentation de la nouvelle fonction dans le code. Le vert symbolise la section de code nécessaire à cette fonction pour réussir le test. L’idée est d’écrire un test qui permet de rédiger le moins de code possible.

Branching-by-Abstraction

Cette méthode de refactoring décrit une modification d’un système par étapes et le fait d’adapter d’anciennes lignes de code aux nouvelles sections de code. La technique Branching-by-Abstraction est généralement utilisée lors de grandes modifications portant sur la hiérarchie des classes.

On peut aussi utiliser les méthodes pull-up ou push-down en créant un lien entre une nouvelle fonction, de meilleure qualité, et l’abstraction.

On peut enfin supprimer les anciennes fonctions et remplacer certaines lignes de code, section par section, sans prendre de risque pour le fonctionnement de l’ensemble.

Compiler des méthodes

Le refactoring doit rendre aussi lisibles que possible les méthodes du code de sorte qu’un développeur qui ne connait pas le code soit capable de comprendre la logique d’une méthode. L’objectif de chaque modification est de distinguer chaque méthode, de supprimer les doublons et de diviser les méthodes un peu longues pour faciliter leur modification ultérieure.

Organisation des données

Cette méthode a pour objectif de répartir les données au sein des classes et de les maintenir aussi courtes et claires que possible. Les liens inutiles entre les classes, qui entravent le bon fonctionnement du logiciel dès la moindre modification, doivent être supprimés et répartis entre les classes adéquates.

Mais il est aussi question de DRY (code dupliqué), polymorphisme (remplacement du conditionnel) et SRP (responsabilité unique)… Bref, vous l’aurez compris. Le sujet est vaste. Les travaux foisonnants de Martin Fowler et Kent Beck en proposent un aperçu complet :

« Refactoring: Improving the Design of Existing Code »

Ne ratez plus aucune actualité avec la newsletter mensuelle de SoftFluent

Newsletter SoftFluent