cursus.

Cours 4 · Qualité du codeLeçon 1 sur 2

Écrire un code lisible

5 h de lecture8 sections Version PDF

À la fin de cette leçon, vous saurez

Conventions de nommage et d'indentation ; découpage en fonctions courtes ; commentaires utiles contre commentaires bruyants ; documentation ; lecture croisée entre binômes.

Le bloc III a fixé quoi construire. Le bloc IV s'attaque au comment — la qualité du code lui-même. Et il commence par ce qui paraît le plus modeste et se révèle le plus rentable : écrire un code lisible.

Le chapitre 1 l'a chiffré : la maintenance domine le coût d'un logiciel, et sa moitié se passe à comprendre du code existant avant d'oser le modifier. Autrement dit, un code se lit bien plus souvent qu'il ne s'écrit — par vos coéquipiers, par vous-même dans six mois, redevenu étranger à ce que vous aviez écrit. Écrire pour le lecteur, et non pour la machine seule, est le premier réflexe du génie logiciel.

Nommer, le geste qui compte le plus

Le nom est la première chose que lit un humain, et de loin la plus importante. Un bon nom dit l'intention ; il épargne au lecteur de reconstituer ce que le code fait.

✗  function f(a, b, c) { ... }✓  function prixAnnuel(prixMensuel, estEtudiant, anciennete) { ... }

f, a, x obligent à relire tout le corps pour deviner leur rôle, à chaque lecture. prixAnnuel, estEtudiant se comprennent d'un coup d'œil. Quelques principes :

  • un nom décrit ce que la chose EST ou FAIT : estValide (un booléen), calculerTotal() (une action), nombreEtudiants (un compte) ;
  • on évite les abréviations obscures : nbEtudInscr économise trois lettres et coûte une relecture ;
  • la longueur suit la portée : un compteur de boucle peut s'appeler i ; une variable qui vit dans toute une fonction mérite un vrai nom.

Nommer est un travail — pas une formalité. Le temps passé à trouver le bon nom est rendu au centuple à la relecture.

Les nombres magiques et les conventions

Un nombre magique est une valeur posée en dur, sans explication : x = x * 0.85. Que signifie 0.85 ? Une remise de 15 % ? Un taux de change ? Le lecteur ne peut pas savoir, et si la règle change, il faut retrouver toutes les occurrences. On le remplace par une constante nommée :

✗  prix = prix * 0.85;✓  const REMISE_ETUDIANT = 0.85;   // -15 %   prix = prix * REMISE_ETUDIANT;

