Une revue de code, un mardi après-midi. Sous une pull request de deux cents
lignes, un seul commentaire :

> "Ce n'est pas très propre."

Mets-toi à la place de l'auteur. Qu'est-ce qu'il corrige ? Les noms ? Le
découpage ? L'indentation ? Il ne le sait pas. Ce qu'il sait, en revanche,
c'est qu'on vient de lui dire que son travail est sale.

Soit il se défend, et la revue devient une négociation de goûts. Soit il obéit sans
comprendre, réécrit au hasard, et la pull request revient avec un autre
commentaire du même genre.

Dans les deux cas, personne n'a parlé du code.

Cet article ouvre une série sur ce que j'appelle, faute de mieux, la qualité
du code, et sur les *code smells*. Avant d'y entrer, je veux me débarrasser
d'un mot. Pas parce qu'il est faux, mais parce qu'il nous empêche de parler
de ce qui compte.

## Rendons à César ce qui lui appartient

**Clean Code**, le livre de Robert C. Martin paru en 2008, a
rendu un service immense à la profession. Il a mis des mots sur des
choses que beaucoup sentaient sans savoir les nommer : un nom qui ment, une
fonction qui fait trois choses, un commentaire qui compense un code obscur.
Il a fait de la qualité du code un sujet dont on pouvait parler, en équipe,
avec des arguments et un vocabulaire commun.

Quand je l'ai lu, il m'a rappelé Baldur's Gate. Dans ce jeu de rôle, on
trouve parfois un vieux grimoire au fond d'un donjon. Le personnage le lit,
et il gagne un point de compétence, pour toujours. J'avais toujours trouvé ça
absurde ! "Comme si la lecture d'un livre pouvait faire progresser quelqu'un d'un coup."

Quand j'ai reposé **Clean Code**, j'avais l'impression d'avoir instantanément
pris un niveau en code, dans la vraie vie. C'est d'ailleurs comme ça que j'ai présenté le livre à un paquet d'étudiants. 

Une bonne partie de ce que j'écris sur ce blog et de ce que j'ai appris est lié à la lecture de ce livre. 

Mais le titre a fait plus que le contenu. « Propre » est devenu le mot qu'on
emploie pour dire « bon code », et ce mot-là porte des choses que le livre ne
disait pas.

Si j'écris cet article, c'est parce que grâce à des discussions avec d'autres professionnels, j'ai fini par admettre qu'il fallait arrêter de recommander ce livre et donner de la visibilité à son auteur. 

## Ce que le mot abîme

### Il juge une personne

« Propre » et « sale » ne sont pas des mots techniques. Ce sont des mots
d'hygiène, de supériorité morale. Un enfant sale, une affaire
sale, avoir les mains sales. Quand on dit d'un code qu'il est sale, on dit,
qu'on le veuille ou non, que celui qui l'a écrit a été négligent.

Or la plupart des codes difficiles à faire évoluer n'ont pas été écrits par
des gens négligents. Ils ont été écrits sous une contrainte de délai, avec
une compréhension du métier qui a changé depuis, par quelqu'un qui ne
pouvait pas savoir ce que le produit deviendrait. Le jugement moral tombe sur
une personne pour une situation.

Et une personne jugée se défend. C'est humain, et c'est exactement ce qui
transforme une revue de code en tribunal, ou en foire d'empoigne.

### Il ne dit pas quoi faire

« Ce n'est pas propre » est un verdict, pas un diagnostic. Il ne dit ni ce
qui pose problème, ni pourquoi, ni dans quelle direction aller. L'auteur doit
deviner ce que le relecteur avait en tête, et le relecteur lui-même aurait
souvent du mal à le formuler.

Un bon commentaire de revue doit pouvoir être suivi par quelqu'un qui n'était
pas dans la tête de celui qui l'a écrit. « Pas propre » ne passe pas ce test.

### Il mesure une esthétique

Le mot désigne une apparence : des fonctions courtes, des noms soignés, une
indentation régulière, pas de duplication visible. Tout cela est souvent
corrélé à un code facile à faire évoluer. Souvent, pas toujours.

On peut avoir du code impeccable à l'œil, découpé en petites classes aux noms
parfaits, et qui oblige à toucher six fichiers pour ajouter un cas. On peut
avoir une fonction de quarante lignes, un peu brute, que personne n'a
modifiée en trois ans parce qu'elle n'avait aucune raison de l'être. Le
premier passe la revue. Le second se fait corriger. Mais c'est le premier qui
coûtera cher.

### Il ignore le contexte

