web-dev-qa-db-fra.com

Pourquoi les variables globales sont-elles mauvaises?

J'essayais de trouver une bonne source qui explique pourquoi l'utilisation de global est considérée comme une mauvaise pratique dans python (et dans la programmation en général). Quelqu'un peut-il m'indiquer un ou expliquer ici?

92
LarsVegas

Cela n'a rien à voir avec Python; les variables globales sont mauvaises dans n'importe quel langage de programmation.

Cependant, les constantes globales ne sont pas théoriquement identiques aux variables globales ; les constantes globales sont parfaitement inoffensives. C'est juste que dans Python il n'y a pas de différence imposée, seulement par convention sont CONSTANTS_CAPITALIZED et globals_are_not.

La raison pour laquelle ils sont mauvais, c’est qu’ils permettent aux fonctions d’avoir des effets secondaires cachés (non évidents, surprenants, difficiles à détecter), ce qui entraîne une augmentation de la complexité, pouvant conduire à code Spaghetti .

Cependant, une utilisation rationnelle de l'état global est acceptable (de même que l'état local et la mutabilité) même en programmation fonctionnelle, que ce soit pour l'optimisation d'algorithme, la complexité réduite, la mise en cache et la mémorisation, ou l'aspect pratique des structures de portage provenant d'une base de code essentiellement impérative.

Dans l’ensemble, il est possible de répondre à votre question de différentes manières. Le mieux est donc de rechercher simplement "pourquoi les variables globales sont-elles mauvaises". Quelques exemples:

Si vous voulez aller plus loin et découvrir pourquoi les effets secondaires sont tous liés, et bien d’autres choses éclairantes, vous devriez apprendre la programmation fonctionnelle:

123
Erik Allik

Oui, en théorie, les globaux (et "l'état" en général) sont diaboliques. En pratique, si vous examinez le répertoire packages de votre python, vous constaterez que la plupart des modules commencent par un ensemble de déclarations globales. De toute évidence, les gens n'ont aucun problème avec eux.

En particulier pour Python, la visibilité des globals est limitée à un module. Par conséquent, il n'y a pas de "vrais" globals qui affectent l'ensemble du programme, ce qui les rend moins dangereux. Autre point: il n’existe pas de const, vous devez donc utiliser une constante pour obtenir une constante.

Dans ma pratique, s'il m'est arrivé de modifier un global dans une fonction, je le déclare toujours avec global, même si cela n'est techniquement pas nécessaire, comme dans:

cache = {}

def foo(args):
    global cache

    cache[args] = ...

Cela facilite la traçabilité des manipulations des globals.

28
georg

Selon un avis personnel sur le sujet, le fait d’utiliser des variables globales dans une logique de fonction signifie qu’un autre code peut modifier la logique et le résultat attendu de cette fonction, ce qui rendra le débogage très difficile (en particulier dans les grands projets) et rendra le test plus difficile. ainsi que.

De plus, si vous considérez que d'autres personnes lisent votre code (communauté open-source, collègues, etc.), elles auront du mal à comprendre où la variable globale est définie, où a été changé et à quoi s'attendre de cette variable globale par opposition à une fonction isolée que sa fonctionnalité peut être déterminée en lisant la définition de la fonction elle-même.

(Probablement) violer la définition de la fonction pure

Je crois qu'un code propre et (presque) sans bug devrait avoir des fonctions aussi pures que possible (voir fonctions pures ). Une fonction pure est celle qui a les conditions suivantes:

  1. La fonction évalue toujours la même valeur de résultat avec la même valeur d'argument (s) . La valeur du résultat de la fonction ne peut dépendre d'aucune information cachée ni d'aucun état susceptible de changer au cours de l'exécution du programme ou entre différentes exécutions du programme, ni des entrées externes des périphériques d'E/S (en général, voir ci-dessous).
  2. L'évaluation du résultat ne provoque aucun effet secondaire ou sortie observable de manière sémantique, telle que la mutation d'objets mutables ou la sortie vers des périphériques d'E/S.

Avoir des variables globales viole au moins l'un des éléments ci-dessus, sinon les deux, car un code externe peut probablement entraîner des résultats inattendus.

Une autre définition claire des fonctions pures: "Fonction pure est une fonction qui prend toutes ses entrées sous forme d'arguments explicites et produit tous ses résultats en tant que résultats explicites . " [1] . Avoir des variables globales viole l’idée de fonctions pures puisqu’une entrée et peut-être l’une des sorties (la variable globale) n’est pas explicitement donnée ou retournée.

(Probablement) violation du principe du test F.I.R.S.TF

De plus, si vous considérez les tests unitaires et le principe FIRST ( [~ # ~] f [~ # ~] , ast testez, [~ # ~] i [~ # ~] tests indépendants, [~ # ~] r [~ # ~] épatable, [~ # ~] s [~ # ~] elf-Validation et [~ # ~] t [~ # ~] immédiatement) violera probablement le principe des tests indépendants (ce qui signifie que les tests ne dépendent pas les uns des autres).

Avoir une variable globale (pas toujours), mais dans la plupart des cas (du moins de ce que j'ai vu jusqu'à présent), c'est préparer et transmettre les résultats à d'autres fonctions. Cela viole également ce principe. Si la variable globale a été utilisée de cette manière (c'est-à-dire que la variable globale utilisée dans la fonction X doit d'abord être définie dans une fonction Y), cela signifie que pour que la fonction de test unitaire X soit exécutée, vous devez d'abord exécuter la fonction de test/exécution Y.

Globals comme constantes

D'autre part et comme d'autres personnes l'ont déjà mentionné, si la variable globale est utilisée comme variable "constante", cela peut être légèrement mieux, car le langage ne prend pas en charge les constantes. Cependant, je préfère toujours travailler avec des classes et avoir les "constantes" en tant que membre de la classe et ne pas utiliser de variable globale. Si vous avez un code dont deux classes différentes ont besoin pour partager une variable globale, vous devrez probablement refactoriser votre solution et rendre vos classes indépendantes.

Je ne crois pas que les globals ne devraient pas être utilisés. Mais s’ils sont utilisés, les auteurs devraient considérer certains principes (ceux mentionnés ci-dessus et peut-être d’autres principes et bonnes pratiques en matière de génie logiciel) pour obtenir un code plus propre et presque sans bugs.

9
Rafael

Ils sont essentiels, l’écran étant un bon exemple. Toutefois, dans un environnement multithread ou impliquant de nombreux développeurs, la question qui se pose est souvent la suivante: qui l'a (à tort) définie ou effacée? Selon l'architecture, l'analyse peut être coûteuse et souvent nécessaire. Bien que la lecture de la variable globale puisse être correcte, l’écriture doit être contrôlée, par exemple, par un seul thread ou une classe threadsafe. Par conséquent, les coûts globaux résultent de la crainte de coûts de développement élevés possibles du fait des conséquences pour lesquelles ils sont considérés comme pervers. Par conséquent, en règle générale, il est judicieux de limiter le nombre de vars globaux.

3
Horst Schlawutzke