- La refactorisation du code joue un rôle important pour maintenir la base de code en bonne santé
- Cependant, une mauvaise refactorisation peut au contraire rendre le code plus complexe et plus difficile à maintenir
- Il faut savoir distinguer une bonne refactorisation d’une mauvaise, et comprendre comment éviter les pièges de la mauvaise refactorisation
Le bon, le mauvais et le laid de la refactorisation
- L’abstraction peut être une bonne ou une mauvaise chose. L’essentiel est de savoir quand et comment l’appliquer
- Explication de quelques pièges courants et de la manière de les éviter (le code de l’article original est omis)
1. Modifier fortement le style de code
- Les développeurs font souvent l’erreur de changer complètement de style de code pendant une refactorisation
- Introduire une nouvelle bibliothèque ou adopter un style de code totalement différent peut nuire à la maintenabilité
- Mieux vaut améliorer le code pour le rendre plus idiomatique et plus lisible, sans introduire un paradigme entièrement nouveau ni des dépendances externes inutiles
2. Les abstractions inutiles
- Ajouter trop de nouvelles abstractions sans comprendre le code existant est problématique
- Cela peut seulement accroître la complexité et rendre le tout plus difficile à comprendre
- Il est préférable de découper la logique en fonctions petites et réutilisables, sans introduire de complexité inutile
3. Ajouter de l’incohérence
- Mettre à jour une seule partie de la base de code pour qu’elle fonctionne d’une manière totalement différente peut provoquer confusion et frustration
- S’il faut introduire un nouveau pattern, mieux vaut d’abord obtenir l’accord de l’équipe
- Il est important de conserver une approche cohérente de la récupération des données dans toute l’application
4. Ne pas comprendre le code avant de refactoriser
- Apprendre le code tout en le refactorisant n’est pas une bonne idée
- Cela peut introduire des bugs, dégrader les performances et supprimer des fonctionnalités
- Avant de refactoriser, il est important de comprendre le code en profondeur et d’améliorer l’existant sans en changer le comportement
5. Comprendre le contexte métier
- Faire des choix techniques sans comprendre le métier peut tourner à la catastrophe
- Pour un site e-commerce fortement dépendant du SEO, le rendu côté client peut être un mauvais choix
- Une approche de rendu côté serveur comme Next.js ou Remix peut être un meilleur choix en matière de SEO et de performances
6. Une consolidation excessive du code
- Fusionner du code pour le rendre « propre » au détriment de la flexibilité n’est pas une bonne idée
- Lorsqu’on crée une abstraction, il faut toujours prendre en compte les cas d’usage qu’elle doit couvrir
- L’abstraction doit permettre toutes les fonctionnalités que l’implémentation d’origine offrait
Refactoriser de la bonne manière
- La refactorisation du code est nécessaire. Mais elle doit être faite correctement
- Notre code n’est pas parfait et a besoin d’être remis en ordre, mais il faut rester cohérent avec la base de code existante
- Il faut bien comprendre le code avant de le refactoriser, et choisir les abstractions avec soin
- Conseils pour réussir une refactorisation :
- Procéder de manière incrémentale : faire de petits changements maîtrisables plutôt qu’une réécriture complète
- Comprendre le code en profondeur avant d’introduire une refactorisation importante ou une nouvelle abstraction
- Respecter le style de code existant : la cohérence est essentielle pour la maintenance
- Éviter d’introduire trop de nouvelles abstractions : garder les choses simples, sauf si la complexité est réellement nécessaire
- Éviter en particulier d’ajouter de nouvelles bibliothèques avec un style de programmation très différent, surtout sans l’accord de l’équipe
- Écrire des tests avant de refactoriser, puis les mettre à jour au fur et à mesure. Cela permet de vérifier que les fonctionnalités d’origine sont bien préservées
- Se responsabiliser mutuellement au sein de l’équipe pour faire respecter ces principes
Outils et techniques pour mieux refactoriser
- Pour mieux refactoriser, on peut envisager d’utiliser les techniques et outils suivants :
Outils de linting
- Utiliser des outils de linting pour appliquer un style de code cohérent et détecter des problèmes potentiels
- Prettier permet un formatage automatique avec un style cohérent
- Eslint permet d’effectuer des vérifications de cohérence plus fines via des plugins personnalisés
Revue de code
- Mettre en place des revues de code rigoureuses afin d’obtenir les retours des collègues avant de fusionner le code refactorisé
- Cela aide à repérer tôt les problèmes potentiels et à vérifier que le code refactorisé respecte les standards et les attentes de l’équipe
Tests
- Écrire et exécuter des tests pour s’assurer que le code refactorisé ne casse pas les fonctionnalités existantes
- Vitest est un test runner particulièrement rapide, robuste et simple à utiliser, sans configuration nécessaire par défaut
- Pour les tests visuels, envisager l’utilisation de Storybook
- React Testing Library est un bon ensemble d’utilitaires pour tester des composants React (avec des variantes pour Angular, etc.)
Outils d’IA (appropriés)
- S’appuyer sur des outils d’IA capables de s’adapter au style et aux règles de code existants pour soutenir les efforts de refactorisation
- Visual Copilot est un outil particulièrement utile pour maintenir la cohérence lors du développement frontend
- Il aide à transformer un design en code tout en respectant le style de code existant et en utilisant correctement les composants et tokens du design system
Conclusion
- La refactorisation est une partie nécessaire du développement logiciel, mais elle doit être menée avec prudence et en tenant compte de la base de code existante et de la dynamique d’équipe
- Le but de la refactorisation est d’améliorer la structure interne du code sans en modifier le comportement externe
- Les meilleures refactorisations sont souvent invisibles pour l’utilisateur final, mais facilitent grandement la vie des développeurs
- Elles améliorent la lisibilité, la maintenabilité et l’efficacité, sans semer la confusion dans l’ensemble du système
- Quand on est tenté d’élaborer un « grand plan » pour le code, il faut prendre du recul, bien comprendre le code, réfléchir à l’impact des changements et viser des améliorations progressives que l’équipe saura apprécier
- Votre futur vous et vos collègues vous seront reconnaissants pour cette approche réfléchie qui permet de garder une base de code propre et maintenable
6 commentaires
Certaines personnes se lancent parfois dans le refactoring sans même avoir de tests.
À les regarder, on a l'impression qu'elles font un numéro d'équilibriste extrêmement risqué, et c'en est presque grisant haha
Le point n°4, « ne pas comprendre le code avant de le refactorer », résonne vraiment beaucoup chez moi.
C’est une remarque tellement évidente, presque une base indispensable haha. C’est agréable de voir ça aussi bien résumé. Je pense que le refactoring aboutit à 100 % à un meilleur code. Si ce n’est pas le cas, ça voudrait dire que mes compétences ont régressé par rapport à hier, non ?
Le fait de voir quelqu’un mettre par écrit des évidences me donne l’impression qu’il a dû tomber sur un code vraiment misérable et l’a écrit sous le coup d’une vraie grosse frustration hahaha
Plutôt qu’un guide pour bien refactorer, c’est surtout une façon d’expliquer comment bien coder concrètement en entreprise..
(On dirait un texte écrit sous le coup de l’agacement après qu’un junior est arrivé, a voulu refactorer un projet legacy, a compliqué des choses un peu partout et a créé des bugs...)
Les personnes qui ne parviennent pas à distinguer, ou qui confondent, l’unité du travail et l’unité du code finissent par faire ce genre de refactoring, quel que soit leur niveau d’expérience. Au final, un code facile à corriger et maintenable doit permettre à quelqu’un d’autre, arrivé plus tard, de comprendre le flux métier ; parfois, je me demande si c’est vraiment quelque chose qu’on ne peut saisir sans l’avoir vécu sur le terrain.
J’ai déjà vu un cas qui montrait les signes d’une abstraction excessive dans React : alors que le composant de tableau est déjà abstrait par le framework UI, si les schémas de deux tableaux paraissent similaires, il faut éviter de créer un nouveau composant sans véritable rôle en utilisant l’inversion de contrôle. En voyant des cas où, au nom de l’application de l’Atomic Design, on abuse de composants vides de dix lignes, j’ai trouvé ça très inconfortable parce qu’il faut regarder trop d’endroits différents.
À l’origine, la règle DRY visait à dire qu’il ne faut pas faire de copier-coller de code ayant exactement la même forme et le même rôle, mais j’ai l’impression qu’il y aura toujours des gens pour la comprendre de travers. Est-ce que l’idée de ne pas vouer un culte aveugle aux design patterns vient de ce contexte ?