« Propre » est absolu. Un code l'est ou ne l'est pas. Mais un script de
migration exécuté une fois et supprimé la semaine suivante n'a pas besoin du
même soin que le cœur du calcul de facturation, modifié tous les mois. Exiger
les deux au même niveau, c'est soit gaspiller de l'effort sur le premier,
soit en manquer sur le second.

## Un exemple

Voici un calcul de frais de livraison. Rien de choquant.

_Trois fonctions, chacune lisible_

**TypeScript**

```ts
type Carrier = 'colissimo' | 'chronopost' | 'relay';

export function shippingFee(carrier: Carrier, weightKg: number): number {
  switch (carrier) {
    case 'colissimo':  return 4.9 + weightKg * 0.5;
    case 'chronopost': return 9.9 + weightKg * 0.8;
    case 'relay':      return 3.5;
  }
}

export function deliveryDelayDays(carrier: Carrier): number {
  switch (carrier) {
    case 'colissimo':  return 3;
    case 'chronopost': return 1;
    case 'relay':      return 4;
  }
}

export function carrierLabel(carrier: Carrier): string {
  switch (carrier) {
    case 'colissimo':  return 'Colissimo';
    case 'chronopost': return 'Chronopost 24h';
    case 'relay':      return 'Point relais';
  }
}
```

**C#**

```csharp
public enum Carrier { Colissimo, Chronopost, Relay }

public static class Shipping
{
    public static decimal Fee(Carrier carrier, decimal weightKg) => carrier switch
    {
        Carrier.Colissimo  => 4.9m + weightKg * 0.5m,
        Carrier.Chronopost => 9.9m + weightKg * 0.8m,
        Carrier.Relay      => 3.5m,
        _ => throw new ArgumentOutOfRangeException(nameof(carrier)),
    };

    public static int DelayDays(Carrier carrier) => carrier switch
    {
        Carrier.Colissimo  => 3,
        Carrier.Chronopost => 1,
        Carrier.Relay      => 4,
        _ => throw new ArgumentOutOfRangeException(nameof(carrier)),
    };

    public static string Label(Carrier carrier) => carrier switch
    {
        Carrier.Colissimo  => "Colissimo",
        Carrier.Chronopost => "Chronopost 24h",
        Carrier.Relay      => "Point relais",
        _ => throw new ArgumentOutOfRangeException(nameof(carrier)),
    };
}
```

Est-ce que c'est propre ? Les fonctions sont courtes, les noms sont clairs,
il n'y a rien à reprocher à l'œil. Un relecteur pourrait le valider sans un
mot. Un autre pourrait écrire « pas très propre, tous ces switch », et
l'auteur ne saurait pas quoi en faire.

Compare avec ce commentaire :

> Si on ajoute un transporteur, il faudra modifier ces trois fonctions, et
> sans doute d'autres ailleurs qui font le même switch. Est-ce qu'on s'attend
> à en ajouter ?

Celui-là parle d'un changement précis. Il chiffre ce qu'il coûterait. Et il
pose la seule question qui permet de trancher, parce que la réponse change
tout : si le catalogue de transporteurs n'a pas bougé depuis cinq ans, ce
code est très bien comme il est. Si le métier en annonce deux par trimestre,
il va coûter cher, et on sait déjà où regarder.

Aucun des deux commentaires n'est plus sévère que l'autre. Mais un seul des
deux peut être discuté avec des arguments factuels.

## Un autre critère : le prochain changement

Je propose de remplacer « propre » par une question, toujours la même :
**à quel point ce code est-il facile et sûr à changer ?**

Kent Beck l'a formulé d'une phrase devenue célèbre : pour chaque changement souhaité, rends le changement facile (attention, ça peut être difficile), puis fais le changement facile. Dans *Tidy First?*, il va plus loin : le
coût d'un logiciel, c'est pour l'essentiel le coût de le changer. Le code qu'on écrit aujourd'hui sera relu, modifié, étendu bien plus souvent qu'il
n'a été écrit. C'est là que se joue sa valeur.

Ce critère a trois avantages sur le mot qu'il remplace.

**Il parle du code, pas de son auteur.** « Ce changement demande de toucher trois fichiers » est un fait. 
On peut le vérifier, le contester, le chiffrer.
Personne n'est mis en cause.

**Il dit quoi faire.** Si le problème est que le changement touche trois endroits, la direction est de les rapprocher. 
Si le problème est qu'on ne sait pas ce qu'on casse, la direction est un test. 
Le diagnostic contient le remède.

