Les commentaires
Le meilleur commentaire est celui qu'on n'a pas eu à écrire : distinguer les bons commentaires du bruit qui ment.
Rien n'est aussi utile qu'un commentaire placé au bon endroit. Rien n'encombre autant un module qu'un commentaire dogmatique et sans valeur. Rien n'est aussi nuisible qu'un vieux commentaire devenu faux qui propage mensonges et désinformation. Les commentaires ne sont pas, en soi, une bonne chose : ce sont, au mieux, un mal nécessaire.
Si nos langages de programmation étaient assez expressifs, ou si nous étions assez habiles pour les employer afin d'exprimer notre intention, nous n'aurions presque jamais besoin de commentaires. La vérité dérangeante, c'est que chaque commentaire représente un échec à s'exprimer dans le code. Avant d'en écrire un, demandez-vous toujours s'il n'existe pas un moyen de vous faire comprendre autrement. Et lorsque vous devez vraiment en écrire un, prenez le temps de le rendre le meilleur possible.
Les commentaires ne rachètent pas un mauvais code
L'une des motivations les plus fréquentes pour écrire un commentaire est… un mauvais code. On écrit un module, on sait qu'il est confus et désorganisé, on sait que c'est un fouillis. Alors on se dit : « Oh, je ferais mieux de commenter ça ! » Non ! Vous feriez mieux de le nettoyer !
Un code clair et expressif avec peu de commentaires est très supérieur à un code touffu et complexe truffé de commentaires. Plutôt que de passer votre temps à rédiger les commentaires qui expliquent le fouillis que vous avez créé, employez-le à ranger ce fouillis.
Attention
Un commentaire qui justifie du code illisible est un pansement sur une plaie ouverte. Le vrai remède, c'est de rendre le code lisible.
S'exprimer dans le code
Il y a certes des moments où le code se prête mal à l'explication. Hélas, beaucoup de développeurs en ont conclu que le code n'est presque jamais un bon véhicule d'explication. C'est manifestement faux. Que préférez-vous lire ? Ceci :
// ❌ Avant : un commentaire compense un test cryptique
// Vérifie si le salarié a droit aux avantages complets
if ((employee.flags & HOURLY_FLAG) && employee.age > 65) {
// ...
} Ou cela ?
// ✅ Après : le code dit lui-même ce que le commentaire disait
if (employee.isEligibleForFullBenefits()) {
// ...
} Il ne faut que quelques secondes de réflexion pour exprimer la plupart de votre intention dans le code. Dans bien des cas, il suffit de créer une fonction qui dit la même chose que le commentaire que vous alliez écrire.
Les bons commentaires
Certains commentaires sont nécessaires ou bénéfiques. Examinons ceux qui méritent les octets qu'ils consomment. Gardez toutefois à l'esprit que le seul commentaire vraiment bon est celui que vous avez trouvé le moyen de ne pas écrire.
Commentaires légaux
Nos conventions d'entreprise nous imposent parfois certains commentaires pour des raisons juridiques. Une mention de copyright ou de licence en tête de fichier est nécessaire et raisonnable.
// Copyright (C) 2026 Boutique SAS. Tous droits réservés.
// Distribué sous licence MIT, voir le fichier LICENSE. De tels commentaires ne doivent pas devenir des contrats ni des traités juridiques. Quand c'est possible, renvoyez vers une licence standard ou un document externe plutôt que d'inscrire toutes les clauses dans le commentaire.
Commentaires informatifs
Il est parfois utile de fournir une information de base. Mais lorsque l'information peut passer par le nom, c'est toujours préférable. Voici un cas légitime : une expression régulière dont le format n'est pas évident.
// Format attendu : kk:mm:ss EEE, MMM dd, yyyy
const timeMatcher = /d*:d*:d* w*, w* d*, d*/; Le commentaire nous informe que la regex vise une date et une heure formatées d'une certaine façon. Cela dit, il aurait été encore plus clair de déplacer ce code dans une classe dédiée au formatage des dates : le commentaire serait alors devenu superflu.
Explication d'intention
Un commentaire peut aller au-delà de l'information utile et exposer l'intention derrière une décision. Vous pouvez être en désaccord avec la solution du programmeur, mais au moins vous savez ce qu'il cherchait à faire.
compareTo(other: unknown): number {
if (other instanceof WikiPagePath) {
const mine = this.names.join("");
const theirs = other.names.join("");
return mine.localeCompare(theirs);
}
// On se classe au-dessus : on est du bon type.
return 1;
} Le commentaire On se classe au-dessus documente un choix de tri arbitraire qu'aucun nom de variable ne pourrait rendre évident.
Clarification
Il est parfois utile de traduire la signification d'un argument ou d'une valeur de retour obscure en quelque chose de lisible. C'est surtout vrai pour du code que vous ne pouvez pas modifier — une bibliothèque standard, par exemple.
expect(a.compareTo(a)).toBe(0); // a == a
expect(a.compareTo(b)).not.toBe(0); // a != b
expect(a.compareTo(b)).toBe(-1); // a < b
expect(b.compareTo(a)).toBe(1); // b > a Piège courant
Un commentaire de clarification risque fort d'être incorrect. Avant d'en écrire un, vérifiez qu'il n'existe pas de meilleure approche, puis vérifiez encore plus soigneusement qu'il est exact.
Avertissement de conséquences
Il est parfois utile de prévenir les autres programmeurs de certaines conséquences. Voici un exemple frappant : un objet qui n'est pas thread-safe.
function makeStandardHttpDateFormat(): DateFormatter {
// SimpleDateFormat n'est pas thread-safe : il faut donc
// créer chaque instance indépendamment.
const df = new DateFormatter("EEE, dd MMM yyyy HH:mm:ss z");
df.setTimeZone("GMT");
return df;
} On pourrait objecter qu'il existe de meilleures façons de résoudre le problème, et ce serait peut-être vrai. Mais le commentaire est parfaitement raisonnable : il empêchera un programmeur trop zélé de transformer cet objet en instance partagée au nom de l'efficacité.
Commentaires TODO
Il est parfois raisonnable de laisser des notes « à faire » sous forme de commentaires // TODO. Ce sont des tâches que le programmeur juge nécessaires mais qu'il ne peut accomplir sur l'instant : un rappel de supprimer une fonctionnalité dépréciée, un appel à l'aide, une demande de meilleur nom.
// TODO ces données ne sont plus nécessaires.
// À supprimer quand on passera au modèle de paiement v2.
function makeLegacyInvoice(): Invoice | null {
return null;
} Note
Les IDE modernes savent localiser tous les TODO du projet : ils ne risquent pas de se perdre. Mais ne laissez pas votre code en être jonché. Passez-les en revue régulièrement et éliminez ceux que vous pouvez. Un TODO n'est jamais une excuse pour laisser du mauvais code dans le système.
Amplification
Un commentaire peut servir à amplifier l'importance de quelque chose qui paraîtrait autrement anodin.
const content = match[3].trim();
// Le trim est crucial : il supprime les espaces de tête
// qui feraient reconnaître l'élément comme une autre liste.
items.push(new ListItem(content, this.level + 1)); Sans ce commentaire, un futur relecteur pourrait croire le trim() accessoire et le retirer « pour faire propre », introduisant un bug subtil.
Javadoc d'une API publique
Rien n'est aussi utile et satisfaisant qu'une API publique bien décrite. Si vous écrivez une API destinée à d'autres, documentez-la soigneusement (avec TSDoc en TypeScript). Mais gardez à l'esprit tout le reste de ce chapitre : une documentation d'API peut être tout aussi trompeuse, non locale et malhonnête que n'importe quel autre commentaire.
Les mauvais commentaires
La plupart des commentaires tombent dans cette catégorie. Ce sont généralement des béquilles, des excuses pour du code médiocre ou des justifications de décisions bancales — guère plus que le programmeur se parlant à lui-même.
Marmonnements
Glisser un commentaire juste parce que vous croyez le devoir, ou parce que le « process » l'exige, est un bricolage. Voici un cas où un commentaire aurait pu être utile, mais où l'auteur, pressé, a laissé une énigme :
function loadProperties(): void {
try {
const stream = fs.readFileSync(propertiesPath);
loadedProperties.load(stream);
} catch (e) {
// L'absence de fichier signifie que tous les défauts
// sont chargés.
}
} Que signifie ce commentaire ? Qui charge les valeurs par défaut ? Avant cet appel ? Après ? L'auteur cherchait-il à se rassurer d'avoir laissé un catch vide ? Tout commentaire qui vous oblige à fouiller un autre module pour le comprendre a échoué à communiquer et ne vaut pas les octets qu'il consomme.
Commentaires redondants
Un commentaire qui prend plus de temps à lire que le code lui-même, et qui n'apporte rien, est pur bruit.
// ❌ Avant : redondant, moins précis que le code
// Méthode utilitaire qui se termine quand this.closed
// vaut true. Lève une exception si le délai est dépassé.
async waitForClose(timeoutMillis: number): Promise<void> {
if (!this.closed) {
await this.wait(timeoutMillis);
if (!this.closed) {
throw new Error("Impossible de fermer le canal");
}
}
} Ce commentaire n'est ni plus informatif ni plus facile à lire que le code. Il est même moins précis et incite le lecteur à se contenter de ce manque de précision au lieu d'une vraie compréhension.
Commentaires trompeurs
Le commentaire ci-dessus n'est pas seulement redondant : il est aussi subtilement trompeur. La méthode ne se termine pas « quand this.closed devient vrai » ; elle se termine si this.closed est déjà vrai, sinon elle attend un délai à l'aveugle. Un autre programmeur, croyant la fonction quasi instantanée, se retrouverait à déboguer un code qui s'exécute lentement sans comprendre pourquoi.
À retenir
Un commentaire ment d'autant plus qu'il vieillit. Le code, lui, dit toujours la vérité : il est l'exécution. Quand le commentaire et le code divergent, c'est le commentaire qui trahit.
Commentaires imposés
Il est tout simplement absurde d'avoir une règle qui exige une Javadoc pour chaque fonction ou un commentaire pour chaque variable. Ces commentaires encombrent le code, propagent des mensonges et sèment la confusion.
// ❌ Avant : documentation imposée, vide de sens
/**
* @param title Le titre du CD
* @param author L'auteur du CD
* @param tracks Le nombre de pistes
* @param durationInMinutes La durée en minutes
*/
function addCD(
title: string,
author: string,
tracks: number,
durationInMinutes: number,
): void {
cdList.push({ title, author, tracks, durationInMinutes });
} Chaque ligne de cette TSDoc ne fait que paraphraser une signature déjà parfaitement claire.
Commentaires de journal
Certains ajoutent un commentaire en tête de module à chaque modification, formant peu à peu un journal des changements. J'ai vu des modules avec des pages entières de ces entrées.
// ❌ Avant : ce que Git fait déjà, en mieux
/*
* Changements (depuis le 11-10-2001)
* ----------------------------------
* 11-10-2001 : Réorganisation de la classe (JC)
* 05-11-2001 : Ajout de getDescription() (JC)
* 12-11-2001 : Correction de bugs sur les dates (JC)
* 29-05-2002 : Constantes de mois déplacées (JC)
*/ Il fut un temps où ces journaux avaient un sens : nous n'avions pas de système de gestion de versions. Aujourd'hui, Git mémorise tout pour nous — qui a changé quoi, quand, et pourquoi. Ces journaux ne sont plus que de l'encombrement : supprimez-les.
Commentaires de bruit
Certains commentaires ne sont que du bruit : ils répètent l'évidence sans rien apporter.
/** Constructeur par défaut. */
constructor() {}
/** Le jour du mois. */
private dayOfMonth = 0;
/**
* Retourne le jour du mois.
* @return le jour du mois.
*/
getDayOfMonth(): number {
return this.dayOfMonth;
} Ces commentaires sont si bruyants qu'on apprend à les ignorer ; nos yeux glissent dessus. Et un jour, le code change autour d'eux et ils se mettent à mentir. Méfiez-vous tout particulièrement des copier-coller : combien de fois trouve-t-on /** La version. */ au-dessus d'un champ qui n'a rien à voir avec une version ? Si l'auteur ne fait pas attention en écrivant, pourquoi le lecteur en profiterait-il ?
Plutôt que de céder à la tentation du bruit, prenez la résolution de nettoyer votre code. Souvent, un commentaire de bruit dans un catch trahit une frustration qui se résout en extrayant le bloc dans une fonction au nom parlant :
// ✅ Après : la frustration devient une fonction nommée
private startSending(): void {
try {
this.doSending();
} catch (e) {
if (e instanceof SocketException) return; // normal : arrêt demandé
this.addExceptionAndCloseResponse(e);
}
} Pas de commentaire quand une fonction ou une variable suffit
Considérez ce fragment, où le commentaire pose une question à laquelle le code lui-même devrait répondre :
// ❌ Avant
// Le module de la liste globale dépend-il du
// sous-système dont nous faisons partie ?
if (
smodule.getDependSubsystems().includes(subSysMod.getSubSystem())
) {
// ...
} On peut reformuler sans le commentaire, en nommant les intermédiaires :
// ✅ Après
const moduleDependees = smodule.getDependSubsystems();
const ourSubSystem = subSysMod.getSubSystem();
if (moduleDependees.includes(ourSubSystem)) {
// ...
} Marqueurs de position
Certains aiment marquer une position dans un fichier par une bannière. Il existe de rares cas où regrouper des fonctions sous une telle bannière a du sens, mais en général ce n'est que de l'encombrement — surtout la traîne bruyante de slashes.
// ❌ Avant
// Actions //////////////////////////////////// Une bannière n'est frappante que si on en voit rarement. Si vous en abusez, elles se fondent dans le bruit de fond et finissent ignorées.
Commentaires de fin d'accolade
Certains placent des commentaires sur les accolades fermantes pour repérer leur appariement. Cela peut se justifier dans de longues fonctions profondément imbriquées, mais cela ne fait qu'encombrer les fonctions courtes et bien encapsulées que nous préférons.
// ❌ Avant
while ((line = reader.readLine()) !== null) {
wordCount += line.split(/W/).length;
} // while
console.log(`wordCount = ${wordCount}`);
// main Si vous éprouvez le besoin de marquer vos accolades fermantes, raccourcissez plutôt vos fonctions.
Attributions et signatures
// ❌ Avant
/* Ajouté par Rick */ Le système de gestion de versions sait parfaitement qui a ajouté quoi, et quand. Inutile de polluer le code avec ces petites signatures. On pourrait croire qu'elles aident à savoir à qui parler — mais en réalité elles restent en place des années, devenant de moins en moins exactes et pertinentes.
Code commenté
Peu de pratiques sont aussi détestables que de mettre du code en commentaire. Ne faites pas ça !
// ❌ Avant
const response = new InputStreamResponse();
response.setBody(formatter.getResultStream(), formatter.getByteCount());
// const resultsStream = formatter.getResultStream();
// const reader = new StreamReader(resultsStream);
// response.setContent(reader.read(formatter.getByteCount())); Ceux qui le voient n'oseront pas le supprimer : ils croiront qu'il est là pour une raison, trop important pour disparaître. Et il s'accumule comme la lie au fond d'une mauvaise bouteille. Supprimez-le. Git s'en souvient. Vous ne le perdrez pas. Promis.
Astuce
La règle est simple : si une ligne de code n'est pas exécutée, elle n'a rien à faire dans le fichier. L'historique de version est votre archive — pas le bloc de commentaires.
HTML, information non locale, et excès
Quelques fautes plus discrètes, mais tout aussi nuisibles :
| Anti-pattern | Pourquoi c'est nocif |
|---|---|
| HTML dans les commentaires | Illisible là où ça devrait être lisible : l'éditeur. C'est à l'outil de doc d'ajouter le balisage, pas à vous. |
| Information non locale | Un commentaire doit décrire le code proche. Documenter une valeur par défaut que la fonction ne contrôle pas, c'est garantir un mensonge futur. |
| Trop d'information | Pas de digressions historiques ni de détails arcanes. Un numéro de RFC suffit ; le texte de la RFC, non. |
| Lien non évident | Si le commentaire a lui-même besoin d'être expliqué, il a échoué. Quel est ce « filter byte » ? Se rapporte-t-il au +1 ou au *3 ? |
| En-têtes de fonction superflus | Une petite fonction au nom bien choisi vaut mieux qu'un en-tête de commentaire. |
Sur le dernier point, l'exemple le plus parlant du livre est le générateur de nombres premiers. Dans sa version « bien documentée », chaque ligne est annotée (// déclarations, // crible, // combien de premiers ?). Après refactorisation, ces commentaires disparaissent : ils sont remplacés par des fonctions aux noms explicites.
// ✅ Après : les noms remplacent les commentaires
function generatePrimes(maxValue: number): number[] {
if (maxValue < 2) return [];
uncrossIntegersUpTo(maxValue);
crossOutMultiples();
return collectUncrossedIntegers();
} Il ne reste qu'un seul commentaire vraiment nécessaire : celui qui explique pourquoi la racine carrée sert de limite d'itération — un raisonnement mathématique qu'aucun nom ne pourrait porter.
function determineIterationLimit(crossedOut: boolean[]): number {
// Tout multiple a un facteur premier inférieur ou égal à la
// racine de la taille du tableau : inutile de cribler au-delà.
return Math.floor(Math.sqrt(crossedOut.length));
} C'est exactement la frontière : on commente le pourquoi d'une décision non évidente, jamais le quoi que le code dit déjà.
À retenir
- Chaque commentaire est l'aveu d'un échec à s'exprimer dans le code : préférez extraire une fonction au nom parlant.
- Les commentaires ne rachètent pas un mauvais code — nettoyez le code plutôt que de le commenter.
- Sont légitimes : mentions légales, intention d'une décision, avertissements de conséquences, clarifications de code non modifiable, TODO, amplification, doc d'API publique.
- Sont nuisibles : redondances, marmonnements, bruit, journaux d'historique, code commenté, signatures, marqueurs et accolades — tout ce que Git ou un bon nom font déjà mieux.
- Un commentaire vieillit et finit par mentir ; le code, lui, dit toujours la vérité.
- Le seul commentaire vraiment bon est celui que vous avez trouvé le moyen de ne pas écrire.