Le nombre se comprend et se modifie en un seul endroit. Au-delà, les conventions — de nommage (camelCase, snake_case…), d'indentation, de mise en forme — n'ont pas de valeur en soi, mais une valeur immense partagée : un code où tout le monde suit la même convention se lit sans friction. La règle d'équipe est simple : peu importe la convention, pourvu qu'elle soit unique et respectée par tous. Un formateur automatique (comme Prettier ou l'outil de votre langage) règle la question sans débat.

Quiz · vérifiez votre compréhension Sans réponse

Pourquoi remplace-t-on un « nombre magique » comme 0.85 par une constante nommée REMISE_ETUDIANT = 0.85 ?

Des fonctions courtes, qui font une chose

Une fonction devrait faire une seule chose, et tenir sous les yeux — idéalement quelques lignes, à la rigueur un écran. Une fonction de 200 lignes qui recueille les entrées, calcule, met en forme et affiche est illisible : on ne peut pas la comprendre sans la parcourir en entier, ni la tester par morceaux, ni en réutiliser une partie.

Le remède est le découpage : extraire chaque sous-tâche dans une fonction bien nommée. Le corps de la fonction principale devient alors une suite d'appels qui se lit comme un résumé :

function traiterCommande(commande) {  verifierStock(commande);  const total = calculerTotal(commande);  enregistrer(commande, total);  envoyerConfirmation(commande);}

On comprend ce que fait traiterCommande sans lire le détail de chaque étape. C'est le même principe que le découpage en modules du chapitre 7, appliqué à l'échelle d'une fonction : un niveau d'abstraction à la fois.

Commentaires : utiles contre bruyants

Le bon commentaire n'est pas celui qui abonde, mais celui qui ajoute quelque chose. La règle tient en une phrase : le code dit COMMENT, le commentaire dit POURQUOI.

Un commentaire bruyant répète ce que le code dit déjà :

// on multiplie a par 12let x = a * 12;

Il n'apporte rien, encombre la lecture, et devient mensonger dès que le code change sans qu'on pense à le mettre à jour. Un commentaire utile explique ce que le code ne peut pas dire : une raison, une règle métier non évidente, un choix contre-intuitif, un piège à éviter :

// La fidélité ne s'applique qu'au-delà de 3 ans (règle commerciale, contrat client).if (anciennete > SEUIL_ANCIENNETE) prix -= REDUCTION_FIDELITE;

Le meilleur commentaire est souvent celui qu'on n'écrit pas, parce qu'un bon nom l'a rendu inutile. Réservez les commentaires aux pourquoi que le code ne montre pas.

Documentation et lecture croisée

Deux pratiques complètent la lisibilité.

La documentation du code — au niveau d'une fonction (que fait-elle ? que prend-elle en entrée ? que rend-elle ?) et au niveau du projet (un fichier README : à quoi sert-il, comment le lancer). Elle s'adresse à qui emploie le code sans vouloir en lire le détail. La bonne documentation est au plus près du code et maintenue avec lui, sinon elle diverge et ment.

La lecture croisée entre binômes (revue de code) est le meilleur test de lisibilité qui soit : un coéquipier lit votre code et dit ce qu'il ne comprend pas. Deux vertus. D'abord, si le lecteur ne comprend pas, c'est le code qu'il faut corriger, pas le lecteur. Ensuite, la revue attrape des bugs et diffuse la connaissance dans l'équipe — personne n'est le seul à connaître un morceau. C'est une pratique centrale de votre projet : relisez-vous mutuellement, tôt et souvent.

Quiz · vérifiez votre compréhension Sans réponse

Lequel de ces commentaires est « utile » plutôt que « bruyant » ?

À vous

L'exercice résume tout le chapitre en une transformation : prendre une fonction qui marche mais que personne ne comprend — noms opaques, nombres magiques, commentaires bruyants — et la rendre lisible, sans changer son résultat. La vérification l'exige : mêmes sorties sur tous les cas.

Ce dernier point est capital et prépare le chapitre 7 : améliorer la forme d'un code sans en toucher le comportement, c'est du refactoring — et cela ne se fait en confiance que sous la protection de tests.

Exercice · JavaScript · à vous de jouer

Rendez lisible une fonction opaque (noms, nombres magiques, commentaires bruyants) SANS changer son résultat — la vérification l'exige. Distinguez le commentaire utile (le pourquoi) du bruyant (le quoi), et retenez que la lecture croisée entre binômes est le vrai test de lisibilité.

En attente
// Cette fonction MARCHE, mais personne ne peut dire ce qu'elle calcule.
// Noms opaques, nombres magiques, commentaires qui répètent le code.
function f(a, b, c) {
  // on multiplie a par 12
  let x = a * 12;
  // si b est vrai on enleve 15 pourcent
  if (b) { x = x * 0.85; }
  // si c est plus grand que 3 on enleve encore 10
  if (c > 3) { x = x - 10; }
  return x;
}

// (Contexte, découvert en interrogeant l'auteur : a = prix mensuel, b = client
//  étudiant, c = nombre d'années d'ancienneté. La fonction calcule le prix
//  annuel après remises.)

// ── À VOUS : réécrire de façon LISIBLE, SANS changer le résultat ────────────
// - des noms qui disent l'intention (fonction ET paramètres) ;
// - les nombres magiques (12, 0.85, 10, 3) remplacés par des constantes nommées ;
// - pas de commentaire qui répète le code ; un commentaire seulement là où le
//   POURQUOI n'est pas évident.
function prixAnnuel(/* à nommer */) {
  return 0; // à réécrire
}

// ── Vérification : MÊME résultat que f, sur tous les cas ────────────────────
const cas = [ [30, false, 0], [30, true, 0], [30, true, 5], [50, false, 4], [50, true, 10] ];
let ok = true;
for (const [a, b, c] of cas) {
  const attendu = f(a, b, c);
  const obtenu = prixAnnuel(a, b, c);   // adapter à votre signature
  const bon = attendu === obtenu;
  ok = ok && bon;
  console.log((bon ? "  ok " : " ✗  ") + "f(" + a + "," + b + "," + c + ") = " + attendu + " / " + obtenu);
}
console.log(ok ? "Comportement préservé." : "Le résultat a changé — ce n'est plus le même code !");

Console de sortie
Le résultat s'affiche dans la console

Ce que la suite en fait

La lisibilité agit à l'échelle d'une ligne, d'une fonction. Le chapitre 7 monte d'un cran : la conception, c'est-à-dire la manière d'organiser le code en modules qui résistent au changement. On y verra la séparation des responsabilités, le couplage et la cohésion, la lutte contre la duplication, la notion de dette technique — et le refactoring, cette amélioration à comportement constant dont l'exercice de ce chapitre vient de donner un premier exemple.

À retenir

Flashcards · 1 / 4Toucher pour retourner
Fin de la leçon

Vous avez parcouru les 8 sections.

Marquez-la terminée pour faire avancer votre parcours, ou revenez sur un point avant de passer à la suite.