Clean Code : partie 2 – le nommage

N’importe quel développeur peut produire du code qu’un ordinateur est capable de comprendre. Ce qui caractérise un bon développeur, c’est qu’il écrit du code que d’autres développeurs sont capables de comprendre. Dans cette optique, un nommage rigoureux des éléments du code est essentiel.

Limiter les commentaires

En matière de nommage des identificateurs, la règle d’or suivante devrait rester en permanence à l’esprit : si j’ai besoin de commentaires pour décrire ce que fait un élément, alors je peux probablement faire mieux au niveau du nommage.

Voici un exemple :

int number = 0; // number of items in basket

En utilisant un nom plus explicite, on peut se passer d’utiliser un commentaire :

int numberOfItemsInBasket = 0;

De plus, étant portée par son nom, la description de ce que fait la variable est présente à chaque fois qu’elle est utilisée. Il n’est plus nécessaire de revenir à sa déclaration pour se remémorer ce qu’elle fait.

D’une manière générale, dès qu’un commentaire est présent dans le code, il faut se demander si on peut le supprimer en utilisant un nommage explicite. Les commentaires ne devraient être présents que pour expliquer des choix de conception ou des règles de gestion assez pointues.

Moins le code contient de commentaires, et mieux il se porte : en effet, les commentaires sont difficiles à maintenir et deviennent rapidement obsolètes. De ce fait, les commentaires peuvent contenir des informations erronées, alors que le code, lui, ne ment pas.

Une autre façon de limiter les commentaires consiste à extraire une méthode afin d’indiquer ce que fait un bloc de code. Au lieu de commenter pour indiquer ce que fait ce bloc, on peut l’extraire dans une nouvelle méthode dont le nom indique le comportement effectué par le bloc de code.

Les commentaires devraient être utilisés dans les cas suivants : documentation d’API (ex: Javadoc), expression d’une intention subtile, ou encore mentions légales.

Utiliser des noms informatifs

Séries de nombres

Les nommages utilisant des séries de nombres (n1, n2, n3, etc.) sont à proscrire car ils ne donnent aucune indication sur le rôle de la variable. Lorsqu’ils sont présents en grande quantité dans un bloc de code, ils obligent à se creuser la tête pour essayer de comprendre ce que le code est supposé faire.

Pour copier un fichier par exemple, on évitera la signature suivante :

void copyFile(File f1, File f2);

On utilisera à la place cette signature, beaucoup plus claire sur le sens de la copie :

void copyFiles(File sourceFile, File destinationFile);

L’utilisation de nombres reste toutefois acceptable pour certaines opérations mathématiques (même si dans l’exemple donné on pourrait envisager d’utiliser les noms leftOperand et rightOperand). Par exemple :

Integer add(Integer operand1, Integer operand2);

Nommages similaires

Cet anti-pattern est proche de l’utilisation des séries de nombre, si ce n’est qu’au lieu de numéroter les variables, on fait varier légèrement leur nom : par exemple, si on a plusieurs chaînes de caractères avec des noms ststrstrraStr, …

Ce type de nommage ne fournit aucune information sur le rôle des variables dans le bloc de code.

Précision des mots

En nommant les identificateurs, il faut éviter d’insérer des mots qui n’ont pas de valeur ajoutée, qui sont synonymes ou dont la signification est floue. Voici quelques exemples de ce qu’il faut éviter :

  • les articles a, antheanAccounttheAccount ; on préférera directement account, ou si le contexte le permet on ajoutera une précision : activeAccountmainAccount.
  • les mots à faible valeur ajoutée comme info, object, data : quelle différence entre Customer, CustomerInfo, CustomerObject et CustomerData ? Ces termes n’apportent rien et ne permettent pas de faire une distinction efficace.

Collections

Le nom des variables désignant des collections devrait être pluralisé. Par exemple, on préférera accounts à accountList : il n’est pas toujours nécessaire de donner des détails d’implémentation sur le type de collection employé. En revanche, cette information sera importante dans le cas de transformation de collection : accountsAsListaccountsAsSet.

Pour le nommage des Maps, une bonne pratique peut être d’indiquer la signification fonctionnelle de la clé dans le nom : par exemple avec numberToAccountnameToCustomeraccountsByNumbercustomersByName. Ce nommage avec « To » possède un avantage par rapport au nommage avec « By », car il permet d’indiquer si la Map est mono ou multi-valuée, respectivement avec numberToAccount ou numberToAccounts.

Respect de l’intention

Avant de nommer une variable, une méthode ou une classe, il est important de se demander ce qu’on cherche à faire avec le code en question. Dans une certaine mesure, le nom devrait être en adéquation avec le comportement réel.

Si le nom rentre en conflit avec ce qui est fait réellement, et qu’il est compliqué de changer le nom, alors cela traduit peut être un problème de conception ou d’architecture dans le code. Plus qu’un renommage, c’est peut-être davantage un refactoring qui s’impose.

Variables à usage unique

Une variable ne devrait servir qu’un seule finalité, et ne devrait pas être réutilisée pour servir un autre objectif : il est préférable de déclarer une nouvelle variable dont le nom indiquera la finalité. Des noms de variables tels que temp ou tmp sont donc à proscrire.

Faciliter les recherches

Lorsqu’un identificateur est nommé de façon appropriée, il est plus aisé de s’y référer par la suite. Il peut s’agir d’une recherche full text, par nom de classe ou de méthode, ou encore en activant l’auto-complétion. Les astuces suivantes rendent les éléments du code plus faciles à rechercher et à retrouver :

  • Utilisez des noms d’une longueur appropriée. Si ils sont trop courts,ils seront perdus aux milieux de résultats dont les noms sont proches.
  • Utilisez des noms en rapport avec la terminologie du domaine. Cela permet de retrouver plus facilement le code relié à un aspect métier particulier.
  • Évitez de préfixer les noms en fonctions des conventions de code : le I devant les noms d’interfaces (ex : IWorkable), le nom de l’application en préfixe du nom de classe ou encore les préfixes de type (iCounter, strNom, etc.). Ce type de convention de code fait perdre l’auto-complétion en efficacité.
  • Le préfixage de noms de classes en fonction du domaine ou sous-domaine métier peut en revanche être approprié : on retrouvera facilement les classes liées à un aspect métier donné.

Le nommage : un travail d’équipe

Etant donné que l’objectif principal du nommage est d’améliorer la lisibilité et la compréhension du code pour les autres développeurs, il peut être pertinent de se confronter à leur avis lors de choix délicats de nommage, ou qui concerne des éléments à forte visibilité (noms de classes, méthodes d’API).

Cela permet rapidement d’adopter un vocabulaire commun à l’équipe de développement, que tout le monde comprend, et améliore d’autant la qualité. Les phases de revue de code peuvent s’avérer également essentielles pour effectuer des renommages a posteriori.

 

Laisser un commentaire