La règle NUMÉRO 1 pour écrire du code impeccable.


Nommage : la bonne pratique la plus efficace pour avoir un code de qualité, facile à comprendre et à maintenir.


Sortez votre plus belle plume

Avez-vous déjà été dans un aéroport ? Bons moments n’est-ce pas ?

Vous êtes en retard, vous ne savez pas où aller, tout le monde bouge autour de vous, vous devez passer par 30 portiques de sécurité, bref, du fun à l’état pur.

Heureusement, chaque aéroport dispose d’un plan que vous pouvez consulter pour savoir exactement là où vous devez aller.

C’est là qu’on se rend compte qu’il est important de mettre des mots sur les choses. Car si votre plan vous montre des zones appelées A, B et C, où :

  • A est un quai.
  • B est un restaurant.
  • C sont les toilettes.

Vous allez perdre vos repères et il n’y a aucune chance que vous vous y retrouviez.

Cette règle s’applique absolument partout, surtout en programmation.

Quand vous voyez un élément (module ou variable), vous devriez comprendre immédiatement ce qu’il fait simplement en lisant son nom.

Vous ne devriez pas avoir à lire l’algorithme, tout comme vous ne devriez pas avoir à analyser la forme des bâtiments pour les reconnaitre sur un plan d’aéroport.

Malheureusement, beaucoup de développeurs pensent encore que choisir un nom est quelque chose qui se fait « à la légère ».

Pourquoi ? Simplement par manque de conscience.

Tant qu’on ne voit pas le problème, on n’est pas prêt de le résoudre.

Si un module nous semble simple à comprendre, c’est surtout parce qu’on en est l’auteur, et non pas parce qu’il est réellement bien écrit.

On ne prend pas assez en compte les autres personnes qui vont devoir lire notre code.

Car pour eux, c’est une autre paire de manches : ils doivent le découvrir avant de le comprendre, et s’ils ne peuvent pas se fier au nom, ils seront complètement perdus, comme dans l’aéroport de tout à l’heure.

Pour s’en sortir, ils devront analyser l’implémentation, ce qui prend, sans exagérer, 4 à 20 fois plus de temps que de lire un simple nom.

Tenez, faites le test. Essayez de trouver ce que font ces deux algorithmes.

public static string Sub(string str, int i1, int i2)
{
    string r = "";

    if(i1 < 0 || i1 > i2 || i2 >= str.Length)
    {
        throw new ArgumentException();
    }

    for(int i = i1; i < i2; i++)
    {
        r += str[i];
    }

    return r;
}
public static string Substring(string initialString, int startIndex, int endIndex)
{
    string result = "";

    if(startIndex < 0 || startIndex > endIndex || endIndex >= initialString.Length)
    {
        throw new ArgumentException();
    }

    for(int i = startIndex; i < endIndex; i++)
    {
        result += initialString[i];
    }

    return result;
}
Vous l’aurez deviné, ce sont exactement les mêmes. L’un est juste nettement plus parlant que l’autre. Vous n’avez peut-être même pas eu à regarder l’implémentation pour le comprendre.

Et je dis ça, mais c’est en considérant que la personne ait réussi à comprendre l’algorithme.

Parfois, il est tellement tordu qu’elle devra solliciter une deuxième personne (souvent plus expérimentée) juste pour comprendre un bout de code.

Dans un aéroport, on ne devrait pas avoir à interrompre le travail d’un agent de sécurité pour lui demander où aller, non ? Et bien ici, c’est pareil. Tout le monde devrait pouvoir comprendre ce que fait un module, même un néophyte.

Mais attendez, on peut faire encore bien pire.

Dans certaines situations, un mauvais nommage peut mêmeinduire en erreur un développeur, en lui faisant croire qu’il a compris un algorithme.

Donc le gars va travailler gaiement dans une direction, avant de se rendre compte des heures plus tard qu’il fait fausse route.

Et quand je dis des heures, je suis gentil. J’ai déjà connu une situation où j’ai eu la surprise après 2 mois de travail. Il y en a qui ont été maudits pour moins que ça.

