
Rappel de définition
Une variable est une allocation mémoire servant à stocker une valeur qui sera utile à la bonne exécution du programme.
Les variables sont l’un des éléments les plus fondamentaux d’un programme. Il n’est pas rare de voir dans un programme des variables mal utilisées. Elles peuvent être puissantes si elles sont correctement utilisées, mais elles peuvent également montrer des lacunes ou des erreurs de conception si elles sont mal utilisées.
Lors d’une relecture d’un code écrit par une autre personne, des variables mal utilisées ou mal placées peuvent rendre la relecture difficile, car il sera nécessaire d’examiner le contenu et l’affectation de ces variables à chaque lecture.
Donc avoir un ensemble de variables claires et correctement placées permet une meilleure lecture du code.
Les types de variable
Dans la plupart des langages des Programmations Orientées Objet (POO), nous pouvons classer les variables dans trois catégories :
1 – Les variables locales
Une variable déclarée dans un bloc, une méthode ou un constructeur est dite locale. La portée de ces variables n’existe que dans le bloc dans lequel la variable est déclarée. C’est-à-dire que la variable est seulement accessible dans ce bloc. Une fois le bloc de code exécuté, la variable est détruite.
public class PersonneDetail
{
public int PersonneAge()
{
int age = 24; // Variable local à la méthode PersonneAge()
return age;
}
public bool EstPersonneMajeur()
{
string paysOrigine = "France";
int agePersonne = 24;
if(paysOrigine == "Etat-Unis")
{
int ageMajorite = 21; // Variable local au bloc conditionnel
if(agePersonne >= ageMajorite)
return true;
else
return false;
}
else
{
if(agePersonne >= 18)
return true;
else
return false;
}
}
}
2 – Les variables d’instance
Les variables d’instance sont des variables non statiques qui sont déclarées dans une classe en dehors de méthode, constructeur, ou bloc. Les variables d’instance sont créées à l’instanciation de la classe. Il est possible d’ajouter un niveau de visibilité sur ces variables.
public class PersonneDetail
{
public int Age; // variable visible par l'ensemble de la classe PersonneDetaile
public int PersonneAge()
{
return Age;
}
3 – Les variables statiques
Les variables statiques sont aussi appelées variables de classe. Ces variables sont déclarées de la même façon que les variables d’instance, à la seule différence qu’elles sont déclarées à l’aide du mot static. Les variables statiques sont créées au début de l’exécution du programme, ce qui implique qu’il n’est pas possible d’avoir plusieurs copies d’une variable statique, quelles que soient le nombre d’instances de l’objet créé.
public class PersonneDetail
{
public static int Age {get; set;} // variable static
public int PersonneAge()
{
return Age;
}
}
public void Main()
{
var personne = new PersonneDetail();
personne.Age = 24;
Console.Write(personne.Age) // Affiche 24;
personne = new PersonneDetail()
Console.Write(personne.Age) // Affiche 24;
}
4 – Const vs Readonly
Les variables constantes doivent contenir une valeur au moment de la compilation et sont statiques. Si une constante n’est pas renseignée à la compilation, une erreur de compilation sera levée. Ces variables sont dites compileTime.
Une variable marquée de readonly est similaire à une variable de type constante, mais elle est initialisée par le constructeur de la classe contenant la variable. Ces variables sont dites runTime. Leurs valeurs sont définies à l’exécution du programme.
Comment différencier les mots-clés readonly et const ? On pourrait dire que la différence réside dans le moment où la valeur est initialisée. Pour le mot-clé readonly, la valeur est connue du runtime. Pour le mot-clé const la valeur doit-être connue au moment de la compilation.
Le point commun de ces deux mots-clés est qu’ils couvrent tous les deux des données dites immuables, ce qui signifie que la valeur ne peut pas changer tout au long de la vie de l’application.
Pour le mot-clé const, la variable marquée comme telle est placée par le compilateur dans les métadonnées d’assembly et incorpore la valeur dans le code IL après l’initialisation. Cela signifie qu’il n’y a pas d’allocation de mémoire pour les constantes pendant l’exécution. Une valeur en lecteur seule n’est pas une constante; elle est stockée dans le tas du chargeur, qui est un type de mémoire qui ne peut pas être alloué tant que le type n’est pas chargé. Les champs en lecture seule sont stockés dans la mémoire dynamique, les valeurs ne sont accessibles qu’au moment de l’exécution et sont soumises au gerbage collector.
Les noms de variable
Une variable doit décrire le plus clairement possible son contenu pour faciliter la lecture du code. Par exemple, pour stocker le nombre de personnes majeures dans la région Normandie, il est souhaitable de voir apparaître les mots nombre, personnes, majeures, Normandie dans le nom de la variable. Par exemple : nombrePersonnesMajeuresNormandie.
Attention toutefois, certains mots sont réservés et ne peuvent être utilisés comme nom de variable. Chaque langage de programmation a sa propre liste de mots réservés. Voici une liste de mots réservés que l’on retrouve couramment dans les langages de programmation:
false | true | if | else | return |
in | try | is | while | as |
finally | yield | break | for | class |
1 – Les différentes notations
- La notation Camel : le premier mot constituant la variable est mis en minuscule, puis chaque nouveau mot constituant la variable commence par une majuscule. Exemple : nombrePersonnesMajeures
- La notation Pascal : tous les mots constituant la variable commencent par une majuscule. Exemple : NombrePersonnesMajeures
- La notation Snake : les mots constituant la variable sont séparés par des caractères « _ ». Exemple : nombre_personnes_majeures
Les programmeurs débattent régulièrement de la meilleure notation pour une variable. Il n’y a pas de bonne ou de mauvaise notation. La bonne notation est celle que l’on choisit tant que l’on conserve cette notation tout au long du code.
2 – Des outils pour nous aider
Depuis plusieurs années maintenant, Visual Studio et la plupart des IDEs modernes supportent le format .editorconfig qui permet justement de configurer des conventions de nommage au niveau d’un projet ou d’une solution.
Pour uniformiser l’ensemble des conventions de nommage à utiliser par l’équipe en charge du projet ou de la solution, il suffit de créer un fichier .editorconfig dans la solution ou le projet. Dans ce fichier il faudra insérer les règles de nommage que l’on souhaite suivre.
Pour connaitre la liste des règles possibles, je vous invite à lire la documention détaillée réalisée par Microsoft sur le sujet :
Le mythe de la lisibilité
Il existe différentes théories chez les programmeurs, dont celle consistant à privilégier la création de variables pour rendre un code plus lisible. Cependant, cette philosophie se heurte à deux problèmes principaux
1 – Les variables nuisent à la lisibilité
La multiplicité des variables dans un code source nuit à la lecture du code, c’est-à-dire qu’il faut un effort supplémentaire à la personne relisant le code pour retenir le nom et les valeurs associées aux variables qu’il croise. Il devient alors compliqué pour cette personne de déchiffrer la ligne de code qu’il a devant les yeux
2 – Une variable de lisibilité est presque toujours un raccourci.
Si l’objectif d’une variable est d’améliorer la lisibilité d’un morceau de code, il est facile de déduire qu’un raccourci a été pris. La lisibilité provient en grande partie d’un bon design. L’utilisation d’une variable pour rendre une partie de code plus claire vient surtout a posteriori, ce qui est rarement synonyme d’une bonne conception
3 – Faut-il abuser de l’inférence de type ?
L’inférence de type permet de déclarer une variable locale sans avoir à écrire implicitement son type, car le compilateur déterminera ce type à partir de la valeur d’initialisation qui est obligatoire. Mais est-ce une bonne pratique ?
Pour les cas où nous connaissons le contenu de la variable, il est important de choisir le type de la variable afin d’éviter une sélection arbitraire du type par le compilateur. Par exemple pour un identifiant de type numérique, le compilateur peut choisir un type long, short ou byte, voire uint, ulong, ushort, sbyte,… en fonction de la plage de valeur possible. Il faut aussi garder à l’esprit que toute ligne de code écrite à un instant T sera à maintenir à l’instant T+1. Ecrire explicitement le type de la variable facilitera la maintenance du code.
L’inférence de type est utile dans les cas suivant :
- Sauvegarder en mémoire un objet anonyme.
- Typer les variables d’entrée des expressions lambda
- Quand une fonction retourne une structure de données multidimensionnelles complexes (type générique imbriqué). Même si le type de données retourné peut-être écrit, il risque d’être difficilement lisible lors d’une relecture. Il est alors préférable de solliciter l’aide du compilateur avec l’inférence de type et d’écrire un commentaire décrivant la structure de la donnée.
Rien ne remplace un bon design
À ce stade, nous pouvons voir que les variables dans un code ne sont pas si anodines. Simples d’utilisation, les variables peuvent être utilisées pour rendre un code plus esthétique, mais comme nous l’avons vu, ce n’est pas le meilleur moyen pour gagner en lisibilité. Elles peuvent même nuire à la lisibilité générale. Rien ne peut remplacer un bon design de conception. Lors d’une révision de code, il est préférable de prendre du temps pour examiner l’utilité d’une variable et voir si elle est réellement à sa place. En vous entraînant à reconnaître les variables mal utilisées et en retravaillant le code, vous deviendrez un réviseur beaucoup plus efficace.
La vie d’une variable
La vie d’une variable commence lors de sa création, moment où au moins une référence est créée. Pendant toute la vie d’une variable, il est possible d’ajouter des références ou d’en supprimer, d’affecter de nouvelles valeurs, de manipuler son contenu ou toute autres chose permise par le langage de programmation. Une variable reste en vie tant qu’au moins une référence à cette variable existe.
Lorsque le nombre de références à la variable arrive à zéro, elle devient inaccessible. À ce stade la vie de la variable est terminée, elle devient « orpheline ». De nombreux langages de programmation embarquent un « garbage collector » (ramasse-miettes en français) pour libérer l’allocation mémoire de la variable. Une fois le garbage collector passé, il ne reste plus de trace de l’existence de la variable.
Plus d’articles :
Le paiement mobile
Quels sont les pros et les cons de ce nouveau mode de paiement ? Quelles sont les technologies d’intelligences artificielles derrière cette révolution de paiement ? Quels enjeux envisage-t-on dans un futur proche ?
L’éco-conception, un moyen de contrer les impacts environnementaux du web ?
Sobritété numérique, éco-conception… Quelle est la réponse du numérique face à l’urgence climatique ? Quelles mesures appliquer sur vos sites ?
Techniques de débogage d’une application – De la traque à la livraison
Méthodes de débogage : traquer les bugs, identifier les parties erronnées, formuler des hypothèses, appliquer les correctifs…