Bibliothèque · Résumé et avis

A Philosophy of Software Design

De John Ousterhout. Le plaidoyer d'un prof de Stanford pour les modules profonds, et la réponse la mieux argumentée à Clean Code.

FR EN
Couverture de A Philosophy of Software Design, John Ousterhout

A Philosophy of Software Design

A Philosophy of Software Design, 2nd Edition

8 /10

« Cent quatre-vingt-seize pages contre la complexité, et pas un mot de trop. »

  • AuteurJohn Ousterhout · « créateur de Tcl/Tk »
  • VOYaknyam Press, 2021 · 196 pages
  • Édition2ᵉ édition (2021), en anglais uniquement
  • Fiche~10 min de lecture
Notation du livre sur 5 dimensionsIdées9/10Applicable7/10Lisibilité9/10Actualité9/10Exemples6/10

Le contre-poids à Clean Code : modules profonds, interfaces simples, par un prof de Stanford.

Pourquoi ce livre

Quand on a lu Clean Code, on finit toujours par tomber sur le nom d'Ousterhout. C'est le livre qu'on vous cite pour vous contredire : là où Robert Martin prêche les fonctions de trois lignes, Ousterhout démontre, exemples à l'appui, que découper à l'excès aggrave la complexité au lieu de la réduire. Les deux livres ne sont pas d'accord, et c'est exactement pour ça qu'il faut lire les deux.

Ousterhout n'est pas un consultant : c'est un professeur de Stanford qui a construit de vrais systèmes (le langage Tcl, le système de fichiers log-structuré, le système de stockage RAMCloud). Le livre est né de son cours de design logiciel, où les étudiants écrivent un programme, le critiquent, puis le réécrivent. Résultat : 196 pages, zéro remplissage, et une seule obsession du début à la fin, la complexité. Il prévient lui-même : « tout problème décrit ici, je l'ai vécu personnellement, et toute technique proposée, je l'ai utilisée avec succès dans mon propre code ».

Les idées qui restent

Le livre tient en 196 pages et 22 chapitres courts. Voilà ce qui reste, une fois refermé.

1La complexité a une définition, et elle est sournoise

Ousterhout refuse de parler de complexité « en général ». Il la définit : tout ce qui rend un système difficile à comprendre et à modifier. Elle se manifeste de trois façons :

  • La modification en chaîne : changer la couleur d'une bannière oblige à éditer chaque page qui la recopie.
  • La charge cognitive : tout ce qu'un développeur doit garder en tête pour toucher une ligne sans rien casser.
  • Les inconnues inconnues (le pire) : vous ne savez même pas quel bout de code il faudrait modifier, vous le découvrez quand le bug apparaît.

Deux causes seulement nourrissent tout ça : les dépendances et l'obscurité. Et le constat qui fait mal : « la complexité est plus visible pour le lecteur que pour celui qui écrit » (p. 9). Celui qui pond le code ne la sent pas ; celui qui le reprend, si.

2Un bon module est profond

C'est l'idée centrale du livre, et le contre-pied le plus net à Clean Code. Un module profond, c'est beaucoup de fonctionnalité derrière une interface simple : « les meilleurs modules sont ceux dont l'interface est bien plus simple que l'implémentation » (p. 22). L'exemple parfait : les cinq appels d'entrée-sortie d'Unix (open, read, write, lseek, close). Cinq signatures triviales qui cachent des centaines de milliers de lignes (permissions, caches disque, ordonnancement, pilotes).

À l'inverse, un module peu profond (shallow) a une interface presque aussi compliquée que ce qu'il fait : il vous coûte en apprentissage sans rien vous épargner. Ousterhout met un nom sur la maladie : la « classite » (classitis), la croyance que « les classes c'est bien, donc plus de classes c'est mieux ». Empiler des mini-classes d'une méthode chacune ne simplifie rien, ça ajoute des interfaces à apprendre. Voilà pourquoi il s'oppose frontalement au culte de la petite fonction.

3Tactique contre stratégique : méfiez-vous du tornado

Faire marcher le code ne suffit pas. Le programmeur tactique se concentre sur la prochaine fonctionnalité, livre vite, et accumule de la complexité à chaque raccourci. Le programmeur stratégique considère que le bon design EST l'objectif, pas un bonus.

Ousterhout décrit une figure que tout le monde a croisée : le « tornado tactique », ce développeur ultra-productif qui pond du code plus vite que tout le monde, adulé par le management, et qui laisse derrière lui « un sillage de destruction » que les autres passeront des mois à nettoyer. Sa recommandation : investir 10 à 20 % de votre temps dans le design en continu. Parce que la dette technique, contrairement à la dette bancaire, n'est presque jamais remboursée.

