Réécrire un legacy avec l'IA : le piège des 80 %
Il existe un scénario qui se répète aujourd’hui dans beaucoup d’équipes.
Un vieux module que personne n’ose toucher, quelques milliers de lignes écrites des années plus tôt, souvent par quelqu’un qui a quitté l’entreprise depuis longtemps. Un jour, quelqu’un ouvre Claude Code ou Cursor, donne l’ancien fichier, décrit l’architecture cible. En quelques heures, une version moderne apparaît : services découplés, types stricts, tests unitaires au vert. La démonstration est bluffante. On merge, fier d’avoir enfin tué le dragon.
Puis, quelques jours plus tard, un comportement disparaît en production. Un client ne reçoit pas sa facture. Un calcul tombe faux dans un cas que personne n’avait en tête.
Le problème ne vient presque jamais du code qu’on a lu, compris et réécrit. Il vient d’une ligne qu’on a à peine regardée, une condition obscure qui gérait un cas particulier, un type de contrat dont on ignorait l’existence. L’ancien code le gérait. Le nouveau, non. L’IA avait reproduit fidèlement 80 % du comportement. Et c’est précisément ce qui endort.
L’IA ment sur la difficulté
Réécrire un système legacy ressemble à une traduction. On prend du vieux code, on le transpose dans une stack moderne, on change la syntaxe, on réorganise. Et la traduction, c’est exactement ce que l’IA fait le mieux. Donnez-lui un fichier Java de 2015 et demandez une version TypeScript propre : elle vous la rendra en quelques secondes, élégante, idiomatique, plausible.
C’est là que le piège se referme. Parce que réécrire un legacy n’est pas un problème de traduction. C’est un problème d’archéologie.
Le code legacy n’est pas seulement du code ancien. C’est de la connaissance métier fossilisée. Chaque if bizarre, chaque cas particulier, chaque commentaire énigmatique « ne pas toucher, voir ticket #4471 » est la trace d’un problème réel rencontré un jour par quelqu’un. Le système legacy est la somme de toutes les corrections, de tous les contournements, de toutes les exceptions que la réalité a imposées au fil des années.
L’IA, elle, ne fait pas la différence entre l’essentiel et l’accidentel. Elle reproduit ce qu’elle comprend de l’intention apparente du code. Quand elle rencontre une ligne dont la justification s’est perdue, un comportement qui n’a de sens qu’au regard d’un client disparu, d’une réglementation abrogée, d’un bug compensé ailleurs, elle a deux options : la reproduire sans la comprendre, ou la « nettoyer » parce qu’elle semble incohérente. Les deux sont dangereuses.
Le legacy ne vit pas dans les 80 % de code que l’IA traduit sans effort. Il vit dans les 20 % que plus personne ne sait justifier. C’est le prolongement direct d’une idée que j’ai déjà explorée : quand l’IA livre plus vite que le produit ne pense, la vitesse devient une illusion qui masque le vrai travail.
La bonne méthode
Si la difficulté n’est pas de traduire mais de comprendre, alors la méthode doit faire de la compréhension son centre de gravité, pas un préalable qu’on expédie. Voici l’ossature que j’utilise désormais, à deux niveaux.
Le cadre macro : le strangler fig
La pire décision face à un legacy, c’est le big-bang rewrite : tout réécrire, puis basculer d’un coup. L’IA rend cette tentation plus forte que jamais, parce qu’elle fait croire que « tout réécrire » est désormais à portée de week-end. Ne cédez pas.
Le pattern du strangler fig, l’arbre étrangleur qui pousse autour de son hôte jusqu’à le remplacer, reste la seule approche saine. On encercle l’ancien système. On remplace un module à la fois. L’ancien et le nouveau cohabitent en production, derrière une façade qui route le trafic vers l’un ou l’autre. Chaque module migré est validé en conditions réelles avant de passer au suivant.
L’avantage n’est pas que technique. C’est que chaque incrément est assez petit pour qu’un humain le comprenne vraiment. On ne demande jamais à l’IA, ni à soi-même, d’avaler trois mille lignes d’un coup.
La discipline micro : comprendre → spécifier → régénérer
À chaque module, je m’interdis désormais le réflexe « ancien code dans le prompt, nouveau code en sortie ». Je passe par trois temps.
Comprendre. J’utilise l’IA comme un outil d’archéologie, pas de production. Je lui demande d’expliquer le module, de lister les cas qu’il gère, de repérer les branches étranges, de formuler des hypothèses sur le pourquoi. Elle est excellente pour ça : elle lit plus vite que moi et ne se fatigue pas. Mais c’est moi qui valide, qui croise avec les anciens tickets, qui vais interroger les rares personnes qui se souviennent.
Spécifier. Le livrable de cette phase n’est pas du code. C’est une spécification du comportement réel, y compris les bugs qu’on décide consciemment de conserver. En parallèle, j’écris des tests de caractérisation : des tests qui ne décrivent pas ce que le système devrait faire, mais ce qu’il fait réellement, aujourd’hui, bugs compris. Ces tests sont le filet de sécurité. Ils sont la seule preuve objective que le nouveau code est équivalent à l’ancien.
Régénérer. Seulement maintenant, je demande à l’IA de produire le nouveau module, à partir de la spécification, pas du code legacy. La différence est fondamentale : régénérer depuis une spec force à avoir compris ; traduire depuis du code permet de ne jamais comprendre. Les tests de caractérisation tournent en continu et valident l’équivalence à chaque itération.
Dans tout ce processus, l’IA est un accélérateur encadré, jamais le pilote. Elle lit, propose, génère. Mais c’est la compréhension humaine qui définit ce qui est essentiel, et ce sont les tests qui tiennent la barre.
Les 20 % qui comptent
On pourrait croire que cette méthode est lente. Elle l’est, comparée à l’illusion du week-end. Mais elle est rapide comparée à la vraie alternative : découvrir les 20 % manquants un par un, en production, à travers des incidents.
Car c’est là que vit le legacy. Pas dans la logique principale, propre et lisible, que l’IA reproduit sans peine. Mais dans :
- Les règles métier implicites, ce cas de TVA que personne n’avait documenté.
- Les dépendances cachées, ce module qui suppose qu’un autre a déjà écrit dans le cache, sans que rien ne l’indique.
- Le « pourquoi » perdu, ces comportements qui n’ont de sens qu’au regard d’un contexte historique évaporé.
Toute la méthode, strangler fig, caractérisation, spécification, n’existe que pour une raison : exhumer ce savoir avant de le détruire. L’IA ne peut pas faire ce travail à votre place, parce que ce savoir n’est écrit nulle part. Il faut le reconstituer, fragment par fragment, en lisant, en testant, en demandant. Le code legacy est souvent le seul endroit où ce savoir existe encore. Le réécrire sans le comprendre, c’est brûler la bibliothèque pour gagner de la place.
Ce que la méthode coûte, et ce qu’elle évite
Reprenons le scénario du début, mais fait dans le bon ordre. On écrit d’abord les tests de caractérisation. Souvent, certains d’entre eux décrivent des comportements qui semblent aberrants, et qui se révèlent être des règles métier parfaitement légitimes, juste mal nommées ou jamais documentées.
La réécriture prend alors quelques jours au lieu de quelques heures. Mais aucun comportement ne disparaît silencieusement, et aucun client ne manque sa facture.
L’IA n’a rien retiré à la difficulté de réécrire un legacy. Elle a simplement déplacé l’endroit où elle se cache. Avant, la difficulté était visible : c’était le temps qu’il fallait pour tout retaper. Maintenant, ce temps a disparu, et la difficulté s’est réfugiée là où on ne la regarde plus, dans la compréhension de ce qu’on est en train de remplacer.
La sagesse, face à un legacy, n’a jamais été de savoir réécrire vite. C’est de savoir, à chaque ligne, si on a compris pourquoi elle existe. L’IA peut écrire les 80 % à votre place. Elle ne peut pas vous dire ce qu’il y a dans les 20 % restants. Et c’est là, comme toujours, que se trouve le vrai travail.
// À lire ensuite