SECTEUR · LA POSTURE · WILLIAM LEEMANS
La dette générée
Lecture ~7 min
EN CHANTIER Cette section est en cours d’écriture : ce texte est lisible mais pas encore finalisé, son contenu peut évoluer.
La dette technique a toujours eu un garde-fou naturel : la vitesse à laquelle des humains tapent du code. Ce garde-fou vient de sauter.
Un agent dépose de la dette au rythme où il produit des diffs. Si vous la remboursez comme avant, au fil de l’eau, vous ne suivrez pas — c’est arithmétique.
Bonne nouvelle quand même : l’asymétrie qui crée cette dette est aussi celle qui rend son remboursement bon marché.
Pourquoi personne n’a emprunté cette dette ?
Parce que ce n’est pas un emprunt, c’est un résidu de production.
La métaphore de la dette décrit à l’origine une décision. On livre maintenant, on paye plus tard, et quelqu’un a tranché : c’est daté, discutable, parfois même documenté. On savait où était le raccourci, on pouvait planifier son remboursement.
La dette générée, elle, n’a pas d’emprunteur. C’est ce qui se dépose quand on accepte, diff après diff, du code vraisemblable produit sans mémoire du reste. Personne n’a décidé d’avoir quatre variantes du même helper ou trois façons de gérer les erreurs. Chaque diff, pris isolément, était acceptable.
J’aime bien l’image du calcaire. Personne ne l’a versé dans les tuyaux, et un beau jour le débit n’y est plus.
Cette dette ne se voit donc pas dans le diff : elle n’existe que dans la somme, exactement là où la relecture, qui juge un diff à la fois, ne regarde pas.
À quoi ressemble la dette générée ?
À trois espèces bien identifiables, et aucune ne déclenche d’alarme au moment du merge.
- La duplication paraphrasée. L’agent n’a pas de mémoire : chaque session redécouvre le code et réinvente ce qu’elle n’a pas trouvé. Et ce n’est pas du copier-coller, un outil le verrait. C’est de la paraphrase : même logique, forme différente, invisible aux détecteurs. Ensuite chaque copie vit sa vie, et le bug que vous corrigez dans l’une survit tranquillement dans les trois autres.
- Le slop. Toute cette masse plausible que personne n’a demandée : le
catchdécoratif, l’abstraction à usage unique, l’option que rien n’appelle, le commentaire qui paraphrase sa ligne, le helper « au cas où ». Pris un par un, chaque élément se défend — c’est bien pour ça qu’il passe la relecture. Le problème, c’est la masse : du code en plus à lire, une taxe prélevée sur chaque lecture future. Et la machine paye cette taxe aussi, on y revient. - La divergence des conventions. Chaque génération échantillonne une convention vraisemblable. Pas forcément la vôtre, pas forcément celle de la session précédente. Une équipe humaine converge par friction — relectures croisées, habitudes, mémoire partagée. Un agent n’a aucune friction. La session de mardi ignore les choix de lundi, et le dépôt perd peu à peu ce qui le rendait navigable : une seule façon de faire chaque chose.
Pourquoi cette dette s’aggrave toute seule ?
Parce qu’elle prélève un second intérêt, et c’est celui-là qui change tout. La dette classique prélevait ses intérêts sur les humains : compréhension plus lente, modifications plus risquées. Celle-ci en prend un de plus, sur la machine.
« Le contexte est la seule réalité du modèle » l’a posé : le modèle ne connaît de votre projet que ce que son contexte contient. Autrement dit, votre code est son exemple. Un dépôt dupliqué lui enseigne la duplication. Trois idiomes en place rendent un quatrième vraisemblable. Chaque déchet accepté entre dans le contexte des générations suivantes.
Plus de dette produit de pires générations, qui produisent plus de dette. C’est la seule dette qui dégrade l’outil censé aider à la rembourser. Et elle dégrade votre relecture au passage : la passe d’intégration suppose de connaître l’existant, et un existant divergent devient tout simplement inconnaissable.
Ce qui renverse un vieux rapport de force, et c’est l’argument que j’attendais depuis quinze ans : la propreté du code n’est plus une élégance d’artisan à défendre contre les délais. C’est un avantage opérationnel mesurable. Un dépôt cohérent et dense produit de meilleures générations, plus vite, avec moins de contexte.
Entretenir le code, c’est entretenir la machine.
Comment la contenir à la porte ?
En traitant la dette avant le merge, et même avant la génération. C’est le moment le moins cher, et de très loin.
- La passe d’intégration est votre filtre anti-duplication. « Le code s’appuie-t-il sur l’existant ou le réinvente-t-il ? » : c’est la question qui attrape la paraphrase avant qu’elle n’entre. Et exigez la recherche avant la production. Un agent à qui on demande d’inventorier les helpers et les conventions du périmètre avant d’écrire duplique beaucoup moins.
- Encodez le canon là où l’agent le lit. Une convention qui ne vit que dans les têtes ne survit pas aux sessions. Le fichier d’instructions porte les choix non mécanisables. Le lint porte tout ce qui peut faire échouer un build : une règle qui casse la CI ne dépend de l’attention de personne. Et un fichier exemplaire désigné (« fais comme ici ») vaut mieux qu’un paragraphe de style. C’est la même logique que dans « Les tests comme contrat » : la consigne durable est celle qui s’exécute.
- Comptez les lignes nettes comme un coût. L’agent ne paye pas la ligne qu’il ajoute. Vous, si — à chaque lecture, pour toujours. Demandez le diff qui en ajoute le moins, refusez le défensif non motivé. Et gardez le critère de la relecture : un volume de code que vous auriez refusé d’un humain ne devient pas acceptable parce qu’il a coûté trois minutes.
Comment la rembourser ?
Avec l’outil qui l’a produite, et c’est la bonne surprise de cette Étape. La même asymétrie joue dans l’autre sens.
Ce qui rendait le remboursement rare, c’était son coût : des heures d’édition minutieuse, la peur de casser, aucune feature à montrer en face. Or les transformations qui résorbent la dette générée — consolider quatre variantes en une, inliner l’abstraction à usage unique, supprimer les branches mortes, aligner un module sur la convention canonique — sont exactement les tâches où un agent excelle sous harnais : mécaniques, à comportement constant, intégralement jugées par la suite de tests du contrat.
Encore faut-il une discipline, sans quoi vous remplacez une dette par une autre :
- Le refactoring est un geste séparé. La relecture refusait le refactoring opportuniste dans un diff de feature ; la symétrie vaut aussi. Un diff de remboursement ne change pas de comportement, et la suite verte avant et après en est la preuve.
- Programmez le troisième temps. Rouge, vert… puis refactor. C’est le temps que les agents sautent par défaut, parce que le vert ressemble à une fin. Après chaque vert, posez la question en standard : qu’est-ce qui peut être supprimé ou consolidé sans casser la suite ? Un diff net-négatif régulier, c’est un signe de santé du dépôt.
- Remboursez par petites coupures. Une consolidation par session, dans le périmètre que vous touchez déjà : la règle du campeur. Les grandes campagnes de nettoyage attendront d’avoir le harnais qu’elles méritent.
LE CRAFTOMANCER
Ne lancez jamais un agent « améliorer le code » sans harnais ni périmètre. Sans suite verte avant et après, un refactoring généré n’est pas un remboursement : c’est une génération de plus, avec les mêmes propriétés que la première. Plausible, fluide, non vérifiée. Et relisez les remboursements comme le reste. Un agent qui « simplifie » supprimera volontiers le cas limite qui ressemblait à du slop. La frontière entre code mort et code rare, c’est la suite de tests qui la connaît. Si elle ne la connaît pas, personne ne la connaît.
En pratique
- La dette générée n’a pas d’emprunteur et ne se voit pas dans le diff. Surveillez la somme : duplication paraphrasée, slop, conventions qui divergent.
- Votre code est l’exemple du modèle. Chaque déchet accepté dégrade les générations suivantes ; la propreté est un avantage opérationnel, plus seulement une élégance.
- Filtrez à la porte : recherche de l’existant avant génération, passe d’intégration sans complaisance, lignes nettes comptées comme un coût.
- Encodez le canon là où l’agent le lit : le lint pour le mécanisable, le fichier d’instructions et les fichiers exemplaires pour le reste.
- Remboursez sous contrat : refactoring en geste séparé, suite verte avant et après, une consolidation par session plutôt qu’une grande campagne.
- Après chaque vert, exigez le troisième temps : que peut-on supprimer sans casser la suite ? Le diff net-négatif est un signe de santé.
Rembourser localement ne suffit pas si la structure d’ensemble dérive. Reste à décider quelle cohérence défendre, et comment faire tenir une architecture quand chaque session repart de zéro. C’est le sujet de la prochaine Étape : cohérence et architecture.