Guide pratique pour le nommage de ses variables (en python 🐍)

Roy Bellot
7 min readMay 25, 2023

--

Est-ce que Ă©crire du code est facile, mais le reprendre aprĂšs quelques mois, c’est la cata ? On te dit qu’une variable avec son type dans son nom, ça ne se fait pas, mais personne ne dit pourquoi ni quoi faire Ă  la place ?

Tu souffres peut-ĂȘtre d’une carence en nommage. Pas de panique, suivez le guide !

Je parle pour python car j’y suis plus Ă  l’aise, cependant les bonnes pratiques se dĂ©clinent peu importe le langage.

I. La base de la base

Avant de chercher ce qui fait un bon nom, on va reprendre au début sur ce qui fait un nom acceptable. Petit tour rapide :

  • On nomme avec un mot qui a un sens.
  • On ne redĂ©finit pas des mots rĂ©servĂ©s au langage (sinon, Ă©videmment, ça casse tout).
  • On suit une convention de style, en python on a la fameuse PEP8.
a = "mauvais"
🐍 = "rigolo, mais non"
agagougou = "fais un effort"
PasLaBonneConvention = "c'est non"
False = "pire idée"
nom_a_rallong_parce_que_jai_pas_trouve_mieux_mais_quelquechose_me_dit_qu...

Si la sacro-sainte PEP8 ne dit rien contre les nom d’une seule lettre, ce n’est pas le cas de pylint et flake8 (deux linters : des outils qui vĂ©rifient le style. Si tu n’en utilises pas, utilise-en un !) qui ronchonnent, Ă  raison, sur ces noms qui ne portent aucun sens. Seule tolĂ©rance : ces petites variables dans les comprĂ©hensions de liste (de dict, de set).

primes = [x for x in range(30) if x % 2 == 0]  # x n'a pas besoin de sens

Parlant de la PEP8, pour rappel :

  • les constantes tout en MAJUSCULES,
  • les classes en CamelCase,
  • tout le reste en snake_case.

II. La rigueur de nommage

Dans l’intro, je disais qu’on entend souvent dire que des variables avec leur type dans leur nom, ça ne se fait pas. Pour ĂȘtre exact, je pense qu’on peut dire qu’avoir le type comme nom, prend la place d’une meilleure information : pourquoi on a ce type ?

age_int = int(age_str)
# Pourquoi j'ai un age_str ? Parce que c'est un input user :
age = int(inputed_age)

user_list = [...]
# Pourquoi j'ai "list" ? Pour indiquer qu'il y en a plusieurs :
users = [...]

NĂ©anmoins, je pense qu’un bon nom doit donner un indice sur le type. Si on voulait formaliser, ça donnerait ça :

Liste, set et tout ce qui est itérable => son contenu au pluriel. Instance de classe => nom de cette classe en minuscules. Booléen => une question avec un verbe. Dictionnaire =>contenu **by** clé ou clé **to** contenu, Fonction => phrase avec un verbe

Ce tableau se lit dans les deux sens : par exemple, une variable au pluriel doit au moins pouvoir s’itĂ©rer.

user = User()  # les majuscules sont importantes
users = [user] # singulier et pluriel sont importants
for user in users: # singulier et pluriel sont importants
...

user_accepted_conditions = True # le verbe m'indique que c'est un booléen.
conditions_are_accepted = True # fonctionne en mode phrase...
are_conditions_accepted = True # ...ou en mode question.

events_by_date = { 1963 : [...]} # "by" : sert Ă  ordonner
users_id_to_name = { 1: "mimi" } # "to" sert Ă  transformer

tokenize(synopsis) # une action est toujours une fonction

Pour un nommage rigoureux, une autre rĂšgle est de ne pas utiliser le mĂȘme nom pour diffĂ©rentes choses, en particulier dans le mĂȘme scope. Oui, on peut avoir un gros cerveau et suivre le contenu de la variable au fil de l’exĂ©cution mais pourquoi faire compliquĂ© quand on peut faire simple ?

Je le met en gros pour qu’on le voit de loin :

1 bon nom + 1 scope = 1 mĂȘme chose

class DontDoThis:
def x(self):
return 3
def y(self):
self.x = 3 # 2h de debug garantit, pourquoi se compliquer la vie ?

III. Mais pourquoi ?

Si personne ne va prĂ©tendre que du beau code, ça sert Ă  rien, on peut prendre le temps de se poser la question : pourquoi bien nommer, c’est important ?

Avec un peu de chance, pas du tout ta réaction devant cet article

Pendant la lecture de code, pas mal de zones neurologiques sont impliquĂ©es : celles de la lecture du langage, mais aussi celles des mathĂ©matiques et rĂ©solution de problĂšmes. En lisant, on va chercher non seulement Ă  comprendre la syntaxe, mais aussi et surtout Ă  crĂ©er du sens et Ă  percer la logique de ce qu’on a sous les yeux (un peu comme si quelqu’un nous racontait comment rĂ©soudre un sudoku). Mine de rien, ça prend de la place, comme si ton cerveau cherchait Ă  tout charger en RAM ! Si jamais il t’arrive d’avoir du mal Ă  relire le lendemain ton travail de la veille, c’est cette RAM de cerveau qui a Ă©tĂ© vidĂ©e, et il faut tout te remettre en tĂȘte.