Un développeur héros porté en triomphe sur les épaules d'une petite foule devant, tandis que derrière, un tornado de câbles emmêlés et de papier volant laisse une traînée de chaises et de bureaux renversés
Le tornado tactique : ovationné devant, le sillage de dégâts derrière.

4Cacher l'information, ne pas la découper dans le temps

La meilleure façon d'obtenir des modules profonds : l'information hiding, un principe que David Parnas posait déjà en 1972. Chaque module encapsule une décision de design qui n'apparaît pas dans son interface (le format d'un fichier, un protocole réseau, une structure d'arbre).

L'erreur inverse, c'est la décomposition temporelle : structurer le code selon l'ordre d'exécution. Vous lisez un fichier, vous le modifiez, vous le réécrivez, donc vous créez trois classes Lecture, Traitement, Écriture. Sauf que la classe qui lit et celle qui écrit doivent toutes les deux connaître le format du fichier. La même décision se retrouve dans deux endroits : c'est une fuite (information leakage), « l'un des red flags les plus importants du design » (p. 31). Le jour où le format change, vous éditez deux classes au lieu d'une. La bonne réponse : un seul module qui connaît le format, point.

5Tirez la complexité vers le bas

Face à une complexité inévitable, deux choix : la gérer dans le module, ou la repousser sur tous ceux qui l'utilisent. Ousterhout tranche : « il est plus important pour un module d'avoir une interface simple qu'une implémentation simple » (p. 61). Autrement dit, « mieux vaut que les développeurs souffrent que les utilisateurs » (p. 63) : une seule équipe encaisse la difficulté à l'intérieur, plutôt que mille appelants la subissent dehors.

Exemple concret, en code :

# ✗ complexité POUSSÉE dehors : chaque appelant doit deviner la valeur
client = Client(retry_interval=0.5)   # 0.5 ? 2 ? personne ne sait régler ça

# ✓ complexité TIRÉE dedans : le module mesure les temps réels et décide
client = Client()                     # interface nue, une équipe gère, mille appelants soulagés

6Faites disparaître les erreurs

L'idée la plus originale et la plus sous-estimée du livre. La gestion d'exceptions est « l'une des pires sources de complexité ». La meilleure parade n'est pas de mieux les attraper : c'est de redéfinir la sémantique pour que l'erreur n'existe plus.

Son propre aveu : en concevant le langage Tcl, il avait fait que supprimer une variable inexistante lève une erreur. Résultat, tout le monde entourait l'appel d'un catch pour l'ignorer. La bonne définition : « garantir que la variable n'existe plus ». Avec ça, supprimer une variable absente devient normal, l'erreur a disparu. Même logique pour substring en Java, qui lève une exception si l'index dépasse la longueur, vous forçant à écrire des vérifications partout. Python a choisi l'inverse : une tranche hors limites renvoie simplement un résultat vide. Pas d'exception, pas de code de garde, une méthode plus profonde.

// Java : lève IndexOutOfBoundsException, à blinder de checks
"hi".substring(0, 10);   // 💥 exception

# Python : tranche hors limites = résultat vide, aucune erreur
"hi"[0:10]               # → "hi"

7Le clash frontal avec Clean Code

C'est là que les deux livres s'affrontent. Ousterhout cite Robert Martin mot à mot : « la première règle des fonctions, c'est qu'elles doivent être petites. La deuxième, c'est qu'elles doivent être plus petites que ça. » Sa réponse : passé une certaine taille, raccourcir encore n'aide plus personne.

// ✗ trop découpé : on ne comprend pas l'une sans sauter à l'autre
function lirePrix(c) { return c.prix }          // "méthodes siamoises"
function avecTVA(c)  { return lirePrix(c) * 1.2 }

// ✓ une fonction "profonde" : autonome, lisible d'un seul bloc
function prixTTC(c)  { return c.prix * 1.2 }

