Code propre : l'ingénierie pour les humains
Le code est lu 10 fois plus qu’il n’est écrit. Un guide technique sur le nommage, le principe de responsabilité unique et pourquoi le « Clever Code » est en fait une dette technique.
“N’importe quel imbécile peut écrire du code qu’un ordinateur peut comprendre. Les bons programmeurs écrivent du code que les humains peuvent comprendre.” —Martin Fowler.
Cette citation est le fondement d’une culture d’ingénierie spécifique à Maison Code Paris. Nous n’optimisons pas pour les “Lignes de Code”. Nous n’optimisons pas la “vitesse de frappe”. Nous optimisons pour la Maintenabilité.
Le compilateur ne se soucie pas de savoir si vous nommez votre variable « x » ou « daysUntilExpiration ». Le processeur l’exécute exactement dans la même nanoseconde. Mais le développeur junior qui se réveille à 3h00 du matin pour corriger un bug critique s’en soucie profondément. S’ils doivent passer 10 minutes à déchiffrer les noms de vos variables, l’entreprise perd de l’argent. Clean Code est un acte d’empathie.
Pourquoi Maison Code en parle
Chez Maison Code Paris, nous agissons comme la conscience architecturale de nos clients. Nous héritons souvent de stacks “modernes” construites sans compréhension fondamentale de l’échelle.
Nous abordons ce sujet car il représente un point de pivot critique dans la maturité de l’ingénierie. Une mise en œuvre correcte différencie un MVP fragile d’une plateforme résiliente de niveau entreprise.
1. Nommer : le problème le plus difficile en informatique
Les noms doivent révéler l’intention. Un nom de variable doit vous dire trois choses :
- Ce qu’il fait.
- Pourquoi ça existe.
- Comment il est utilisé.
La règle du « pas de cartographie mentale »
Mauvais :
const d = 10 ; // jours
liste const = []; // utilisateurs
Le lecteur doit traduire « d » -> « jours » dans sa tête. Cela utilise la charge cognitive (RAM).
Bien :
const joursSinceLastLogin = 10 ;
const utilisateursactifs = [];
Le code se lit comme de la prose anglaise.
La règle de la longueur de la portée
- Small Scope (Loop) : Les noms courts sont acceptables.
for (let i = 0; i < 10; i++)est très bien. - Grande portée (globale/classe) : les noms doivent être explicites. « je » est interdit. Utilisez
globalRetryCounter.
2. Fonctions : faire une chose
Le principe de responsabilité unique (SRP) s’applique aux fonctions, pas seulement aux classes. Une fonction doit avoir un niveau d’abstraction.
Mauvais (la fonction divine) :
fonction asynchrone registerUser(req) {
// 1. Analyse
const { email, mot de passe } = req.body;
// 2. Validation
if (!email.includes('@')) throw new Error('Invalid Email');
// 3. Logique de base de données
const utilisateur = attendre db.users.create({
courrier électronique,
mot de passe : bcrypt.hashSync (mot de passe)
});
// 4. Logique de courrier électronique
wait mailgun.messages().send({ à : email, texte : "Bienvenue !" });
// 5. Logique de réponse
return {statut : 200, identifiant : user.id } ;
}
Cette fonction change si :
- La base de données change (Postgres vers Mongo).
- Le fournisseur de messagerie change (Mailgun vers SendGrid).
- Le format de l’API change. C’est fragile.
Bon (L’Orchestrateur) :
fonction asynchrone registerUser(req) {
const accountInfo = parseRequest(req);
validateAccount(accountInfo);
const user = wait createUserInDatabase(accountInfo);
attendre sendWelcomeEmail(utilisateur);
format de retourRéponse(utilisateur);
}
Désormais, registerUser n’est qu’un orchestrateur. Cela raconte une histoire. Les détails de mise en œuvre sont cachés dans de petites fonctions ciblées.
3. Commentaires : L’échec de l’expression
Les meilleurs ingénieurs écrivent moins de commentaires, pas plus. Pourquoi? Parce que Les commentaires sont une odeur de code. Si vous devez écrire un commentaire pour expliquer ce que fait le code, votre code est trop complexe. Refactorisez-le.
Mauvais :
// Vérifiez si l'utilisateur est éligible à la réduction senior
if (user.age > 65 && user.purchases > 10 && user.country === 'FR') {
appliquerDiscount();
}
Bien :
if (user.isEligibleForSeniorDiscount()) {
appliquerDiscount();
}
Quand commenter ?
Commentez le POURQUOI, pas le QUOI. Le code explique ce qui se passe. Le commentaire explique le contexte commercial ou l’étrange solution de contournement.
// Nous utilisons ici un délai de 500 ms car l'API de paiement externe
// a une condition de concurrence critique s'il est interrogé immédiatement après la création.
// Voir billet n°452.
délai d'attente (500);
Ce commentaire évite au prochain développeur de “optimiser” le délai.
4. Conditionnels : évitez le code fléché
Le « code de flèche » se produit lorsque les instructions « if » imbriquées créent une forme comme une flèche « > ». Cela pousse la logique vers le côté droit de l’écran et rend difficile le suivi de l’état.
Mauvais :
function processPaiement (commande) {
si (commande) {
si (order.isPaid) {
si (commande.montant > 0) {
// Logique
}
}
}
}
Bon (clauses de garde) : Revenez tôt. Tuez la fonction dès que possible.
function processPaiement (commande) {
si (!commande) return ;
si (!order.isPaid) retourne;
si (order.amount <= 0) return ;
// Logique (Pas d'indentation)
}
5. Obsession primitive
Ne transmettez pas de chaînes et de chiffres bruts. Transmettez des Objets qui appliquent des règles.
Mauvais :
fonction bookFlight (origine : chaîne, destination : chaîne)
« NYC » est-il valide ? « New York » est-il valide ? “JFK” est-il valide ?
Bien :
fonction bookFlight (origine : AirportCode, destination : AirportCode)
La classe AirportCode garantit que seuls des codes IATA valides à 3 lettres peuvent exister dans le système.
Vous rendez les états invalides irreprésentables.
7. Tests comme documentation
La meilleure documentation est un test unitaire.
Les documents deviennent obsolètes. Les tests ne le font pas.
Si vous voulez savoir comment fonctionne calculateDiscount(), lisez les cas de test.
it('devrait appliquer 10 % pour les nouveaux utilisateurs')it('devrait échouer si le panier est vide')L’écriture de tests vous oblige à écrire du Clean Code. Si une fonction est difficile à tester, c’est un mauvais code. “Je ne peux pas tester cela car il interroge la base de données à l’intérieur de la fonction.” Refactor : injectez la dépendance DB. Maintenant, c’est testable.
8. La culture de révision du code
La révision de code ne sert pas à trouver des bogues. C’est à cela que sert CI. La révision du code est destinée au partage de connaissances. Il s’agit d’une séance de mentorat. “Pourquoi avez-vous choisi un ensemble au lieu d’un tableau ici ?” “Ce modèle est intéressant, pouvons-nous également l’utiliser dans le module Utilisateur ?” Les ingénieurs seniors ne devraient pas simplement dire « LGTM ». Ils doivent expliquer pourquoi quelque chose est bon ou mauvais. Nous avons besoin d’au moins 1 « Nitpick » ou « Suggestion » par PR. Cela force l’engagement.
9. La règle des scouts
“Laissez toujours le terrain de camping plus propre que vous ne l’avez trouvé.”
C’est l’antidote à la dette technique.
Vous corrigez un bug dans le module Pricing. Vous remarquez une variable nommée « x ».
** Renommez-le. **
Vous remarquez une fonction trop longue.
** Divisez-le. **
Ne demandez pas la permission. Ne créez pas de ticket « Refactor Pricing ». Faites-le simplement dans le cadre de votre travail.
Si chaque ingénieur nettoie 1 % du code qu’il touche, la base de code reste intacte pour toujours.
7. DRY vs WET (Le piège de l’abstraction)
On nous enseigne DRY (Don’t Repeat Yourself).
C’est une bonne règle. Mais c’est dangereux.
Si vous voyez deux morceaux de code qui se ressemblent, vous les fusionnez dans une fonction partagée.
Le problème : désormais, les deux endroits s’appuient sur cette fonction.
Si la fonctionnalité A nécessite une légère modification de la fonction, vous ajoutez un indicateur booléen.
fonction doThing(isFeatureA)
Ensuite, la fonctionnalité B doit être modifiée.
fonction doThing(isFeatureA, isFeatureB)
Bientôt, vous avez une fonction divine avec 10 drapeaux.
WET (Write Everything Twice) est souvent meilleur.
La duplication coûte moins cher qu’une mauvaise abstraction.
Si deux fonctionnalités partagent accidentellement une logique mais ont des raisons commerciales différentes de changer, copiez-collez le code.
8. La théorie des « fenêtres cassées »
En criminologie, si un bâtiment a une fenêtre cassée qui n’est pas réparée, les vandales briseront bientôt toutes les fenêtres. Le code est le même. Si vous laissez une fonction en désordre, le prochain développeur pensera : “De toute façon, ce fichier est une poubelle, je vais simplement pirater mon correctif.” Si le dossier est intact, ils ressentiront la pression sociale pour le garder intact. Soyez le jardinier. Éliminez le désordre quotidiennement.
9. Conclusion
Clean Code n’est pas une question d’esthétique. Il s’agit d’économie. Le code désordonné pourrit. Cela devient un « Legacy Code » auquel tout le monde a peur de toucher. Les fonctionnalités prennent plus de temps à être créées. Les bugs apparaissent plus souvent. Clean Code est un atout. Il vous permet de vous déplacer rapidement indéfiniment.
La base de code est en désordre ?
Votre vitesse ralentit-elle à cause du « Spaghetti Code » ?
Planifier un audit de code. Découvrez les Tests unitaires et le Refactoring.
Clean Code n’est pas une question d’esthétique. Il s’agit d’économie. Le code désordonné pourrit. Cela devient un « Legacy Code » auquel tout le monde a peur de toucher. Les fonctionnalités prennent plus de temps à être créées. Les bugs apparaissent plus souvent. Clean Code est un atout. Il vous permet de vous déplacer rapidement indéfiniment.
Écrivez du code pour l’humain qui le lira. Parce que dans 6 mois, cet humain sera vous.
La base de code est en désordre ?
Votre vitesse ralentit-elle à cause du « Spaghetti Code » ?