Bonjour ! Dans la leçon précédente, nous avons découvert comment appeler une fonction et utiliser la valeur qu'elle retourne. Nous avons entrevu que les variables définies à l'intérieur d'une fonction semblaient être "privées" et indépendantes de l'algorithme principal.
Aujourd'hui, nous allons approfondir et formaliser cette idée cruciale. L'objectif est de distinguer la portée des variables locales de celle des variables globales. Comprendre cette distinction est absolument fondamental pour atteindre votre but : écrire du "code clean", prévisible et facile à déboguer. Nous verrons comment la gestion de la "portée" (où une variable est visible et utilisable) est l'une des clés pour créer des modules de code robustes et autonomes.
1. La notion de "portée" (Scope)
Imaginez qu'un algorithme soit un grand bâtiment. Le programme principal est le hall d'entrée, accessible à tous. Chaque fonction est une pièce fermée à l'intérieur de ce bâtiment. La portée d'une variable définit simplement dans quelles parties de ce bâtiment (hall, pièces) cette variable est connue et peut être utilisée.
- Une variable globale est déclarée dans le hall (l'algorithme principal). Tout le monde, où qu'il soit dans le bâtiment, peut la voir et l'utiliser.
- Une variable locale est déclarée à l'intérieur d'une pièce (une fonction). Seules les instructions à l'intérieur de cette même pièce peuvent la voir et l'utiliser. Dès que l'on quitte la pièce (la fonction termine son exécution), tout ce qui était local est "oublié" et détruit.
Les paramètres que vous passez à une fonction sont également considérés comme des variables locales à cette fonction.
Observons cette idée de "bloc de code". Un bloc est une section de votre algorithme, souvent délimitée. Dans notre cas, le corps d'une fonction, entre Début et FinFonction, forme un bloc distinct.

Pour une définition plus formelle, étudions un court extrait.
cours algorithmes et programmation pour débutant
La présentation 'cours algorithmes et programmation pour débutant' offre des définitions claires et concises pour ces concepts.
Consultez la diapositive 57, intitulée 'Visibilité, localité et globalité des objets'. Lisez attentivement la section 'Définitions'. Notez comment un 'objet local' est lié à la fonction où il est défini, tandis qu'un 'objet global' est défini au niveau du programme principal (niveau 0).
2. Règles de visibilité et conflits de noms
Maintenant que les définitions sont claires, voyons les règles du jeu.
- Accès aux variables globales : Une fonction peut lire (et même modifier) une variable globale.
- Priorité en cas de conflit de nom : Que se passe-t-il si une variable locale porte le même nom qu'une variable globale ? La variable locale a toujours la priorité à l'intérieur de sa fonction. On dit que la variable locale masque (ou shadows en anglais) la variable globale.
Analysons ce pseudo-code :
Algorithme ExperiencePortee
// --- Variable Globale ---
Variables
message: chaîne de caractères
// --- Définition de la fonction ---
Procédure AfficherMessage()
// --- Variable Locale ---
Variables
message: chaîne de caractères
Début
message ← "Ceci est le message local."
Ecrire(message) // Affiche la variable LOCALE
FinProcédure
// --- Programme Principal ---
Début
message ← "Ceci est le message global."
Ecrire("Avant l'appel : ", message)
AfficherMessage() // Appel de la procédure
Ecrire("Après l'appel : ", message)
Fin
Si nous exécutons cet algorithme, voici ce qui s'affichera :
Avant l'appel : Ceci est le message global.Ceci est le message local.(Affiché par la procédure)Après l'appel : Ceci est le message global.
Remarquez que l'assignation message ← "Ceci est le message local." n'a affecté que la variable message qui vit à l'intérieur de la fonction. La variable globale message est restée intacte.
Le document que nous avons consulté précédemment formalise également cette règle.
cours algorithmes et programmation pour débutant
Revenons à notre présentation pour confirmer cette règle de priorité, qui est un point fondamental pour éviter les bugs.
Sur la même diapositive 57 ('Visibilité, localité et globalité des objets'), lisez maintenant la section 'Règle de visibilité des objets'. La première puce est la plus importante : 'Dans le cas où un objet local ... et un objet global ... portent le même nom, l’objet qui sera considéré est l’objet local'.
3. Pourquoi privilégier les variables locales ?
Votre objectif est d'écrire du "code clean". L'une des règles d'or pour y parvenir est de minimiser l'utilisation des variables globales.
- Effets de bord (Side Effects) : Une fonction qui modifie une variable globale est imprévisible. Elle peut avoir des conséquences inattendues sur d'autres parties de votre programme. Cela brise le principe de la "boîte noire" que nous avons évoqué : la fonction n'est plus autonome, son comportement dépend d'un état extérieur et elle le modifie en secret.
- Lisibilité et maintenance : Quand vous analysez une fonction, si elle ne manipule que ses paramètres et ses variables locales, sa logique est entièrement contenue. Vous n'avez pas besoin de chercher dans tout le reste du programme pour comprendre ce qu'elle fait. C'est infiniment plus simple à lire et à déboguer.
- Modularité et réutilisabilité : Une fonction qui n'utilise pas de variables globales est comme une brique de Lego. Vous pouvez la prendre et la réutiliser dans n'importe quel autre projet sans aucune modification.
cours algorithmes et programmation pour débutant
Pour bien ancrer cette philosophie de programmation, examinons les arguments contre l'usage excessif des variables globales.
Lisez les diapositives 59 ('Principe de la « boîte noire »') et 60 ('Local ou global ?'). Portez une attention particulière aux listes des 'Inconvénients d'une utilisation systématique de variables globales' et des 'Avantages d'une utilisation de variables locales'.
4. À vous de jouer : traçage de variables
Le meilleur moyen de maîtriser la portée est de tracer l'exécution d'un algorithme pas à pas. Analysons le code suivant. Il contient une fonction qui modifie intentionnellement une variable globale pour illustrer le mécanisme (même si c'est une pratique déconseillée !).
Algorithme :
// --- Variables Globales ---
Variables
compteur_g: entier // 'g' pour global
valeur_g: entier
// --- Définitions des Fonctions ---
Fonction Calcul(val_entree: entier): entier
Variables
compteur_g: entier // Variable LOCALE qui masque la globale
Début
compteur_g ← 10
Ecrire("-> Dans Calcul, le compteur (local) vaut : ", compteur_g)
retourner val_entree * 2
FinFonction
Procédure IncrementeGlobal()
Début
// Pas de variable locale 'compteur_g', donc on utilise la globale.
compteur_g ← compteur_g + 1
Ecrire("-> Dans IncrementeGlobal, le compteur (global) vaut : ", compteur_g)
FinProcédure
// --- Programme Principal ---
Début
compteur_g ← 1
valeur_g ← 5
Ecrire("1. Au début, compteur_g=", compteur_g, ", valeur_g=", valeur_g)
valeur_g ← Calcul(valeur_g)
Ecrire("2. Après Calcul, compteur_g=", compteur_g, ", valeur_g=", valeur_g)
IncrementeGlobal()
Ecrire("3. Après IncrementeGlobal, compteur_g=", compteur_g, ", valeur_g=", valeur_g)
IncrementeGlobal()
Ecrire("4. Après le 2e IncrementeGlobal, compteur_g=", compteur_g, ", valeur_g=", valeur_g)
Fin
Prenez un papier et un crayon et essayez de prédire ce que l'algorithme va afficher à chaque étape.
Cliquez ici pour voir le déroulement et la solution
Étape par étape :
-
Début du programme principal :
- La variable globale
compteur_gest initialisée à1. - La variable globale
valeur_gest initialisée à5. - Affichage 1 :
1. Au début, compteur_g=1, valeur_g=5
- La variable globale
-
Appel de
Calcul(valeur_g):- La fonction
Calculest appelée avec l'argument5. - À l'intérieur de
Calcul, une nouvelle variable localecompteur_gest créée et masque la globale. Elle est initialisée à10. - Affichage (interne) :
-> Dans Calcul, le compteur (local) vaut : 10 - La fonction retourne
5 * 2 = 10. - De retour dans le programme principal, la variable globale
valeur_greçoit la valeur de retour10. - La variable locale
compteur_gde la fonction est détruite. La variable globalecompteur_g(qui valait1) n'a jamais été touchée. - Affichage 2 :
2. Après Calcul, compteur_g=1, valeur_g=10
- La fonction
-
Appel de
IncrementeGlobal():- La procédure
IncrementeGlobalest appelée. - Elle ne déclare aucune variable locale
compteur_g. Elle accède donc à la variable globale. - Elle exécute
compteur_g ← compteur_g + 1, ce qui fait passer la variable globale de1à2. - Affichage (interne) :
-> Dans IncrementeGlobal, le compteur (global) vaut : 2 - Affichage 3 :
3. Après IncrementeGlobal, compteur_g=2, valeur_g=10
- La procédure
-
Second appel de
IncrementeGlobal():- La procédure est de nouveau appelée.
- Elle accède à la variable globale
compteur_gqui vaut maintenant2. - Elle l'incrémente à
3. - Affichage (interne) :
-> Dans IncrementeGlobal, le compteur (global) vaut : 3 - Affichage 4 :
4. Après le 2e IncrementeGlobal, compteur_g=3, valeur_g=10
Conclusion
La maîtrise de la portée des variables est une étape décisive dans votre parcours. Elle vous donne le pouvoir d'isoler la logique, de prévenir les bugs et de construire des algorithmes propres et modulaires.
Les points clés à retenir :
- Variable locale : Existe seulement dans sa fonction. Elle est créée à l'appel et détruite à la fin. C'est le mode de fonctionnement à privilégier.
- Variable globale : Accessible partout dans l'algorithme. Son utilisation doit être limitée car elle crée des dépendances cachées et des "effets de bord".
- Conflit de nom : Une variable locale masque toujours une variable globale du même nom à l'intérieur de sa fonction.
- La règle d'or du "code clean" : Une fonction doit être une "boîte noire". Elle reçoit des informations via ses paramètres et communique ses résultats via sa valeur de retour. Elle ne devrait idéalement ni lire ni écrire dans des variables globales.
Et après ?
Nous avons vu que les paramètres sont comme des variables locales. Mais comment une valeur est-elle transmise à un paramètre ? Est-ce une simple copie, ou la fonction peut-elle modifier la variable originale de l'algorithme appelant ? C'est la question du passage de paramètres par valeur ou par référence, que nous explorerons dans la prochaine leçon. Cela affinera encore notre compréhension des interactions entre les différentes parties d'un programme.