---
title: "Code répétitif verbeux"
type: "ai-smell"
slug: "verbose-boilerplate"
url: "http://localhost:3000/fr/ai-smells/verbose-boilerplate.md"
category: "Clarté"
description: "Les assistants IA alourdissent une logique simple de commentaires redondants, de cérémonie défensive et de blocs quasi dupliqués copiés-collés au lieu de réutiliser ou d'extraire le code existant, gonflant le nombre de lignes sans ajouter de valeur."
---
# Code répétitif verbeux

> Les assistants IA alourdissent une logique simple de commentaires redondants, de cérémonie défensive et de blocs quasi dupliqués copiés-collés au lieu de réutiliser ou d'extraire le code existant, gonflant le nombre de lignes sans ajouter de valeur.

## Signs and Symptoms

Un relecteur repère le code répétitif verbeux quand un diff est bien plus long que le problème ne le justifie : chaque ligne est narrée par un commentaire qui se contente de la reformuler, les expressions simples sont enveloppées dans des échelles défensives de `null`/`undefined`, et la même forme de code réapparaît deux ou trois fois au lieu d'être factorisée en un seul helper. L'indice est un fort ratio _commentaire/logique_ et _ligne/comportement_, plus des blocs qui auraient pu tenir en trois lignes de code idiomatique.

```ts
// Fonction pour obtenir le nom complet de l'utilisateur
function getFullName(user: User): string {
  // Vérifie si l'utilisateur est défini
  if (user === null || user === undefined) {
    // Retourne une chaîne vide quand aucun utilisateur n'est fourni
    return "";
  }
  // Récupère le prénom, par défaut chaîne vide
  const firstName = user.firstName ? user.firstName : "";
  // Récupère le nom, par défaut chaîne vide
  const lastName = user.lastName ? user.lastName : "";
  // Concatène le prénom et le nom avec un espace
  const fullName = firstName + " " + lastName;
  // Supprime les espaces et retourne le résultat
  return fullName.trim();
}

```

Trois lignes de comportement enterrées dans \~12 lignes de cérémonie. Dans une vraie PR, on voit typiquement ce _même_ schéma copié-collé en `getDisplayName`, `getLabel` et `getInitials`, chacun réécrivant à la main une logique qu'un util `formatName()` couvre déjà — l'odeur classique du **Code dupliqué**. Autres indices : constructeurs/wrappers vides de transmission, cérémonie `try { ... } catch (e) { throw e }`, et un validateur d'e-mail/URL sur mesure assis à côté du module de validation existant du projet.

## Reasons for the Problem

**Pourquoi les modèles le produisent**

* **Biais de verbosité du token suivant.** Les LLM sont entraînés sur d'énormes volumes de code de tutoriel, de Stack Overflow et de débutant où les commentaires pas à pas et la cérémonie explicite sont la norme. La suite la plus _probable_ est la plus abondamment expliquée, pas la plus concise.
* **Le RLHF récompense l'« apparence de minutie ».** L'ajustement à l'utilité/la verbosité pousse les modèles vers une sortie qui paraît complète et auto-explicative — des commentaires sur chaque ligne, des vérifications défensives partout — que les évaluateurs et les utilisateurs récompensent même quand cela n'apporte aucune valeur.
* **Aucun contexte du dépôt = aucune réutilisation.** Sans la base de code environnante en contexte, le modèle ne peut savoir qu'un util `formatName()` ou `validateEmail()` existe déjà, alors il le réécrit en ligne. C'est exactement la **Sur-spécification** d'OX Security (« des solutions hyper-spécifiques, à usage unique, au lieu de composants généralisables et réutilisables », trouvée dans 80 à 90 % du code IA) et l'**Évitement des refactorings** (80 à 90 %).
* **Génération, pas consolidation.** Les agents émettent du code frais à chaque prompt et ne reviennent jamais dédupliquer. L'analyse 2025 par GitClear de 211 millions de lignes modifiées a constaté que le code copié-collé est passé de 8,3 % (2020) à 12,3 % (2024) et a dépassé pour la première fois les lignes « déplacées » (refactorisées), tandis que les lignes refactorisées chutaient d'environ 24 % à 9,5 % et que les blocs dupliqués de 5 lignes et plus étaient multipliés par \~8.
* **Tout-commenter par défaut.** OX Security a trouvé « des commentaires partout » dans 90 à 100 % du code généré par IA.

**Pourquoi c'est nuisible**

