Refactoring de code

La refactorisation du code est un effort direct pour améliorer le code sans créer de nouveaux modules ou fonctionnalités, conduisant ainsi à un code plus convivial, propre et lisible.

Chaque fois que nous modifions le code sans le refactoriser, la pourriture s'aggrave et se propage. La pourriture du code nous frustre, nous coûte du temps et raccourcit indûment la durée de vie des systèmes utiles. Dans un contexte agile, cela peut faire la différence entre respecter ou non un délai d'itération.

La refactorisation du code empêche impitoyablement la pourriture, en gardant le code facile à maintenir et à étendre. Cette extensibilité est la raison de refactoriser et est la mesure de son succès. Mais notez que ce n'est que "safe" pour refactoriser le code de manière approfondie si nous avons des suites de tests unitaires étendues du type que nous obtenons si nous travaillons en testant d'abord. Sans pouvoir exécuter ces tests après chaque petite étape d'un refactoring, nous courons le risque d'introduire des bogues. Si vous effectuez un véritable développement piloté par les tests (TDD), dans lequel la conception évolue en permanence, vous n'avez pas le choix de refactoriser régulièrement, car c'est ainsi que vous faites évoluer la conception.

Code d'hygiène

Une métaphore populaire de la refactorisation consiste à nettoyer la cuisine pendant que vous cuisinez. Dans toute cuisine dans laquelle plusieurs repas complexes sont préparés par jour pour plus d'une poignée de personnes, vous constaterez généralement que le nettoyage et la réorganisation se produisent en continu. Quelqu'un est responsable de garder la vaisselle, les casseroles, la cuisine elle-même, la nourriture, le réfrigérateur propres et organisés d'un moment à l'autre. Sans cela, la cuisson continue s'effondrerait bientôt. Dans votre propre foyer, vous pouvez voir des effets non triviaux en reportant même de petites quantités de remaniement de plats : avez-vous déjà essayé de gratter la boue formée par des croustillants au cacao séchés dans un bol ? Une occasion manquée de deux secondes de rinçage peut se transformer en dix minutes de grattage agressif.

« Refactorings » spécifiques

Les refactorisations sont le contraire de jouer sans fin avec du code ; elles sont précises et finies. Le définitif de Martin Fowler livre sur le sujet décrit 72 "refactorisations" spécifiques par leur nom (par exemple, "méthode d'extraction", qui extrait un bloc de code d'une méthode et crée une nouvelle méthode pour celle-ci). Chaque refactorisation convertit une section de code (un bloc, une méthode, une classe) de l'un des 22 états « malodorants » bien compris en un état plus optimal. Il faut un certain temps pour apprendre à reconnaître les opportunités de refactoring et à implémenter correctement les refactorings.

Refactoring en modèles

La refactorisation ne se produit pas seulement à des niveaux de code bas. Dans son récent livre, Refactorisation aux modèles, Joshua Kerievsky démontre habilement que la refactorisation est la technique que nous devrions utiliser pour introduire des modèles de conception « gang de quatre » dans notre code. Il soutient que les modèles sont souvent surutilisés et souvent introduits trop tôt dans les systèmes. Il suit le format original de Fowler consistant à montrer et à nommer des « refactorisations » spécifiques, des recettes pour obtenir votre code du point A au point B. Les refactorisations de Kerievsky sont généralement de niveau supérieur à celles de Fowler et utilisent souvent les refactorisations de Fowler comme blocs de construction. Kerievsky introduit également le concept de refactorisation "vers" un modèle, décrivant combien de modèles de conception ont plusieurs implémentations différentes, ou profondeurs d'implémentation. Parfois, vous avez besoin de plus d'un modèle que vous n'en avez à d'autres moments, et ce livre vous montre exactement comment faire une partie du chemin, ou tout le chemin.

Le flux de refactoring

Dans un contexte de test d'abord, la refactorisation a le même flux que tout autre changement de code. Vous avez vos tests automatisés. Vous commencez la refactorisation en effectuant la plus petite modification discrète possible qui compilera, exécutera et fonctionnera. Dans la mesure du possible, vous apportez ces modifications en ajoutant au code existant, en parallèle avec celui-ci. Vous lancez les tests. Vous effectuez ensuite la prochaine petite modification discrète et exécutez à nouveau les tests. Lorsque la refactorisation est en place et que les tests fonctionnent tous correctement, vous revenez en arrière et supprimez l'ancien code parallèle malodorant. Une fois que les tests sont exécutés proprement après cela, vous avez terminé.

Refactorisation de l'automatisation dans les IDE

Le refactoring est beaucoup, beaucoup plus facile à faire automatiquement qu'à la main. Heureusement, de plus en plus d'environnements de développement intégrés (IDE) intègrent un support de refactorisation automatisé. Par exemple, un IDE populaire pour Java est éclipse, qui inclut toujours plus de refactorisations automatiques. Un autre favori est IntelliJ IDEA, qui a historiquement inclus encore plus de refactorisations. Dans le monde .NET, il existe au moins deux plugins d'outils de refactoring pour Visual Studio 2003, et on nous dit que les futures versions de Visual Studio auront un support de refactoring intégré.

Pour refactoriser le code dans eclipse ou IDEA, vous sélectionnez le code que vous souhaitez refactoriser, déroulez la refactorisation spécifique dont vous avez besoin à partir d'un menu, et l'IDE fait le reste du travail acharné. Des boîtes de dialogue vous invitent de manière appropriée à fournir de nouveaux noms pour les éléments nécessitant un nom et pour une entrée similaire. Vous pouvez ensuite relancer immédiatement vos tests pour vous assurer que le changement n'a rien cassé. Si quelque chose était cassé, vous pouvez facilement annuler la refactorisation et enquêter.