public static bool CompareId(int requestId, int responseId)
{
    return (requestId & responseId) != 0;
}
C’était sur un cas similaire à celui-ci. Le nom m’a laissé penser qu’il s’agissait ici d’une égalité, alors que c’était une opération bitwise… De plus, on ne sait pas s’il faut s’attendre à un true ou un false si l’ID correspond bien.

Et pourtant, la solution à ce problème ne pourrait pas être plus évidente : investir du temps de qualité dans le nommage des modules.

Ouais, mais c’est…

Super chiant, exact. Mais vous savez ce qui est encore plus chiant ? Livrer du code en retard parce qu’on a passé plus de temps à comprendre qu’à produire. C’est du vécu.

Le nommage est le B. A. BA du code propre. Je ne connais aucune bonne pratique qui apporte plus de valeur en aussi peu de temps.

Vous améliorez grandement la qualité de votre code source ce qui fait gagner une productivité d’équipe considérable et faites baisser la dette technique du programme.

Vos collègues dégusteront votre code aussi bien qu’une pièce de Molière.
Mais si je travaille tout seul, ce n’est pas utile, non ?

Faites-le quand même !

Votre code vous parait peut-être évident maintenant, mais pensez à votre vous du futur après 172 bonnes nuits de sommeille.

Son premier réflexe sera de tout réusiner en maudissant la personne qui a écrit toute cette *****.

Encore une fois, je parle d’expérience. N’est-ce pas, Léo du passé ? 😠

private void btnChangeCouleur_Click(object sender, EventArgs e)
{
    this.BackColor = Color.FromArgb(rnd.Next(256), rnd.Next(256), rnd.Next(256)); //form
    btnChangeCouleur.BackColor = Color.FromArgb(rnd.Next(256), rnd.Next(256), rnd.Next(256)); //btn
    lblNbAlea.BackColor = Color.FromArgb(rnd.Next(256), rnd.Next(256), rnd.Next(256));
    btnNbAlea.BackColor = Color.FromArgb(rnd.Next(256), rnd.Next(256), rnd.Next(256));
    btnQuitter.BackColor = Color.FromArgb(rnd.Next(256), rnd.Next(256), rnd.Next(256));
}
Un exemple issue de mon premier programme en C#. J'en suis vraiment pas fier du tout 😰

Nommage aux petits oignons

D’accord, mais c’est quoi un « nom de qualité » ?

Bonne question. Il ne s’agit pas juste d’un nom qui « sonne bien », il faut être un peu plus pointu que ça.

Vous n’êtes pas sans savoir qu’un module possède une responsabilité : il fait une chose concrète, et c’est pour cela que vous l’avez créé.

Dans l’idéal, chaque module ne doit avoir qu’une seule responsabilité, c’est une règle fondamentale appelée principe de responsabilité unique (SRP).

Si ce n’est pas le cas, commencez par éclater votre module en plusieurs, de manière à ce que toutes les responsabilités soient séparées (cf. cet article). C’est fait ? Bien, on passe à la suite.

Un nom de qualité exprime intégralement cette responsabilité de la manière la plus claire, précise et compacte possible.

Ça demande de prendre du recul. Il ne s’agit pas d’exprimer la responsabilité pour vous (c’est facile, puisque vous la connaissez déjà), mais pour quelqu’un d’autre.

Il faut que cette personne sache exactement à quoi s’attendre sans jeter un œil à l’implémentation, et le module doit effectivement correspondre à ses attentes.

Et tout ça en quelques mots et le plus rapidement possible. Allez, tchao, merci d’avoir lu, partage, commente, clique sur la cloche.


Technique pour trouver les noms parfaits

Attends, ne me laisse pas dans le pétrin ! Je suis censé faire comment, moi ?

Ça n’a pas l’air dit comme ça, mais nommer des modules est une compétence qui s’apprend et se travaille avec de la pratique.

Plus vous allez en faire, plus vous allez devenir bon, et plus ça va vous sembler naturel. Mais au début, c’est chiant, je ne vous le cache pas.

