Un mauvais code peut fonctionner. Mais s’il n’est pas propre, il peut mettre une société de développement de logiciels à genoux. Dans le monde entier, des ressources exceptionnelles sont perdues à cause d’un code mal conçu. Mais ce n’est pas une fatalité. En août 2008, le célèbre expert en logiciels Robert C Martin a présenté un livre complet intitulé Clean Code. Ce livre vous inculque les valeurs fondamentales d’un artisan du logiciel et des approches pour concevoir un code propre et faire de vous un meilleur programmeur.
COMMENT CE LIVRE NOUS A-T-IL AIDÉS ?
Ce livre nous a aidés à comprendre que devenir de meilleurs artisans du logiciel et écrire un code propre est ce que nous devons faire pour nous considérer comme des professionnels. Le code propre nous éclaire sur les tests unitaires, le formatage, le débogage et l’utilisation de noms descriptifs, qui nous aident à écrire un code plus propre et plus robuste pour nos clients. L’écriture d’un code propre est une question d’habitude personnelle et de compétence. Au fil du temps, vous devrez acquérir de l’expérience et des connaissances pour écrire du code propre.
LE LIVRE EXPLIQUÉ EN MOINS DE 60 SECONDES
L’auteur met l’accent sur les fonctions : elles doivent être petites, effectuer une seule tâche et avoir des noms descriptifs. Il affirme que si une fonction nécessite de nombreux arguments de configuration, il faut envisager de les intégrer dans une seule variable d’options de configuration.
Le livre insiste sur le fait que les développeurs doivent s’en tenir au principe de la responsabilité unique, qui stipule qu’une classe ou un module ne doit avoir qu’une seule raison de changer. Ce principe nous a donné une définition de la responsabilité et des lignes directrices pour la taille des classes. Les classes doivent avoir une seule responsabilité et une seule raison de changer.
TROIS CITATIONS PRINCIPALES
« Un code sans tests n’est pas propre. Quelle que soit son élégance, sa lisibilité et son accessibilité, il est impur s’il n’est pas testé ».
« Chaque système est construit à partir d’un langage spécifique à un domaine, conçu par les programmeurs pour décrire ce système. Les fonctions sont les verbes de ce langage et les classes sont les noms.
« La gestion des erreurs est importante, mais si elle obscurcit la logique, elle est erronée.
RÉSUMÉS ET NOTES DE LECTURE
Premier chapitre : Un code propre
La propreté du code est importante : un code erroné finira par entraîner l’effondrement d’une entreprise car, au fur et à mesure du développement, la productivité se rapproche progressivement de zéro.
Le coût total du désordre augmente avec le temps. Plus le code devient désordonné, moins il y a de chances de le nettoyer. La productivité de l’équipe diminue au fur et à mesure que le désordre s’accroît parce qu’elle est sous pression pour respecter un délai ou qu’elle veut augmenter sa productivité.
Il faut du temps et des ressources pour reconstruire un système à partir de zéro. Le remaniement et les améliorations progressives sont généralement les meilleures options à prendre. Garder votre code propre est rentable et c’est une question de survie professionnelle.
Vous passeriez des mois à essayer d’accomplir une tâche qui n’aurait pris que quelques heures dans un code désordonné. Un bon code pourrit rapidement un mauvais code parce que les changements d’exigences dans les approches contrecarrent la conception d’origine.
Un code propre est bien testé et exécute efficacement une seule tâche, alors qu’un code médiocre en fait généralement trop par négligence.
Les codes désordonnés ralentissent les développeurs, mais tous se sentent obligés de faire du désordre pour respecter les délais. En général, vous ne respecterez pas le délai en faisant du désordre. La seule façon de respecter le délai est de maintenir un code propre.
Citation préférée du chapitre : « Écrire du code propre est ce que vous devez faire pour vous considérer comme un professionnel. Il n’y a pas d’excuse raisonnable pour ne pas faire de son mieux. »
Chapitre deux : Noms significatifs
Il n’est pas nécessaire de préciser que les noms doivent divulguer leur raison d’être. La sélection de bons noms prend du temps mais permet d’en gagner plus qu’il n’en faut. Prenez soin des noms que vous avez choisis et changez-les lorsque vous en trouvez de meilleurs.
Le choix d’un bon nom est complexe, et le nom d’une fonction ou d’une variable doit expliquer ce qu’elle est, comment elle est utilisée et pourquoi elle existe. Si un nom appelle un commentaire, il ne révèle pas son intention.
Vous devez éviter de laisser de faux indices qui cachent le sens du code. Évitez les mots dont le sens établi diffère du sens que vous souhaitez donner.
Évitez d’utiliser des abréviations dans les noms de fonctions et les noms de variables à un seul caractère, à l’exception des noms couramment utilisés tels que « i » pour la variable compteur dans une boucle.
Les variables doivent être prononçables afin que vous puissiez en parler et les dire à haute voix. Vous ne pouvez en discuter avec vos coéquipiers que si vous pouvez les prononcer.
Les noms à une lettre et les constantes numériques posent un problème spécifique. Il faut du temps pour les localiser dans un corps de texte. Les noms à une lettre ne peuvent être utilisés comme variables locales qu’à l’intérieur de méthodes courtes.
Citation préférée du chapitre : « Un long nom descriptif vaut mieux qu’un long commentaire descriptif ».
Chapitre trois : Les fonctions
La première règle des fonctions est qu’elles doivent être mineures et la seconde qu’elles ne doivent exécuter qu’une seule tâche. Les fonctions doivent être insignifiantes au point de contenir des structures imbriquées. Par conséquent, le niveau d’indentation d’une fonction ne doit pas être supérieur à un ou deux. Les fonctions sont ainsi plus faciles à lire et à comprendre.
Les fonctions devraient avoir le moins de paramètres possible. Les paramètres ont tendance à rendre les fonctions difficiles à comprendre et se situent à un niveau d’abstraction inférieur. Évitez autant que possible d’utiliser des paramètres en introduisant des classes d’aide abstraites ou en transformant les arguments en variables membres.
Pour vous assurer que vos fonctions exécutent une seule tâche, vous devez veiller à ce que les instructions qu’elles contiennent se situent toutes au même niveau d’abstraction.
Utilisez des noms significatifs pour désigner vos fonctions. Les noms descriptifs expliquent ce que fait une fonction. Plus une fonction est petite et ciblée, plus il est facile de choisir un nom descriptif.
Citation préférée du chapitre : « Vous savez que vous travaillez sur un code propre lorsque chaque routine s’avère être à peu près ce à quoi vous vous attendiez. »
Chapitre quatre : Commentaires
L’utilisation des commentaires compense votre incapacité à vous exprimer en code. Les commentaires sont des échecs constants. Vous devez les avoir parce que vous n’arrivez que parfois à vous décrire sans eux.
Un code propre et expressif avec peu de commentaires est bien meilleur qu’un code encombré et complexe avec de nombreux commentaires. Par conséquent, passez du temps à nettoyer le désordre de votre code plutôt qu’à rédiger des commentaires qui expliquent votre désordre.
La plupart des commentaires sont des béquilles et des justifications pour un code médiocre. Les commentaires peuvent être évités en utilisant des variables nommées distinctement et en extrayant des sections de code dans des fonctions clairement nommées.
N’utilisez pas les Javadocs juste pour le plaisir de les utiliser. Les commentaires qui expliquent ce que fait une méthode, les arguments qu’elle prend et ce qu’elle renvoie sont généralement au mieux redondants et au pire trompeurs.
Les commentaires doivent contenir toutes les informations applicables et le contexte dont les personnes qui les lisent auront besoin. Ne soyez pas paresseux dans la rédaction de vos commentaires.
Citation préférée du chapitre : « Ne commentez pas un mauvais code, réécrivez-le ».
Chapitre 5 : Mise en forme
Veillez à ce que votre code soit formaté de manière attrayante. Sélectionnez un ensemble spécifique de règles gérables qui contrôlent le format de votre code. Ensuite, appliquez systématiquement ces règles à votre code. Il est préférable de disposer d’un outil pour mettre en œuvre ces règles de formatage.
Le formatage des codes est essentiel. Elle est trop cruciale pour être ignorée. Ne comptez pas sur les humains pour détecter et corriger manuellement chaque erreur de formatage. Utilisez plutôt un formateur de code automatisé et un linter de code. Cette méthode est efficace et productive et permet de gagner du temps lors des revues de code.
Les fichiers sources doivent ressembler à un article de journal. Le nom doit être simple mais explicite. Le nom doit permettre de savoir si vous vous trouvez dans un module approprié. Les parties les plus élevées de votre fichier source doivent présenter des concepts et des algorithmes de haut niveau. Ensuite, les détails doivent augmenter au fur et à mesure que vous descendez.
Les variables doivent être déclarées à proximité de l’endroit où elles sont utilisées. Pour les petites fonctions, il s’agit généralement du début de la fonction. Même pour les fonctions courtes, mettez-les bien en forme au lieu de les écrire sur une seule ligne.
Citation préférée du chapitre : « Le formatage des codes est important. Il est trop important pour être ignoré, et il est trop important pour être traité religieusement. La mise en forme du code est une question de communication, et la communication est la première tâche du développeur professionnel. »
Chapitre six : Objets et structures de données
Vous gardez vos variables privées parce que vous ne voulez pas que quelqu’un d’autre en dépende. Vous voulez conserver la liberté de modifier leur type ou leur implémentation de manière impulsive. De nombreux développeurs ajoutent automatiquement des getters et setters à leurs objets, révélant ainsi leurs variables privées comme si elles étaient publiques.
N’ajoutez pas de getters et de setters par défaut, mais fournissez plutôt une interface abstraite pour les données afin que vous puissiez ajuster l’implémentation sans penser aux clients.
Les objets placent leurs données derrière des abstractions et révèlent les fonctions qui travaillent sur ces données à l’abri des regards. Les structures de données exposent leurs données et n’ont pas de fonctions significatives.
La loi de Demeter stipule qu’un module ne doit pas connaître les entrailles de l’objet qu’il manipule. Cela signifie qu’un objet ne doit pas révéler sa structure interne par le biais d’accesseurs, car cela revient à exposer, au lieu de cacher, sa structure interne. Comme les objets cachent les données et exposent le comportement, il est facile d’ajouter de nouveaux objets sans modifier les comportements actuels. Les structures de données révèlent les données et n’ont pas de comportement inhabituel, ce qui facilite l’ajout de nouveaux comportements aux structures de données existantes.
Citation préférée du chapitre : « Dans un système donné, nous voudrons parfois avoir la flexibilité d’ajouter de nouveaux types de données, et nous préférerons donc les objets pour cette partie du système. D’autres fois, nous voudrons avoir la possibilité d’ajouter de nouveaux comportements. Nous préférons alors les types de données et les procédures dans cette partie du système. »
Chapitre sept : Gestion des erreurs
La gestion des erreurs est essentielle, et il y en a généralement beaucoup au cours de la programmation. Cependant, elle ne doit pas masquer l’intention principale du code. Par conséquent, utilisez des attentes plutôt que des codes de retour.
Les exceptions doivent être informatives et fournir des informations objectives, contextuelles et détaillées sur le type d’erreur à une personne qui reçoit le message d’erreur et qui a besoin d’un dépannage efficace.
Les exceptions définissent la portée de votre programme. Lorsque vous implémentez du code dans la partie try d’une instruction try-catch-finally, vous indiquez que l’exécution peut s’arrêter à n’importe quel point et redémarrer au niveau du catch.
Lorsque vous enveloppez les API de tiers dans une fine couche d’abstraction, il devient plus facile d’échanger une bibliothèque contre une autre à l’avenir et de simuler la bibliothèque pendant les tests.
Citation préférée du chapitre : « Un code propre est lisible, mais il doit aussi être robuste. Ces objectifs ne sont pas contradictoires. Nous pouvons écrire un code propre et robuste si nous considérons la gestion des erreurs comme une préoccupation particulière. »
Chapitre huit : Limites
Le code tiers vous aidera à obtenir plus de fonctionnalités en moins de temps. Ce n’est pas à vous de tester le code tiers, mais vous devriez avoir intérêt à écrire des tests pour le code tiers que vous utilisez.
Les tests d’apprentissage sont des expériences précises qui permettent d’améliorer votre compréhension. Les tests d’apprentissage confirment que les paquets tiers que vous utilisez fonctionnent comme vous l’avez prévu. Il n’y a aucune garantie que le code tiers restera compatible avec vos besoins lorsqu’il sera combiné.
Les bons logiciels s’adaptent aux changements sans nécessiter d’investissements importants ni de remaniements. Lorsque vous utilisez un code sur lequel vous n’avez aucun contrôle, des précautions exceptionnelles doivent être prises pour protéger votre investissement et faire en sorte que les changements futurs soient gérables.
Les limites des tiers sont gérées par quelques endroits du code qui y font référence.
Évitez de laisser une trop grande partie de votre code connaître les particularités de la tierce partie. Il est préférable de s’appuyer sur quelque chose que vous pouvez contrôler plutôt que sur quelque chose que vous ne pouvez pas contrôler.
Citation préférée du chapitre : « Nous devrions éviter de laisser une trop grande partie de notre code connaître les particularités des tiers. Il vaut mieux dépendre de quelque chose que vous contrôlez que de quelque chose que vous ne contrôlez pas, de peur qu’il ne vous contrôle. »
Chapitre neuf : Tests d’unité
Le développement piloté par les tests exige que vous écriviez des tests unitaires avant d’écrire le code de production. Vous ne pouvez pas écrire le code de production tant que vous n’avez pas écrit un test unitaire qui échoue. Le code de test doit être aussi propre que le code de production, à quelques exceptions près, généralement liées à la mémoire ou à l’efficacité.
Veillez à ce que vos tests soient propres ou moins, vous les perdrez. Et en leur absence, vous perdez la seule chose qui permet à votre code d’être réutilisable, flexible et maintenable. Vous ne craindrez pas de modifier votre code en présence de tests, mais sans eux, chaque modification est un bogue réalisable.
La lisibilité est ce qui rend un test propre. La lisibilité est peut-être encore plus essentielle dans les tests unitaires que dans le code de production. La clarté, la simplicité et la densité d’expression sont ce qui rend les tests lisibles. Dans un test, vous devez dire beaucoup de choses avec le moins d’expressions possible.
En général, vous souhaitez tester un seul concept dans chaque fonction de test. Vous ne voulez pas de fonctions de test étendues qui testent une chose diversifiée après l’autre.
Tout comme le code de production, les tests sont également essentiels à la robustesse du projet. Les tests sont nécessaires parce qu’ils améliorent et préservent la réutilisation, la maintenabilité et la flexibilité du code. Veillez à ce que vos tests soient propres et faites en sorte qu’ils soient significatifs et brefs. Développez des API qui agissent comme un langage spécifique au domaine qui vous aide à écrire des tests.
Citation préférée du chapitre : « Les tests doivent être écrits en temps voulu. Les tests unitaires doivent être écrits juste avant le code de production qui les fait passer. »
Chapitre dix : Les classes
Les classes doivent commencer par une liste de variables. Les constantes statiques publiques doivent venir en premier, puis les variables statiques privées, suivies des variables d’instance privées. Les utilitaires privés appelés par une fonction publique doivent être placés juste après.
La première règle des classes est qu’elles doivent être petites. Tout comme les fonctions, la petite taille est la règle principale pour créer des classes. Mais la vraie question est toujours : « quelle taille ? ». Avec les fonctions, vous calculez la taille en comptant les lignes physiques. Avec les classes, vous mesurez la taille en comptant les responsabilités.
Les classes doivent avoir un petit nombre de variables d’instance. Chaque méthode d’une classe doit contrôler une ou plusieurs de ces variables. Plus une méthode influence de variables, plus elle est cohérente avec sa classe.
Utilisez de nombreuses petites classes plutôt que quelques grandes classes dans votre application. Cela minimise la quantité d’informations qu’un collègue développeur devra comprendre lorsqu’il travaillera sur une tâche donnée.
Citation préférée du chapitre : « Une classe ou un module doit avoir une, et une seule, raison de changer. »
COMMENT CE LIVRE PEUT-IL AIDER LES DÉVELOPPEURS DE LOGICIELS ?
« Clean Code » de Robert C. Martin peut aider les développeurs de logiciels à améliorer la qualité de leur code. Il fournit des conseils pratiques et des lignes directrices sur la manière d’écrire un code lisible, facile à maintenir et efficace. Le livre couvre les thèmes du nommage, des commentaires, du formatage et des tests et souligne l’importance de la simplicité, de la clarté et de la cohérence dans les pratiques de codage. En suivant les principes décrits dans le livre, les développeurs peuvent réduire la dette technique, augmenter la productivité et créer des logiciels plus faciles à comprendre, à modifier et à étendre. Il fournit aux développeurs de logiciels une approche complète du codage qui peut les aider à améliorer leurs compétences et à réduire le coût de la maintenance. Ce livre aide les programmeurs à écrire un code facile à modifier et à remanier à l’avenir. Il s’agit d’un ouvrage incontournable pour tout développeur de logiciels qui souhaite devenir un meilleur programmeur.