Pour fêter la naissance de ce blog, j'ai décidé de partager une technique que j'ai mis au point : le Comment Driven Refactoring (Refactorisation Pilotée par les Commentaires).
C'est une manière de refactorer du code (aka "refactoriser"), qui risque de changer radicalement la manière dont tu vois les commentaires et le refactoring en général.
Pour explorer cette pratique, je vais d'abord te parler des avantages que le CDR va t'apporter et puis j'entrerais dans les détails.
Les avantages
Pourquoi utiliser le Comment Driven Refactoring ?
- Cette technique est simple ! Deux étapes, et une seule règle à suivre à chaque étape. Le reste, c'est toi qui vois. On peut difficilement faire mieux, tu ne trouves pas ?
- Le code n'aura jamais été aussi bon. Grâce au CDR, tu as le pouvoir de transformer le code en ce que tu veux qu'il soit. Le code final sera à l'image de ce que tu auras réussi à formuler.
- Cette méthode ne nécessite aucune connaissance préalable en Clean Code, en architecture logicielle, ou même en refactoring. Elle ne nécessite qu'une seule chose : une petite dose d'ingéniosité. 😉
Je vais détailler chaque point, commençons par le premier.
Les deux étapes
Le CDR se pratique en suivant deux étapes simples :
- Ajouter des commentaires
- Retirer des commentaires

Si, si, je t'assure ! Je suis sérieux ! 😁
En revanche, tu t'en doutes, on ne va pas faire ça n'importe comment.
Tout est une histoire de qualité.
Mesurer la qualité
Pour comprendre comment le Comment Driven Refactoring fonctionne, parlons déjà de refactoring.
Pourquoi refactorer du code ? Après tout, refactorer, c'est "modifier du code sans changer son comportement". Alors à quoi bon le faire si ça ne change rien ? Pourquoi les développeurs se bornent à vouloir refactorer le code en permanence ?

