Massacre à l'IDE ou les joies du refactoring par le vide
Dans la vie de toute application vient le moment de cesser de développer de nouvelles fonctionnalités afin de consolider l’existant. C’est l’occasion de mettre ses librairies et dépendances à jour, mais surtout de faire un grand nettoyage de printemps dans son code, le refactoring, et plus exactement le refactoring par le vide.
Bloquez-vous quelques heures, armez-vous de votre IDE ou de votre éditeur de textes préféré, c’est parti pour un joyeux massacre à la tronçonneuse.
1. Fusionnez le fonctions dupliquées
Dans un premier temps, votre but va être de réduire le nombre de fonctionnalités proposées, sans toucher au périmètre fonctionnel. Dans de grosses applications, ou dans des applications ayant un certain historique, on a souvent plusieurs fonctionnalités quasiment semblables et qui pourraient être fusionnées à un seul endroit.
Le cas s’est présenté de manière particulièrement aiguë sur Typo, dans le fonctionnement des commentaires. Nous fonctionnions en effet avec :
- Une partie de gestion / modération des réactions au fil de l’eau, ajoutée lors de la mise en place de l’anti spam, avec un contrôleur
feedback. - Une partie de gestion des commentaires au sein des articles, création, suppression… autour du contrôleur
comments. - Une partie de gestion des trackbacks au sein des articles, création, suppression… autour du contrôleur
trackbacks. Ce dernier était identique au précédent.
Nous avons tout regroupé au sein du contrôleur feedback, en gardant l’interface de modération, et en regroupant les interfaces de gestion des commentaires et trackbacks par article qui sont maintenant sur une seule page. Résultats, 102 lignes de contrôleur et 174 lignes de vues supprimées, sans compter les tests, pour autant de code dupliqué, et une gestion plus rationnelle du feedback.
2. Supprimez le code dupliqué
Plus nombreux sont les développeurs étant intervenus sur le projet, plus nombreuses sont les fonctionnalités ajoutées puis supprimées, plus important sera la dose de code dupliquée que vous aurez à nettoyer. Ne souriez pas en vous disant “moi, ça ne m’arrivera pas”, vous en avez obligatoirement. Commencez votre refactoring au sein des modèles et des contrôleurs, histoire de nettoyer un peu tout ça. Allez ensuite voir dans les helpers, il y a certainement quelque chose à faire. Puis, faites une lecture transverse de votre application, vous allez certainement retrouver du code dupliqué d’un contrôleur à l’autre, d’un modèle à l’autre… Peut-être est-ce le moment de créer de nouvelles classes pour rassembler tout ça non ?
Tout les contrôleurs de Typo avaient le même problème : les méthodes de création et de mise à jour d’objets contenaient systématiquement le même code à 3 lignes près. Dans le cas d’un nouvel enregistrement, nous avions @objet = Objet.new, et dans le cas d’une mise à jour, @objet = Objet.find(params[:id]). Nous avons rassemblé tout le code en double dans une même méthode de traitement appelée depuis les méthodes de création et d’édition, avec l’objet instancié en fonction du besoin. Résultat, 244 lignes de code supprimées sans compter les tests juste pour ça, et un risque d’erreurs bien moindre lors des prochaines évolutions.
3. Supprimez le code mort
Après ces deux premières étapes, vous allez certainement vous retrouver avec du code mort, c’est à dire des méthodes qui ne sont jamais appelées dans l’application. Si vous avez basé votre application sur le modèle MVC, les différentes itérations sur les vues ont du laisser un grand nombre de helpers orphelins. Au passage, les deux précédentes étapes ont certainement du laisser quelques méthodes sur le carreau, et c’est tant mieux.
Les 3 admins et 3 thèmes par défaut qu’a connu Typo sous ma seule impulsion ont laissé dans l’ombre un nombre impressionnant de helpers abandonnés. Pas loin d’une quarantaine de méthodes, pour un total de 337 lignes de code supprimées lors de cette seule passe.
4. Élargissez la couverture de tests
À ce moment de la partie, vos tests devraient exploser dans tous les sens (ne me dites pas que vous développez sans tests…). Si ce n’est pas le cas, c’est que toutes vos méthodes ne sont pas couvertes. Tant que vous avez la tête dans le guidon, c’est le moment d’élargir un peu la couverture de tests de votre projet.
- Testez les méthodes non couvertes.
- Ajoutez des tests sur les cas limites que vous auriez oubliés.
Bien que testant près de 500 assertions, la couverture de tests de Typo est très insuffisante. J’en veux pour preuve l’ensemble des tests qui passent alors même que j’ai violemment explosé certaines fonctionnalités. Une spec party a été planifiée avec Cyril afin de l’améliorer un peu.
5. Supprimez les fonctionnalités inutiles
J’avais dit en début d’article que nous ne toucherions pas au spectre fonctionnel de l’application. J’ai menti. Maintenant que vous avez bien nettoyé le code, posez vous cette question : votre application ne propose-t-elle pas des fonctionnalités superflues ou qui la rendent moins facilement utilisable par ses utilisateurs, et qui, accessoirement, en la ralentissent un peu ?
Lorsque j’ai travaillé sur la version 5.1.3 de Typo, j’ai commencé à réfléchir à ce problème. Nous avions clairement des choses en trop, et le fait de proposer une interface d’administration simplifiée ne réglait en fait pas le problème. La 5.1.3 a donc été l’occasion de supprimer certaines fonctionnalités :
- La notification des nouveaux billets par Jabber, inutilisable tellement elle n’était pas évidente à mettre en place, et pas utilisée.
- L’administration simplifiée, trop sommaire pour réellement travailler.
- Le choix des filtres de texte par billet au profit d’un choix global. Ils reviendront plus tard au niveau des profils utilisateurs.
- Le live preview en cours de frappe, sympathique mais qui mettait les serveurs à genoux en générant un article complet à chaque frappe du clavier (hem).
Je me rends compte que j’ai oublié un élément important en introduction de cet article. Le but du refactoring par le vide n’est pas un concours à celui qui supprimera le plus grand nombre de lignes de codes. C’est la rationalisation du projet par la suppression du code inutile, mort, ou redondant.
Évidemment, vous n’êtes pas obligé de faire tout cela à la main, et sur des projets de centaines de milliers de lignes, c’est même impossible : essayez d’appliquer ça au noyau Linux qui vient de passer la barre des 10 millions de lignes de code. Il existe des outils d’analyse de code automatisés entrant dans le scope plus large de l’intégration continue, dont nous parlerons dans un prochain article.
Publié le 26 octobre 2008 à 10h52 Publié sous Développement
Mots clés développement, tdd, code, refactoring
Si cet article vous a plu, suivez-moi sur Twitter
1 commentaire sur Massacre à l'IDE ou les joies du refactoring par le vide »
-
Par Guillaume Desrat le 28 octobre 2008 à 07h51 :
Trackbacks sur Massacre à l'IDE ou les joies du refactoring par le vide
Les trackbacks sont fermés pour cause de spam.
L'ergonomie web, l'utilisabilité et la qualité des logiciels sont trois grandes passions mises au services de ma profession.
Pour ma part, je pense que dans la pratique [1], on peut fusionner les points 3 et 4.
Car pour moi, le révélateur le plus simple du code mort, c’est que d’une part il n’est pas couvert par un test, et que d’autre part, en cherchant où on l’appelle on ne le retrouve pas. Ainsi, en raffinant le code après plusieurs rcov (par exemple) successifs, on en vient à éliminer très facilement le code mort.
Pour ce qui est du point 4 en lui-même, étendre la couverture du code, c’est quelque chose dans lequel je me suis lancé au bureau, sur une application, il y a quelques temps [2]. Ce n’est pas laborieux du tout, et on “voit” les progrès, grâce aux statistiques produites. Qui plus est, la couverture de code m’a permis de pousser certains de mes collègues à ne pas se contenter des tests unitaires, mais également à passer par les tests fonctionnels… juste pour augmenter ces stats ! :D On se prend facilement au jeu, et c’est un jeu payant, pour la qualité (et la tranquilité d’esprit).
[1] je dis bien dans la pratique ; pour l’explication il fallait bien dissocier ces deux processW méthodes.
[2] aujourd’hui, la couverture du code par les tests est de 95,8 %