ScalerRefactorer du code généré par IA : par où commencer
· 6 min de lecture · par l'équipe Agenticiel
Le code généré par un assistant, qu’il sorte de Lovable, Bolt, v0, Cursor ou Claude Code, a une propriété que l’on découvre souvent trop tard : il est optimisé pour la démonstration, pas pour la durée. Il produit le bon résultat dans le cas heureux, il se lit d’un seul tenant, et il se dégrade dès qu’il faut le modifier, l’étendre ou le transmettre. Le fondateur qui a construit vite se retrouve alors avec un produit qui marche et un code que personne ne veut reprendre.
La tentation, là encore, est de tout réécrire proprement. Mais un code qui a des utilisateurs et qui rapporte ne se jette pas : il se reprend. La question de ce qu’on garde et ce qu’on réécrit lors d’une reprise se pose d’ailleurs rarement en ces termes : le plus souvent, on garde et on améliore. Le refactoring, c’est précisément cela : transformer un code qui fonctionne en un code que l’on peut modifier sans peur, sans changer ce qu’il fait. C’est un travail ingrat, invisible pour l’utilisateur, et pourtant décisif pour la survie du produit au-delà de son créateur.
Cet article explique par où commencer quand on refactore du code généré par IA : poser un filet de tests d’abord, repérer les points chauds ensuite, puis nommer, structurer et simplifier dans un ordre qui ne casse rien à chaque étape.
Poser le filet avant de toucher au code
La règle première du refactoring s’applique avec encore plus de force au code généré par IA : on ne modifie pas un code sans filet si l’on ne peut pas vérifier qu’il fait encore ce qu’il faisait avant. Or le code généré par IA est précisément celui qui a le moins de tests, parce que la vitesse de production n’en prévoyait pas (nous revenons sur ce point dans développer avec l’IA ne dispense pas de tests). La première étape consiste donc à poser des tests sur le comportement existant, avant toute modification.
Ces tests s’appellent des tests de caractérisation : ils ne vérifient pas ce que le code devrait faire, mais ce qu’il fait réellement. On exécute le module, on observe ses sorties sur des entrées représentatives, et on fige ces sorties comme référence, avec les outils habituels de l’écosystème : Vitest ou Jest pour la logique, Playwright pour les parcours de bout en bout. Claude Code ou Cursor accélèrent l’écriture de ces tests, à condition que chaque test soit relu. L’objectif n’est pas de valider que le comportement est correct, mais de le rendre observable et reproductible, pour que toute modification ultérieure soit détectée si elle le change.
Ce filet n’a pas besoin d’être exhaustif, mais il doit tourner à chaque modification, dans une CI comme GitHub Actions. Il doit couvrir les chemins critiques : ce qui rapporte de l’argent, ce qui touche aux données, ce qui casse le plus souvent. Quelques dizaines de tests bien placés suffisent pour que le refactoring cesse d’être un pari et devienne un travail contrôlé.
Repérer les points chauds avant de tout nettoyer
Une fois le filet posé, il faut résister à l’envie de tout nettoyer d’un coup. Le refactoring se joue sur les points chauds, pas sur le code dans son ensemble. Un point chaud, c’est un endroit que l’on modifie souvent, que l’on comprend mal, et où chaque changement casse quelque chose. Ce sont ces endroits qui coûtent cher, et c’est sur eux que le travail doit se concentrer.
Les points chauds se repèrent par l’historique des modifications et par l’usage : les fichiers les plus touchés, les fonctions les plus longues, les modules sans séparation claire des responsabilités. Un outil de mesure simple suffit pour les classer : l’historique Git donne les fichiers les plus modifiés, un analyseur comme SonarQube la complexité et la duplication. On ne refactore pas ce qui est stable et inoffensif, aussi laid soit-il ; on refactore ce qui résiste et qui revient sans cesse dans les incidents.
Cette focalisation change l’échelle du chantier. Au lieu d’un refactoring général qui dure des mois et dont on ne voit jamais la fin, on a une liste de points chauds, chacun traitable en quelques jours, chacun livrable et vérifiable. C’est ce découpage qui rend le travail faisable sans arrêter le développement, et c’est le principe de la méthode de refactoring incrémentale.
Nommer et structurer avant d’optimiser
Le défaut le plus courant du code généré par IA n’est pas la lenteur, c’est l’illisibilité : des noms de variables sans signification, des fonctions qui font trop de choses à la fois, des responsabilités mélangées. Un développeur qui arrive sur ce code ne peut pas le comprendre, donc il ne peut pas le modifier sans risque, donc il refuse. Le premier chantier de refactoring est donc la lisibilité, pas la performance.
Nommer correctement est l’intervention au meilleur rapport coût-bénéfice qui soit. Renommer une variable, une fonction, un module, pour que son nom dise ce qu’elle fait, ne change rien au comportement et transforme la compréhension du code entier. Vient ensuite la structuration : découper les fonctions trop longues, séparer les responsabilités, regrouper ce qui va ensemble. Chaque découpage est vérifié par le filet de tests posé au début. Sur un projet Next.js ou React sorti de Lovable, Bolt ou v0, activer le mode strict de TypeScript et un linter comme ESLint fait aussi apparaître une bonne partie des incohérences.
Il faut ici un mot sur la documentation : dans un code généré par IA, documenter ne consiste pas à décrire ce que le code fait, que l’on peut lire, mais à expliquer pourquoi il le fait. Les choix, les contraintes, les cas limites que l’assistant n’a pas documentés, et que seul le fondateur connaît. C’est cette documentation-là qui rend le code transmissible.
Simplifier et supprimer la duplication
Une fois le code lisible, on peut s’attaquer à la duplication, l’autre fléau du code généré par IA. Un assistant qui produit vite a tendance à recopier des blocs entiers avec de légères variations, car il ne garde pas la mémoire d’une fonction déjà écrite. Cette duplication est sournoise : elle fonctionne, mais chaque correction doit être reportée à la main dans tous les exemplaires, et l’on en oublie toujours un.
La suppression de la duplication consiste à extraire le motif commun dans une fonction unique, et à faire appeler cette fonction par les anciens exemplaires. Là encore, le filet de tests garantit que l’extraction n’a rien changé au comportement. C’est un travail mécanique en apparence, mais il simplifie durablement la maintenance, car une règle ne se corrige plus qu’à un seul endroit.
Il faut toutefois savoir s’arrêter. La duplication n’est pas toujours un mal : deux blocs qui se ressemblent aujourd’hui mais qui divergent demain gagnent parfois à rester séparés. Le critère est la probabilité qu’ils évoluent ensemble. S’ils doivent changer de concert, on factorise ; s’ils sont appelés à diverger, on les laisse. Le refactoring n’est pas une croisade contre la duplication, c’est une discipline contre le coût de maintenance.
Passer à l’action : rendre votre code reprenable
Refactorer du code généré par IA demande du temps et de la méthode, deux choses que les équipes qui ont lancé vite n’ont pas en réserve. L’ordre décrit ici reste le même quel que soit l’outil d’origine, Lovable, Bolt, v0, Cursor ou Claude Code : filet de tests, cartographie des points chauds, noms et structures, puis duplication.
Le plus difficile n’est pas technique, c’est de tenir cet ordre quand le produit continue d’évoluer et que les demandes des utilisateurs arrivent en parallèle. C’est là qu’un regard extérieur aide : il ne connaît pas l’histoire du code, donc il voit tout de suite ce qui empêche un nouveau développeur de s’y retrouver.
Si votre produit en est à ce stade, c’est exactement ce qu’on traite dans la reprise de produits construits avec l’IA : l’Audit de reprise à 750 € pour cartographier le code et les risques, puis un refactoring par étapes, sans arrêter la production, qui vous laisse un code que l’on peut modifier sans peur.