**Il dépend du contexte, et c'est voulu.** 
Le même code peut être parfait dans un module que personne ne touche et coûteux dans un module qui bouge chaque semaine. 
Le critère oblige à se demander ce qui va changer, ce que « propre » ne demande jamais.

## Ce qui rend un changement coûteux

En pratique, un changement coûte cher pour l'une de trois raisons. 
Elles reviendront dans chaque épisode de cette série.

1. **Il faut comprendre avant de toucher.** Le code est long, les noms
   trompent, la logique est dispersée. Avant d'écrire une ligne, on passe une
   heure à reconstituer ce que fait l'existant.
2. **Il faut toucher à plusieurs endroits.** Une seule décision du métier est
   répartie dans le code. L'exemple des transporteurs en est un cas d'école.
3. **On ne sait pas ce qu'on va casser.** Le changement lui-même est simple,
   mais rien ne prévient d'un effet de bord. Alors on avance lentement, on
   teste à la main, ou on ne touche à rien.

La lisibilité n'a pas disparu de ce tableau, elle est dans la première
cause. Elle n'est simplement plus une fin en soi : elle compte parce qu'un
code qu'on ne comprend pas coûte cher à changer.

Et les *code smells*, ces symptômes catalogués par Martin Fowler et Kent Beck
dans *Refactoring*, trouvent leur place naturellement : chacun est un signal
qu'un changement futur coûtera plus cher qu'il ne devrait, pour l'une de ces
trois raisons. Un smell n'est pas une faute. C'est une facture qui n'est pas
encore arrivée.

## Trois questions pour la prochaine revue

Si tu ne retiens qu'une chose de cet article, que ce soit ces trois questions.
Elles remplacent « est-ce que c'est propre ? », et elles se posent à voix
haute sans blesser personne.

1. **Quel est le prochain changement probable ici, et combien d'endroits
   faudra-t-il toucher ?**
2. **Qu'est-ce qu'il faudra comprendre avant de pouvoir le faire ?**
3. **Si on se trompe en le faisant, qu'est-ce qui nous préviendra ?**

Si les réponses sont « un seul endroit », « pas grand-chose » et « un test
rouge », le code est en bon état, quelle que soit son allure. Si elles sont
« je ne sais pas », c'est là qu'il faut regarder.

Et parfois, la réponse honnête est : ce changement coûtera cher, mais il
n'arrivera probablement jamais. Alors on l'accepte, en le sachant. C'est une
décision, et c'en est une bien meilleure que de réécrire un code au nom d'une soi-disant
propreté que personne ne sait définir.

## « Ce n'est qu'un mot »

C'est l'objection que j'entends le plus souvent. Tout le monde sait bien ce
qu'on veut dire par « propre », non ?

Justement, non. Demande à cinq développeurs ce qui rend un code
propre, tu auras six réponses, dont certaines se contredisent. Le mot donne
l'illusion d'un accord qui n'existe pas, et c'est en revue de code, quand
deux personnes ne voient pas la même chose sous le même mot, que l'illusion
coûte le plus.

Les mots qu'on emploie façonnent ce dont on parle. Un vocabulaire
moral produit des conversations morales. Pour avoir des
conversations d'ingénieurs, il faut un vocabulaire basé sur des hypothèses ou sur des faits.

## La suite de la série

Les prochains épisodes passent en revue les familles de *code smells*, chacune
sous l'angle du changement qu'elle rend coûteux :

- **[Ce qui rend un changement coûteux](/blog/ce-qui-rend-un-changement-couteux/)** :
  les trois causes, en détail, la grille de lecture de la série, et pourquoi
  les agents IA rendent la question plus urgente.
- **Bloaters** : quand comprendre coûte plus cher que changer.
- **Change Preventers** : quand un changement en exige dix.
- **Object-Orientation Abusers** : quand ajouter un cas oblige à modifier
  l'existant.
- **Dispensables** : le code qui coûte sans rien rapporter.
- **[Couplers](/blog/code-smells-couplers-detecter-le-couplage/)** : déjà
  publié, quand une classe en sait trop sur les autres.
- **Un smell n'est pas une règle** : quand traiter un smell, et quand
  l'accepter.

D'ici là, essaie les trois questions à ta prochaine critique. Et observe ce qui
se passe quand tu t'interdis d'utiliser le mot « propre ».

---

*Tu veux creuser ces sujets avec ton équipe ? J'interviens en
[Brown Bag Lunch](/presentations/) dans vos locaux, ou par mail à
[edouard@lacrafterie.tech](mailto:edouard@lacrafterie.tech).*