Donc voici ma technique secrète à faire de tête pour trouver des noms de qualité :


Décrire la responsabilité

Trouvez une SEULE phrase qui décrit exhaustivement la responsabilité du module. Il faut explorer chaque recoin pour ne rien oublier : if/else, while, catch, etc.

Ne vous souciez pas du nombre de mots pour l’instant. De toute façon si votre module n’a réellement qu’une seule responsabilité, vous ne devriez pas avoir à écrire la suite d’Harry Potter.

// Check if two integers have one or more bit in common.
public static bool X(int a, int b)
{
    return (a & b) != 0;
}
Notez que comme a et b ne représentent rien de particulier et qu’elles ont une portée très réduite (une ligne, littéralement), je me suis permis de leur donner un nom très simple. Voir la fin de l’article.

Astuce : vous pouvez recycler cette phrase pour écrire le commentaire de définition du module. Ce n’est pas obligatoire, mais très pratique !


Dresser les mots-clefs percutants

Virez le blabla pour ne garder que les mots-clefs qui décrivent l’essentiel à eux tout seuls.

// Check, integers, true bit, common
public static bool X(int a, int b)
{
    return (a & b) != 0;
}

Notez que parfois, le mot parfait ne fait même pas partie de la phrase, et se trouvait sous votre nez depuis le début.

// Extract a part of a string
// Extract, part, string => subpart
public static string Substring(string initialString, int startIndex, int endIndex)
{
    string result = "";

    if(startIndex < 0 || startIndex > endIndex || endIndex >= initialString.Length)
    {
        throw new ArgumentException();
    }

    for(int i = startIndex; i < endIndex; i++)
    {
        result += initialString[i];
    }

    return result;
}

Assembler les mots-clefs de manière cohérente

Une poêlée de mots-clefs ne forme pas un nom. Il faut les assembler de manière cohérente pour pas qu’ils piquent les yeux à la lecture.

Réorganisez et ajoutez des mots de liaison, mais sans reconstruire la phrase d’origine. Le but est de faire un texte à trou que vous arrivez à remplir naturellement.

Notez que certains mots importants ne sont pas nécessaires, car ils sont déjà exprimés dans la signature du module (type, paramètres…).

// J'ai remplacé "check" par "has", qui est beaucoup plus clair sur la valeur de retour.
// "Integers" est inutile car il est déjà dans la signature.
public static bool HasCommonTrueBit(int a, int b)
{
    return (a & b) != 0;
}
Honnêtement, je n’ai pas pris l’exemple le plus simple. Dites-moi en commentaire si vous avez d’autres suggestions ^^

Et si votre nom fait 140 caractères, pas graves ! Ce n’est pas la taille qui compte, mais la façon dont les autres le perçoivent… Bref, faites de votre mieux.


OK, l’exercice prend un peu de temps au début. Comptez 30-40s par module (moins pour les variables).

Mais croyez-moi, on est très loin des loooongues minutes perdues par vos collègues dont le cerveau (et la haine) est en train de bouillir à feu ardent.

Mais comment je sais si j’ai choisi le nom parfait ? Au feeling ?

Et bien… oui ? En réalité, vous ne pouvez pas vous juger à 100 % vous-même, car il y aura toujours un détail qui vous aura échappé.

Heureusement, il y a une solution pour ça : les revues de code par une tierce partie.

Si elle arrive à comprendre les tenants et les aboutissants de vos modules en lisant UNIQUEMENT les noms de ses éléments, c’est parfait, ne changez rien !


Conseils et astuces

À ce stade, vous deviez déjà être en train d’aiguiser votre plume pour vos prochaines sessions de programmation.

C’est parfait, mais laissez-moi quand même vous donnez quelques conseils avant de finir.

