Guide pratique pour le nommage de ses variables (en python đ)
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 :
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 ?
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 ?
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 !