« Tout code que vous écrivez aujourd’hui, vous le relirez demain. Écrivez pour votre futur vous. »
Cette page est une annexe de cours, pas un article. Elle synthétise huit ouvrages de référence en extrayant ce qui s’applique directement à un projet web d’étudiant — un site, une appli, un projet d’intégration.
Elle se consulte plutôt qu’elle ne se lit d’un bout à l’autre. Les articles du blog font le travail inverse : ils prennent un désaccord entre ces auteurs et le déplient. Les deux formats se complètent, et ni l’un ni l’autre ne remplace les livres.
1. Les fondamentaux du métier
The Pragmatic Programmer — Hunt & Thomas
Le livre-boussole. Ses principes s’appliquent dès vos premiers projets.
DRY — Don’t Repeat Yourself. Chaque morceau de connaissance doit avoir une représentation unique et non ambiguë. En pratique : si vous copiez-collez du CSS ou du JS entre plusieurs pages, c’est un signal. Factorisez.
flowchart TD
A["3 pages
3 copies des styles"] -->|extraire| B["styles.css
source unique"]
B -->|un lien chacune| C["3 pages
1 seule définition"]
class A alerte
class B okLa théorie de la vitre brisée. Un console.log oublié, un nom cryptique :
la négligence appelle la négligence. Maintenez la qualité dès le départ, même
sur un TD.
flowchart TD
A["1 console.log oublié"] --> B["Personne ne le retire"]
B --> C["Trois autres s'ajoutent"]
C --> D["Variables nommées x, y, z"]
D --> E["Code mort non supprimé"]
E --> F["Projet illisible"]
class A attention
class F alerteLe prototypage comme outil de réflexion. Avant de coder une fonctionnalité complexe, faites un prototype jetable. L’objectif n’est pas du code propre, c’est d’apprendre vite. Puis jetez-le.
flowchart TD
A["Idée"] --> B["Prototype
rapide et sale"]
B --> C{"On a appris ?"}
C -->|pas encore| B
C -->|oui| D["Jeter
le prototype"]
D --> E["Implémenter
proprement"]
class B attention
class D alerte
class E okL’estimation. « Combien de temps pour cette maquette ? » ne se répond jamais au jugé. Décomposez, identifiez les inconnues, donnez une fourchette. C’est une compétence professionnelle autant que technique.
Avec une IA. Un modèle vous aide à prototyper vite — un squelette HTML/CSS en deux minutes pour tester une idée. Mais le code généré viole souvent DRY : duplications, styles inline. Explorez avec l’IA, nettoyez avec ces principes. Et pour l’estimation, elle n’a aucune idée du temps que vous mettrez.
A Philosophy of Software Design — Ousterhout
Une idée centrale : la complexité est l’ennemi principal. Tout en découle.
Modules profonds contre modules superficiels. Un bon module offre une
interface simple et cache une implémentation riche. validerFormulaire(données)
qui renvoie un booléen est profond. Dix petites fonctions verifierEmail(),
verifierNom(), verifierAge() exposées séparément sont superficielles : elles
déplacent la complexité vers l’appelant.
flowchart TD
P1["Module profond
validerFormulaire()"] --> P2["Cache email, nom, âge,
format, cohérence"]
P2 -.->|à l'opposé| S1["Module superficiel
six fonctions exposées"]
S1 --> S2["Deux ou trois lignes
chacune"]
class P1,P2 ok
class S1,S2 alerteLa complexité vient de l’accumulation. Aucune ligne isolée ne rend un projet ingérable. C’est l’empilement de petites décisions floues. À chaque ajout : est-ce que je rends le projet plus simple ou plus compliqué à comprendre ?
%%{init: {"xyChart": {"width": 300, "height": 230}}}%%
xychart-beta
title "La complexité s'accumule"
x-axis ["S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8"]
y-axis "Complexité perçue" 0 --> 100
line [5, 10, 18, 28, 42, 60, 78, 95]Les commentaires stratégiques. N’écrivez pas ce que fait le code — il le dit déjà. Écrivez pourquoi vous avez fait ce choix.
// Délai de 300 ms : évite de relancer la recherche à chaque frappe
setTimeout(lancerRecherche, 300);
Concevoir deux fois. Avant d’implémenter, esquissez deux approches. Comparez. Même si vous gardez la première, avoir envisagé l’alternative améliore votre compréhension du problème.
Avec une IA. Elle produit souvent des modules superficiels — beaucoup de petites fonctions sans cohérence d’ensemble. Du code qui fonctionne sans avoir été pensé : exactement le piège décrit ici. Demandez-lui deux approches différentes, puis choisissez vous-même.
2. Écrire du code lisible
Clean Code — Robert C. Martin
Des noms qui ont du sens. d ne veut rien dire, delaiEnJours dit tout.
Entre div1, container et grille-produits, le troisième transforme la
lisibilité de votre HTML et de votre CSS.
Des fonctions courtes, à responsabilité unique. Si vous pouvez extraire un bloc en lui donnant un nom explicite, faites-le.
// Trop de responsabilités
function gererPanier(action, produit, quantite) {
// quarante lignes qui font tout
}
// Chaque fonction a un rôle
function ajouterAuPanier(produit, quantite) { /* … */ }
function calculerTotal(panier) { /* … */ }
function afficherPanier(panier) { /* … */ }
La règle du boy-scout. Laissez le code plus propre que vous ne l’avez trouvé. Trente secondes pour corriger un nom flou pendant que vous travaillez à côté.
Avec une IA. Les modèles nomment de façon générique : data, result,
item, temp. La première chose à faire sur du code généré est de renommer —
et c’est un excellent exercice, puisqu’il faut comprendre le code pour lui
donner de meilleurs noms.
The Art of Readable Code — Boswell & Foucher
Le test du temps de compréhension. Le meilleur code est celui qu’un camarade — ou votre futur vous dans trois mois — comprend le plus vite. Chaque décision doit réduire ce temps.
Simplifiez les conditions. Les if imbriqués sur quatre niveaux sont un
cauchemar. Préférez les retours anticipés.
// Difficile à suivre
function traiterCommande(commande) {
if (commande) {
if (commande.estValide) {
if (commande.articles.length > 0) {
// enfin le vrai code
}
}
}
}
// Lisible d'un coup d'œil
function traiterCommande(commande) {
if (!commande) return;
if (!commande.estValide) return;
if (commande.articles.length === 0) return;
// le vrai code, au bon niveau d'indentation
}
Réduire la portée des variables. Déclarez au plus près de l’utilisation.
const par défaut, let quand nécessaire, jamais var.
Avec une IA. « Aplatis ces if imbriqués » fonctionne très bien : c’est un
refactoring mécanique. En revanche elle ne peut pas juger si votre code est
compréhensible par un humain — ce test-là reste le vôtre.
Refactoring — Fowler
Restructurer du code existant sans changer son comportement.
Quand refactorer : les signaux.
| Signal | Ce que ça veut dire | Action |
|---|---|---|
| Code dupliqué | La même logique à deux endroits | Extraire une fonction commune |
| Fonction trop longue | Plus de vingt ou trente lignes | Découper |
| Paramètres en cascade | f(a, b, c, d, e, f) | Regrouper dans un objet |
| Commentaire compensatoire | Il explique un code confus | Rendre le code assez clair |
| Fichier fourre-tout | Un utils.js de 500 lignes | Séparer par responsabilité |
Petit pas, test, petit pas. Ne refactorez jamais en gros. Un changement minimal, on vérifie, le suivant. En web : rouvrez la page après chaque modification.
flowchart TD
A["Repérer un signal"] --> B["Petit changement"]
B --> C["Tester dans
le navigateur"]
C --> D{"Ça marche ?"}
D -->|non| E["Annuler"]
E --> B
D -->|oui| F{"D'autres
signaux ?"}
F -->|oui| A
F -->|non| G["Fini"]
class E alerte
class G okExtraire une fonction est le refactoring le plus utile. Si un bloc mérite un commentaire explicatif, il mérite probablement d’être une fonction dont le nom remplace le commentaire.
Avec une IA. Domaine où elle brille et où elle est dangereuse : elle peut proposer un refactoring qui change le comportement sans le signaler. Le cycle petit pas → tester est votre filet. Jamais un gros refactoring d’un coup.
3. Coder avec une IA
Tous les principes ci-dessus deviennent plus importants avec un assistant, pas moins.
La règle d’or
Ne validez jamais du code que vous ne comprenez pas. Si un modèle génère trente lignes et que vous ne pouvez pas les expliquer à un camarade, vous ne pouvez pas les utiliser. Pas pour une raison morale : parce que vous ne saurez ni les déboguer, ni les faire évoluer.
flowchart TD
GEN["Le modèle génère
du code"] --> Q{"Pouvez-vous expliquer
chaque ligne ?"}
Q -->|non| L["Arrêter —
apprendre d'abord"]
Q -->|oui| USE["Relire,
puis utiliser"]
L --> R["Explication ligne à ligne,
doc, un camarade"]
R --> Q
class L alerte
class USE okOù elle aide vraiment
Générer un squelette de départ, refactorer mécaniquement, expliquer une erreur, traduire entre deux syntaxes, explorer deux approches.
Où elle guide mal
Décider l’architecture, juger la lisibilité pour un humain, estimer le temps, garantir que le code est correct, remplacer votre compréhension.
Le prompt clair, c’est la pensée claire
Bien demander à un modèle relève exactement des mêmes principes que bien nommer une variable.
| Principe | Application au prompt |
|---|---|
| Noms explicites | « Un formulaire d’inscription avec email et mot de passe » plutôt que « fais-moi un formulaire » |
| Une responsabilité | Un prompt, une tâche |
| Commentaire stratégique | Donnez le contexte et le pourquoi |
| Concevoir deux fois | « Propose deux approches différentes » |
| DRY | Donnez vos conventions pour qu’il ne réinvente pas |
4. La culture professionnelle
Design Patterns — Gamma, Helm, Johnson & Vlissides
Vous n’avez pas besoin de tous les connaître. Quatre comptent en web.
Observer. Vous le pratiquez déjà : element.addEventListener('click', fn)
en est une implémentation. Un sujet notifie ses observateurs. C’est le cœur du
modèle événement → état → rendu.
%%{init: {"sequence": {"actorMargin": 4, "width": 68, "boxMargin": 4, "noteMargin": 4, "messageFontSize": 11, "actorFontSize": 12}}}%%
sequenceDiagram
participant U as Utilisateur
participant B as Bouton
participant E as État
participant R as Rendu
U->>B: clic
B->>E: notifie
E->>E: change
E->>R: rend
R->>U: écran à jourModule. Encapsuler dans un espace clos avec une interface publique. Les
modules ES (import/export) font exactement ça. Le pourquoi : limiter ce
qui est accessible de l’extérieur réduit les effets de bord.
Iterator. for...of, .map(), .filter(), .reduce() : parcourir une
collection sans exposer sa structure.
Strategy. Changer un comportement à l’exécution. Au lieu d’un gros switch,
passez une fonction.
const strategies = {
parPrix: (a, b) => a.prix - b.prix,
parNom: (a, b) => a.nom.localeCompare(b.nom),
};
produits.sort(strategies[critereChoisi]);
Avec une IA. Elle connaît les patterns et tend à en mettre partout, y
compris là où un if suffirait. Demandez-lui plutôt : « mon code utilise-t-il
déjà un pattern sans le savoir ? »
Working Effectively with Legacy Code — Feathers
Du code legacy, vous en rencontrerez dès vos stages : tout code existant que vous n’avez pas écrit et devez modifier.
Comprendre avant de modifier. Résistez à l’envie de tout réécrire. Lisez, tracez les flux, identifiez les dépendances — les outils de débogage du navigateur sont faits pour ça.
Le filet de sécurité. Avant de toucher au code existant, un commit Git. Si tout casse, une commande vous ramène en arrière.
gitGraph TB:
commit id: "Existant"
commit id: "Filet"
branch essai-1
commit id: "Approche A"
commit id: "Ça casse"
checkout main
branch essai-2
commit id: "Approche B"
commit id: "Ça marche"
checkout main
merge essai-2Avec une IA. Excellent guide touristique du code legacy : « explique-moi ce que fait ce code, étape par étape » est souvent plus rapide que de déchiffrer seul. Mais elle peut se tromper sur l’intention d’origine, surtout avec des effets de bord subtils. Vérifiez en traçant vous-même.
Software Engineering at Google — Winters, Manshreck & Wright
La revue de code comme apprentissage. En entreprise, chaque modification est relue avant intégration. En projet, montrez votre code et relisez celui d’un camarade : vous apprendrez plus en une heure de relecture mutuelle qu’en trois heures seul.
La documentation vivante. Une documentation non mise à jour est pire que pas de documentation : elle induit en erreur. Documentez les décisions, pas les évidences.
Automatiser les corvées. Si vous faites la même chose à la main plus de trois fois, automatisez. Un linter, un formateur, un script de déploiement — le temps investi est récupéré la première semaine.
Penser à l’échelle du temps. Le code écrit aujourd’hui sera relu dans six mois, deux ans, cinq ans, peut-être par quelqu’un d’autre.
flowchart TD
A["Semaine 1
vous écrivez, tout est frais"] --> B["Mois 3
un camarade doit le modifier"]
B --> C["Mois 6
vous relisez, sans souvenir"]
C --> D["An 2
un stagiaire hérite du projet"]
D --> E["An 5
ça tourne, il faut migrer"]
class A ok
class E attentionAvec une IA. La revue par un modèle est un bon complément, un mauvais remplacement. Elle repère les bugs mécaniques et les incohérences de style, mais ne peut pas juger si votre code communique son intention. Les deux : l’IA en première passe, un camarade pour la vraie relecture.
Les dix réflexes
| # | Réflexe | Source |
|---|---|---|
| 1 | Ne vous répétez pas | Pragmatic Programmer |
| 2 | Nommez clairement | Clean Code, Art of Readable Code |
| 3 | Fonctions courtes et focalisées | Clean Code, Refactoring |
| 4 | Combattez la complexité | Philosophy of Software Design |
| 5 | Refactorez par petits pas | Refactoring, Legacy Code |
| 6 | Commit avant chaque modification risquée | Legacy Code |
| 7 | Commentez le pourquoi | Philosophy of Software Design |
| 8 | Relisez et faites relire | Software Engineering at Google |
| 9 | Automatisez les corvées | Software Engineering at Google |
| 10 | Pensez événement → état → rendu | Design Patterns |
Dans quel ordre les lire
flowchart TD
A["Maintenant
Art of Readable Code
Philosophy of Software Design"] --> B["Après quelques projets
Refactoring · Clean Code
Pragmatic Programmer"]
B --> C["Stages et emplois
Software Eng. at Google
Legacy Code · Design Patterns"]
class A ok
class B attention
class C neutreCommencez par The Art of Readable Code, court et applicable immédiatement, puis A Philosophy of Software Design, dont les principes changent la façon de penser.
Quand vous serez à l’aise, Refactoring — les exemples de la deuxième édition sont en JavaScript —, puis The Pragmatic Programmer un chapitre à la fois, et Clean Code, dont certains exemples sont datés mais dont les principes tiennent.
Plus tard, Software Engineering at Google, Working Effectively with Legacy Code dont vous aurez besoin, c’est garanti, et Design Patterns à consulter comme une référence plutôt qu’à lire de bout en bout.
Sur ce blog
Les articles ne reprennent pas cette liste : ils prennent un désaccord entre ces auteurs et vont au bout. Les règles sont un point de départ explique pourquoi un catalogue de principes ne suffit pas, et pourquoi deux principes justes peuvent se contredire sur le même bout de code — suivi de quatre articles qui déplient chacun un de ces désaccords. Ils paraissent à l’automne, et se trouvent dans la liste des articles.
Références
- Hunt, A. & Thomas, D. (1999). The Pragmatic Programmer. Addison-Wesley.
- Ousterhout, J. K. (2021). A Philosophy of Software Design (2ᵉ éd.). Yaknyam Press.
- Martin, R. C. (2008). Clean Code. Prentice Hall.
- Boswell, D. & Foucher, T. (2011). The Art of Readable Code. O’Reilly.
- Fowler, M. (2018). Refactoring: Improving the Design of Existing Code (2ᵉ éd.). Addison-Wesley.
- Gamma, E., Helm, R., Johnson, R. & Vlissides, J. (1994). Design Patterns. Addison-Wesley.
- Feathers, M. (2004). Working Effectively with Legacy Code. Prentice Hall.
- Winters, T., Manshreck, T. & Wright, H. (2020). Software Engineering at Google. O’Reilly.