Privilégiez les noms :

  • Simples à rechercher (avec CTRL+F).
  • Avec des conventions de nommages.
    • Préfixe get pour les accesseurs.
    • Préfixe set pour les mutateurs.
    • Préfixe is ou has pour les fonctions retournant des booléens, etc.
  • Décrivant le contexte dans lequel le module doit être utilisé. Parfois, l’implémentation d’un module n’aide pas à comprendre quand il est pertinent. Le nom doit capturer ce phénomène.
  • Décrivant les spécificités techniques du module, notamment les patrons de conception. Ils sont souvent ajoutés en suffixe (CarDecorator, TableAdapter, FormFactory…).

Et fuyez comme la peste les noms :

  • Abrégés (cstmer, num, addr…). C’est juste de la fainéantise.
  • Impossibles à prononcer. C’est chiant à lire de tête, et ça l’est encore plus devant d’autres personnes.
  • Trop ambigus ou génériques. Ils peuvent facilement être confondus avec quelque chose d’autre et induire les développeurs en erreur. Par exemple :
    • id : identifiant de quoi ?
    • builder : qu’est-ce qu’il construit ?
    • customer : c’est un objet ? Son nom ? Son ID ? Sa taille ?
  • Jargonnés. Je sais que c’est tentant d’étaler sa science dans son code (n’est-ce pas, messieurs/dames en R&D :p), mais c’est contreproductif. Pensez aux petits nouveaux !
public bool IsCX360InInfluxState(int externalWindSpeed, int externalWindAngle)
{
    return this.GroundSpikeStability >= 4 && externalWindSpeed > 32 && Math.Abs(externalWindAngle) > 20;
}
Parfois, ce genre de nom est nécessaire pour vraiment capturer le phénomène en question. Dans ce cas, assurez-vous que tous les développeurs sont familiers avec ses concepts, et dans le doute, écrivez un commentaire de définition de qualité.

Autre chose, choisissez bien votre nom en fonction de la portée de votre module/variable.

Personne ne viendra vous hurler dessus si vous définissez un entier « i » dans une boucle for. En revanche, si vous avez une propriété publique définissant le nombre moyen de clients par région, et que vous l’appelez « i », ça risque de chauffer pour vous.

Plus la portée d’un module est grande (plus il peut être utilisé « loin de sa définition »), plus vous allez devoir vous creuser la tête pour le nommer.

Les développeurs de frameworks/bibliothèques, je vous ai à l’œil 🧐

Je vous laisse imaginer l’angoisse pour réusiner un nom tout pourri dans un scope aussi énorme.

Enfin, une dernière chose. Si en lisant le code d’un autre, vous vous rendez compte qu’un nom n’est pas approprié, modifiez-le !

Avec les outils d’aujourd’hui, ça prend 30 s, et vous pourrez vous vanter d’avoir fait gagner quelques minutes à vos collègues. Un acte de bravoure qui ne passera pas inaperçu, en tout cas, pas si je suis dans votre équipe 😉


Voilà pour le nommage des modules. Beaucoup n’y verront que des évidences, mais elles méritent d’être répétées.

Un bon nommage est la manière la plus simple d’améliorer considérablement la propreté d’un programme, quel que soit le langage, quel que soit le framework, quel que soit le projet, quel que soit le contexte.

Donc, ne vous précipitez pas ! Car ces 30 s soigneusement investies dans le nommage de votre fonction vont peut-être faire gagner des heures à un développeur junior dans 10 ans. À votre place, je le ferais juste par sérénité d’esprit :D


Merci d’avoir suivi cet article jusqu’au bout, c’est à cela qu’on reconnait ceux qui ont soif d’efficacité 😊 Partagez l’article autour de vous, car si ça peut ouvrir l’esprit de certains développeurs rabat-joie, j’aurais accompli ma mission.

Suivez-moi sur Twitter @ITExpertFr, c’est là que je poste mes conseils et meilleures trouvailles au quotidien.

Et comme je sais qu’il y a des amateurs de code impeccable, voici d’autres articles pour vous :

Quant à moi, je vous laisse, je vais aller faire du ski en prenant soin de remonter les pistes à pieds.

Je vous donne rendez-vous la semaine prochaine pour un nouvel article sur le blog des développeurs ultra-efficaces. Tchao !