Ce qu'un agent de code fait mal, et ce qu'on met en face

Un agent de code produit vite du code correct. Ses modes d'échec ne sont pas ceux d'un développeur débutant : ils sont plus difficiles à repérer, parce que le résultat est toujours plausible.

Ce qu'un agent de code fait mal, et ce qu'on met en face

Un agent de code écrit vite, connaît les bibliothèques, et produit un résultat qui compile. Ce constat est acquis, et ce n'est pas le sujet intéressant.

Le sujet, c'est la nature de ses erreurs. Elles ne ressemblent pas à celles d'un développeur débutant. Un débutant produit du code qui échoue visiblement. Un agent produit du code plausible, qui échoue dans des conditions qu'il n'a pas envisagées.

Cette différence change la manière de relire, et les garde-fous à mettre en place.

La vérification qui ne vérifie rien

Le mode d'échec le plus insidieux tient en une phrase : l'agent conclut qu'une chose fonctionne à partir d'une observation qui ne le prouve pas.

Un exemple vécu sur notre propre projet. Pour vérifier qu'une couleur était bien compilée dans la feuille de styles, j'avais cherché son code hexadécimal dans le fichier produit. Aucun résultat. J'en ai conclu que la compilation avait échoué.

En réalité, l'outil de compilation écrit les couleurs au format RGB. La couleur était bien présente. Ma vérification était fausse, pas la compilation.

Cette famille d'erreurs revient constamment : une recherche textuelle qui ne trouve rien parce que le motif est mal formé, un test qui passe parce qu'il ne teste pas ce qu'on croit, un compteur qui renvoie zéro parce que la commande a échoué silencieusement.

La parade est simple à énoncer : une vérification doit pouvoir échouer. Si un contrôle renvoie toujours le même résultat quel que soit l'état réel, il ne contrôle rien. Le réflexe utile consiste à vérifier que la vérification détecte bien un cas négatif avant de lui faire confiance.

Le code mort qui s'accumule

Un agent ajoute plus volontiers qu'il ne supprime. Le résultat est une accumulation lente de code inutilisé, qui a une caractéristique désagréable : il paraît actif.

Sur notre plateforme, nous avons trouvé un générateur de données structurées pour les moteurs de recherche, jamais appelé, contenant l'ancien positionnement de l'entreprise et un numéro de téléphone fictif. Il ne nuisait à personne tant qu'il dormait. Le risque était qu'un jour, quelqu'un l'active en le croyant à jour.

Nous avons aussi trouvé une interface de programmation complète pour le téléversement d'images, avec ses routes, son contrôleur et ses tests, qui ne pouvait pas fonctionner : le fichier de routes n'était chargé nulle part, et la bibliothèque d'authentification dont elle dépendait n'était pas installée. Cinq tests échouaient depuis des mois en testant du code inaccessible.

La parade tient en deux gestes. D'abord, chercher les points d'entrée avant de conclure qu'un code est utilisé : une classe peut exister sans être jamais instanciée. Ensuite, traiter un test qui échoue durablement comme une information, pas comme une nuisance. Un test rouge depuis trois mois signale soit un défaut réel, soit du code qui n'aurait pas dû survivre.

La dérive du périmètre

Demandez une correction, obtenez une refonte. C'est un travers connu, et il a une conséquence pratique : la relecture devient difficile parce que le changement utile est noyé dans des modifications de confort.

Le symptôme se mesure : un correctif d'une ligne qui touche quinze fichiers mérite une question. Souvent, quatorze de ces fichiers relèvent d'un nettoyage opportuniste, parfois pertinent, mais qui aurait dû faire l'objet d'un changement séparé.

La parade est de découper. Un changement, une intention. Cela facilite la relecture, et surtout le retour arrière : annuler une correction ne devrait pas annuler trois améliorations sans rapport.

La panne masquée par une correction

Voici le cas le plus coûteux, parce qu'il donne l'illusion du progrès.