Une belle preuve de l’importance de la charge de la lecture est qu’il est possible d’offusquer du code, c’est Ă  dire de l’écrire de maniĂšre tellement difficile Ă  lire qu’il devient ardu voir impossible Ă  un humain de le comprendre.

def delete_user(dog):
add_wheel(dog)
return dog.phone
# Mais Ă  quoi je pensais hier, je comprend plus rien !

Tout l’idĂ©e de rendre le code plus clair tourne en fait autour de l’idĂ©e de minimiser la charge nĂ©cessaire pour le lire. Quand dans un bloc de code tout se comporte comme les noms le suggĂšrent, on a tout gagnĂ© : le debug sera facile, la communication avec l’équipe pareil.

IV. Les conseils de pro

1. À quoi je sert ?

ScÚne de Rick et Morty : un robot conçu pour passer le beurre demande quel est son but dans la vie.
Une jeune variable, quelques secondes aprùs sa naissance. [À quoi je sert ?]

Toujours dans l’idĂ©e de guider la lecture du code, on peut placer les noms dans deux catĂ©gories : ceux qui vont se faire remarquer et ceux qui vont se faire oublier.

Ceux qui vont se faire oublier sont ceux qu’on mentionne à peine quand on explique ce que l’algo fait (le compte user qui fait l’action, un texte à traiter, un nom de fichier
). Tout comme self , ils n’alourdissent pas la lecture. Ils n’ont pas besoin de porter de sens particulier.

Les autres, qui vont se faire remarquer, sont au contraire ceux qui vont Ă©voluer. Leur nom indique leur rĂŽle dans les Ă©vĂšnements Ă  venir.

def change_subscription(user, previous_subscription, next_subscription):
# ici, il est Ă©vident qu'on va parler d'un user
# ce qui est intéressant et ce sur quoi notre attention va se porter
# sont les deux abonnements.
# Pratique pour mon cerveau, je l'ai pas besoin de lire plus loin pour
# deviner ce qu'il va se passer
...

2. Homogénéité

C’est le moment de donner le conseil ultime, la vraie rùgle qui fonctionne partout :

Un bon nom dĂ©pend de ce qu’il y a autour.

# disons que j'ai souvent ça dans mon projet :
obj = Object()

my_object = Object() # Non : j'ai l'habitude du nom obj
obj = Objection() # Non : j'ai l'habitude que obj soit une instance de Object

Toujours pour faciliter la lecture, on va chercher Ă  faire prendre des raccourcis Ă  notre cerveau ! Au sein d’un mĂȘme projet, on va manipuler souvent les mĂȘmes objets, les instances des mĂȘmes classes
 Plus le projet est gros, plus on va voir des habitudes Ă©merger. Ces habitudes forment un style, une convention Ă  respecter comme on respecte les conventions du langage.

Suivre ces habitudes, et rectifier les cas oĂč les habitudes ne sont pas suivies, va permettre de rendre le code homogĂšne. En lisant un nom familier, on sait directement quel est son sens.

(C’est aussi bien plus facile de lancer des recherches globales dans le projet quand on sait que 80% des cas vont porter le mĂȘme nom !)

Quand cette convention est brisée, la lecture devient confuse. Illustration en français avec des homographes :

Devant lĂ  oĂč les poules du couvent couvent,
nous portions nos portions
lorsque mon fils a cassé les fils.

Conseils supplémentaires (sur place ou à emporter ?)

1. _

En Python, _ est un semi-standard pour indiquer que la variable existe, mais qu’on s’en fout et qu’on ne l’utilisera pas.

id, _, name = (1, "Organa", "Leia")
for _ in range(3):
print("Toc toc toc Penny !")

MĂȘme vide, ce nom est un guide : pas de nom âžĄïž pas de sens âžĄïž pas d’utilitĂ©.

Un autre avantage est d’éviter de polluer la lecture avec des a , x , et autres i si ce n’est pas nĂ©cessaire.

2. Refacto ? Renommage

Une erreur courante des dĂ©butant·e·s dĂ©veloppeur·se·s est, lors d’un fix ou d’une refactorisation, de modifier le moins possible le code au lieu de le faire profondĂ©ment Ă©voluer.

Si un type ou une utilisation change, son nom doit changer aussi.

Heh oui, rien n’est gravĂ© dans le marbre ! La rĂšgle que j’utilise est que tout ce que j’ai modifiĂ© ou utilisĂ© est mon problĂšme. Peu importe la maniĂšre dont le code Ă©tait avant de travailler dessus, ce qui compte est la maniĂšre dont il va ĂȘtre aprĂšs mon passage.

TL;DR : J’ai pas le teeeeeeeeeeeeeeeemps

Vite, un résumé !

Un bon nom :

  • respecte les conventions du langage et du projet,
  • si possible, indique le sens fonctionnel,
  • n’est pas contre-intuitif
  • est unique (au moins dans son scope).

Si on ne compte plus les ressources pour commencer Ă  dĂ©velopper, il peut ĂȘtre difficile de trouver le petit quelque chose pour sortir de la junioritĂ© (mais si, ça se dit). J’essaie ici de compiler les conseils que j’aurais aimĂ© qu’on me donne.

Tout est bien sûr à prendre à la lettre, sans contexte, et à appliquer sans se poser la question de si le conseil est pertinent !

--

--

Roy Bellot

Je partage les conseils que j'aurais aimé qu'on me donne en commençant le métier de développeur.