- Les agents de codage LLM ne parviennent pas à effectuer naturellement des déplacements de code du type copier-coller
- Lors du refactoring de code, leur façon d’écrire le code en s’appuyant sur la mémoire rend difficile de garantir la cohérence
- Ils posent très peu de questions pendant la résolution de problèmes et enchaînent les tentatives spéculatives
- Les développeurs humains clarifient le problème par des questions lorsqu’une situation est ambiguë, mais les LLM répètent leurs essais jusqu’à se heurter à un mur
- À cause de ces caractéristiques, les agents LLM sont perçus non pas comme un remplacement des développeurs humains, mais comme des stagiaires trop sûrs d’eux
Principales limites des agents de codage LLM
On tente récemment d’utiliser les LLM comme outils d’aide au codage, mais certains aspects continuent de sembler peu naturels aux développeurs humains. Cet article explique clairement deux raisons en particulier pour lesquelles les agents de codage LLM sont inconfortables à utiliser
1. Une approche maladroite du déplacement de code et du refactoring
- Les LLM n’effectuent pas réellement l’action « copier-coller »
- Par exemple, lorsqu’on leur demande de refactoriser un gros fichier en plusieurs petits fichiers, le LLM « mémorise » une partie des blocs de code, utilise la commande
deletedans le fichier source, puis écrit le code « retenu en mémoire » dans un nouveau fichier avec la commandewrite - Sans utiliser d’outils de type « cut » ou « paste », toutes les modifications sont reconstruites depuis la mémoire
- Lorsqu’un humain déplace du code, il utilise le copier-coller, ce qui lui donne l’assurance de la correspondance exacte du code ; le LLM, lui, ne la garantit pas
- Jusqu’à présent, seul Codex a parfois montré des tentatives d’imiter le « copier-coller » humain via des commandes
sedouawk, mais cela reste imparfait
- Par exemple, lorsqu’on leur demande de refactoriser un gros fichier en plusieurs petits fichiers, le LLM « mémorise » une partie des blocs de code, utilise la commande
2. Une approche de résolution de problèmes sans questions
- Le processus de résolution de problèmes des LLM est lui aussi très différent de celui des humains
- Les LLM posent rarement des questions et tentent de résoudre les problèmes à partir de nombreuses hypothèses
- Les développeurs humains, face à des changements importants ou à des situations peu claires, vérifient toujours le contexte en posant des questions, selon le principe qu’« il n’y a pas de mauvaise question »
- À l’inverse, les LLM ont tendance à continuer à répéter les tentatives, puis à les intensifier quand un problème survient
- On peut concevoir des prompts de manière excessive pour les inciter à poser des questions, mais sauf dans certains outils comme Roo, ce comportement apparaît rarement
- Fondamentalement, cela peut venir du fait que les entreprises qui développent les LLM ont appliqué du RL (apprentissage par renforcement) centré sur « écrire du code plus vite »
Conclusion
- En raison de ces caractéristiques, les LLM sont encore insuffisants pour remplacer les développeurs humains
- Dans le travail réel, ils montrent plutôt un niveau de « stagiaire excessivement confiant »
- C’est l’une des raisons pour lesquelles l’expérience de collaboration avec un LLM ne paraît pas encore totalement naturelle
1 commentaires
Avis Hacker News
J’ai eu récemment une expérience intéressante. Ce n’était pas lié au code, mais cela aurait très bien pu arriver dans le code ou dans un domaine voisin également (et c’est d’ailleurs arrivé à un collègue). Sur HN, dans une discussion sur la raison pour laquelle une réglementation adoptée il y a 15 ans n’avait pas été davantage généralisée, j’ai émis l’hypothèse qu’à l’époque le niveau technologique n’était pas suffisant pour gérer les cas généraux, et que la réglementation n’avait donc été appliquée qu’aux parties alors faisables (commentaire concerné). Quelques heures plus tard, en revenant sur la discussion, j’ai vu que plusieurs personnes disaient qu’à l’époque déjà, la technologie en question était suffisamment peu coûteuse. J’ai donc demandé à un LLM de trouver des éléments à l’appui sur ce sujet, et il m’a répondu que c’était à cause de limites techniques. J’ai vérifié les sources qu’il citait, et en réalité une seule parlait de limites techniques — et cette source, c’était précisément mon propre commentaire sur HN. En racontant cela au bureau, un collègue m’a dit avoir laissé sur GitHub un avis du type « voici comment X fonctionne sous Windows », puis avoir constaté plus tard, via une recherche Google, qu’une réponse basée sur un LLM reprenait exactement cette affirmation en s’appuyant sur son commentaire. Du coup, j’ai envie de demander au LLM non pas « comment fonctionne X ? », mais plutôt « si quelqu’un te demandait comment fonctionne X, montre-moi une liste de liens qu’on pourrait citer »
Je pense que poser la question ainsi ressemble à un « sorting prompt ». C’est une technique que j’ai apprise dans cet article de Mike Caulfield, et que j’utilise aussi quand j’écris du code (par exemple avec la slash command de Claude Code). Au lieu de simplement demander au LLM de répondre, si on lui confie la recherche, le tri et l’évaluation des sources, on obtient des résultats bien plus précis
La plupart des gens, eux aussi, lorsqu’ils lisent des commentaires sur un sujet donné sur HN, ont tendance à faire confiance en se disant : « cette personne a l’air de s’y connaître, donc je vais provisoirement considérer ça comme vrai ». Comme l’expérience directe ou l’acquisition de connaissances vérifiées coûtent en réalité énormément, je pense que ce type de « savoir bon marché » a malgré tout de la valeur
J’ai déjà essayé d’exiger des justifications d’un LLM, mais jusqu’à présent il ne m’a encore jamais fourni de véritable preuve soutenant réellement ce qu’il avançait
Les LLM inventent parfois même les liens. Il faut un mode de recherche approfondie qui fasse un vrai travail d’investigation, et malgré cela, la manière d’interpréter les informations trouvées dans les liens restera de toute façon influencée par l’entraînement
Récemment, j’ai donné à NotebookLM 6 à 8 sources fiables (spécifications IETF, OpenID et documents complémentaires), puis j’ai posé une question extrêmement simple : « quels formats de credential OID4VP autorise-t-il ? ». Il a répondu correctement à 90 %, mais a ajouté avec aplomb un format totalement aléatoire, sans aucun fondement réel, comme s’il était l’auteur de la spécification. J’ai eu un doute, j’ai vérifié la spec moi-même, et il est immédiatement apparu que c’était faux. Même avec un LLM « bien ancré », on peut dire que la confiance dans les faits s’est complètement effondrée
J’ai récemment demandé à Codex CLI de refactorer un fichier HTML, et au lieu de copier-coller le code comme je l’attendais, le LLM l’a remplacé par du code réécrit de mémoire, en supprimant aussi les commentaires. Il y avait une section avec 40 liens complexes à la suite, et lors de la dernière vérification juste avant déploiement, je les ai testés un par un : le début fonctionnait, mais à partir du milieu, 31 liens renvoyaient tous des 404. Le domaine n’était pas en cause, seuls les chemins d’URL avaient été transformés. En vérifiant les anciennes URL dans le commit git, j’ai vu que le LLM avait « halluciné » et remplacé les chemins par des routes qui n’existaient pas. Ce genre d’erreur discrète et subtile est vraiment dangereux. Il faut absolument faire attention
Je pense que ce dernier point est très important. À cause de ces « erreurs très subtiles et silencieuses », même si un LLM fait le travail aussi bien qu’un humain, voire mieux, ce n’est pas traité de la même manière. En particulier, la code review a traditionnellement été une couche essentielle de prévention des problèmes, mais si le type d’erreurs à vérifier change, les méthodes classiques de revue de code deviennent inefficaces. Avant, lors de grands déplacements de code, on pouvait supposer que le bloc avait été déplacé tel quel et se concentrer davantage sur un niveau plus élevé ; avec un refactoring par LLM, le code « déplacé » peut en réalité être du code « nouveau », résumé ou reconstruit, donc il faut relire chaque caractère. C’est pourquoi je pense qu’ajouter une section « utilisation de l’IA » dans la description d’une Pull Request, afin d’indiquer où et comment l’IA a été utilisée, aide à repérer les zones à examiner en priorité pendant la review
J’ai souvent eu une expérience similaire en posant des questions de code ou de recherche. Le LLM démarre bien, puis à partir du Nième échange, il commence à inventer librement. Avant un voyage récent, j’ai demandé à Gemini une liste de brasseries à jour, et il y a inclus sans problème des lieux déjà fermés ou qui n’avaient été ouverts que temporairement. Je lui ai demandé d’ajouter des liens vers les horaires d’ouverture et de retirer les lieux fermés ; il n’a appliqué la consigne qu’au début de la liste, puis a fait plus loin des modifications sans rapport, voire n’a pas du tout supprimé certains établissements fermés. Pourtant, à chaque fois, il répondait avec assurance qu’il avait fait une recherche parfaite
Ce n’est pas une histoire de code, mais un jour j’ai demandé à un LLM de vérifier uniquement l’orthographe et la grammaire d’une annonce d’événement. Il m’a renvoyé une version légèrement modifiée, mais en décalant discrètement la date d’un jour. Heureusement je m’en suis aperçu et je l’ai corrigé, mais j’en ai tiré la leçon qu’il ne faut pas faire aveuglément confiance, même pour une tâche très simple. Même avec un prompt d’une seule phrase, simple et clair, les LLM peuvent faire des choses impressionnantes, mais parfois se tromper de façon imprévisible sur les choses les plus élémentaires
Il y a 5 minutes, j’ai demandé à Claude d’ajouter uniquement des instructions de debug dans du code, et il a quand même modifié silencieusement une regex. Le diff l’a fait ressortir facilement, mais dans un gros changement ce serait vraiment facile à manquer
Re-vérifier les 40 liens juste avant le déploiement était une décision avisée. En revanche, savoir que tu as poussé sur master après l’exécution de Codex sans faire de
git diff, ça me surprend un peuJe suis d’accord avec la thèse de l’article. Mais, à mon avis, le plus gros problème est que l’agent ne voit qu’une infime partie du dépôt de code. Il ignore les fonctions helper déjà existantes et recrée sans cesse la même chose. En développement UI, comme il ne peut pas comparer l’ensemble de la structure de l’interface, du code incohérent se répète. Au final, c’est à l’humain de fournir le bon contexte : « réfère-toi aux helpers de ce fichier », « fais-le comme cette implémentation », « lis absolument ce document », etc. Si on donne soi-même le bon contexte, on peut fortement augmenter l’utilité de l’agent. À noter qu’un autre problème est sa maladresse à explorer l’arborescence dans un gros monorepo : par exemple, il échoue très souvent à exécuter correctement
npm testdepuis le bon sous-répertoireC’est exactement le problème que je rencontre. J’ai récemment relu environ 200 lignes de nouveau code produit avec Cursor pour implémenter une fonctionnalité, alors qu’en réalité très peu de ce code était nécessaire. Chercher des fonctions déjà présentes dans la bibliothèque utilitaire est vraiment pénible, donc on laisse souvent passer. Il y a 5 ans, ce type de review relevait beaucoup de l’onboarding de juniors, donc il était important de leur montrer où chercher ; aujourd’hui, avec Cursor et autres, la quantité de code augmente, tandis que le développeur connaît souvent la structure mais produit quand même ce genre de code à cause de la politique de l’entreprise, et j’ai l’impression que cela fait baisser la productivité
Le fait d’exécuter des commandes comme
npm testdans un sous-dossier a toujours été un problème. Dans un repo séparé entre un frontend Vite/React et un backend .NET, si une commande npm échoue, l’agent panique, répète plusieurs fois la même chose sans résoudre le problème et ne fait que du troubleshooting inutile. Une fois, j’avais même écrit dansCLAUDE.mdune consigne pour qu’il vérifie toujours d’abord le répertoire courant, mais il continuait aléatoirement à oublier les chemins. J’ai donc ajouté des alias commerun-dev server restartetrun-dev client npm install, utilisables depuis n’importe quel répertoire, puis mis les commandes brutes de type dotnet/npm sur une liste interdite, afin d’obliger l’IA à consulter la documentation du projet et à utiliser les alias. Cette méthode était la plus stable que j’aie trouvée, mais y parvenir m’a coûté beaucoup de temps, d’efforts et de stressJe me dis qu’un grand modèle à large contexte serait utile s’il était exploité via des tool calls. Gemini chat a la capacité d’ingérer un dépôt GitHub entier. Et s’il existait un outil « not-invented-here » qui vérifierait, avant d’écrire une nouvelle fonction, si l’équivalent existe déjà dans la codebase ? Bon, il faudrait sans doute commencer par vérifier si quelqu’un a déjà construit un tel outil
C’est précisément pour cela qu’il faut des documents du type
claude.md. Si l’on veut que nos propres règles soient suivies, il faut impérativement les documenterEn réalité, ce genre de situation est très courant quand un ingénieur senior travaille au quotidien avec des collègues
Je partage complètement le passage cité dans l’article. Je suis d’accord pour dire que les LLM ne remplacent pas les développeurs de haut niveau. À ce stade, quelqu’un de raisonnable ne peut pas soutenir sérieusement le contraire. En revanche, je pense que les développeurs faibles ou moyens sont déjà remplacés. Par exemple, nous avions dans mon organisation trois personnes issues d’un bootcamp de 6 mois, embauchées à une époque où il était très difficile de recruter de bons développeurs. En pratique, elles peinaient même sur des tâches vraiment très simples, et je devais réécrire leur code à chaque review. Puis les outils d’IA se sont améliorés de manière exponentielle et ont dépassé leur niveau. Résultat : deux ont été licenciées, la troisième est partie d’elle-même. Dernièrement, nous recrutons à peine des juniors, et nous ne comptons plus embaucher de profils issus de bootcamps. Autour de moi, c’est pareil, et c’est probablement pour cela que tout le secteur des bootcamps est en train de disparaître. Je ne sais pas si l’IA pourra un jour remplacer même les bons développeurs, mais les données actuelles montrent clairement qu’elle progresse à une vitesse énorme. Les opinions négatives ferment les yeux sur la réalité. Aux débuts des États-Unis, 90 % de la population travaillait dans l’agriculture ; aujourd’hui, c’est à peine 2 %. Pourtant, la production alimentaire et sa diversité sont bien plus grandes. Tout cela est le résultat du progrès technologique. Je pense qu’à un rythme rapide, la même chose peut se reproduire dans l’industrie du développement
Certes, la technologie a augmenté la production alimentaire, mais en réalité il est aussi vrai que la valeur nutritionnelle a baissé et que la toxicité a augmenté
Je me demande quelle est, selon toi, la raison pour laquelle les profils issus de bootcamps n’ont pas réussi à progresser
La leçon la plus importante, c’est peut-être que les LLM restent très fragiles sur des tâches pourtant assez simples sans un grand nombre d’instructions et de supervision. Sur mon petit projet (2,5K lignes), j’ai demandé un refactoring du parseur, et le plan paraissait plausible. J’avais défini des checkpoints étape par étape et je l’ai fait avancer séquentiellement, mais chaque fois que je demandais « l’ancienne structure a-t-elle bien été supprimée ? » ou « a-t-elle bien été remplacée par la nouvelle ? », la réponse était « non, elle est toujours là ». 80 % des tests échouaient, et même en lui indiquant précisément la direction des corrections, il échouait toujours de la même manière sur cette tâche abstraite qu’est le « refactoring ». Au final, il fallait lui écrire des consignes très détaillées du type « telle classe doit changer ceci », sinon cela ne marchait pas. À ce niveau-là, on ne peut pas le faire travailler de manière autonome, et l’intérêt même d’utiliser un LLM s’en trouve réduit
Mon expérience est un peu différente. Mon parseur d’arbres d’expressions en typescript (tinqerjs.org) contient 0 ligne écrite à la main : il a été terminé en 2 semaines (à temps partiel) uniquement avec Codex+Claude, avec en plus des centaines de tests ajoutés, y compris des doublons. J’ai aussi construit un ORM, et avec les LLM j’ai gagné au minimum entre 4x et 10x en temps. J’ai eu besoin de très peu de supervision ; au final, je pense que tout dépend du cas d’usage et du fait d’avoir ou non établi un vrai processus. Les développeurs habitués à tirer parti des LLM construisent chacun leur propre workflow, mais ils ont tous un point commun : ils se concentrent sur les tests, la documentation et la revue de code
Le problème du type « si les instructions de refactoring doivent être trop détaillées, cela ne vaut plus le coup » doit peut-être être reformulé ainsi : « si je découpe bien les étapes de haut niveau et que je lui donne ces consignes, c’est beaucoup plus rapide que de le faire seul »
Cela rejoint bien l’idée mentionnée dans l’article : l’IA ne fait pas du cut-paste, elle supprime puis régénère. Une légère dérive du code au fil du processus est, en pratique, difficile à éviter
Je serais curieux de savoir quel modèle ou quel outil a été utilisé. Même avec Cursor ou Copilot, j’ai souvent ce problème de devoir surveiller constamment ce type de petit refactoring
Les LLM aident clairement sur certains points. Par exemple, ce matin, j’ai corrigé un bug dans un parseur de métadonnées PDF avec l’aide d’un LLM, sans avoir à plonger profondément dans la spécification PDF. Mais dans la plupart des cas, le résultat final est moins efficace que si je le faisais moi-même. Autrefois, quand j’essayais de faire écrire des tests unitaires avec Codex Code, j’avais déjà mis en place différents setups, mais je l’avais sollicité parce que le mocking des données était pénible. Il a fallu 8 essais, des corrections manuelles en plus, et il n’a même pas compris que certaines entités étaient obsolètes et n’étaient plus utilisées par le service. Au final, c’était décevant. Ce n’est pas suffisant pour remplacer complètement un développeur, mais comme Stack Overflow autrefois, je trouve qu’il est très bon pour exposer des connaissances sur des sujets peu familiers et orienter vers une solution
AGENTS.md(ouCLAUDE.md). En conclusion, le débat « l’IA / les LLM peuvent-ils ou non remplacer les développeurs ? » devient lassant. La vraie question est plutôt : « que puis-je faire, moi, pour mieux outiller mon LLM ? »Je ne pense pas que concevoir de façon poussée des « prompts qui amènent à poser des questions plus clairement » soit excessif. Au contraire, le fait d’indiquer dans le prompt « si ce n’est pas clair, pose d’abord des questions » s’est révélé très efficace. Un bon programmeur sait d’instinct si une spécification est complète ou s’il faut des clarifications supplémentaires, et peut donc amener l’IA à poser à l’avance les questions nécessaires
On peut même lui indiquer directement combien de questions poser. Sur des sujets complexes, je demande parfois d’avance 20 à 30 questions, et les résultats sont assez satisfaisants. Il est aussi utile de conserver cette Q&A dans un fichier séparé pour la réutiliser dans une session suivante ou avec un autre agent
Grâce à cette façon de faire, je n’écris plus mes prompts comme avant. Je lance juste l’idée et j’ajoute « pose des questions si nécessaire », et l’IA pointe souvent très bien des aspects auxquels je n’avais pas pensé
Le passage du texte sur le copy-paste m’a inspiré et j’ai ajouté un outil de buffer d’agent dans clippy (un utilitaire macOS). clippy dispose d’un serveur MCP qui interagit avec le presse-papiers système, et ici l’usage d’un buffer privé séparé était plus approprié. Les fonctions ajoutées sont
buffer_copy(copier une plage de lignes précise d’un fichier et la stocker dans le buffer privé),buffer_paste(insérer/remplacer dans le fichier cible les octets exacts présents dans le buffer) etbuffer_list(consulter le contenu du buffer). Par exemple, si l’agent demande « copie les lignes 50 à 75 de auth.py », le serveur n’effectue lui-même que les entrées/sorties de fichiers, sans génération de tokens ni hallucination. Cela n’affecte pas non plus le presse-papiers système. Jusqu’ici, on pouvait aussi copier directement dans le presse-papiers du code généré par l’IA pour le réutiliser. L’objectif principal de clippy est d’améliorerpbcopysur macOS — pour copier le contenu réel de fichiers et pouvoir les coller tels quels depuis le terminal dans Slack ou dans un email. Les utilisateurs macOS de Claude ou d’autres agents compatibles MCP peuvent regarder ici. Installation possible viabrew install neilberkman/clippy/clippyBeaucoup de développeurs ne savent pas bien poser des questions non plus. Ils considèrent beaucoup de choses comme allant de soi et les omettent. En 25 ans de carrière dans le développement, plus de la moitié de mes collègues avaient ce deuxième défaut. J’étais moi-même comme ça pendant la moitié de ma carrière, donc ça me parle d’autant plus
Comme l’affirme le texte principal, « les LLM ne font pas de copy-paste (ou de cut-paste) » : ils se souviennent du code, le suppriment puis le réécrivent, ce qui donne l’impression qu’ils n’émettent à chaque fois qu’une nouvelle commande d’écriture. En refactoring, il n’y a de toute façon pas tant de véritables copy/paste ; en pratique, cela repose bien davantage sur le rappel à partir du contexte. Dans le travail réel, je ne suis même pas certain que les commandes de copy/paste soient particulièrement utiles (du moins, dans mes tests, cela n’a pas fait une grande différence). En revanche, pour les parties répétitives et très gourmandes en contexte, il est plus efficace d’utiliser des outils comme fastmod et de demander à codex ou à claude d’aider à « modifier ceci en masse ». Leur manière d’aborder les problèmes est différente de celle des humains, ce qui peut sembler étrange, mais si on prépare bien le plan et qu’on communique correctement, l’approche elle-même peut beaucoup changer
Un IDE peut renommer instantanément une signature de fonction ou un nom dans plusieurs fichiers, alors qu’un agent LLM met souvent plusieurs minutes à essayer sans parvenir à le faire correctement. Je pense donc que l’utilité d’un vrai support copy/paste est évidente
Le copy/paste sert aussi beaucoup à réduire l’explosion de contexte. Le modèle n’a alors plus besoin de mémoriser le contenu des blocs de code, puisqu’il peut y accéder à tout moment quand nécessaire