💡 Key Takeaways
- Rule I Follow #1: Functions Should Do One Thing (But That Thing Can Be Bigger Than You Think)
- Rule I Follow #2: Names Should Reveal Intent (Even If They're Long)
- Rule I Follow #3: Comments Explain Why, Not What (But Use More Than You Think)
- Rule I Follow #4: Fail Fast and Fail Loud
Je regarde le code des autres depuis 14 ans maintenant en tant qu'architecte logiciel senior dans une entreprise fintech qui traite 2,3 milliards de dollars de transactions par mois. Mardi dernier, j'ai examiné une demande de tirage qui m'a fait grimacer physiquement — 847 lignes dans une seule fonction, des noms de variables tels que "data2" et "temp", et des commentaires qui disaient littéralement "// ici, la magie opère." Le développeur qui l'a écrit ? Un diplômé en informatique de Stanford avec une moyenne de 3,9.
💡 Principaux Enseignements
- Règle que je Suis #1 : Les Fonctions Doivent Faire Une Chose (Mais Cette Chose Peut Être Plus Grande Que Vous Ne Le Pensez)
- Règle que je Suis #2 : Les Noms Doivent Révéler l'Intention (Même S'ils Sont Longs)
- Règle que je Suis #3 : Les Commentaires Expliquent Pourquoi, Pas Quoi (Mais Utilisez-en Plus Que Vous Ne Le Pensez)
- Règle que je Suis #4 : Échouez Vite et Échouez Fort
C'est alors que j'ai réalisé : nous avons enseigné le code propre de manière erronée.
Tout le monde cite "Clean Code" de l'oncle Bob comme s'il s'agissait d'une écriture sacrée. Ils mémorisent les principes SOLID, débattent des tabulations contre les espaces, et écrivent des fonctions si petites qu'il leur faut un microscope pour les lire. Mais voici ce que personne ne vous dit : certaines de ces règles rendent activement votre code pire.
Je ne suis pas ici pour dénigrer le travail de Robert Martin — c'est fondamental et important. Mais après avoir examiné plus de 3 000 demandes de tirage, mentoré 47 développeurs et maintenu une base de code en production depuis 2011, j'ai appris quelles règles comptent vraiment et lesquelles ne sont que du théâtre pour développeurs. Laissez-moi vous montrer ce que je veux dire.
Règle que je Suis #1 : Les Fonctions Doivent Faire Une Chose (Mais Cette Chose Peut Être Plus Grande Que Vous Ne Le Pensez)
Le "principe de responsabilité unique" pour les fonctions est probablement la règle la plus mal comprise en matière de code propre. Je vois des développeurs créer des fonctions de trois lignes, avec des noms comme "validateUserEmailFormat" qui sont appelées par "validateUserEmail" qui est appelé par "validateUser." C'est des tortues tout le long, et vous devez ouvrir sept fichiers juste pour comprendre ce qui se passe lorsque un utilisateur s'inscrit.
Voici ce que je fais réellement : j'écris des fonctions qui accomplissent une opération commerciale significative, pas une opération technique. Quand j'écris une fonction appelée "processPayment", elle peut faire 45 lignes de long. Elle valide le moyen de paiement, vérifie la fraude, crée un enregistrement de transaction et envoie un email de confirmation. Ce sont quatre opérations techniques, mais c'est une opération commerciale : traiter un paiement.
La clé est que chacune de ces étapes est clairement délimitée dans le code. J'utilise des lignes vides pour séparer les sections logiques, et j'ajoute de brefs commentaires qui expliquent le "pourquoi" de chaque section. Lorsque qu'un autre développeur lit "processPayment", il peut comprendre l'ensemble du flux de paiement sans sauter entre douze fichiers différents.
J'ai mesuré cela une fois. Dans notre ancienne base de code, où nous suivions religieusement la règle "les fonctions doivent être petites", le développeur moyen devait ouvrir 8,3 fichiers pour comprendre un seul flux utilisateur. Après avoir refactorisé pour utiliser des fonctions "d'opération significative", ce nombre est tombé à 2,1 fichiers. Le temps de revue de code a diminué de 34%. Le temps de correction des bogues a chuté de 28%.
La règle n'est pas "rendre les fonctions petites". La règle est "rendre les fonctions compréhensibles". Parfois cela signifie 10 lignes. Parfois cela signifie 50. Ce que cela ne signifie jamais, c'est forcer les développeurs à jouer les détectives à travers votre base de code juste pour comprendre comment fonctionne un clic de bouton.
Règle que je Suis #2 : Les Noms Doivent Révéler l'Intention (Même S'ils Sont Longs)
Une fois, j'ai travaillé avec un développeur qui insistait sur le fait que les noms de variables ne devaient jamais dépasser 15 caractères parce que "cela rend le code plus difficile à lire." Il a écrit du code comme ça : "const usrPmtMthd = getUserPaymentMethod();" J'avais envie de jeter mon clavier par la fenêtre.
"Le meilleur code n'est pas le plus astucieux—c'est le code que le prochain développeur peut comprendre à 2 heures du matin lorsque le système est en panne et que les clients appelent."
Voici ma règle : si je ne peux pas comprendre ce qu'une variable contient en lisant son nom une fois, le nom est faux. Je me fiche que cela fasse 40 caractères. Je préfère lire "userSelectedPaymentMethodFromDropdown" que de passer trois minutes à comprendre ce que "pmtMthd" signifie.
Dans notre système de traitement des paiements, nous avons une variable appelée "transactionRequiresAdditionalFraudVerificationBasedOnUserHistory." Elle fait 71 caractères. Elle est également parfaitement claire. Lorsque vous voyez cette variable dans une instruction if, vous savez exactement ce qui est vérifié et pourquoi. Pas de commentaires nécessaires. Pas de traduction mentale requise.
L'argument contraire que j'entends toujours est "mais de longs noms rendent les lignes trop longues!" Bien sûr, si vous prétendez encore que nous écrivons du code sur des terminaux de 80 colonnes de 1985. Nous avons maintenant des moniteurs de 27 pouces. Utilisez-les. J'ai fixé ma limite de longueur de ligne à 120 caractères, et je n'ai jamais eu de problème de lisibilité.
Voici le test que j'utilise : si un développeur junior peut lire le nom de votre variable et savoir immédiatement ce qu'elle contient, de quel type elle est, et à quoi elle sert à peu près, vous l'avez nommée correctement. S'il doit faire défiler vers le haut pour voir où elle a été déclarée ou vérifier la définition du type, vous avez échoué.
J'ai vu cela améliorer la qualité des revues de code de manière spectaculaire. Lorsque les noms sont clairs, les réviseurs passent moins de temps à demander "que fait cela ?" et plus de temps à demander "est-ce la bonne approche ?" C'est là que se trouve la vraie valeur.
Règle que je Suis #3 : Les Commentaires Expliquent Pourquoi, Pas Quoi (Mais Utilisez-en Plus Que Vous Ne Le Pensez)
Les puristes du code propre vous diront que "le bon code n'a pas besoin de commentaires." Ils ont à moitié raison. Le bon code n'a pas besoin de commentaires qui expliquent quoi le code fait. Mais il a absolument besoin de commentaires qui expliquent pourquoi le code existe.
| Règle de Code Propre | Ce Que Disent les Livres | Ce Qui Fonctionne Réellement | Quand la Contredire |
|---|---|---|---|
| Longueur de Fonction | Gardez les fonctions en dessous de 20 lignes | Gardez les fonctions sous un écran (40-60 lignes) | Lorsque la séparation crée plus de confusion que de clarté |
| Commentaires | Le code doit être auto-documenté | Expliquez pourquoi, pas quoi | Algorithmes complexes, règles commerciales ou décisions non évidentes |
| Principe DRY | Ne vous répétez jamais | Ne vous répétez pas encore (attendez la troisième occurrence) | Lorsque l'abstraction lie des fonctionnalités non liées |
| Noms de Variables | Utilisez toujours des noms descriptifs | Le contexte compte : 'i' est acceptable dans les boucles, 'userAuthenticationToken' dans des portées limitées est excessif | Compteurs de boucle, abréviations bien connues dans le contexte du domaine |
Le mois dernier, j'ai trouvé une fonction dans notre base de code qui avait un contournement bizarre : elle ajoutait un délai de 50 millisecondes avant de traiter un webhook. Aucun commentaire. Aucune explication. Juste "await sleep(50);" là comme une mine terrestre. J'ai passé deux heures à essayer de comprendre si c'était un bogue ou intentionnel. Il s'avère que c'était un contournement pour une condition de course dans une API tierce que nous avons découverte après trois jours de débogage en production.
Maintenant, ce code a un commentaire : "// Délai de 50 ms requis : le webhook de Stripe peut arriver avant que leur API ne reflète l'état de la charge. Découvert lors de l'incident #2847 le 15-08-2023. Supprimez ceci après que Stripe ait corrigé son problème de cohérence éventuelle (ticket #45892)."
🛠 Découvrez nos Outils
C'est un bon commentaire. Il explique pourquoi le code existe, fait référence à l'incident qui l'a causé, et fournit même un chemin pour le supprimer à l'avenir. Sans ce commentaire, le prochain développeur aurait pu le supprimer en pensant que c'était une erreur.
J'ajoute des commentaires généreusement dans trois situations : lorsque je contourne un bogue dans une dépendance, lorsque je mets en œuvre une règle commerciale non évidente, et lorsque j'optimise pour la performance d'une manière qui rend le code moins lisible. Dans chaque cas, le commentaire explique le contexte qui n'est pas visible dans le code lui-même.