La programmation agentique sur du code ancien
Se servir de son LLM préféré pour créer un produit sympa, c'est la grande mode en ce moment. Mais la majorité des logiciels en production tournent depuis des décennies, et une bonne partie tient avec des ficelles et une prière. C'est là que les paradigmes agentiques habituels s'effondrent, parce que ces systèmes présupposent une base prévisible sur laquelle travailler. Chaque nouvelle session que vous ouvrez n'a qu'une petite fraction du code en mémoire, ce qui veut dire que les vraies cochonneries ne sont jamais prises en compte. Pendant ce temps, les tutoriels supposent un repositoire propre, une stack moderne et une suite de tests. Le code ancien n'offre rien de tout ça. Nous avons passé trois ans à pointer des agents de programmation sur ces systèmes, et presque tout ce qui suit vient d'un moment précis où l'on s'est d'abord planté.
On ne peut pas sauter la mise en place
Quand on plonge dans une nouvelle base de code, c'est très tentant de démarrer claude et d'attaquer un backlog de bugs comme un pro, histoire de montrer au reste de l'équipe qu'on sait ce que l'on fait. Mais franchement, prenez du recul, passez une semaine environ à faire de l'audit. Posez des questions à l'équipe, puis posez les mêmes questions à votre IA. Cartographiez le repositoire, repérez où la dette technique la plus sale est concentrée, déclarez explicitement les gros fichiers comme interdits à vos agents (à moins qu'ils aient absolument besoin d'y jeter un œil), et documentez tout jusqu'à l'écœurement.
Il y a quelques années, on a hérité d'un ERP en .NET. Un seul fichier solution, avec près de cinquante répertoires csproj accrochés dessus. J'ai pris le chemin paresseux. Un seul prompt : « comment peut-on améliorer ça ». L'agent a réfléchi un moment, j'ai attendu, et il est revenu avec un plan qui avait l'air solide. J'ai failli applaudir.
Puis je l'ai lu. Il n'avait pas lu cinq fichiers avant de se mettre à halluciner, chacun faisant plus de trois mille lignes. Ce qu'il n'avait aucun moyen de savoir, c'est que la moitié de ces projets étaient abandonnés, et que d'autres ne portaient qu'un ou deux fichiers vivants à eux tous. Le plan était donc assuré, détaillé, et complètement fictif. Il décrivait un système qui n'existait pas.
Voilà la leçon, et elle est ennuyeuse exprès. Consacrez du vrai temps à la recherche et à la documentation avant que l'agent ne touche à quoi que ce soit, pour qu'il ne s'égare pas dans du code mort et ne s'en fasse pas une vision du monde. Donnez-lui un endroit où garder ce savoir, séparé du code :
/votre-projet-super-ancien
/docs-de-contexte
/plans-de-traveaux
/instructions-pour-agents
/vrai-repo
La carte des fichiers vit dans docs-de-contexte, et elle accompagne chaque prompt par la suite. Attendez-vous à refaire la passe de cartographie plus d'une fois avant qu'elle soit juste. Sautez cette étape et chaque tâche ultérieure partira d'un modèle halluciné du système, et vous ne vous en rendrez pas compte avant que le résultat soit déjà cassé.
Une dernière chose pendant que vous y êtes. Les repositoires ancien sont pleins de secrets : un mot de passe de banque de données dans un fichier de configuration enregistré sur git, une clé d'API dans un commentaire. Vous devriez probablement les chercher à la main. Claude se fera un plaisir d'envoyer ça au QG, et je vous parie cinq moutons et une chèvre que ça finira par fuiter un jour. Une fois repérés, nettoyez-les du repositoire, ou à tout le moins, soustrayez ces fichiers à la portée de votre agent.
Le code n'a aucun style, et les agents ne font pas par l'exemple
C'est l'échec qui nous a coûté le plus cher, et c'est celui dont personne ne vous prévient.
Le code ancien n'a pas un seul style. Il en a cinq, ou quinze. Vous avez le code d'origine, la réécriture abandonnée à mi-chemin, le bout laissé par le sous-traitant, les reparations de panique, la super nouvelle fonctionnalité du stagiaire que plus personne n'utilise parce qu'elle est trop instable, et tout ce que la dernière personne à avoir démissionné a laissé derrière elle. Les antipatterns sont rarement isolés, eux non plus.
Un système qu'on a repris avait un frontend Angular qui faisait de son mieux pour imiter React, et un backend Java avec un excellent ORM posé juste à côté de rien d'autre que du SQL brut. Le pire, c'était le cloisonnement des données. C'était une application mutualisée, et la vérification qui empêchait une organisation d'accéder aux données d'une autre vivait à l'intérieur de chaque requête individuelle, recopiée à la main, plutôt que dans un seul endroit central. Oubliez-la une seule fois et vous avez une fuite de données.
Pointez un agent là-dessus avec un simple « fais ça » et il fait exactement ce que vous lui demandez, mais dans le style du code voisin. Encore du SQL brut. Encore un bouton entièrement stylé à la main, légèrement différent du précédent. Encore une vérification d'isolation recopiée à la main, ou pire, une oubliée. Il photocopie les erreurs qu'on n'a jamais nettoyées, et voilà que la dette technique est plus grosse qu'au départ. La réponse tentante, c'est « le code ne coûte rien, on s'en fout ». Ça vous rattrape plus tard, en général dans la partie du système que vous surveilliez le moins.
Alors quel est le problème, on n'a qu'à dire à Claude d'être bien sage et de ne faire les choses que de la « bonne manière » et c'est réglé, non ? Eh bien, pas si simple. Il n'y a pas toujours une seule « bonne manière » de faire quelque chose, il existe en général plusieurs approches correctes pour du bon code, et les partisans de l'une diront le plus souvent que toutes les autres ne valent rien. Les agents se forgent leur opinion sur le meilleur pattern à chaque fois que vous initialisez une nouvelle fenêtre de contexte, alors tantôt vous verrez une approche, tantôt une autre.
La solution n'a rien de subtil. Dites à l'agent, explicitement et à chaque fois, à quoi ressemble le bon code dans ce repositoire, et que le code environnant n'est pas la référence. « Imite le style existant » est le comportement par défaut, et « suis les bonnes pratiques » est trop ambigu. On garde une courte liste d'exemples tirés de la base de code, fichier par fichier, dans instructions-agent, et on la cite comme le Saint Graal. Ensuite, quand une nouvelle partie du code est remise à neuf, cette partie s'ajoute à la liste d'exemples à utiliser par la suite.
Un seul audit n'est pas un audit
Un client s'est présenté avec une stack Vue et PHP qui était, pour rester diplomatique, grande ouverte. Elle tournait sur une simple instance EC2, sans rien devant. On a passé deux jours à scanner avec Claude et quelques autres outils, à la chasse aux trous. On en a trouvé. Beaucoup. On a tout corrigé en quelques heures, livré un gros déploiement de sécurité, en grande pompe.
Puis, surtout pour rigoler, on a relancé le scan complet après le déploiement. Et le voilà : d'autres trucs critiques, tout aussi graves que ceux de la première passe était passée tout droit.
Voici ce que je crois qu'il se passe : le modèle veut vous pondre un article. Ça me rend dingue, je déteste ça, mais c'est comme ça. Vous obtenez un rapport bien propre avec deux critiques, trois élevées, deux moyennes, cinq faibles et une conclusion. Ça ressemble à un rapport professionnel, et avoir l'air du rôle, c'est exactement ce que le modèle a été entraîné à produire. La vraie forme d'un système ancien est plutôt de l'ordre de quinze fois chacun de ces chiffres, avec plus de dimensions qu'une liste bien rangée ne peut en contenir. Certains problèmes sont assez obscurs pour que personne ne songe jamais à les chercher, et assez graves pour couler l'entreprise si quelqu'un le faisait. D'autres sont quasiment inoffensifs, mais tellement visibles qu'ils font fuir des clients tous les jours. Et certains problèmes n'en sont un que dans des contextes précis que l'agent suppose tout simplement absents (alors qu'ils pourraient être bien présents).
Traitez les audits comme une tâche récurrente, pas comme un événement unique. Lancez-les sur un horaire, relancez-les après chaque lot de correctifs, et partez du principe que la liste est toujours plus courte que la vérité. Le but, ce n'est pas un rapport parfait, c'est une couverture qui s'accumule avec le temps. Tant qu'à y être : c'est tentant de partager l'alarmisme de votre agent devant les problèmes de sécurité ultra-critiques qu'il déniche. Mais il est important de remettre en question ses conclusions pour voir si c'en est vraiment un.
Refactorer sans tests vous garantit un revert
On a laissé un agent nettoyer une chaîne de traitement de commandes emmêlée. Il a rangé la logique, simplifié une boucle, et passé sa propre vérification. Il a aussi supprimé une règle non documentée qui exonérait de taxe un type de client particulier. Personne n'avait noté cette règle nulle part. Il n'y avait aucun test. On l'a découvert quand les chiffres sont revenus faux, en production, une semaine plus tard.
Le code ancien est plein de comportements que personne n'a documentés, et l'agent va les optimiser jusqu'à les faire disparaître parce qu'il ne voit pas pourquoi ils comptent. Avant tout refactoring, mettez des tests de caractérisation autour du code. Vous devrez comprendre ce qui se passe, car laisser un agent écrire des tests à l'aveugle vous laissera dans la même situation, mais vous n'avez pas à les écrire vous-même. Un agent peut pondre plus de tests en une seule séance que je n'en ai écrit dans toute ma carrière, alors profitez-en.
Pensez à lancer un agent sur l'historique Git
Un projet en particulier qu'on a eu le plaisir de côtoyer suivait le git flow à l'envers. Ils avaient une branche development, une staging et une master comme toutes les autres entreprises. Sauf qu'ils travaillaient directement sur master. Ensuite, tous les changements étaient cherry-pickés dans les deux autres branches deux fois par semaine. Comprendre comment on en arrive là avec un cerveau humain est un brin déroutant, alors on a utilisé Claude pour démêler tout ça. Il n'y a pas de leçon ici, juste un bon conseil en général. Pour les points bonus, on a précisé dans le prompt que ça devait avoir le ton d'un téléroman.
Vous pouvez demander à quelqu'un de vous raconter comment les choses en sont arrivées là, mais une partie de ce que vous entendrez n'est souvent que la régurgitation de ce qu'une autre personne lui a déjà raconté. Une entreprise n'aboutit pas à une situation pareille en quelques mois, il faut des générations d'employés aux prises avec de beaux problèmes pour en arriver là. Ça veut dire des générations de commits git remplis de lore d'entreprise dont vous ne pouvez tout simplement pas vous passer, mais que vous ne pouvez pas non plus lire facilement tout seul. C'est tentant de pointer un bug rigolo et de rire, mais il y a probablement une très bonne raison à sa présence.
Choisissez d'abord vos réécritures et vos zones interdites
L'erreur classique, c'est de traiter tout le système comme également modifiable. Il ne l'est pas.
Certaines choses sont coulées dans le béton. Le modèle de données est l'exemple évident. Chaque rapport, intégration et procédure stockée en dépend, et un agent qui décide d'« améliorer » le nom d'une colonne fera tomber six choses que vous ne saviez pas reliées. On marque ces éléments comme interdits dès le départ, dans les consignes de l'agent, et on ne plaisante pas. Y toucher, c'est un projet, pas un prompt.
D'autres choses sont des gains rapides, et vous les voulez tôt. Sur un mandat, le backend était terrifiant, mais l'interface d'administration était simplement vieillotte. On a fait moderniser l'interface par l'agent en premier. Faible risque, rien de structurel, et le client pouvait soudainement voir du progrès. Ça nous a acheté la confiance et la marge de manœuvre pour nous approcher des parties effrayantes plus tard. L'élan compte sur du travail ancien, parce que la plupart des vrais changements restent invisibles pendant des semaines. Dépensez une victoire précoce là où quelqu'un peut réellement la voir.
Bref
- Cartographiez-le avant de lui faire confiance
- Dites à l'agent à quoi ressemble le bon code, sinon il copie le pire code de la pièce
- Auditez en boucle
- Testez avant de refactorer, et laissez le code bizarre tranquille jusqu'à ce que vous sachiez pourquoi il est bizarre
- Décidez ce qui est sacré et ce qui est un gain rapide avant de commencer
Rien de tout ça n'est exotique. La chose à intégrer, c'est que l'agent ne doutera pas à votre place. Il sonne l'alarme là où il n'y a aucun problème, et il vous accepte, vous et le code devant lui, sans le moindre mot de contestation, à moins que vous lui demandiez d'argumenter. Le scepticisme doit venir de vous. Les systèmes ancien étaient là avant les agents, et ils survivront aussi à ce billet de blogue.