Je vais essayer de décrire dans ce documents quelques principes de base que j'applique en programmant. Pour trouver l'essentiel, il m'a fallu prendre du recul sur mes habitudes.
Le nom doit permettre de comprendre ce que fais la fonction ou la variable
Pour les fonctions, l'habitude et de mettre un verbe d'action dans le nom. Pour les plus courants on trouve :
récupère (get) : elle renvoie quelque chose (il n'y a aucune raison que dans son code elle modifie une quelconque variable !! sinon, lui trouver un autre nom)
modifie/ajoute/supprime (set/add/del) : modifie une valeur/une liste ou un tableau
On peut l'étendre à n'importe quel verbe d'action : tri, analyse, nettoie...
Si la fonction est dans un package, il peut parfois être pratique (en C, par exemple), de donner le nom du package aux fonctions. Par exemple : donnéesInit, donnéesReset, donnéesAjout...
Important : si on modifie le contenue d'une fonction, il faut penser aussi à mettre à jours son nom si son but change, ou au moins sa documentation.
Pour les tableau, utiliser le terme "tab" dans le nom est souvent assez pratique.
Documenter ses fonctions (toutes)
Description de la fonction
Paramètres : liste des paramètres avec l'utilité. Indiqué s'il sont modifiés.
Retour : ce qui est retourné.
Sur les fonctions ou procédures complexes, on peut ajouter les champs suivants :
Requis : ce qui doit être fait avant l'appel. Par exemple : appel à "init" requis.
Garantie : ce que l'on assure après (par exemple, "le tableau T est trié ou vide")
Dans le cas où le champ requis a été utilisé, il est peut-être intéressant de placer une assertion en début de fonction, pour assurer que cela a été fait.
Être capable de dessiner sa structure de données
Prendre une feuille de papier et dessiner ses tableaux, ses listes chainées... Ce conseil est sans doute le plus "scolaire" que je puisse donner, mais il vous propulse instantanément au rang de serial coder, surtout dans les langages comme le C où les pointeurs rendent le code peu lisibles.
Il n'y a plus qu'à faire la correspondance. En C, le tableau deviendra [], les pointeurs, dessinés par des flèches, deviendront des étoiles...
Classer ses fonctions par package (même en C, avec les .h)
Permet de leur donner une logique globale. Cela facilite aussi la factorisation du code. Être capable de classer ses fonctions traduit le fait que l'on comprend l'architecture de son programme. Dans le meilleur des cas, il faut décrire quel seront les packages avant même de commencer à coder. Il est intéressant aussi de décrire les interactions entres les différents packages.
Nb. Pour la programmation objet (Java, C++), c'est encore plus vrai.
Éviter les effets de bords (modification de variables)
Il faut éviter de modifier des variables du programme depuis une fonction (mais c'est parfois indispensable ou juste plus lisible). Dans ce cas, on doit comprendre ce qui est modifié juste en lisant la documentation de la fonction et son nom.
Exemple (trivial), en lisant la documentation de la fonction int get_numéro(), on ne s'attends pas à ce qu'elle modifie une variable. On s’attend juste à ce qu'elle renvoie le numéro.
Pour les procédures c'est moins vrai : "l'effet de bord" est leur seul moyen d’interagir avec l'extérieur. Cependant, si elles modifient plusieurs variables, il faut se demander si le développeur s'y attend, juste en lisant la doc.
Appeler ses fonctions avant de les écrire
Cela permet de s'assurer qu'elle est utile avant de l'appeler et d'évaluer quels seront les paramètres. Parfois, j'aime même effectuer les appels de toutes mes fonctions, et les écrire ensuite. Ça peut être inutile, si vous savez exactement quoi coder.
En conclusion, nous voyons que la programmation nécessite une certaine rigueur : savoir à tout instant POURQUOI j'écris cette ligne. Le code est à destinations de machines, mais il doit surtout être lisible par des humains, c'est pourquoi il est important de le rendre compréhensible.