Le "Refactoring"

Le réusinage de code (refactoring en anglais) est l'opération consistant à retravailler le code source d'un programme informatique – sans toutefois y ajouter des fonctionnalités ni en corriger les bogues – de façon à en améliorer la lisibilité et par voie de conséquence la maintenance, ou à le rendre plus générique (afin par exemple de faciliter le passage de simple en multiple précision) ; on parle aussi de « remaniement ». Cette technique utilise quelques méthodes propres à l'optimisation de code, avec des objectifs différents.

1. Pourquoi refactoriser ?

Au cours de la vie d'un logiciel, on lui ajoute souvent des fonctions, et en tout cas on corrige ses bogues. Ces modifications successives, n'améliorant pas en général la lisibilité du logiciel, ne facilitent pas, de ce fait, sa maintenance ultérieure.
Le code source d'un programme a tout intérêt à rester, malgré ses modifications, le plus clair possible.
Les techniques de programmation agile, où évolution et mise à disposition se font en quasi-continu, rendent cette exigence encore plus fondamentale.
Pour toujours conserver un code aussi simple que possible, on :
  • S'assure que toute l'information nécessaire est disponible ;
  • Supprime toute information redondante ou duplication de code ;
  • Simplifie lorsque c'est possible l'algorithmique des méthodes ;
  • Limite la complexité de chaque classe ;
  • Limite le nombre de classes.

2. Comment refactoriser ?

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 si le besoin s’en fait sentir uniquement.

Etape 1 : Elimination du code mort

Si un objet contient des méthodes qui ne sont plus utilisées depuis longtemps, cela veut dire que ces méthodes ne sont plus tenues à jour à cause de leur inutilité. La crainte d’avoir un jour besoin de ces méthodes pousse à les garder en place, mais le manque de maintenance du code fera prendre un risque considérable le jour où on voudra l’utiliser. De plus, les outils de gestion de source (type Subversion) permettent justement de retrouver les anciennes versions d’un fichier. Alors autant effacer immédiatement le code inutile. Cette remarque s’applique aussi aux blocs de code qui sont laissés en commentaire depuis la nuit des temps, et que personne n’ose toucher « au cas où on en aurait besoin ».

Etape 2 : Normalisation et documentation du code

Le code restant, celui qui est réellement utilisé, doit ensuite être nettoyé pour le rendre compréhensible de nouveau. Si vous avez mis en place des normes de codage, assurez-vous qu’elles soient appliquées. Reprenez la documentation « externe » (celle qui permet d’utiliser ce code) ; assurez-vous que les paramètres et les valeurs de retours 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. Ainsi, ils seront disponibles le jour où vous aurez besoin de tracer finement l’exécution du programme.

Etape 3 : Renommage et harmonisation

Vous aviez un petit objet nommé SimpleUserManager, mais qui contient maintenant 80 méthodes ? Ou un autre a été rapidement nommé GlobalApplicationProxy ? Prenez le temps de les renommer intelligemment. Faites de même avec les méthodes, qui devraient idéalement se comprendre rien que par leur nom, sans nécessiter de documentation. S’il le faut, reprenez aussi l’ordre des paramètres pour qu’ils restent logiques d’une méthode à l’autre. Le mot d’ordre doit être de créer une harmonie à travers le code, pour simplifier sa maintenance future. L’harmonisation du code consiste aussi à déplacer des bouts de code (d’un fichier à un autre, d’un objet à un autre, …) pour remettre les choses logiquement à leur place. Demandez-vous « Où aurais-je tendance à chercher cette fonction ? » ; c’est souvent là où elle devrait être, et non pas là où elle a été codée.

Etape 4 : Optimisation

Si et seulement si les étapes précédentes ont été réalisées sérieusement, vous pouvez procéder à l’amélioration du code pour des raisons de performance. Cela peut concerner un algorithme un peu délicat, ou des requêtes complexes sur une base de données. Mais souvenez-vous que les optimisations doivent toujours se faire en dernier, à l’unique condition que le périmètre applicatif soit connu et bien défini. Il est déjà assez risqué d’optimiser un système sans le mettre en vrac, ne vous lancez surtout pas dans une optimisation mélangée avec des modifications fonctionnelles, vous iriez droit dans le mur.