Pourquoi les variables globales sont-elles mauvaises? [fermé]

121

J'essaie de savoir pourquoi l'utilisation de globalest considérée comme une mauvaise pratique en python (et en programmation en général). Quelqu'un peut-il expliquer? Des liens avec plus d'informations seraient également appréciés.

LarsVegas
la source
Voter pour rouvrir - J'ai édité la question pour déplacer l'attention vers les explications et loin des ressources hors site. (Je suppose que ce pourquoi il a été fermé, mais juste au cas où il y a quelque chose à voir avec une question sur les mauvaises pratiques, comparer ces questions sur les mauvaises pratiques qui sont encore ouvertes: eval, import *, concaténation de chaînes , variablesid , les ombres d'attributs )
wjandrea

Réponses:

156

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 conceptuellement les mêmes que les variables globales ; les constantes globales sont parfaitement inoffensives. En Python, la distinction entre les deux est purement par convention: CONSTANTS_ARE_CAPITALIZEDet globals_are_not.

La raison pour laquelle les variables globales sont mauvaises est qu'elles permettent aux fonctions d'avoir des effets secondaires cachés (non évidents, surprenants, difficiles à détecter, difficiles à diagnostiquer), conduisant à une augmentation de la complexité, conduisant potentiellement au code Spaghetti .

Cependant, une utilisation sensée de l'état global est acceptable (tout comme l'état local et la mutabilité) même dans la programmation fonctionnelle, que ce soit pour l'optimisation des algorithmes, la réduction de la complexité, la mise en cache et la mémorisation, ou le caractère pratique du portage de structures provenant d'une base de code principalement impérative.

Dans l'ensemble, votre question peut trouver une réponse de plusieurs manières, donc votre meilleur pari est simplement de google "pourquoi les variables globales sont-elles mauvaises". Quelques exemples:

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

Erik Kaplun
la source
35

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

Spécifiquement pour python, la visibilité des globaux est limitée à un module, donc il n'y a pas de "vrais" globaux qui affectent l'ensemble du programme - ce qui les rend moins dangereux. Autre point: il n'y en a pas const, donc lorsque vous avez besoin d'une constante, vous devez utiliser un global.

Dans ma pratique, s'il m'arrive 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 globaux.

Georg
la source
3
à bien des égards, un module en python est similaire à une classe singleton, et les globaux de module sont similaires aux propriétés de classe.
Corley Brigman
9
@CorleyBrigman: les classes singleton souffrent souvent des mêmes problèmes généralement attribués aux globals :)
Erik Kaplun
4
la visibilité des modules python n'est pas limitée à un module. Ils sont disponibles dans l'intégralité de l'interpréteur, et (c'est important ici) les modifications affectent l'ensemble de l'interprète. Ce n'est pas comme une chaîne que vous créez des instances ... c'est comme modifier toutes les instances de chaîne. Odeur de patch de singe.
graffic
2
La plupart des modules ne commencent pas par définir des globaux à l' exception des constantes. Les globaux sont mauvais signifie que les variables / l'état global ne sont pas des constantes.
BlackJack
2
L'utilisation de globals est une idée horrible, une des raisons pourrait être l'incapacité de tester correctement les fonctions qui mettent à jour un dictionnaire arbitraire qui existe «quelque part». Une base de code avec des globaux ne peut pas être réellement prouvée fonctionnelle.
Tomasz Sosiński
10

Une opinion personnelle sur le sujet est que l'utilisation de variables globales dans une logique de fonction signifie qu'un autre code peut modifier la logique et la sortie attendue de cette fonction, ce qui rendra le débogage très difficile (en particulier dans les grands projets) et rendra les tests plus difficiles. 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 à essayer de comprendre où la variable globale est définie, où a été modifiée 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 fonction elle-même.

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

Je crois qu'un code propre et (presque) sans bogue devrait avoir des fonctions aussi pures que possible (voir les 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 ou les mêmes valeurs d'argument . La valeur du résultat de la fonction ne peut dépendre d'aucune information cachée ou d'un état pouvant changer pendant l'exécution du programme ou entre différentes exécutions du programme, ni d'une entrée externe des périphériques d'E / S (généralement - voir ci-dessous).
  2. L'évaluation du résultat n'entraîne aucun effet secondaire ou sortie sémantiquement observable , comme la mutation d'objets mutables ou la sortie vers des périphériques d'E / S.

Le fait d'avoir des variables globales enfreint 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: "Une fonction pure est une fonction qui prend toutes ses entrées comme arguments explicites et produit toutes ses sorties comme des 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 FIRST du test unitaire

Plus loin, si l' on considère l' unité-test et le principe FIRST ( F tests ast, I des tests ndependent, R epeatable, S elfe validants et T Imely) violeront probablement les tests indépendants principe ( ce qui signifie que les tests ne dépendent sur l'un et l'autre).

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 tester l'unité de la fonction X, vous devez d'abord exécuter la fonction de test / exécution Y.

Globals comme constantes

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

Je ne pense pas que les globaux ne devraient pas être utilisés. Mais s'ils sont utilisés, les auteurs devraient considérer certains principes (ceux mentionnés ci-dessus peut-être et d'autres principes de génie logiciel et bonnes pratiques) pour un code plus propre et presque exempt de bogues.

Rafael
la source
1
J'aime les "globales en tant que constantes est un problème" ... parce que si vous faites du design OO ... c'est vraiment le cas. Pourquoi quelqu'un d'autre que la classe IdCreator a-t-il besoin de connaître l'ID_LEN?
Erik Aronesty
3

Ils sont essentiels, l'écran en est un bon exemple. Cependant, dans un environnement multithread ou avec de nombreux développeurs impliqués, dans la pratique, la question se pose souvent: qui l'a (de manière erronée) définie ou effacée? En fonction de l'architecture, l'analyse peut être coûteuse et souvent requise. 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 vars mondiaux suscitent la peur des coûts de développement élevés possibles par les conséquences pour lesquelles ils sont considérés comme mauvais. Par conséquent, en général, il est recommandé de maintenir le nombre de variables mondiales bas.

Horst Schlawutzke
la source