Le code Claude 'qui marche' est souvent celui qui vous coûte le plus cher
En construisant crmcoaching avec Claude, j'ai vu ces 3 faux amis s'installer dans mes premiers commits bien avant d'avoir mis la discipline en place. Tests verts, ESLint au vert, tout compilait. Et pourtant, chaque nouvelle feature prenait de plus en plus de temps, et modifier un use case existant devenait une navigation dans de la complexité que je n'avais jamais demandée. Pas à cause d'une mauvaise architecture de départ. À cause de 3 patterns que Claude installe silencieusement si on ne lui oppose pas de contraintes explicites.
Voici les 3 patterns que j'ai identifiés sur mes propres commits, les chiffres de leur coût caché, et la règle craft de 2026 qui les neutralise.
Le mythe du "ça compile, c'est bon"
Le constat de base est documenté. Selon le GitClear AI Copilot Code Quality Report 2024, sur les repos qui utilisent intensivement un assistant comme Claude, le ratio de code "copié-collé" a augmenté de 8 fois depuis 2022. La taille moyenne des PR a grossi de 12%. Le temps de revue par PR a baissé de 14%. Concrètement : on écrit plus, on revoit moins, on duplique plus, ce qui correspond exactement au pattern que je décris dans le retour d'expérience sur la code review IA.

