Tous les articles et vidéos

Rétrograder, pas supprimer : le plan de migration qui tient

Demandez à un agent de migrer un module Angular legacy : son plan commence par « supprimer ». Il est faux. Voici celui qui marche, et la revue qui le repère.

Adil Ben Moussa
07 novembre 2026· 5 min
Rétrograder, pas supprimer : le plan de migration qui tient

La partie précédente a donné à l'agent un fichier de tâche pour une nouvelle fonctionnalité. Une migration est plus délicate, car le code est déjà en production. Demandez à un IA de moderniser un module , et il vous rend un plan en trente secondes.

Dans les essais que j'ai vus, ce plan commence par « supprimer ». Voici pourquoi il échoue, quel plan fonctionne, et quelle revue de cinq minutes permet de les distinguer.

Le plan de l'agent, et ses trois points de rupture

Le cas concret, c'est libs/legacy/transfers dans le dépôt de démonstration : un NgModule, un composant avec des *ngIf, des abonnements manuels, des appels à markForCheck() et sa propre table de plafonds de virement. La partie moderne de l'application dispose déjà d'un de , AccountsStore, et des règles métier dans libs/domain.

On demande « migre ça vers les signals », et le plan type compte quatre étapes (l'exercice du vérifie justement celles-là) : supprimer LegacyTransfersModule, convertir le composant sur place, écrire une fonction utilitaire validateTransfer(), et mettre à jour les tests. Sur le papier, c'est propre. Dans les faits, c'est un , et il cède à trois endroits.

Des usages que vous ignorez. Dans une vieille base de code, le code legacy est utilisé à des endroits que l'agent n'a pas cherchés avec  : une route, un lien sur une autre page, un . Supprimez la source, et c'est en production que vous les découvrez.

Aucun point d'arrêt livrable. Convertir sur place, c'est perdre l'ancienne version avant que la nouvelle ne fonctionne. À mi-chemin, rien n'est livrable, et le seul retour possible est un .

Un impossible à relire. Personne ne lit une migration livrée en une seule . La revue se résume à « les tests passent, on livre », alors que ces tests ont été réécrits par le même agent qui a écrit le code.

L'indice est dans la première ligne.

Tout plan de migration qui commence par « supprimer X » est faux.

Rétrograder, pas supprimer

Le plan qui tient compte trois étapes, et chacune peut être livrée seule.

Construire à côté. La nouvelle fonctionnalité va dans sa propre lib, libs/feature/transfers, à côté de l'ancienne. Le module legacy continue de servir la page, sans modification.

Basculer la route. Une fois le nouveau formulaire validé, une seule ligne change dans app.routes.ts. Le module legacy est alors rétrogradé : toujours dans l'arborescence, mais il ne sert plus personne.

# apps/atlas/src/app/app.routes.ts : toute la bascule
- { path: 'transfers', loadChildren: () => import('@atlas/legacy-transfers').then((m) => m.LegacyTransfersModule) },
+ { path: 'transfers', loadChildren: () => import('@atlas/feature-transfers').then((m) => m.transfersRoutes) },

En cas de problème en production, le retour en arrière tient dans le même diff d'une ligne.

Supprimer en dernier. Quand plus rien n'importe la lib legacy, la supprimer retire du code sans rien changer. Dans le dépôt de démonstration, les règles de n'autorisent que l'application à importer une lib type:legacy : aucune lib moderne ne peut donc s'appuyer dessus. Après la suppression, une vérification des types au vert prouve que l'application ne le fait plus non plus. Supprimez avant la bascule, et le compilateur vous arrête aussitôt :

error TS2307: Cannot find module '@atlas/legacy-transfers' or its corresponding type declarations.

C'est la seule suppression qui vaille : celle que le compilateur vérifie pour vous.

Demandez d'abord le plan

Ne demandez pas de code. Demandez le plan, puis confrontez-le aux règles :

Prompt · le plan d'abord

Lis AGENTS.md et tous les fichiers sous libs/legacy/transfers/src. Propose un plan pour migrer le module legacy des virements vers une fonctionnalité standalone, basée sur les signals, qui s'intègre à ce workspace. Uniquement le plan : des étapes numérotées, les fichiers créés, modifiés ou supprimés à chaque étape, et l'étape à laquelle la route /transfers/new/:accountId bascule. N'écris pas de code et ne modifie aucun fichier.

Quand les quatre étapes vues plus haut reviennent, la revue est courte :

  • Supprimer le module d'abord : non. Le module legacy continue de servir /transfers/new/:accountId tant que la nouvelle fonctionnalité n'a pas fait ses preuves. Il part en dernier, dans un changement à part.
  • Convertir sur place : non. On construit à côté, dans libs/feature/transfers, pour avoir toujours quelque chose à livrer.
  • Une fonction utilitaire validateTransfer() : elle duplique des règles qui existent déjà. Le fichier de règles impose de chercher dans libs/domain avec grep avant d'ajouter une valeur magique, et canTransfer() s'y trouve, avec ses messages.
  • Mettre à jour les tests : non. On ne modifie jamais une existante pour faire passer un diff. Si l'une d'elles est fausse, l'agent le signale dans la pull request et s'arrête.

Ensuite, trois fichiers de tâche au lieu d'une seule pull request, chacun avec sa propre limite de taille : figer le comportement du code legacy (tâche 000), construire la nouvelle fonctionnalité à côté et basculer la route (tâche 002), supprimer la lib legacy (tâche 003).

Avec ces fichiers de tâche, le composant que construit l'agent ressemble au reste de la base de code. Dans la référence du dépôt de démonstration, il ne contient que des signals et des computed, et les règles viennent d'un seul appel au domaine, canTransfer(), qui avait déjà ses tests. Aucun abonnement, aucun markForCheck(), aucune table de plafonds.

Le fichier de tâche demande aussi à l'agent de signaler le seul vrai changement de comportement. L'ancienne table ignorait les virements déjà effectués dans la journée ; canTransfer() les compte. La table dupliquée cachait un bug, et la pull request le dit au lieu de le glisser en douce.

Dès lundi

  • Un plan de migration qui commence par « supprimer » : renvoyez-le.
  • Construire à côté, basculer la route, supprimer en dernier.
  • Faites proposer un plan à l'agent avant qu'il ne code, et confrontez-le à vos règles. Cinq minutes.

Exercice : le module 2 du dépôt de démonstration, scènes 1 et 2, avec le module gelé libs/legacy/transfers et les fichiers de tâche. Départ : git switch -c m2/you main. Référence : origin/track1/m2-ngmodule-solution.

Le premier de ces fichiers de tâche, la tâche 000, passe avant tout nouveau code : la partie suivante fige ce que fait aujourd'hui le code legacy.


Parcours 1, partie 4 de la série gratuite qui accompagne le workshop Vite et sûr : l'IA dans votre code Angular.

Partager cet article
Workshop

Vite et sûr : l'IA dans votre code Angular

Laissez des agents écrire de l'Angular sous règles, modernisez le code legacy sans casser la production, et gardez le tout sécurisé, en trois jours, sur un code à l'échelle d'une entreprise.

Voir le programme
À lire ensuite