L’IA nous force à écrire du bon code
(bits.logic.inc)- À mesure que les agents IA occupent une place centrale dans l’écriture du code, des bonnes pratiques autrefois « facultatives » comme les tests, la documentation et le typage statique deviennent désormais indispensables
- Une couverture de code à 100 % est exigée, afin que chaque ligne de code soit réellement vérifiée et étayée par des exemples d’exécution
- Une structure de répertoires et un nommage de fichiers clairs facilitent l’exploration de la base de code par les LLM, et favorisent une organisation en petits fichiers
- Des environnements de développement rapides, éphémères et exécutables en parallèle permettent à plusieurs agents de travailler simultanément
- Le maintien d’un écosystème de code fiable pour l’IA repose sur un système de types statiques et des outils automatisés de contrôle qualité
IA et nécessité du « bon code »
- Depuis longtemps, les développeurs considèrent les tests, la documentation, les petits modules et le typage statique comme des critères de bon code, mais dans la pratique ils sont souvent omis
- Or, les agents IA ne sont pas très bons pour remettre eux-mêmes le code en ordre, ce qui rend ces bonnes pratiques indispensables
- Pour empêcher un agent de partir dans la mauvaise direction, il est essentiel de mettre en place des garde-fous clairs et appliqués de façon stricte
- Avec des garde-fous solides, les LLM convergent uniquement vers la bonne trajectoire ; dans un environnement incomplet, ils amplifient les problèmes
Couverture de code à 100 %
- L’équipe impose une couverture de code à 100 %, non seulement pour éviter les bugs, mais surtout pour vérifier le comportement de tout le code écrit par les agents
- Avec 95 % ou 99,99 % de couverture, l’origine du code non testé reste floue, tandis qu’à 100 %, chaque ligne non validée peut être identifiée clairement
- Le rapport de couverture sert de liste des éléments à tester, et le LLM doit impérativement fournir un exemple exécutable lors d’une modification du code
- Cette approche a aussi des effets bénéfiques annexes : suppression du code inatteignable, explicitation des cas limites, amélioration de l’efficacité des revues de code
Espaces de noms et structure des fichiers
- Les agents explorent la base de code via le système de fichiers, si bien que la structure des répertoires et les noms de fichiers jouent un rôle d’interface essentiel
- Un chemin clair comme ./billing/invoices/compute.ts transmet bien plus d’informations que ./utils/helpers.ts
- Il faut privilégier des fichiers petits et bien délimités, afin que le LLM puisse charger l’intégralité du fichier dans son contexte et ainsi éviter une baisse de performance
- Cette structuration permet d’améliorer la vitesse d’exploration et la précision des agents
Des environnements de développement rapides, éphémères et parallélisables
- Au lieu d’un environnement de développement unique, le développement basé sur des agents évolue vers une gestion parallèle de plusieurs processus
- Fast : les procédures de test et de validation doivent s’exécuter rapidement ; l’équipe a optimisé plus de 10 000 assertions pour qu’elles soient terminées en moins d’une minute
- La vitesse est obtenue grâce à une parallélisation poussée, une forte isolation et une couche de cache pour les appels tiers
- Ephemeral : la commande
new-feature <name>permet de créer un nouvel environnement en 1 à 2 secondes, avec configuration automatique et lancement de l’agent- Si une configuration manuelle est nécessaire, la fréquence d’usage chute fortement ; l’automatisation complète est donc essentielle
- Concurrent : pour exécuter simultanément plusieurs environnements de développement, il faut éviter les conflits liés aux ports, à la base de données, au cache, etc.
- Isolation via Docker ou via une configuration fondée sur des variables d’environnement
Système de types de bout en bout et contrôle qualité automatisé
- Il faut automatiser autant de bonnes pratiques que possible afin de réduire la marge de liberté du LLM et de maintenir une qualité constante
- Configurer des linters et formatters automatiques de manière stricte, afin que des corrections automatiques soient appliquées chaque fois que le LLM termine une tâche
- Il est recommandé d’utiliser un langage à typage statique, en s’appuyant notamment sur TypeScript et son système de types puissant
- Des noms de types porteurs de sens comme
UserId,WorkspaceSlug,SignedWebhookPayloadrendent l’intention du code plus explicite
- Des noms de types porteurs de sens comme
- OpenAPI permet de maintenir la cohérence des types entre le frontend et le backend
- Le système de types et les triggers de Postgres garantissent l’intégrité des données, tandis que Kysely génère un client type-safe
- Tous les clients tiers doivent eux aussi disposer de définitions de types précises, ou être utilisés via des wrappers
Conclusion : redéfinir la qualité du code à l’ère de l’IA
- Les agents sont des codeurs infatigables et performants, mais leur niveau dépend de la qualité de l’environnement
- Le « bon code » n’est plus un choix, mais une condition préalable au bon fonctionnement de l’IA
- La mise en place initiale peut sembler lourde, mais il s’agit d’un investissement indispensable longtemps repoussé
- Avec le soutien du leadership technique, il faut viser la construction d’une base de code adaptée à l’IA
1 commentaires
Avis sur Hacker News
Le piège quand on atteint 100 % de couverture, c’est que si le code et les tests sont écrits par le même agent, on peut tomber dans une validation auto-contradictoire
Si l’agent produit une logique erronée et écrit aussi des tests erronés pour la valider, les tests passent mais le code reste faux en pratique
Cette couverture n’a de sens que si les tests sont écrits avant le code, ou si un humain les vérifie rigoureusement
Sinon, cela ne fait que créer une illusion de fiabilité
Le point clé, c’est que plusieurs personnes avec des façons de penser différentes vérifient mutuellement leurs angles morts
Même avec plusieurs modèles d’IA, il faut au final les considérer comme un seul « esprit »
L’idéal, c’est des tests IA sur du code humain, des tests humains sur du code IA, ou encore des revues croisées
Cela dit, même entre humains, les rapports de pouvoir font parfois qu’une seule opinion l’emporte, et l’IA n’empêche pas ça
Il faut insérer volontairement des bugs et vérifier qu’ils échouent bien
Ce n’est pas un problème propre à l’IA, c’est pareil avec les humains
Malgré tout, c’est une bonne chose que grâce à l’IA beaucoup de développeurs apprennent enfin de vrais principes d’ingénierie
SQLite ou les logiciels aéronautiques visent ce niveau
Cela dit, ce n’est pas encore une hypothèse validée académiquement
C’est pour ça qu’il faut valider les scénarios réels d’utilisation avec des tests d’intégration ou des tests automatisés d’interface utilisateur
Des données issues de la production ou des tests en environnement miroir peuvent aussi aider
Avant les LLM, leur mise en place était fastidieuse, mais maintenant le ROI s’est amélioré
Comme le soulignait Uncle Bob, il est important d’investir dans la structuration des tests
Les LLM écrivent volontiers des tests répétitifs, mais si on le leur demande, ils appliquent aussi très bien le principe DRY ou le pattern factory
C’est une méthode que j’essaie depuis hier : j’écris d’abord les spécifications en TLA+/PlusCal, puis je demande à Codex de les implémenter telles quelles
Je lui demande de s’en tenir strictement aux specs, sans créativité
Le code obtenu est laid mais correct, et bien plus rapide à produire que si je le traduisais moi-même
En revanche, quand l’optimisation manque ou que c’est trop brouillon, je corrige certaines parties
En particulier, j’expérimente des structures de données sans verrou, mais Codex essaie encore d’utiliser des verrous, donc je dois le corriger moi-même
Au final, je me concentre sur la logique mathématique et l’IA prend en charge les détails d’implémentation
C’est exactement le flux idéal : « spécifications d’abord, code ensuite »
Je me retrouve dans le billet de Martin Kleppmann
Avec les modèles récents, cela fonctionne réellement bien, et la rentabilité est 10 à 100 fois meilleure
Ça ressemble à une hallucination ou à un argumentaire commercial
Si les bugs en production et le coût de maintenance ne suffisent pas à imposer du bon code, l’IA n’y arrivera pas non plus
Au niveau actuel, l’IA risque au contraire d’aggraver la qualité du code
Alors qu’on n’arrive même pas à se mettre d’accord sur la longueur d’une méthode, il n’existe pas de critère universel de qualité
Même des indicateurs comme la couverture de tests se manipulent facilement et, mal appliqués, peuvent devenir nuisibles
Surtout quand c’est l’IA qui écrit les tests, cela peut donner une fausse impression de confiance
Je pense que le développement logiciel est peut-être la seule application vraiment concrète des LLM
On peut y créer des boucles de feedback bien plus rapides que dans d’autres domaines
On établit un plan avec le LLM, puis quelques heures plus tard on constate l’échec, et le LLM dit : « voilà pourquoi il ne fallait pas faire comme ça »
C’est comme construire une maison aux normes électriques américaines puis découvrir un problème au moment d’installer un lave-vaisselle canadien
Le logiciel était relativement sûr, ce qui permettait le développement anonyme, mais une culture de la signature responsable est en train d’émerger
À l’avenir, seules les personnes qui écrivent du code innovant à haut risque seront peut-être très bien payées
L’IA continue de produire du code absurde, nous le déboguons, puis elle produit encore autre chose d’absurde : on tombe juste dans une boucle infinie
Il suffit simplement que les spécifications de courant soient compatibles pour que ce soit sûr
Cela dit, je trouve rassurant de garder un point de contact avec le réel via les tests unitaires
Moi, j’utilise les LLM pour étudier des circuits RLC et des inerters
Beaucoup de gens sont impressionnés par la vitesse à laquelle les LLM génèrent du code, mais la vitesse ou le volume ne sont pas le goulet d’étranglement de la qualité
La vraie révolution arrivera quand l’IA produira du code plus exact que les humains
La vraie valeur vient du fait de savoir comment le code fonctionne
Dans une réunion remplie d’ingénieurs qui ne font que supposer, le moment le plus précieux est celui où l’un d’eux ouvre le vrai code et le montre
Le « bon code » est peut-être simplement du code optimisé pour la mémoire de travail limitée des humains
Les modèles peuvent voir tout le contexte d’un seul coup, ils n’ont donc pas cette contrainte
Si la fenêtre de contexte devient 100 fois plus grande, ce débat perdra peut-être de son importance
J’ai peur qu’exiger 100 % de couverture d’un LLM fige de mauvaises hypothèses
Mais s’il y a une revue humaine, on peut toujours dire : « c’est faux, supprimons ces tests et réécrivons-les », non ?
On rédige aussi le PRD avec le LLM, comme dans un entretien, afin de clarifier le périmètre et les attentes
Les « best practices » changent selon l’environnement technique
Maintenant qu’écrire du code est devenu plus facile, une couverture à 100 % peut être plus utile aux LLM
Les tests donnent au LLM un objectif clair et rendent les interactions suivantes plus sûres
Chaque test renvoie à d’anciens tickets de bug et garantit que les correctifs restent en place
Si on donne un scénario à un LLM, il produira dans la plupart des cas un code d’une qualité similaire
Contrairement à l’art créatif, le logiciel est une industrie particulièrement adaptée à l’automatisation
En voyant le titre, je pensais que l’article allait expliquer que pour que l’IA soit efficace, il faut que nous écrivions du bon code
En pratique, Claude se trompe souvent face à des noms de variables ambigus ou à du code illogique
Si une variable s’appelle « iteration_count » mais contient une somme, l’IA se fait piéger
Au final, du code propre aide autant l’IA que les humains
Comme l’IA utilise la documentation interne comme ressource d’apprentissage, une documentation à jour est désormais considérée comme indispensable
Avant, c’était une faible priorité, mais aujourd’hui cela affecte directement la qualité du modèle
Cela dit, ce point s’améliorera probablement avec le temps
Cela augmente les chances qu’un LLM produise directement une implémentation correcte
Cet article révèle la compréhension superficielle de l’ingénierie qu’ont les entreprises du prompt
Une couverture à 100 % ne vérifie pas toutes les combinaisons d’entrée
Elle signifie seulement que toutes les lignes ont été exécutées avec quelques exemples
Au final, il faut des preuves formelles, mais leur coût est astronomique et les LLM n’y servent à rien
À l’inverse, bâtir un environnement de développement réactif grâce aux tests pourrait ouvrir un nouvel âge d’or
Si la couverture pose problème, on pourra l’étendre plus tard
Le mieux est de mettre en place dès le départ des tests aussi complets que possible
Il existe déjà de nombreuses tentatives de connexion avec des proof assistants
Même quand les spécifications contiennent quelques erreurs, ils produisent dans la plupart des cas des résultats exploitables