Le piège, c'est que tout ça produit du code qui marche. Les tests passent. Les utilisateurs sont contents. ESLint ne crie pas. Le piège n'apparaît pas tout de suite, il apparaît à 3 ou 6 mois, quand vous devez modifier ce code et que vous découvrez le coût réel des choix initiaux.
Ce que j'ai observé : dans les premiers commits de crmcoaching, j'ai compté les fonctions dupliquées à plus de 70% de similarité. Plusieurs paires identifiées, toutes nées du même réflexe Claude : je prompte pour résoudre un problème dans un use case, Claude livre une fonction ressemblant à une qui existe déjà ailleurs dans le repo, je ne vais pas chercher l'existante, je colle la nouvelle. Chaque paire est une dette future : il faudra modifier 2 endroits, faire le diff cognitif, risquer la divergence.
Donald Knuth avait écrit en 1974 que "premature optimization is the root of all evil". Sa formule s'applique aussi à l'abstraction. En 2026, je dirais que "l'abstraction prématurée IA-générée est la racine du mal silencieux". Le mal silencieux, c'est celui qui ne fait pas planter la prod, mais qui ralentit tout le monde sans que personne ne sache pourquoi. C'est aussi ce qu'éclairent les principes Clean Code et software craftsmanship : la qualité ne se voit pas dans le code "qui marche", elle se voit dans le code "qu'on peut modifier sans souffrir".
Faux ami #1 : le copier-coller invisible
C'est le plus fréquent et le plus sous-estimé. Claude répète des fonctions parce que c'est plus statistique que de chercher la fonction existante dans le repo. Le développeur l'accepte parce que le code "marche".
Voici un exemple tiré de mes premiers commits sur crmcoaching. Deux use cases différents, CreateOffer et CreateMentoringCheckoutIntent, écrits à quelques semaines d'écart. Deux fonctions quasi identiques, à 6 fichiers de distance :
// apps/api/src/application/offer/use-cases/create-offer.use-case.ts
function computeMonthlyOfferPrice(
yearlyPrice: number,
fees: number,
): number {
const subtotal = yearlyPrice / 12;
const withFees = subtotal + fees / 12;
return Math.round(withFees * 100) / 100;
}
// apps/api/src/application/mentoring/use-cases/create-mentoring-checkout-intent.use-case.ts
function calculateSubscriptionAmount(
annualAmount: number,
charges: number,
): number {
const base = annualAmount / 12;
const total = base + charges / 12;
return Math.round(total * 100) / 100;
}
Même calcul, deux noms, deux fichiers, deux tests, deux maintenances. Le jour où la logique d'arrondi change (par exemple passer à Math.ceil pour la comptabilité), il faut retrouver les 2 endroits. La dette n'est pas dans le code lui-même, elle est dans la divergence future.
Le contre-pattern craft : avant chaque PR, je demande explicitement à Claude "cherche dans le repo s'il existe déjà une fonction équivalente à ce que tu viens d'écrire, et propose une refacto qui mutualise". Claude fait ce travail très bien si on le lui demande. Il ne le fait jamais spontanément. Et c'est ce réflexe que la Boy Scout Rule impose à chaque PR : on laisse le repo un peu plus propre qu'on l'a trouvé.
Sur le crmcoaching, j'ai aujourd'hui 3 utilitaires de calcul financier dans packages/shared. Sur un repo équivalent IA-heavy non audité, j'en aurais vu 12 à 15. La différence se voit au bout de 12 mois sur le temps de modification.
Faux ami #2 : les abstractions accidentelles
Le deuxième faux ami est plus subtil. Claude adore les interfaces, les classes abstraites, les patterns enterprise. Si vous lui demandez un service de notation de leads, il vous livre, sur un projet NestJS :
// 1. L'interface
export interface LeadScorer {
score(lead: Lead): number;
}
// 2. L'unique implémentation, déjà injectable via @Injectable()
@Injectable()
export class StandardLeadScorer implements LeadScorer {
score(lead: Lead): number {
return lead.interactionCount * 10 + (lead.hasEmail ? 20 : 0);
}
}
// 3. La factory superflue, jamais utilisée par le DI NestJS
export class LeadScorerFactory {
static create(type: string): LeadScorer {
return new StandardLeadScorer();
}
}
Une interface, un @Injectable(), une factory. Pour calculer un score avec 2 opérations. Une seule implémentation concrète. NestJS injecte directement StandardLeadScorer partout. La factory n'est appelée nulle part, sauf dans un test. Aucun besoin d'inversion réel.
Cette sur-ingénierie a un coût concret. À chaque modification, vous passez par 3 fichiers au lieu d'un. Vous écrivez 2 fois plus de tests (le mock de l'interface + le test de l'implémentation). Vous augmentez la charge cognitive pour tout nouveau dev. Et le pire : si le métier demande un jour une vraie variation, vous ne la verrez pas dans le pattern existant parce que tout est déjà "préparé" pour des variations qui n'existent pas.
Le contre-pattern craft, c'est ce que Martin Fowler appelait "Rule of Three" dans Refactoring (2018). Vous ne créez une abstraction qu'à partir du troisième cas concret. Si une fonction n'a qu'une implémentation, c'est une fonction. Pas une interface, pas une factory, pas une classe abstraite. Une fonction. C'est exactement la philosophie défendue dans YAGNI : écrire du code de qualité sans fonctionnalités inutiles et dans le principe KISS appliqué en Java.
Sur le crmcoaching, j'ai 47 use cases sans aucune interface devant eux. Quand j'aurai une vraie variation à modéliser (typiquement après 6 mois de production), je créerai l'interface à partir des 3 cas réels. Pas avant.
Vous voulez repérer ces abstractions accidentelles dans vos PR Claude avant de les merger ?
Refuser une interface inutile ou une factory qui ne sert à rien, ça ne s'apprend pas en lisant un article : ça se travaille sur votre propre code. En mentoring 1:1, je relis vos PR Claude avec vous, je vous montre où l'IA installe de la sur-ingénierie en silence, et vous repartez avec le réflexe YAGNI qui garde votre repo simple. C'est du face à face pour monter en niveau, pas un audit d'équipe.
Faux ami #3 : la sur-ingénierie déguisée
Le troisième faux ami est le plus visible mais le plus accepté. Claude adore livrer des architectures enterprise pour des problèmes triviaux. Vous demandez un handler pour récupérer un client par id, vous recevez :
// QueryHandler + ClientRepositoryPort + EventBusPort + MetricsPort + 2 adapters
@Injectable()
export class GetClientQueryHandler {
constructor(
private readonly clientRepository: ClientRepositoryPort,
private readonly eventBus: EventBusPort,
private readonly metrics: MetricsPort,
) {}
async handle(query: GetClientQuery): Promise<GetClientResult> {
const client = await this.clientRepository.findById(query.clientId);
if (!client) {
throw new ClientNotFoundException(query.clientId);
}
await this.eventBus.publish(new ClientRetrievedEvent(query.clientId));
this.metrics.increment('client.retrieved');
return new GetClientResult(client);
}
}
30 lignes, 4 fichiers, 3 ports, 1 event qui n'est lu par personne. Pour faire prisma.client.findUnique({ where: { id } }). Le coût direct : 4x plus de code à lire pour un nouveau dev. Le coût indirect : la signature de tous les handlers du repo devient ce pattern, donc même les use cases qui justifieraient un découpage simple le portent.
Le contre-pattern, c'est le principe de proportionnalité. Sur le crmcoaching, j'applique cette règle : si l'opération métier tient en une phrase ("lire un client par id"), le code tient en une fonction avec une query Prisma directe. Si elle nécessite 3 étapes coordonnées avec compensation possible, alors un handler peut se justifier. Sinon, c'est de la dette emballée en pattern.
Robert C. Martin, dans Clean Architecture (2017), insiste sur ce point : l'architecture doit suivre la complexité du domaine, pas la précéder. Si vous précédez une complexité qui n'existe pas, vous payez aujourd'hui un coût pour des cas qui ne viendront jamais. C'est aussi ce que rappelle le guide du code lisible en software craftsmanship.
Calcul du vrai coût caché
J'ai mesuré le coût cumulé des 3 faux amis en comparant mes commits de début de projet (avant discipline) avec l'état actuel de crmcoaching. Voici les chiffres, comparés à un repo équivalent où la discipline craft est tenue depuis le début.
| Métrique | Repo IA non audité | Repo IA + discipline craft |
|---|---|---|
| Temps moyen pour ajouter une feature simple | 3,5 jours | 1,2 jour |
| Temps moyen pour modifier une feature existante | 5 jours | 1,8 jour |
| Onboarding d'un nouveau dev (jusqu'à 1ère PR mergée) | 7 semaines | 3 semaines |
| Bugs régression par release | 4-6 | 0-1 |
| Lignes de code pour 1 use case métier | 280 LOC en moyenne | 95 LOC en moyenne |
Le ratio est de 1 à 3 sur la plupart des métriques. Concrètement, sans discipline craft, une équipe de 5 développeurs paie l'équivalent d'1,5 développeur de "taxe complexité" chaque mois, sans valeur ajoutée pour les utilisateurs. À 8 000 euros de coût total mensuel chargé par développeur, c'est 12 000 euros par mois. 144 000 euros par an. Sans qu'aucune feature ne s'ajoute en plus.
C'est le coût silencieux dont je parle quand je dis qu'une codebase IA-heavy non auditée coûte cher, et c'est l'angle business que je détaille dans l'ingénierie logicielle comme avantage concurrentiel. Personne ne le voit dans le P&L, parce que c'est de la vélocité non gagnée, pas une dépense identifiable. Mais il est là.
La règle 2026 : YAGNI + AI
Voici la règle que j'applique sur crmcoaching et que je recommande à toutes les équipes IA-heavy.
Règle 1 : pas d'abstraction sans 3 implémentations réelles. Pas d'interface devant une seule classe. Pas de factory pour 1 type. Pas de port hexagonal devant un module qui ne peut pas être remplacé. La règle des 3 vient de Martin Fowler, elle date des années 2000, elle s'applique parfaitement à 2026.
Règle 2 : avant chaque PR Claude, prompter "cherche les doublons". "Avant de finaliser, vérifie dans le repo s'il existe déjà une fonction qui fait à 80% la même chose. Si oui, refactore pour mutualiser plutôt que dupliquer." Claude le fait très bien quand on lui demande. Il ne le fait jamais spontanément.
Règle 3 : proportionnalité code/domaine. Une opération métier triviale = une fonction. Une opération métier coordonnée = un handler/service. Une opération métier critique avec compensation = un saga ou un pattern de coordination explicite. Le code suit le domaine, pas l'inverse.
Règle 4 : audit des LOC par feature. Je mesure tous les 3 mois le nombre de lignes ajoutées par feature livrée. Si la métrique grimpe de plus de 30%, c'est un signal de sur-ingénierie qui s'installe. C'est la même logique qu'en clean code : on ne contrôle que ce qu'on mesure, et la Definition of Done doit inclure ce signal.
Avec ces 4 règles, le repo crmcoaching tourne à environ 95 LOC par use case métier complet (avec tests + adapter + handler). C'est 3x moins que la moyenne IA-heavy que je vois sur des repos partagés. C'est aussi 3x plus rapide à modifier.
Ce que ça change concrètement
Sur les 3 dernières missions où j'ai installé cette discipline (audit + refacto + grille de review), voici les chiffres avant/après mesurés sur 6 mois.
| Métrique | Avant audit | Après 6 mois |
|---|---|---|
| LOC moyennes par use case | 280 | 110 |
| Fonctions dupliquées dans le repo | 47 | 8 |
| Temps d'onboarding d'un nouveau dev | 7 semaines | 4 semaines |
| Bugs de régression par release | 4-6 | 0-1 |
| Vélocité (story points/sprint) | stable | +28% |
Le gain n'est pas qu'esthétique. La vélocité augmente parce que les développeurs passent moins de temps à naviguer dans la complexité accidentelle, et plus de temps à livrer de la valeur métier. C'est ce que la DORA mesure quand elle parle de throughput et de stability combinés, et c'est précisément le levier qu'une revue de code structurée permet d'enclencher.
Conclusion
Ce que je veux que vous reteniez de cet article, c'est que le code Claude "qui marche" n'est pas une garantie de qualité, c'est une garantie de fonctionnement à T0. La qualité d'un code se mesure à 3 mois, à 6 mois, à 12 mois, sur le coût de modification et le temps d'onboarding. Les 3 faux amis que j'ai décrits (copier-coller, abstractions accidentelles, sur-ingénierie) sont les 3 mécanismes qui font diverger ce coût silencieusement.
La règle YAGNI + AI, ce n'est pas du conservatisme. C'est une discipline économique. Vous économisez aujourd'hui sur du code que vous n'écrivez pas, ce qui réduit la complexité que vous porterez demain. Quand le besoin réel émerge (3 implémentations, vraie variation, vraie criticité), vous créez l'abstraction à ce moment-là, avec la connaissance que la pratique vous a donnée. Pas avant.
Si en lisant ces lignes vous reconnaissez votre situation, vous avez deux choix. Vous pouvez continuer à accepter les PR Claude qui ajoutent 280 LOC pour un use case qui en demande 95. Ou vous pouvez commencer lundi matin, par une grille de 4 règles, et reprendre le contrôle du coût caché de votre codebase.
Pour la suite des patterns craft que je documente chaque semaine sur crmcoaching, retrouvez-moi sur mon profil Instagram kamangacode.
La règle des 3 et le réflexe anti-doublons ne sont que 2 pratiques sur 100
Cet article détaille une poignée de pratiques craft qui neutralisent la sur-ingénierie IA-générée. Le Craft Bundle réunit les 100 pratiques que j'applique pour garder un code simple et modifiable : le référentiel complet de ce que je vérifie sur chaque PR Claude. Ce sont celles que l'IA ne vous apprendra jamais, parce qu'elle ne les a jamais vues coûter cher en production.
FAQ sur les faux amis Claude et le coût caché
1. Comment détecter les doublons dans un repo TypeScript de taille moyenne ?
Trois outils combinés font le travail. D'abord jscpd (Copy-Paste Detector, compatible TS/JS) : sortie rapide des blocs dupliqués sur tout repo, configurable par seuil de tokens. Ensuite SonarQube en mode "duplications" : vue agrégée sur le repo entier. Enfin, des passes Grep ciblées sur les noms de domaine ("calculate", "compute", "process") pour repérer les paires sémantiquement proches mais nommées différemment. L'arsenal complet est détaillé dans les outils d'analyse statique en 2026.
2. La règle des 3 implémentations n'empêche-t-elle pas l'architecture hexagonale ?
Non, parce que l'architecture hexagonale est justifiée par la testabilité, pas par la variation d'implémentation. Vous créez un port pour pouvoir tester avec un fake en mémoire. C'est 1 implémentation réelle + 1 fake de test : ça compte pour 2. Si en plus vous avez une vraie variation (Postgres + Redis, ou SMTP + Brevo), vous êtes à 3. La règle s'applique aux abstractions purement spéculatives, pas à celles qui ont une justification claire et nommée.
3. Comment convaincre une équipe attachée aux patterns enterprise ?
Avec des chiffres sur leur propre repo. Comptez les interfaces qui n'ont qu'une implémentation, comptez les factories appelées une seule fois, comptez les LOC par use case. Présentez ça en revue d'architecture. Personne ne défend une factory inutilisée quand elle apparaît dans un tableau à côté de "temps d'onboarding +4 semaines". Le débat passe du dogme à l'économique.
4. Quel rapport entre ces faux amis et la code review IA ?
Direct. Une revue de code IA-générée doit poser systématiquement 3 questions : "Y a-t-il un doublon ailleurs dans le repo ?", "Cette abstraction est-elle justifiée par 3 cas réels ?", "La complexité de cette solution est-elle proportionnelle au besoin métier ?". Ces 3 questions, en 2 minutes par PR, attrapent 80% des 3 faux amis avant le merge.
5. Le code Claude qui suit cette discipline est-il toujours du code "généré par IA" ?
C'est une bonne question, et la réponse est : oui, mais pas par n'importe quel prompt. Le code Claude bien promté (avec contraintes YAGNI + recherche de doublons + proportionnalité) reste majoritairement du code IA-généré. Le développeur ajoute le contexte et la discipline. Claude exécute. C'est exactement la collaboration qu'on cherche : l'IA fait le travail mécanique, l'humain garde le jugement architectural.
6. Quelle est la métrique unique à suivre pour mesurer ces 3 faux amis ?
Le ratio LOC par story point livré, mesuré sur 3 sprints glissants. Si la métrique monte, vous accumulez de la complexité accidentelle. Si elle baisse à valeur métier équivalente, vous gagnez en simplicité. C'est la métrique méta qui agrège les 3 faux amis sans avoir à les détecter individuellement, et c'est aussi un sujet que je détaille dans l'illusion de productivité IA.
Ressource gratuite : Engineering Maturity Assessment
L'EMA est l'outil que je propose au début de chaque mission. Il mesure la maturité de votre équipe sur plusieurs axes engineering : qualité du code, gouvernance IA, dette technique, vélocité réelle vs vélocité perçue. Quelques minutes pour identifier lequel des 3 faux amis s'installe le plus vite dans votre repo, et où concentrer vos efforts en priorité.


