Le livre qui a appris à une génération de développeurs que le code se lit dix fois plus qu'il ne s'écrit.
Pourquoi ce livre
Quand j'étais formateur, je corrigeais des dizaines de projets d'étudiants. Des variables $a, des fonctions de 200 lignes, des commentaires qui mentaient sur ce que faisait le code en dessous. Et le pire, c'est que je ne pouvais pas trop leur en vouloir : mon propre code d'il y a quinze ans ressemblait exactement à ça.
Clean Code, c'est le livre que j'aurais voulu qu'on me mette dans les mains à mes débuts. Il met des mots sur ce qu'on finit tous par sentir après des années de maintenance : la lisibilité n'est pas du confort, c'est de la survie. J'en ai tiré une synthèse chapitre par chapitre : pour mes étudiants d'abord, publiée sur GitHub ensuite.
Les idées qui restent
Le livre fait 464 pages et 17 chapitres. Voilà ce qui m'en reste vraiment, des années après.
1Nommer, c'est concevoir
Le chapitre sur le nommage vaut à lui seul l'achat du livre. Son exemple d'ouverture : int d; // elapsed time in days. Le commentaire essaie de sauver le nom. Martin le remplace par elapsedTimeInDays et pose sa règle : « si un nom a besoin d'un commentaire, c'est qu'il ne révèle pas son intention » (p. 18). Derrière l'évidence, une idée plus profonde : si vous n'arrivez pas à nommer clairement une fonction, c'est souvent qu'elle fait trop de choses. Le nom est un test de design déguisé.
2Une fonction fait une chose
Courte, un seul niveau d'abstraction, deux ou trois arguments maximum. Un seul niveau d'abstraction signifie que la fonction nomme ses étapes sans les implémenter : expedierCommande() appelle verifierStock(), calculerTotal(), imprimerEtiquette() : elle ne fait rien de tout ça elle-même. Le code doit se lire de haut en bas comme un article de journal : le titre d'abord, les détails ensuite. C'est le principe que j'applique le plus au quotidien, et celui que je vois le moins appliqué dans le code que je reprends.
3Un commentaire est un aveu d'échec
La formule du livre est plus dure que sa réputation : « les commentaires sont toujours des échecs » (p. 54). Son exemple, en code :
// ✗ le commentaire-déodorant : il explique une condition obscure
// le salarié a plus de 5 ans d'ancienneté ET est à temps plein
if (emp.anciennete > 5 && emp.tempsPlein) { ... }
// ✓ on extrait une méthode qui DIT la même chose, et ne peut pas mentir
if (emp.eligiblePleinsAvantages()) { ... }
Le commentaire vieillit et ment dans six mois ; la méthode bien nommée, elle, est vérifiée par le compilateur et reste vraie. Les seuls commentaires légitimes expliquent le pourquoi, pas le quoi :
- une contrainte métier que le code seul ne peut pas exprimer ;
- un avertissement de conséquence (« ne changez pas cet ordre, le processeur de paiement l'exige ») ;
- une décision délibérée qui surprendrait un futur lecteur.
Le reste ment au bout de six mois, et personne ne le met à jour.
4Les erreurs se gèrent, elles ne se cachent pas
Des exceptions plutôt que des codes de retour, échouer vite et fort plutôt que continuer dans un état pourri. Trois règles que le livre rend non négociables :
- jamais de
catchvide : un bloctry { ... } catch (e) {}est un bug futur avec une date de péremption inconnue ; - ne retournez pas
null: vous créez du travail de vérification pour chaque appelant, et un seul check manquant suffit pour un crash ; - ne passez jamais
nullen argument : l'appelé ne peut pas savoir si c'est un oubli ou une valeur intentionnelle.
// ✗ le catch vide : l'erreur disparaît, le bug reste (et le paiement ?)
try { paiement.debiter(montant) } catch (e) {}
// ✓ on logue et on laisse remonter : jamais on n'avale en silence
try { paiement.debiter(montant) }
catch (e) { logger.error(e); throw e }
5Ne parle pas aux inconnus
Quand un objet connaît la structure interne d'un autre, tout changement interne casse l'appelant. Martin appelle ça la « catastrophe ferroviaire » : $order->getCustomer()->getAddress()->getCity() couple votre code aux structures internes de trois objets à la fois. Le jour où l'un d'eux change, tout casse. La solution : exposer une méthode getShippingCity() qui dit ce que vous voulez, sans révéler comment c'est stocké.
6Le code de test est du vrai code
TDD (Test-Driven Development) : écrire le test avant le code. Le chapitre pose ses trois lois :
- pas de code de production sans un test qui échoue d'abord ;
- écrire juste assez de test pour échouer (une erreur de compilation compte) ;
- écrire juste assez de code pour le faire passer.
Un cycle d'« environ trente secondes » (p. 122), bien plus court qu'on l'imagine. Et l'histoire qui m'a marqué : une équipe décide que le code de test peut rester sale ; les tests pourrissent, finissent jetés, les défauts explosent. Le filet de sécurité meurt avec la propreté des tests.
7SOLID en filigrane
Cinq principes, un acronyme. Le livre ne les présente pas comme un catalogue, il les fait vivre à travers les exemples :
- S : Responsabilité unique (Single Responsibility) : une classe n'a qu'une seule raison de changer. Une classe
UserServicequi gère à la fois l'authentification et l'envoi d'emails en a deux, séparez-les ; - O : Ouvert/fermé (Open/Closed) : ouvert à l'extension, fermé à la modification (ajouter un comportement sans toucher au code existant) ;
- L : Substitution de Liskov (Liskov Substitution) : une sous-classe doit pouvoir remplacer sa classe parent sans rien casser ;
- I : Ségrégation des interfaces (Interface Segregation) : mieux vaut plusieurs petites interfaces qu'une grande qui force les classes à implémenter des méthodes dont elles n'ont pas besoin ;
- D : Inversion des dépendances (Dependency Inversion) : dépendre des abstractions, pas des implémentations concrètes.
Le plus utile au quotidien, le S, en code : une classe ne doit avoir qu'une raison de changer.
// ✗ S violé : UserService change si l'auth change OU si l'email change
class UserService {
authentifier(login, mdp) { ... }
envoyerEmailBienvenue(user) { ... }
}
// ✓ une classe = une seule raison de changer
class Authentificateur { authentifier(login, mdp) { ... } }
class Mailer { envoyerEmailBienvenue(user) { ... } }
C'est exactement le SRP décortiqué dans la fiche Clean Architecture (« un module ne répond qu'à un seul donneur d'ordres ») : ici l'auth répond à l'équipe sécurité, l'email à l'équipe marketing. Deux patrons, deux classes.
8La règle du boy-scout
« Laissez le campement plus propre que vous ne l'avez trouvé » (p. 14), adaptée du message d'adieu de Baden-Powell aux scouts. C'est peut-être la phrase la plus célèbre du livre, et la plus applicable dès demain matin : pas besoin de grand soir du refactoring, juste un renommage ici, une fonction extraite là, à chaque passage dans un fichier. La dette technique recule par petites touches, pas par révolutions.
Trois choses que je ne savais pas avant de le relire
- Le fameux ratio « le code se lit 10 fois plus qu'il ne s'écrit » vient d'une expérience concrète : Martin a rejoué ses sessions d'édition enregistrées par Emacs, comme un film en accéléré. L'essentiel du temps : scroller, lire, effacer, retaper (p. 13-14).
- La règle des fonctions ultra-courtes vient d'une soirée de 1999 chez Kent Beck, devant un petit programme nommé « Sparkle » dont chaque fonction faisait 2 à 4 lignes. Le programme est perdu : il ne reste que le souvenir de Martin (p. 34).
- Le cycle TDD complet (test qui échoue, code, refactor) dure « environ trente secondes » (p. 122). Pas une demi-journée : trente secondes. Ça change complètement l'image qu'on s'en fait.
Mon avis, honnêtement
Les chapitres sur le nommage, les fonctions et les commentaires n'ont pas pris une ride : en 2026, aucun livre plus récent ne les a remplacés sur ces sujets. C'est le premier texte que je donnais à lire à mes étudiants.
Mais le livre a vieilli par endroits, et il faut le dire. Les exemples sont en Java, verbeux, parfois pénibles : les trois derniers chapitres d'études de cas, c'est 90 pages de listings que plus personne ne lit (moi le premier).
Paradoxalement, Martin est plus nuancé que ses lecteurs les plus fermes : il avoue qu'aucune recherche n'étaye la règle des fonctions courtes (p. 34), et que ses propres fonctions naissent longues et brouillonnes avant d'être raffinées sous tests (p. 49). Bref, le dogme « toute fonction doit faire trois lignes » vient plus de ses fans que du livre. Gardez les idées de fond : une fonction fait une seule chose, un nom doit tout dire. Et ne prenez pas les chiffres au pied de la lettre : trois lignes, c'est une direction, pas une règle à faire respecter en revue de code.
Odilon
Toujours valable en 2026 ?
En 2008, Martin répondait à ceux qui prédisaient la fin des programmeurs parce que le code serait « généré au lieu d'écrit ». Sa réponse : spécifier un besoin avec assez de précision pour qu'une machine l'exécute, c'est déjà programmer. En 2026, avec l'IA qui génère du code à la demande, votre boulot glisse de l'écriture vers la relecture. Relire, juger, accepter ou refuser du code généré demande exactement la grille que ce livre installe. Clean Code est plus utile aujourd'hui qu'à sa sortie.
Pour qui ?
Lisez-le si
- Vous codez depuis 1 à 5 ans et personne ne vous a jamais relu sérieusement
- Vous reprenez du code legacy et vous voulez comprendre pourquoi il fait mal
- Vous relisez du code généré par IA et vous voulez des critères pour juger
- Vous encadrez des juniors : c'est un vocabulaire commun tout prêt
Passez votre chemin si
- Vous cherchez un livre d'architecture : ce n'est pas le sujet, voyez plutôt Clean Architecture
- Le Java verbeux vous donne des boutons : la seconde moitié sera rude
- Vous appliquez déjà SOLID, TDD et la revue de code au quotidien : vous n'apprendrez pas grand-chose
Pour aller plus loin
Plusieurs idées de ce livre se pratiquent directement dans mes cours gratuits : le découpage en responsabilités dans le cours POO, la boucle red-green-refactor dans le cours sur les tests, et l'art de relire du code généré dans Coder avec l'IA.
Commentaires (0)