La raison est simple : la refacto, ça change beaucoup de choses qu'on ne voit pas de l'extérieur !
Que ce soit pour gagner en performance, en lisibilité, en modularité ou autre, une refacto a pour but d'améliorer la qualité du code.
Dans l'idéal, on voudrait avoir le code parfait. Et refactorer, ça nous permet de nous rapprocher de cet idéal.
Mais dis donc Jamy, c'est quoi "le code parfait" ?
Ce code parfait, on l'appelle parfois Clean Code (code propre). Ce terme englobe aussi toutes les pratiques qu'on met en oeuvre pour arriver à ce résultat.
Il existe beaucoup de définitions du Clean Code. Pour moi, c'est du code qui exprime :
- Toutes les informations pertinentes. Le code nous fait connaître à la fois ses détails techniques et ses intentions. Tout ce qui est présent est utile.
- Aux endroits adéquats. Les informations sont là où on s'y attend, on n'est jamais perdu dans notre lecture, la structure du code suit la logique de l'idée exprimée. Par extension, on peut aussi modifier ce code simplement.
- D'une manière fluide. Le code s'exprime dans un langage qui nous paraît intuitif. Le nom d'une structure (fonction, méthode, classe) est suffisant pour connaître à l'avance le code qu'elle contient. On pourrait lire le code à haute voix, il ne perdrait pas son sens.
La qualité du code pourrait donc se mesurer à la quantité d'informations pertinentes qu'il contient, associée à la manière dont ces informations sont présentées.
C'est en quelque sorte le fond et la forme du code :
- Le fond, c'est toutes les informations présentes : leur quantité, leur précision et leur pertinence.
- La forme, c'est la manière dont ces informations sont présentées : la formulation, le positionnement et la structure.
Bien sûr, l'un ne va pas sans l'autre ! Une donnée pertinente mais non lisible ne sert à rien, et une donnée lisible mais non petinente ne sert à rien non plus.
Dans notre code, il nous faut les deux.
Exprimer le fond et la forme
Refactorer nous aide à augmenter la qualité du code. Dans l'idéal, cela devrait donc améliorer à la fois le fond et la forme.
Or, les techniques de refactoring actuelles se concentrent essentiellement sur la forme : extraire des méthodes, mettre en place un design pattern, séparer une Entity d'un Value Object, renommer une variable, appliquer le SRP ou le DRY ... tout ça rend le code plus lisible et mieux structuré.
En faisant ça, on s'assure de soigner la forme et l'expressivité du code, mais le fond reste globalement inchangé. On travaille toujours sur la même base d'informations incomplètes ; on se contente de les adapter et de les réorganiser.
Le soucis, c'est qu'en s'occupant de la forme sans vraiment s'occuper du fond, on ignore la moitié de ce qui rend le code Clean !
Si seulement il existait une technique de refactoring qui accorde autant d'importance au fond qu'à la forme !
Tu me vois venir ? 😁
Oui, on va y arriver en utilisant le Comment Driven Refactoring !
Et c'est là que les commentaires entrent en jeu.
Les commentaires comme pilotes
Les commentaires peuvent guider notre refacto pour nous apporter aussi bien le fond que la forme.
Un commentaire, c'est quelque chose qui apporte des précisions au code (donc qui l'améliore), sans changer la manière dont il s'exécute.
"Quelque chose qui améliore le code sans changer son fonctionnement" ... c'est exactement la définition d'un refactoring !
Est-ce que ça veut dire que commenter c'est refactorer ? Je te laisse juger. 😉
Ce qui va nous intéresser ici, c'est deux propriétés que possèdent les commentaires :
1. On y met ce qu'on veut
Dans un commentaire, on peut écrire tout ce qu'on veut. De toute manière, ça ne sera pas exécuté.
On peut apporter au code toutes les informations complémentaires possibles et imaginables, avec autant de détails qu'on le souhaite.
C'est le fond évoqué tout à l'heure.
2. On s'exprime comme on veut
Dans un commentaire, on peut écrire des pavés, ou résumer une idée en quelques caractères. On peut écrire d'une manière technique, ou écrire de la poésie.
Non seulement on peut ajouter des informations au code, mais on peut aussi les exprimer de la manière qui nous convient.
Maintenant, on a aussi la forme !
Ajouter des commentaires, ça apporte au code ce dont il a besoin pour être Clean.
La première étape
C'est exactement en ça que consiste la première étape du Comment Driven Refactoring :
Étape 1 : ajouter des commentaires
Dans un premier temps, on va uniquement se concentrer sur ce qui manque dans le code.
Le but est d'ajouter les informations manquantes sous forme de commentaires.
L'idée ici est de ne laisser aucun non-dit dans le code : type des variables, description de ce que fait le code, précisions diverses ... On ajoute le plus de fond possible : tout ce qui n'est pas dit doit être explicité !
Bien sûr, on ne néglige pas non plus la forme que prennent ces commentaires (ça sera important pour la suite) mais elle ne doit pas prendre l'avantage sur le fond. Il vaut mieux mal dire quelque chose que ne rien dire du tout.
Qu'en est-il de la taille des commentaires ?
Parfois, on a besoin d'ajouter beaucoup de contenu pour expliciter les choses, et c'est pas grave.
Mais le mieux, c'est quand même de faire en sorte que les commentaires restent courts. Un seul mot peut suffire à donner du sens au code. C'est ce qu'on peut voir ici :
// fibonacci
$result = round(1.618 ** $number / 2.236);
Oui, cette formule calcule bien le nème nombre de la suite de Fibonacci (jusqu'à une certaine limite).

Pour résumer, on commence par ajouter des commentaires dans le code qu'on veut refactorer.
Après ça, le code possède toutes les données nécessaires pour devenir Clean ... en tout cas, c'est ce qui arriverait dans un monde idéal.
La règle d'or
En pratique, il est rare qu'on réussisse à commenter du code à la perfection. En y réfléchissant assez longtemps, on peut souvent trouver quelque chose à redire pour améliorer un commentaire.
Mais ça prend beaucoup de temps.
Soyons pragmatiques : il vaut mieux s'arrêter avant d'avoir atteint la perfection, sinon on va y passer une éternité. Donc on oublie ça.
La contrepartie, c'est que comme on va se baser sur les commentaires (et leur qualité) pour guider notre refacto, la refacto ne sera pas parfaite non plus.
On peut donc en retirer la règle suivante :
Règle d'or de l'étape 1 : le code final sera aussi bon que les commentaires qu'il contient.
Cette règle nous incite à prendre soin de la qualité des commentaires, mais elle ne nous force à rien.
Parfois, on veut juste améliorer un peu le code, pas le refondre de la tête aux pieds en mode Clean.
Et c'est OK.
Dans ces cas-là, pas besoin de travailler les commentaires pendant dix minutes avant de passer à la suite : quelques secondes suffiront largement pour apporter des gains suffisants.
C'est un équilibre à déterminer quand on utilise le Comment Driven Refactoring.
Personnellement, j'y vais au feeling : je commence par viser la perfection et je m'arrête quand je sens que mes commentaires sont suffisants pour donner un résultat satisfaisant. Et je place la barre plus ou moins haut selon la situation.
La deuxième étape
À la fin de la première étape, on se retrouve avec un code rempli de commentaires. Et les commentaires, c'est pas très Clean. On va arranger ça.
Pendant la première étape, les commentaires sont quelque chose de positif. On apprécie ce qu'ils nous apportent. Ce sont des alliés qui nous aident à progresser vers le Clean Code. 😇
Mais ça, c'était avant.
À partir de maintenant, on va décider de les détester. Et on va tout faire pour qu'ils disparaissent de notre vue ! Mouahaha ! 😈
C'est là qu'on va commencer à "refactorer vraiment".

Étape 2 : retirer des commentaires
Le but est de refactorer chaque commentaire pour que les informations qu'il contient s'intègrent directement dans le code.
À cette étape, notre seul et unique but est de retirer les commentaires du code, on ne va s'intéresser qu'à ça.
La bonne nouvelle, c'est qu'on n'aura pas besoin de réfléchir aux grands principes de la programmation pour trouver comment faire : les commentaires vont piloter nos actions.
Comment ça marche ?
C'est pas sorcier. On choisit un commentaire, et on modifie le code en fonction de ce commentaire :
Si le commentaire nous explique que telle variable représente un utilisateur, le code doit aussi dire que cette variable représente un utilisateur. S'il nous explique qu'une date est au format JJ/MM/AAAA
, le code doit aussi expliciter ce format.
Bref, le code doit copier le commentaire le plus fidèlement possible.
Une fois que c'est fait, le commentaire et le code expriment les mêmes informations. Le commentaire ne nous apporte donc plus rien de nouveau : il est devenu redondant, inutile.
S'il ne nous sert plus à rien, à quoi bon le garder dans le code ?
Autant le supprimer. Ça nous fait un commentaire de moins dans le code.
Une fois que c'est fait, on peut répéter la manipulation sur un autre commentaire et recommencer jusqu'à ce qu'il n'en reste plus.
Une fois arrivé là, le code exprime toutes les informations qu'on avait ajouté sous forme de commentaires, mais sans avoir besoin de commentaires pour le dire.
Et ça c'est beau !
Exemple
Pour reprendre notre fibonacci de tout à l'heure, on pourrait retirer le commentaire de la manière suivante :
function fibonacci(int $number)
{
return round(1.618 ** $number / 2.236);
}
// fibonacci
$result = round(1.618 ** $number / 2.236)fibonacci($number);
Le commentaire nous disait que la formule était celle de "fibonacci".
En créant une fonction qui contient cette formule et qui s'appelle "fibonacci", le code nous donne maintenant les mêmes informations.
Le commentaire ne nous apporte donc plus rien de nouveau par rapport au code : on n'en a plus besoin.
On peut donc le supprimer.
Bilan : un commentaire a été transformé en code et aucune donnée n'a été perdue dans le processus.
On a amélioré la forme sans apauvrir le fond, et c'est ça le but de la deuxième étape du CDR.
Autres options
Ça n'était pas le seul moyen de retirer le commentaire "fibonacci", on aurait pu faire autrement.
Par exemple, voici une solution qui tire plutôt vers la programmation fonctionnelle :
$fibonacci = fn($number) => round(1.618 ** $number / 2.236);
// fibonacci
$result = round(1.618 ** $number / 2.236)$fibonacci($number);
Et là, on a une autre solution, totalement valide aussi, qui modifie le nom de la variable au lieu de toucher au calcul :
// fibonacci
$result$fibonacciOfNumber = round(1.618 ** $number / 2.236);
La seule limite, c'est ton imagination ; c'est ici que tu peux utiliser toute ton ingéniosité.
Chaque solution a ses avantages et ses inconvénients. Choisis celle que tu préfères, tant que ça te permet de retirer du commentaire.
L'important est que le code parle et que les commentaires partent.
La règle d'or
Pendant cette étape, il y a un seul piège à éviter :
Si le code n'exprime pas toutes les informations données par le commentaire et qu'on retire le commentaire, on fait disparaître des informations du code. Le code perd en fond. Il devient donc plus pauvre et il perd en qualité.
Il faut absolument éviter ça, sinon la refacto sera moins bonne. Accessoirement, si on retire ce commentaire, cela veut aussi dire qu'on a perdu du temps inutilement à ajouter ces détails lors de la première étape du CDR. Quel gâchis !
On peut donc en déduire la règle suivante :
Règle d'or de l'étape 2 : on ne retire que ce qui est déjà clair dans le code.
Cette règle est plus stricte que celle de l'étape 1 : une information pertinente qu'on ajoute dans le code doit y rester. Elle y entre sous forme de commentaires, et on la transforme en code. Mais elle ne s'en va pas.
Par contre, on peut déplacer cette information sans problème si on juge que c'est utile.
En pratique, l'étape 2 du Comment Driven Refactoring est une boucle qui consiste en la chose suivante :
- Choisir un commentaire
- Faire en sorte que le code copie le commentaire
- Supprimer le commentaire devenu inutile
Et on fait ça jusqu'à ce qu'il n'y ait plus de commentaires. Ou bien jusqu'à ce qu'on juge que le code s'est suffisament amélioré.
Le code est clean
Les deux étapes du Comment Driven Refactoring sont suffisantes pour améliorer le code.
Résumons ce qu'on a vu jusqu'à présent :
- La qualité du code se mesure au fond et à la forme.
- En ajoutant les commentaires, on a amélioré le fond (et un peu la forme).
- En retirant les commentaires, on a amélioré la forme (sans perdre le fond).
Logiquement, on peut en déduire que ces deux étapes combinées on forcément amélioré la qualité du code.
Bien sûr, ça ne s'est pas amélioré magiquement. Le fait d'ajouter et de retirer des commentaires n'est pas un rituel mystique au dieu du Clean Code ! 😋
C'est encore mieux que ça : les actions qu'on a mené pendant la refacto ont automatiquement fait intervenir des principes bien connus en programmation.
Les principes des deux étapes
Déjà, les deux étapes du Comment Driven Refactoring sont implicitement basées sur deux principes :
- Rule of Explicitness (RoE) : "l'explicite est meilleur que l'implicite". Celui-là est plutôt intuitif : quand on explique les choses, on les comprend mieux. On l'utilise pendant la première étape, quand on essaie d'expliciter au maximum le code en utilisant des commentaires.
- Don't Repeat Yourself (DRY) : "ne te répète pas". Ce principe, plus connu, est la raison pour laquelle on se permet de retirer les commentaires devenus redondants pendant la deuxième étape. Et c'est parce qu'on peut les retirer du code qu'on se permet de les ajouter en premier lieu. Sans ça, pas de CDR !
Ces deux principes constituent le coeur du Comment Driven Refactoring.
C'est en combinant le RoE et le DRY que le code se métamorphose comme il le fait. Mais ça, on n'a pas besoin de s'en soucier pendant une session de CDR : le simple fait de vouloir ajouter, puis retirer des commentaires nous fait implicitement respecter ces principes.
Les autres principes
En pratiquant le CDR, on en utilise bien d'autres pendant la deuxième étape :
Chaque fois qu'on modifie le code pour rendre un commentaire redondant, on utilise aussi d'autres principes (Single Level of Abstraction, Inversion des Dépendances, Fail Fast, ... selon les cas).
Bien sûr, on ne fait pas ça volontairement. C'est ça qui est cool !
Dans ces moments, notre but est de trouver un moyen d'améliorer la forme (en retirant un commentaire) tout en préservant le fond (les informations que le code exprime).
Peu importe la solution qu'on trouve, on a déjà prouvé que cela va automatiquement améliorer la qualité du code. Et pour ce faire, notre solution va automatiquement adopter des bonnes pratiques. C'est parce que nos modifications respectent ces "grands principes" qu'elles réussissent à rendre les commentaires redondants et le code plus Clean.
L'avantage avec le Comment Driven Refactoring, c'est que ces principes s'appliquent d'eux-mêmes : pas besoin des les maîtriser, ni même de chercher à les utiliser.
On n'a même pas besoin de les connaître pour les appliquer, on est au-delà de ça.
Ces principes ne sont plus des outils qu'on emploie pour progresser, mais des conséquences (positives) du Comment Driven Refactoring.
Nous, on veut juste dégommer du commentaire ! 😈 Le reste se fait tout seul.
Voilà, tu connais maintenant la théorie au sujet du Comment Driven Refactoring !

Tirer profit du CDR
Tu en veux encore plus ?
Maintenant que tu connais les bases du Comment Driven Refactoring, je vais te donner deux astuces pour pouvoir tirer le maximum de cette pratique :
1. Le Comment Driven Refactoring en pair/mob
Un cerveau c'est bien. Plusieurs cerveaux, c'est mieux !
La première étape du CDR consiste à ajouter le plus de choses au code de manière pertinente. C'est l'occasion parfaite pour un brainstorming.
Quels commentaires ajouter ? Que dire ? Comment mieux le dire ? Comment le dire encore mieux que ça ?
C'est en réfléchissant à plusieurs qu'on répond le mieux à ces questions.
Et comme cette première étape ne demande pas de grosses compétences techniques, tout le monde peut participer (pas que les développeurs). On peut alors tirer parti des collègues qui ont une vision métier et/ou plus proche de celle de l'utilisateur.
Ajouter de la vision métier dans le code est une des meilleures choses qu'on puisse faire pour améliorer sa qualité.
On peut aussi en profiter pour que tout le monde progresse en expertise, même les nouveaux venus dans l'équipe. À force de discuter du code et d'essayer de formuler précisément ce qu'il s'y passe, on comprend pas mal de choses !
Dans une moindre mesure, c'est pareil à l'étape 2. Se concerter pour déterminer comment faire disparaître les commentaires, c'est l'occasion de partager de bonnes idées techniques avec les collègues.

2. Le Comment Driven Refactoring en solo
Le CDR est aussi utile pour s'exercer en solitaire.
Oui, je parle des katas, ces petits exercices de programmation jetables qui servent à pratiquer nos compétences.
Pour faire un kata orienté Comment Driven Refactoring, c'est pas compliqué. Il suffit de :
- Fabriquer un morceau de code (celui que tu veux, tu fixes les règles).
- Utiliser le CDR dessus.
En faisant des katas de CDR, tu pratiques des compétences utiles : savoir décrire efficacement du code et savoir le refactorer.
À force de fabriquer du code complètement refactoré, tu t'habitueras aussi à produire directement du code encore plus Clean qu'avant.
Par exemple, depuis que je pratique des katas de Comment Driven Refactoring, j'arrive beaucoup mieux à voir les Primitive Obsessions (quand on représente une donnée en utilisant un type "trop basique").
Avant, j'avais tendance à reproduire ce code smell un peu partout sans m'en rendre compte.
À force d'utiliser le CDR, je me suis rendu compte que que je tombais souvent dans le panneau et j'ai appris à corriger ce problème.
J'ai aussi amélioré mon "radar à code smells" : quand je lis du code ou que je m'aprête à en écrire, je me rends plus facilement compte quand il y a une Primitive Obsession cachée quelque part.
Au fur et à mesure, j'ai appris à ne plus moins reproduire ce code smell.
Combler cette faille et la transformer en force a été une avancée importante dans la qualité générale de mon code.
Autre astuce : le CDR peut aussi être utilisé à la fin d'un autre kata.
En effet, quand tu termines un kata, tu te retrouves avec du code que tu dois jeter. Avant ça, pourquoi ne pas t'entrainer à le refactorer, histoire de faire d'une pierre deux coups ?
Les katas CDR sont donc très formateurs. Niveau programmation, tu deviendras :
- Plus rapide
- Plus précis
- Plus qualitatif

Conclusions
Quand je suis tombé sur l'idée du CDR, j'ai passé pas mal de temps à chercher des références à cette technique sur internet.
Je n'ai rien trouvé.
Bien sûr, je ne doute pas que certaines personnes utilisent déjà le Comment Driven Refactoring de manière régulière, sans forcément lui donner ce nom.
Et le sujet des commentaires n'est pas inconnu non plus : on parle beaucoup de l'importance de commenter le code (quand c'est utile), du fait qu'un code sans commentaires est plus propre, ainsi que de plusieurs manières de refactorer les commentaires.
Mais il semblerait que personne n'ait encore formalisé cette idée d'ajouter puis retirer volontairement des commentaires dans le code afin de guider un refactoring.
C'est maintenant chose faite dans cet article.

Merci d'avoir lu jusqu'au bout ! J'espère que ça t'a plu.
Tu as des questions ou des remarques ? Tu veux discuter du CDR ? Tu pratiques déjà quelque chose qui y ressemble ?
Contacte-moi, ça m'intéresse. 😉