7 signes révélateurs d'un code illisible : Comment identifier et résoudre le problème
Un projet complexe comporte une quantité massive de code.
Des centaines de méthodes et de classes, des milliers de lignes de code.
Si vous voulez éviter de vous perdre dans la jungle du code, un code pertinent et facile à comprendre est un critère indispensable dans les grands projets.
Malheureusement, tous les développeurs ont été confrontés à la question de la mauvaise lisibilité du code. Tout le monde se souvient d'avoir perdu beaucoup de temps à essayer de comprendre pourquoi un code était obscurci.
Lorsque vous lisez les méthodes, classes et variables mal nommées de quelqu'un d'autre, vous passez beaucoup plus de temps à décrypter le code qu'à écrire un nouveau code fonctionnel.
Mais il ne devrait pas en être ainsi, et il n'y a aucune raison d'écrire de cette manière.
Voici les 7 signes que j'ai le plus souvent rencontrés dans les projets :
1) Noms insignifiants pour les variables, les fonctions et les classes
Cela semble facile, mais il est parfois très difficile de nommer correctement les variables, les fonctions ou les classes. Il y a aussi une citation à ce sujet qui dit :
Examinons cet exemple :Il n'y a que deux choses difficiles en informatique : l'invalidation du cache et le fait de nommer les choses.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 function getScore(w, a){ return w + (a * 5) }
Lorsque vous lisez un code comme celui-ci, vous vous demandez immédiatement ce que signifient les variables w et a, et ce qu'elles représentent. w signifie-t-il wins, weight ou width ? La variable a est-elle liée à l'âge ou peut-être à la moyenne ?
Maintenant, considérez ceci :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 function getScore(wins, averageKda){ return wins + (averageKda * 5) }
Ici, il est clair comme de l'eau de roche que la formule pour le score est un nombre de victoires ajouté à la moyenne KDA multipliée par 5.
Un conseil qui m'aide à nommer les variables est de ne pas être avare de noms et d'allonger un peu le nom de la variable.
Je préfère lire un nom de variable un peu plus long que de passer 30 minutes à lire des tonnes de code pour comprendre ce que fait cette variable.
Si le nom de la variable devient trop long, c'est probablement une bonne idée d'ajouter des commentaires à ce code.
Un bon nom pour une variable, une classe ou une fonction doit être descriptif et explicite.
Il n'est pas nécessaire d'ajouter des commentaires si le nom décrit correctement la variable associée.
2) Scripts volumineux
Lorsque vous ouvrez un script auquel vous devez apporter une nouvelle modification et que vous constatez qu'il contient plus de 2000 lignes de code, vous êtes immédiatement déprimé, sachant que vous devrez parcourir tout ce code pour savoir où implémenter votre modification.
En règle générale, si un script contient plus de 500 lignes de code, il a besoin d'être nettoyé et remanié, en exportant des éléments de la logique commerciale vers des scripts distincts, des composants ou des fonctions réutilisables.
Le fait d'accumuler les lignes de code dans d'énormes scripts indique que vous ne pensez pas du tout à la modularité du code.
Cela signifie que vous vous contentez de jeter vos idées dans le code sans penser à la lisibilité du code, au principe DRY, au principe KISS, à la réutilisation et à bien d'autres choses auxquelles les bons développeurs pensent.
3) Chiffres magiques
Celui-ci est un classique. Considérez ce code :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 if(user.status === 0){ //do something }
Lorsque vous le lisez, vous avez une conversation avec vous-même comme celle-ci :
- Que signifie 0 ?
- Hmm, je vois qu'il s'agit d'un certain type de statut d'utilisateur, mais quel type de statut exactement ?
- Je vais probablement devoir lire tout ce code pour arriver à une conclusion sur la signification de 0.
- Comment suis-je censé mettre en œuvre le changement dans le code si je ne sais pas quel type de statut d'utilisateur ce projet a, sinon je risque d'introduire des bogues.
Comparez maintenant avec ce code :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 const USER_STATUS = { active: 0, inactive: 1, banned: 2, } if(user.status === USER_STATUS.active){ //do something }
C'est beaucoup mieux.
Lorsque vous rencontrez des chiffres dans votre code, demandez-vous toujours si vous aimeriez les lire dans la vie réelle :
Au lieu deJe suis allé au cinéma #17 pour voir le film #36
Il en va de même pour le code : lorsque vous le lisez, il ne doit pas y avoir de chiffre.Je suis allé au cinéma CineStar pour voir le film Avatar.
4) Une grosse ligne unique (Big fat one-liners)
Les développeurs aiment montrer à quel point ils sont doués.
L'une des pires façons de le montrer est de raccourcir leur code, et au lieu d'écrire 20 lignes de code, ils l'écrasent en une seule ligne.
Il est possible de faire des one-liners délirants dans presque tous les langages de programmation, mais je pense que Python fait partie du top 3.
C'est vraiment fou ce qu'on peut y taper et faire tenir en une seule ligne.
Considérez ce code :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 array = [29,99,27,41,66,28,44,78,87,19,31,76,58,88,83,97,12,21,44] q = lambda l: q([x for x in l[1:] if x <= l[0]]) + [l[0]] + q([x for x in l if x > l[0]]) if l else [] print(q(array))
Savez-vous ce qu'il fait ? Est-il lisible pour vous ? Combien de temps passeriez-vous à le comprendre ?
Il s'agit du code d'un algorithme de tri rapide.
Je préférerais personnellement une version plus longue mais plus lisible que ce one-liner délirant.
5) Des conceptions de classes ambiguës
Le sujet de la programmation orientée objet est vaste. Il est difficile de comprendre et de mettre en pratique la théorie de la conception des classes.
Les relations entre plusieurs classes peuvent se compliquer au fur et à mesure que le projet prend de l'ampleur. Les principes SOLID sont la méthode idéale pour écrire du code orienté objet dans cette situation.
Prenons l'exemple de cette classe que j'ai rencontrée un jour :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 class AlwaysNotAvailableAvailability{ static _available(){ return false; } }
Tout d'abord, le nom de cette classe est vraiment déroutant. L'auteur a probablement voulu créer quelque chose pour les cas d'utilisation où une entité n'est jamais disponible.
Deuxièmement, cette classe ne fait rien, elle renvoie simplement une valeur fausse.
Pourquoi encapsuler une chose aussi simple qu'une valeur fausse dans la méthode statique de la classe alors que vous pouvez traiter ces cas sans classe ?
Si vous devez ajouter une classe, assurez-vous qu'elle a un sens.
6) Duplication du code
Le développement de logiciels suit la règle quelque peu controversée de « ne pas se répéter », ou « DRY ».
Cette règle vise à rendre le code plus clair, moins sujet aux erreurs et moins difficile à manipuler.
DRY vise à y parvenir en éliminant le code redondant de votre base de code et en le remplaçant par des abstractions telles que des fonctions, des classes et des méthodes.
Il est très simple de remarquer la répétition du code et d'extraire les morceaux de code répétitifs dans des fonctions, des composants ou des classes, selon ce qui vous convient le mieux.
C'est l'un des exemples les plus fous que j'ai vus dans des projets qui violent le principe DRY et le bon sens :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 segments.forEach(function(val){ if(val.id === 32){ result.push(val); } }) segments.forEach(function(val){ if(val.id === 19){ result.push(val); } }) segments.forEach(function(val){ if(val.id === 21){ result.push(val); } }) segments.forEach(function(val){ if(val.id === 7){ result.push(val); } }) segments.forEach(function(val){ if(val.id === 16){ result.push(val); } }) segments.forEach(function(val){ if(val.id === 10){ result.push(val); } }) segments.forEach(function(val){ if(val.id === 11){ result.push(val); } }) return result;
Je ne sais pas comment ce code s'est retrouvé en production, mais il est ahurissant de voir à quel point il est illisible et non optimisé :
- il itère à travers le tableau de segments plusieurs fois sans aucune nécessité
- il compare les conditions avec des nombres magiques
- il n'utilise pas l'opérateur or
Tout ce code peut être remplacé par 2 lignes :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 const allowedIds = [32, 19, 21, 7, 10, 16, 11] return segments.filter(val => allowedIds.includes(val.id))
7) Code mort
Dans les projets anciens, vous trouverez toujours du code mort. Un champ, une méthode, une variable ou une classe n'est plus utilisé (généralement parce qu'il est obsolète).
Cela se produit parce que personne n'a eu le temps de remanier le code obsolète lorsque les spécifications du logiciel ont changé ou que des réparations ont dû être effectuées.
Il y a aussi des développeurs qui aiment conserver ce vieux code, juste au cas où ils en auraient besoin à l'avenir.
Cela n'a pas beaucoup de sens, car il est utilisé dans tous les projets et vous pouvez facilement le retrouver.
L'utilisation d'un bon IDE est l'approche la plus rapide pour découvrir le code mort :
- supprimer les fichiers inutiles et le code non utilisé
- éliminer les paramètres inutiles
- supprimer la classe redondante, en fusionnant la sous-classe et la super-classe en une seule ou en déplaçant toutes les caractéristiques de la classe vers une autre.
Les avantages de la suppression du code mort sont la réduction de la taille du code et une maintenance plus facile du projet.
Source : "7 Tell-Tale Signs of Unreadable Code: How to Identify and Fix the Problem" (Mensur Durakovic)
Et vous ?
Quel est votre avis sur le sujet ?
Voir aussi :
Boostez votre carrière dans le développement de logiciels grâce à ces 10 compétences essentielles
10 vérités difficiles à avaler que l'on ne vous dira pas sur le métier d'ingénieur logiciel, par Mensur Durakovic, ingénieur logiciel
Partager