Le code legacy, c’est comme une grosse pelote de laine : quand tu commences à tirer un fil, tu as vite fait d’embarquer toute la pelote.
Tu t’en rends compte quand tu commences à utiliser du code quelque part et que l’air de rien, tu dois importer une classe… Et puis deux…
Et puis tu te rends compte qu’il en manque encore…
En quelques minutes c’est la moitié, ou plus, de l’application que tu embarques.
Tu te sens de plus en plus à l’étroit dans ton code jusqu’au moment où tu n’oses plus le toucher… A partir de là tu te transformes en Ninja et développes cet art subtil de modifier le code, sans modifier le code…
Tu repères ta cible pendant des heures à la recherche de l’endroit propice. Puis quand tu es sûr de toi, tu frappes et ajoutes les quelques lignes de code avec une précision chirurgicale.
Puis tu t’échappes aussitôt avant que la police du code ne t’attrape.
Quel est le problème ?
Après tout ça marche…
D’abord je m’interroge sur l’efficacité de la démarche. Si tu remarques qu’ajouter du fonctionnel est de plus en plus long et difficile, c’est qu’il y a un souci.
Mais à la rigueur, c’est encore peu visible de l’extérieur.
Ca devient visible quand l’application commence à bugger et que l’équipe n’arrive pas à garantir la stabilité de l’app.
Là ça devient visible par les clients, les managers, le patron.
Enfin je me questionne sur la satisfaction personnelle quand on passe sa journée à régler des bugs en en créant d’autres…
C’est stressant et usant.
Mais il y a pire dans l’histoire : ça serait de finir par se dire que tout ça est normal !
Alors heureusement, il y en a qui refusent de baisser les bras. Ils prennent leur courage à deux mains.
Ils font un serment solennel d’écrire des tests et se jettent à l’assaut du monstre spaghetti.
Et c’est là que le paradoxe du code legacy les frappe de plein fouet, les fauchant dans leur pleine vigueur.
Le paradoxe du code legacy est le suivant :
– Pour remodeler du code en toute sécurité, il faut des tests automatiques.
– Pour écrire des tests automatiques, il faut du code testable.
Le souci c’est que le code legacy n’est pas testable, par définition.
Je reprendrai la définition de Michael Feather : le code legacy est du code qui n’a pas de tests.
Tu remarqueras que je fais une toute petite extrapolation en considérant que du code non testé n’est pas testable. C’est un simple constat empirique depuis 20 ans que je code.
Il faut donc commencer par casser le code, le fragmenter, l’assouplir avant de pouvoir écrire les premiers tests qui me permettront de me créer un filet de sécurité.
Cette partie est inquiétante car tu as peut-être appris à avoir peur du code legacy. Elle est stressante car tu travailles sans filet.
Heureusement, il existe des techniques de remodelage et des principes de conception qui permettent de faire ça en limitant les dégâts.
Ces principes tu peux les apprendre dans le livre de Martin Fowler sur le refactoring. En plus il vient de sortir une nouvelle édition.
Tu peux aussi acheter celui là : Working Effectively with Legacy Code.
Ce sont les deux livres clefs sur lesquels je m’appuie dans mon travail et mes formations.
Enfin si tu n’as pas l’envie ou le temps de lire plusieurs centaines de pages, tu peux aussi suivre le cursus Artisan Développeur dans la maison des compagnon. C’est un super condensé de ce qui te sera vraiment utile pour démarrer.
Le module #3 vient de sortir et il est à un prix canon jusqu’à Dimanche !
Juste une idée: Avant de «casser le code, le fragmenter, l’assouplir», on peut pas envisager d’écrire des tests en «boite noire» pour caractériser le comportement vu de l’extérieur ? Après on peut se servir de ces tests pour s’assurer que «casse le code» ne casse pas (trop) le contrat du code…
J’admets humblement que c’est un point de vue théorique car je n’ai jamais eu à re-travailler en profondeur du code legacy..
Pas si théorique que ça… 🙂
C’est le principe du « Golden Master » : produire une data de référence. A noter qu’il faut quand même disposer d’un test d’intégration « boite noire » qui fait tourner toute l’appli pour produire un log par exemple.
Plusieurs « astuces » ensuite pour produire / améliorer ses Golden Masters:
– rajouter des lignes de log dans l’appli: on prend peu de risque à toucher ainsi le legacy
– modifier la couche / lib qui gère la bdd pour dumper toutes les requêtes SQL générées
– même approche avec les autres IO importantes: réseau (appels REST…), fichiers locaux, hash des data / paramètres envoyés, etc….
On peut avoir besoin d’un petit post-processing pour gérer des diff de temps / date d’exécution et autre variation d’ordre (si multi-threading) des résultats enregistrés dans les logs. Mais en général, il ne faut que quelques jours pour produire une séries de dumps répétables qui couvrent pas mal de pans critiques de l’application. Et qui se montrent très utiles aussi bien pour détecter les régression que simplement étudier et mieux comprendre ce que fait l’application (ordre des requêtes SQL…).
Ce type de testing est plutôt méconnu / sous utilisé alors que c’est un très bon complément aux tests unitaires. Pour les nouveaux venus c’est aussi un bon moyen de découvrir le fonctionnement macro de l’application.
👍