* **Maintenabilité :** plus de surface à lire et à modifier ; les commentaires redondants se désynchronisent du code et deviennent activement trompeurs (odeur des **Commentaires** de Fowler).
* **Correction et sécurité :** les blocs dupliqués signifient qu'un bug ou une vulnérabilité doit être corrigé en N endroits — les **Bugs déjà-vu** d'OX (70 à 80 %). Le code cloné corrèle avec 15 à 50 % de défauts en plus.
* **Charge de revue :** les gros diffs à faible signal masquent les vrais changements et induisent la fatigue du relecteur, si bien que de véritables problèmes passent à travers.
* **Dette technique cumulative :** chaque quasi-doublon rend l'extraction _suivante_ plus difficile, enracinant le problème que le modèle ne peut pas voir d'un fichier à l'autre.

## Treatment

**Tactiques de revue / prompting**

* **Forcez la réutilisation avant la génération :** "Cherche dans la base de code les helpers existants (`formatName`, `validate*`) et réutilise-les ; ne réimplémente pas." Fournissez les utils pertinents en contexte.
* **Budgétez la sortie :** "Garde ceci sous \~15 lignes ; aucun commentaire qui reformule le code — uniquement des commentaires expliquant le _pourquoi_."
* **Faites exécuter les outils par le modèle :** exigez `eslint`/`ruff` et une passe de duplication `jscpd`, et faites-lui rapporter et corriger les violations avant de renvoyer.
* **Demandez le plus petit diff** et une étape de déduplication explicite : "Si un bloc se répète, extrais une seule fonction partagée (Extraire une fonction) et appelle-la."
* **Consolidez en revue :** quand vous voyez la troisième quasi-copie, appliquez **Extraire une fonction**, **Remonter une méthode** ou **Consolider des fragments conditionnels dupliqués**, et **Remplacer un commentaire par du code** (renommez pour que le code se documente lui-même).

**Refactoring (avant → après)**

```ts
// après : commentaires supprimés (le code parle de lui-même), cérémonie réduite,
// util partagé réutilisé au lieu d'être réécrit
function getFullName(user?: User): string {
  return [user?.firstName, user?.lastName].filter(Boolean).join(" ");
}

```

Et éliminez carrément les doublons — si `getDisplayName`/`getLabel` faisaient la même chose, supprimez-les et pointez les appelants vers une seule fonction (**Supprimer le code mort** / **Insérer une fonction**). Remplacez le validateur écrit à la main par l'import du module existant au lieu de garder une copie parallèle.

Règle empirique pour le catalogue : traitez tout bloc IA où les commentaires dépassent les lignes de logique, ou où vous pouvez nommer un helper existant qu'il a ignoré, comme candidat à la suppression-par-réutilisation — le correctif le plus rapide pour le code répétitif est généralement _moins_ de code, pas plus.

## Detected by

- **jscpd** `duplication threshold (--min-tokens / --threshold)` — Détection de copier-coller (seuil min-tokens) (https://github.com/kucherenko/jscpd)
- **SonarQube / SonarCloud** `typescript:S4144` — Les fonctions et méthodes ne doivent pas avoir des implémentations identiques (https://rules.sonarsource.com/typescript/RSPEC-4144/)
- **SonarQube / SonarCloud** `typescript:S1192` — Les littéraux de chaîne ne doivent pas être dupliqués (https://rules.sonarsource.com/typescript/RSPEC-1192/)
- **SonarQube / SonarCloud** `javascript:S1871` — Deux branches d'une structure conditionnelle ne doivent pas avoir exactement la même implémentation (https://rules.sonarsource.com/javascript/RSPEC-1871/)
- **ESLint (eslint-plugin-sonarjs)** `sonarjs/no-identical-functions` — Les fonctions ne doivent pas avoir des implémentations identiques (https://github.com/SonarSource/eslint-plugin-sonarjs/blob/master/docs/rules/no-identical-functions.md)
- **ESLint (eslint-plugin-sonarjs)** `sonarjs/no-duplicate-string` — Les littéraux de chaîne ne doivent pas être dupliqués (https://github.com/SonarSource/eslint-plugin-sonarjs/blob/master/docs/rules/no-duplicate-string.md)
- **ESLint (core)** `no-useless-constructor` — Constructeur vide redondant / code répétitif de transmission (https://eslint.org/docs/latest/rules/no-useless-constructor)
- **ESLint (core)** `max-lines-per-function` — Longueur de fonction excessive/verbeuse (indicateur partiel) (https://eslint.org/docs/latest/rules/max-lines-per-function)