Un agent rencontre une erreur, la contourne, et poursuit. Le contournement fonctionne, la tâche s'achève, et le problème initial reste entier, désormais invisible.

Cas typiques : un bloc de gestion d'erreur qui avale une exception au lieu de la traiter, une valeur par défaut qui masque une configuration absente, une condition ajoutée pour éviter un cas plutôt que pour le résoudre.

Le contournement n'est pas toujours mauvais. Ce qui est mauvais, c'est qu'il soit silencieux. La règle que nous appliquons : un contournement doit laisser une trace, sous forme de journal ou de commentaire expliquant ce qui a été évité et pourquoi.

Le contexte manquant

Un agent voit le code, pas l'histoire du projet. Il ignore pourquoi une décision a été prise, quelle contrainte réglementaire pèse sur un module, ou quel incident a motivé une précaution qui paraît superflue.

Cela produit des suggestions techniquement justes et pratiquement inapplicables : simplifier un contrôle redondant qui existe parce qu'un audit l'a demandé, remplacer un composant maison par une bibliothèque plus complète alors que le composant maison existe justement pour éviter cette dépendance.

La parade relève de l'organisation, pas de l'outil : documenter les décisions structurantes là où elles sont visibles. Un commentaire d'une ligne expliquant pourquoi ce contrôle existe vaut mieux qu'une explication répétée à chaque session.

Les garde-fous qui fonctionnent réellement

Quatre dispositifs, par ordre d'efficacité constatée.

Une suite de tests qui protège. C'est le seul garde-fou qui agit sans intervention humaine. Un agent peut casser du code, il ne peut pas rendre un test vert par persuasion. Encore faut-il que la suite soit crédible : nous nous imposons un seuil de couverture de 80 %, non parce que ce serait un bon chiffre dans l'absolu, mais parce qu'il est tenable sans encourager les tests écrits pour la mesure.

Des vérifications automatiques après modification. Formatage, analyse statique, vérification de syntaxe déclenchés à chaque écriture de fichier. L'agent reçoit le retour immédiatement et corrige, au lieu de propager l'erreur.

Le découpage des changements. Un changement relisible est un changement relu. C'est une discipline humaine, pas un outil.

La relecture ciblée. Relire l'intégralité de ce que produit un agent annule son bénéfice. Relire ce qui touche la sécurité, les données, les paiements et les suppressions est indispensable. Ce tri se décide par avance, pas au cas par cas.

Ce qui reste hors de portée

Trois choses ne se délèguent pas, et il vaut mieux le savoir avant de construire un processus dessus.

Juger si le résultat répond au besoin. Un agent produit ce qui a été demandé, pas ce qui était nécessaire. L'écart entre les deux est le cœur du métier.

Arbitrer un compromis. Rapidité contre lisibilité, généricité contre simplicité, dette assumée contre refonte : ces arbitrages dépendent d'un contexte que l'outil n'a pas.

Assumer la responsabilité. Le code publié engage l'organisation qui le publie. Cette responsabilité ne se transfère pas.

Ce qu'il faut retenir

Les erreurs d'un agent de code ne sont pas des erreurs de compétence, ce sont des erreurs de contexte et de vérification. Elles produisent du code plausible, ce qui les rend plus difficiles à repérer qu'un échec franc.

Cinq modes reviennent : la vérification qui ne vérifie rien, le code mort qui s'accumule, la dérive du périmètre, la panne masquée par un contournement silencieux, et l'ignorance de l'histoire du projet.

Face à cela, les garde-fous efficaces sont mécaniques : des tests qui protègent, des vérifications automatiques, des changements découpés. Le jugement, lui, reste entièrement du côté humain, et c'est là qu'il faut concentrer l'attention plutôt que sur une relecture exhaustive qui annulerait le bénéfice.

3 minutes de lecture
Partager :

Articles similaires

Découvrez d'autres actualités qui pourraient vous intéresser