Des fonctions trop découpées perdent leur indépendance et deviennent des méthodes siamoises (conjoined methods : on ne peut plus en comprendre une sans lire l'autre), ce qui est pire qu'une seule fonction un peu longue. Sa formule : « la profondeur compte plus que la longueur ».

Même bagarre sur les commentaires. Martin écrit « les commentaires sont toujours des échecs » ; Ousterhout, lui, est un défenseur acharné du commentaire, parce qu'il capture ce que le code ne peut pas dire : l'abstraction, l'intention, le pourquoi. Il se moque de la solution de Martin (remplacer un commentaire par un nom de méthode très long), qui finit par produire des noms comme isLeastRelevantMultipleOfNextLargerPrimeFactor.

Il va plus loin : écrivez les commentaires en premier, avant le code. Pas pour la doc, comme outil de conception. Si un commentaire devient long et pénible à écrire, c'est « le canari dans la mine » : le signe que votre abstraction est mauvaise.

8Les opinions qui fâchent, et la liste de red flags

Le chapitre le plus polémique passe les modes au crible d'une seule question : est-ce que ça réduit la complexité ? Le verdict est tranchant. Contre le Test-Driven Development (sauf pour corriger un bug) : « il concentre l'attention sur faire marcher des fonctionnalités précises, pas sur trouver le meilleur design. C'est de la programmation tactique pure ». Contre les getters et setters, « des méthodes peu profondes qui encombrent l'interface sans rien apporter ». Méfiance envers les design patterns, dont le vrai danger est la sur-application : ne forcez pas un problème dans un pattern quand une solution maison serait plus propre.

Et surtout, le cadeau pratique du livre : sa liste de red flags, applicable dès demain en revue de code :

  • module peu profond ;
  • fuite d'information ;
  • décomposition temporelle ;
  • méthode tunnel (pass-through) ;
  • méthodes siamoises ;
  • commentaire qui répète le code ;
  • nom vague ;
  • code non évident.

Quand l'un de ces signaux apparaît, arrêtez-vous : il y a probablement un problème de design caché derrière.

Trois choses que je ne savais pas

Mon avis, honnêtement

C'est, à mes yeux, le meilleur livre de design logiciel des vingt dernières années, et de loin le plus agréable à lire. Là où Clean Code est verbeux et dogmatique, Ousterhout est court, clair, et il argumente au lieu d'asséner. L'idée de module profond a changé ma façon de juger une classe : je ne compte plus les lignes, je regarde le rapport entre ce que l'interface coûte à apprendre et ce qu'elle me rend.

Ce qui l'empêche d'être parfait : les exemples. Ils tournent presque tous autour des mêmes deux ou trois cas (un éditeur de texte, le système RAMCloud), et ça sent l'amphi de fac. On aimerait plus de code du vrai monde, plus varié. Et certaines idées, comme « rendez vos modules profonds », sont plus faciles à comprendre qu'à appliquer : ça demande du jugement, pas une recette. Ce n'est pas une checklist, c'est une façon de penser, ce qui le rend à la fois plus profond et moins immédiat que Clean Code.

Le bon réflexe, c'est de lire les deux et de se faire son avis. Là où ils se contredisent, sur la taille des fonctions, sur les commentaires, Ousterhout a presque toujours raison.

Odilon

Toujours valable en 2026 ?

Plus que jamais, et pour une raison que personne n'avait anticipée. Le livre ne dépend d'aucun langage ni d'aucune mode : il parle de complexité, c'est-à-dire du seul problème qui ne disparaîtra jamais. Et à l'heure où l'IA génère une bonne partie du code, savoir distinguer un module profond d'un module peu profond devient un super-pouvoir. L'IA produit volontiers des interfaces bavardes et des classes peu profondes ; c'est exactement ce que ce livre vous apprend à repérer et à refuser. La grille d'Ousterhout est précisément l'œil critique qui manque à une machine qui pond du code plausible.

Pour qui ?

Lisez-le si

  • Vous avez lu Clean Code et vous voulez entendre l'autre cloche, mieux argumentée
  • Vous concevez des bibliothèques ou des API et vous cherchez à les rendre simples à utiliser
  • Vous reprenez du code qui « marche » mais qu'on n'ose plus toucher, et vous voulez nommer pourquoi
  • Vous relisez du code généré par IA et vous voulez des critères pour juger une interface

Passez votre chemin si

  • Vous débutez complètement : commencez par apprendre à coder, le design viendra après
  • Vous cherchez des recettes prêtes à copier : c'est un livre de jugement, pas un catalogue
  • Vous voulez des exemples variés tirés du web moderne : ici, ce sera l'éditeur de texte et RAMCloud

Pour aller plus loin

Plusieurs idées de ce livre se pratiquent dans mes cours gratuits : le découpage en responsabilités et la conception d'interfaces dans le cours POO, l'art de nommer et de structurer dans le cours sur les tests, et le réflexe de relire du code généré dans Coder avec l'IA.

Commentaires (0)

Voir toute la bibliothèque

D'autres fiches arrivent : un livre à la fois, la substantifique moelle seulement.