Les erreurs classiques du code généré par IA (et comment les corriger)
Filtres côté frontend, une route par champ, l'abstraction CRUD trop générique. Trois erreurs qu'on retrouve dans presque toutes les codebases early-stage, et le correctif de chacune.
Le code généré par IA reproduit les mêmes erreurs que le code écrit par un développeur junior, avec plus d'assurance et beaucoup plus vite. Trois reviennent dans presque toutes les codebases early-stage qu'on ouvre : le filtrage fait côté navigateur, une route d'API par champ à modifier, et le helper générique censé gérer tous les cas. Aucune des trois ne casse quoi que ce soit en démo, et c'est exactement pour ça qu'elles survivent jusqu'à la feature #30.
Ces erreurs sont dans notre style guide depuis des années, section « les erreurs qu'on voit beaucoup trop souvent ». Elles sont antérieures à Claude Code. Ce qui a changé, c'est la vitesse à laquelle elles entrent dans un repo. Un modèle génère la version fautive en quinze secondes, avec des noms de variables corrects et des commentaires propres. Rien dans le résultat ne signale le problème.
1. Les filtres côté frontend
Le pattern : l'API renvoie la collection complète, le navigateur filtre, l'écran affiche dix lignes. Ça marche parfaitement avec les cinquante enregistrements de votre base de développement.
Demandez « une liste avec une recherche et des filtres » à un agent, et vous obtiendrez souvent un GET /items suivi d'un .filter() dans le composant. C'est la solution qui demande le moins de contexte : le modèle ne connaît pas votre volumétrie réelle, et le code client est plus facile à écrire que la requête équivalente.
Ce qui casse ensuite n'est pas seulement la performance. La pagination ment, parce qu'elle pagine ce que le serveur a envoyé et pas ce que l'utilisateur voit. Les compteurs mentent pour la même raison. Le jour où la table passe à 40 000 lignes, vous ne découvrez pas un ralentissement progressif, vous découvrez un onglet qui gèle.
Ce qu'on cherche dans un repo : les appels d'API sans paramètre de requête, les .filter() ou .sort() appliqués à une réponse réseau brute, et les endpoints de liste qui n'acceptent ni limit ni offset.
Le correctif : le filtre vit côté serveur. Les critères passent en paramètres, la base fait le travail, la réponse contient la page demandée et le total. C'est une journée de travail sur un repo jeune. C'est un chantier de plusieurs semaines une fois que douze écrans ont pris l'habitude de recevoir la collection entière.
2. Une route par champ à modifier
POST /users/language. Puis POST /users/name. Puis POST /users/avatar. Chaque route est courte, lisible, testable isolément. Quarante routes plus tard, personne ne sait plus où un champ est modifié, ni qui a le droit de le modifier.
C'est le pattern le plus caractéristique du développement assisté par IA, parce qu'il vient d'une bonne pratique de prompt. Vous demandez une chose à la fois, le modèle vous donne exactement cette chose, correctement. Il ne recule pas d'un pas pour constater qu'il vient d'écrire la trente-neuvième variante de la même opération.
Le vrai coût est sur les permissions. Avec quarante routes, la règle « un utilisateur ne peut pas changer son propre rôle » doit être écrite quarante fois, ou plutôt : elle est écrite trente-huit fois. Les deux oublis sont invisibles jusqu'à ce qu'ils ne le soient plus.
Ce qu'on cherche : plus de trois routes d'écriture sur la même ressource, des noms de routes qui contiennent un nom de champ, et des contrôles d'autorisation dupliqués d'un handler à l'autre avec de légères variations.
Le correctif : un PUT propre sur la ressource, avec une liste explicite des champs modifiables et un contrôle unique sur qui peut toucher quoi. La logique d'autorisation existe une fois, à un endroit qu'on peut lire.
3. L'abstraction CRUD géniale
Le helper générique qui gère « tous les cas ». Une fonction, un objet de configuration, et vos huit ressources sont servies. Sur le moment, c'est la plus belle partie du repo.
Il gère tous les cas pendant trois semaines. Puis les commandes ont besoin d'une vérification de stock avant écriture. Vous ajoutez un flag. Puis les factures ne doivent jamais être supprimées, seulement archivées. Vous ajoutez un deuxième flag. Six mois plus tard, l'abstraction est devenue un langage privé que vous seul comprenez, avec onze options booléennes et un comportement par défaut que personne n'ose changer.
Une IA écrit très bien ce genre d'abstraction, parce qu'un helper générique est un exercice de code sans ambiguïté. Les cas particuliers, eux, n'existent pas encore au moment où le code est généré. Ils appartiennent à votre métier, pas au repo.
Ce qu'on cherche : les fonctions dont la signature contient un objet d'options avec plus de quatre clés, les paramètres booléens qui changent le comportement de la fonction, et les couches génériques écrites avant le troisième usage réel.
Le correctif tient en une règle de séquence : trois usages avant d'abstraire. Les deux premiers restent dupliqués, volontairement. La duplication est visible et se corrige. Une mauvaise abstraction se propage et se défend toute seule.
Le point commun
Rien de tout ça ne se voit en démo. Le produit répond, les écrans s'affichent, la vidéo de présentation est bonne. Tout se paie à la feature #30, sous une forme que les fondateurs décrivent tous de la même façon : chaque nouvelle feature prend plus de temps que la précédente.
C'est pour ça qu'on classe ce qu'on trouve selon l'Expandable Core, notre registre des surfaces critiques : modèle de données, authentification, contrats d'API, points d'intégration, chemins de déploiement. Sur ces trois erreurs, la deuxième touche le core presque à chaque fois, parce qu'elle concerne les autorisations. La première et la troisième restent souvent en périphérie, où elles coûtent du temps sans mettre les données en danger. Un audit utile fait cette distinction au lieu de rendre une liste de quatre-vingts remarques.
Trois questions pour vérifier votre repo
- Si ma table principale passait à 50 000 lignes ce soir, quels écrans deviendraient inutilisables ?
- Combien de routes peuvent modifier un utilisateur, et est-ce que la règle sur les rôles est écrite dans toutes ?
- Est-ce que mes helpers génériques ont été écrits avant ou après le troisième cas d'usage réel ?
Trois réponses gênantes ne veulent pas dire que le produit est en danger. Elles veulent dire que la prochaine feature coûtera plus cher que la dernière.
Le Bunker Test, gratuit. Vous nous donnez un accès en lecture seule à votre repo. On revient sous 5 jours ouvrés avec un score de Solidité et de Structure sur 100, vos 3 risques principaux et un correctif que vous pouvez livrer le jour même. Walkthrough de 15 minutes inclus, aucun engagement.
Want to see this approach running on your repo? Send us access and we'll come back with at least 5 concrete risks within 5 business days.