Legacy remediation : qui, que, quoi, dont, où ?

Two welders at work
Photo by Pete Wright on Unsplash

Tout ce que vous avez toujours voulu savoir sur le refactoring (sans jamais oser le demander).

Il est de notoriété publique que les développeurs préfèrent le greenfield (partir de la page blanche) au brownfield (travailler sur une codebase existante). Brownfield = 💩, si je puis m'exprimer en ces termes fleuris. C'est bien compréhensible, car partir de la page blanche, c'est l'occasion de faire nos propres choix (architectures, technos, paradigmes…), d'imposer nos propres standards et surtout de retranscrire notre schema mental en code.

Travailler à "dérouler" notre schéma mental est, par définition, plus facile que d'aborder une codebase existante, longuement élaborée à partir d'un autre schéma mental que le nôtre. Quand 2 schéma mentaux rentrent en collision, ça donne invariablement le même résultat :

WTF ?!

La distinction entre greenfield et brownfield est pourtant fragile, car il ne faut pas oublier que dès que l'on touche le clavier, on crée de la dette. En effet, l'architecture et les conventions de code émergent au fur et à mesure que l'on implémente les fonctionnalités, a fortiori quand on travaille en équipe. Il est fréquent de refactorer du code écrit à peine une heure auparavant. Donc on passe son temps à refactorer, même dans un projet greenfield. Vu ?

Mais au fait, c'est quoi, le refactoring ? Le refactoring, c'est le "réusinage" en français (*). Alors, pourquoi retravailler du code qui fonctionne ?

C'est bien la première question à se poser : s'il fonctionne et que l'on n'a pas besoin de le faire évoluer, mieux vaut ne pas y toucher, car on ne peut que dégrader son fonctionnement ➡️ Règle N°1 du refactoring.

Oui, disons-le tout de go : refactorer est une tâche ingrate. Sur le plan fonctionnel, au mieux vous n'apportez aucune valeur, au pire vous cassez la prod. Tandis que sur le plan technique, les améliorations que vous apportez resteront invisibles aux yeux des utilisateurs, product owners et autres personnes non directement concernées par la technique.

De leur point de vue, ce que vous faites n'a aucune valeur. Super incitation 👍.

On retravaille donc le code quand on ne peut pas faire autrement, parce qu'il faut corriger un bug ou ajouter de nouvelles fonctionnalités, et que le code est tellement abscons / hermétique / cryptique / je-suis-à-court-de-synonymes qu'on ne peut pas y toucher sans courir le risque de créer un paquet de régressions en prod. Il faut donc impérativement faire place nette avant de commencer à travailler.

Ah, au fait, je vous arrête tout de suite : non, on ne va pas ré-écrire toute la codebase, on a mieux à faire de notre argent 💸. Oui, en fait ça c'est la ➡️ Règle N°0 (mais qui a écrit cet article ?).

Dans tous les cas, refactorer, c'est retravailler le code pour faciliter son évolution future sans modifier son comportement. Le refactoring travaille donc les 3 aspects fondamentaux de l'artisanat logiciel : lisibilité, testabilité et modularité. 3 aspects qui facilitent la maintenabilité du code et augmentent sa capacité à évoluer.

Assez parlé… refactorons, mes bons ! 🧰 ⚙️ 🔧

Je vous préviens, il nous faudra un peu de courage et beaucoup de méthode 👌.

Si la codebase a été écrite avec les pieds 👣, il y a fort à parier qu'il n'y ait aucun test. Comment, dans ces conditions, s'assurer que nos actions n'occasionnent pas de régressions ? Eh bien pour cela, il existe une méthode très simple consistant à rajouter des tests basés sur des logs traduisant le comportement du système dans son ensemble, en termes purement fonctionnels. On fonctionne en boîte noire : on ne veut rien savoir des entrailles du code, puisque tout va changer. C'est la méthode du Golden Master, et ce sera la ➡️ Règle N°2. Ça n'est pas une règle, je sais, arrêtez de chipoter !

Ensuite, nous serions bien inspirés, comme toujours quand on écrit du code, de procéder par petites touches 🧑‍🎨🎨. Allez, tiens, ce sera la ➡️ Règle N°3 du refactoring. Pourquoi ? Parce qu'on aimerait autant que possible éviter de faire un gros refacto "à côté" de la prod, refacto qui sera un cauchemar à merger le moment venu (c'est-à-dire dans 4000 ans, puisqu'on n'a jamais fini de refactorer).

Comment ? Là encore, il y a de la méthode :

  • Méthode Mikado : une méthode simple qui permet, une fois l'objectif du refactoring défini, de tracer un chemin permettant de l'atteindre "sereinement". Parce que le problème du refactoring, c'est qu'un refacto en appelle un 2ème, qui en appelle un 3ème et ainsi de suite. En moins de 2, plus rien ne compile et c'est la guerre atomique dans la codebase.
  • Strangler Pattern : un des plus grands coups d'éclat de Martin Fowler en ce qu'il permet la substitution progressive du code legacy par le code refactoré, apporté en incréments prodables. La meilleure façon d'éviter l'effet tunnel.

Eh ben… y'a plus qu'à ! Allez, bon courage, et faites-moi signe si besoin.

À la semaine prochaine 👋 !

(*) Mais soyons honnêtes : personne ne dit ça, ou alors avec l'accent québécois.

Subscribe to Mathieu Eveillard

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe