L'IA a divisé par 10 le coût du refacto. Pas la nécessité de refactorer

Un jour et demi. 50 $ de tokens. C'est ce que m'aura coûté un refacto structurant sur toute la partie tracking d'une app mobile. Dans le monde d'avant 2026, ce même chantier, je ne l'aurais très probablement jamais lancé : trop long à corriger, compliqué à légitimer auprès des parties prenantes, et en étant honnête avec moi-même, aucune envie de me lancer dans quelque chose dont je n'étais même pas certain du retour sur investissement.

Après quelques mois passés à développer cette app avec des agents IA, une intuition s'ancre solidement : le coût d'un refacto structurel vient de s'effondrer. Ce qui pose une question de fond, à laquelle je ne suis pas certain d'avoir la réponse : est-ce que ça veut dire qu'on peut se permettre de moins bien concevoir au départ, quitte à corriger le tir bien plus tard ? Ou est-ce qu'au contraire, ça ne change rien à la nécessité de traiter sa dette technique au fil de l'eau ?

Retour d'expérience sur ce refacto. Ce que j'ai testé, ce qui a marché, ce qui a foiré. Et surtout les convictions que ça m'a permis d'ancrer pour la suite.

Le contexte

Laissez-moi vous planter le décor. Application mobile B2C, développée dès le départ avec l'aide d'agents IA. Et comme dans beaucoup d'apps B2C, le tracking est un chantier prioritaire. Sauf qu'en l'occurrence le plan de taggage marketing est particulièrement costaud : trois SDK analytics à alimenter (Firebase, AppsFlyer, Batch), avec des périmètres qui se recoupent en partie mais qui divergent sur suffisamment de points pour interdire tout mapping direct. Pour une dizaine d’écrans, il y a une vingtaine d'events et jusqu'à quarante properties par event.

Même avec l’aide des agents, en incluant les allers-retours avec le marketing, cela m’aura pris 4 longues et pénibles semaines. Mais, ça y est, tout est validé fonctionnellement à 100 % ✅.

Sauf que côté code, ça commence à piquer sérieusement. L'archi générale que j’avais en tête dès le premier jour tient la route (une interface AnalyticsTracker, trois implémentations, un composite pour cacher le passe-plat aux écrans). Le vrai problème est ailleurs : mon modèle de tracking, que je souhaitais placer dans le domaine pour l'abstraire des spécificités des SDK, a en réalité été pensé Firebase-first, et je ne l'ai jamais réajusté quand les deux autres SDK sont arrivés. Aussi, pour rattraper le coup dans les implémentations des deux autres SDK, je me suis retrouvé à bricoler une mécanique de white-list/black-list franchement illisible. Résultat : je serais bien incapable d'expliquer proprement à un futur dev (ou encore plus probablement à de futurs agents) comment ajouter un event.

Bref, un beau smell comme on les aime. Exactement le genre de dette que, dans le monde d'avant, j'aurais assumée en silence encore quelques mois. Sauf qu'on est en 2026.

Quand l'IA pointe une dette que je voulais cacher

J'avais déjà eu l'occasion, quelques mois plus tôt, de refactorer un gros pan de l'app pour repenser mon architecture MVVM. Et j'avais pu constater qu'un refacto structurant devenait beaucoup plus envisageable avec une armée d'agents prête à faire le sale boulot. La question n'était donc plus "est-ce que je m'y mets ?", mais plutôt "comment je m'y prends ?".

Première étape : demander un audit. Moi qui d'habitude reste sur Claude Sonnet 4.6, je décide pour l'occasion de cramer davantage de tokens en sollicitant Opus 4.7. La consigne est simple :

Regarde-moi tout le code de tracking, sachant qu'il est validé fonctionnellement à 100 %. Dis-moi ce que tu changerais, dans l'ordre de valeur décroissante. J'ai déjà mon idée, mais j'attends la tienne d'abord.

Et sa réponse me prend à contre-pied. Ce qu'il remonte en priorité, ce n'est pas mon problème de modèle domain biaisé, c'est le fait que 50 % du code de certains écrans est dédié au tracking, et qu'il faut absolument sortir tout ça dans des hooks dédiés. Un problème que j'avais vu assez vite, mais que j'avais assumé jusque-là. Et qui, je l’avoue, au moment de solliciter l’audit n’était plus dans mes priorités. Le reste de ses retours pointe une série de bugs potentiels et de duplications de code que je n'avais pas vus. Mais sur mon problème principal, rien.

Du coup je lui donne ma lecture, je lui demande un plan d'implémentation découpé en étapes, et je bascule ensuite sur Sonnet pour les exécuter séquentiellement, avec un nouveau contexte à chaque étape. Cette pratique que j’utilise dorénavant en permanence a pour moi 2 avantages cruciaux :

  • Avec un contexte le plus léger possible, et une demande très scopée, Claude semble bien plus enclin à respecter mes règles et mes consignes, sans produire de code “ésotérique”.
  • Je consomme moins de tokens que quand je fais tout dans une seule et même fenêtre de contexte qui ne cesse de s’accroître.

Ne laissez jamais une IA valider son propre refacto

Avant de me lancer, un sacré truc qui m'irrite : tout est validé fonctionnellement à 100 %, et là, je m'apprête à tout chambouler… J'ai bien des tests unitaires un peu partout, mais aucun vrai filet qui me garantit que l'intégration reste OK après le refacto.

Opus me suggère deux choses, aussi mauvaises l'une que l'autre. La première : intégrer l'excel du plan de taggage comme source de vérité pour qu'il puisse s'y référer. Oui, mais non. Outre le fait que je ne sais pas du tout comment il s’en serait servi, cet excel est aujourd'hui moins fiable que mon implémentation. Il est truffé de commentaires expliquant que ce qui a été fait diverge de ce qui était initialement prévu, et que c’est OK pour autant. La seconde : passer moi-même sur tous les écrans, ajouter des logs, et lui refiler les logs pour vérification. Amateur. Toujours non.

En insistant sur mon besoin de mettre en place un équivalent de tests d’intégration, Claude me fait découvrir un pattern de test que je ne connaissais pas, ne venant pas du monde Jest : les tests snapshot. Le principe est basique : le test photographie la sortie d'une fonction à la première exécution, la sauvegarde dans un fichier .snap, et compare à chaque exécution suivante. La moindre divergence casse le test. Pile ce qu'il me faut : peu importe comment le code sous-jacent est réorganisé, je veux juste garantir que les appels aux SDK produisent exactement la même chose qu'avant.

Le refacto peut donc commencer.

Les 3 pièges de l'IA (et comment je les ai contournés)

Ce sont donc une succession de refactos ciblés, chacun couvert par ses snapshots, qui vont permettre mon “grand refacto”. Sur le papier, plutôt propre. Dans la pratique, trois observations m'ont surpris.

1. Claude, ce coquin…

Plusieurs fois, en cours de route, j'ai constaté qu'il modifiait la valeur du snapshot quand il voyait que les tests étaient au rouge. Bien tenté. Après quelques remontrances et une précision qui me paraissait pourtant évidente (“ne touche JAMAIS à un snapshot sans me demander”), il n'a plus recommencé. Cela implique donc une vraie rigueur avant de leur laisser la main sur ce type de refacto : il faut piocher dans les outils déterministes classiques et surtout ne jamais laisser l'agent en position de juge et partie sur ses propres modifications.

2. La pollution silencieuse

En extrayant la logique de tracking dans des hooks dédiés, Claude en a profité pour glisser dans ces mêmes hooks du code qui n'avait rien à voir avec le tracking. Simplement car c’était le plus court chemin pour lui. Il a fallu lui expliciter qu'un hook useXxxTracking ne devait contenir que du tracking. Rien d'autre. C'est le genre d'évidence qu'on n'a pas l'idée de formuler quand on discute avec "un pair" apparemment si pertinent. Et pourtant, l’expérience m’a montré qu’il le faut.

3. L'absence totale de cohérence inter-fichiers

C'est ce point-là qui m'a le plus interpellé. Mon architecture ressemble jusque-là à une variante de MVVM : chaque écran consomme son ViewModel, qui centralise les appels aux repositories et aux stores. Simple, rien d'exotique. En sortant le tracking dans des hooks dédiés, Claude a produit quatre schémas différents selon les écrans : parfois le hook reçoit ses données en paramètres depuis l'écran, parfois il importe le ViewModel, parfois c'est le ViewModel qui importe le hook, parfois le hook attaque directement les stores. Encore une fois la solution la plus économe pour lui, sans jamais chercher la cohérence globale.

C'était crédule de ma part d'imaginer qu'un agent devinerait ma préférence. Mais ça m'a forcé à faire quelque chose que je n'avais jamais formalisé auparavant : écrire noir sur blanc les invariants d'architecture que je voulais voir respectés. En l'occurrence : le hook de tracking et le ViewModel doivent être totalement isolés l'un de l'autre, tous deux consommés côte à côte depuis l'écran, avec un flux de données ViewModel → screen → tracking hook. Un fichier de règles conditionnelles, activées automatiquement quand Claude touche à un de ces fichiers, et à partir de là plus une seule erreur.

Un insight que je crois important pour n'importe quelle équipe qui laisse un agent refactorer : ce qui n'est pas écrit n'existe pas. Les conventions d'archi qui n'étaient qu'un "nice to have" pour l'onboarding humain sont donc devenues des "must have" pour piloter les agents.

Ce que ça coûte, ce que j’en retiens

Bilan chiffré, donc : 1,5 jour de mon temps de dev senior, 50 $ de tokens. Un chantier que j'aurais estimé à 1 ou 2 semaines dans le monde d'avant, soit un facteur 5 à 10 sur le temps humain. Je suis allé m'excuser d'avance auprès du marketing pour leur redemander une recette complète, mais à deux petites coquilles près, tout était encore fonctionnellement bon ✅.

Cette journée et demie était éreintante. Pas tant à cause du volume de code modifié par les agents, mais à cause de la nature même de la relecture : il m'a fallu une très grande concentration pour repérer la ligne foireuse noyée dans 99 % de code correct. Et c'est là que je bénis mes années d'expérience à faire de la code review, celles qui m'ont appris à détecter machinalement "le petit truc bizarre" en un coup d'œil. J'ai franchement du mal à imaginer que j'en aurais été capable au début de ma carrière.

Ce refacto s'inscrivait dans ma première mission "full IA", dans laquelle j'ai fait des erreurs que je ne referai plus, mais qui ont eu le mérite d'ancrer quelques convictions.

Oui, les agents permettent d'absorber de la dette technique dans des proportions inenvisageables jusqu'alors. Non, ce n'est ni magique ni gratuit : la méthode, les filets de sécurité et l'expérience de code review restent absolument indispensables, sinon on détruit ce qui marche. L'IA agentique ne dispense en rien de continuer à traiter sa qualité logicielle. Elle rebat juste les cartes de quand on peut se le permettre.

Une réserve avant de généraliser trop vite : ce REX porte sur un périmètre bien délimité, le tracking d'une app mobile d’une dizaine d’écrans, un dev seul, une codebase encore jeune. Le facteur 5 à 10 sur le temps ne se transpose pas mécaniquement à un legacy de 500k lignes de code maintenu par 15 devs. Mais l'insight de fond, à savoir que le seuil de tolérance à la dette structurelle a bougé, me paraît, lui, transposable partout.

Mon refacto tracking a été réalisé bien trop tard, et c'est ce qui l'a rendu si énergivore, pour moi comme pour mes agents. Avec le recul : dès l'arrivée du deuxième SDK, la whitelist/blacklist que je sentais déjà ne pas scaler m'aurait suffi comme signal. Deux heures de refacto à ce moment-là, plutôt qu’un jour et demi un mois plus tard.

Si je fais un parallèle avec le monde d'avant, le TDD me permettait de faire des petits refactos tout au long de mes journées, et au bout d'une dizaine de jours, je commençais à entrapercevoir des problèmes de conception plus profonds, que je corrigeais alors dans la foulée. Cette "dizaine de jours", j'ai constaté que c'est le temps nécessaire à mon cerveau pour bien maîtriser ce qui fonctionne et ce qui est perfectible dans le code que je produis. Ce temps n'a pas changé : c'est le même. Être armé d'une flopée d'agents et produire 3 ou 4 fois plus de code dans le même intervalle n'y change rien. Ma règle post-2026 : continuer à refactorer au fil de l'eau, tous les 10 jours, comme avant. L'IA a divisé par 10 le coût d'un gros refacto structurel, mais elle n'a pas changé d'un iota la nécessité de refactorer petit et souvent**.**