J'essaie de comprendre pourquoi l'utilisation de global
est considéré 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.
Réponses
Trop de publicités?Cela n'a rien à voir avec Python ; les variables globales sont mauvaises dans tous les langages de programmation.
Toutefois, 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 conventionnelle : CONSTANTS_ARE_CAPITALIZED
y 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), ce qui entraîne une augmentation de la complexité et peut conduire à Code spaghetti .
Cependant, une utilisation raisonnable 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 l'aspect pratique du portage de structures provenant d'une base de code à prédominance impérative.
Dans l'ensemble, on peut répondre à votre question de bien des façons, et le mieux est donc de chercher sur Google "why are global variables bad" (pourquoi les variables globales sont-elles mauvaises ?). Quelques exemples :
- Les variables globales sont mauvaises - Wiki Wiki Web
- Pourquoi l'État mondial est-il si mauvais ? - Software Engineering Stack Exchange (en anglais)
- Les variables globales sont-elles mauvaises ?
Si vous voulez aller plus loin et découvrir la raison d'être des effets secondaires, et bien d'autres choses éclairantes, vous devriez apprendre la programmation fonctionnelle :
Oui, en théorie Les globaux (et l'"état" en général) sont diaboliques. En pratique, si vous regardez dans le répertoire des paquets de Python, vous verrez que la plupart des modules commencent par un tas de déclarations globales. Manifestement, les gens n'ont aucun problème avec ces déclarations.
En ce qui concerne spécifiquement Python, la visibilité des globales est limitée à un module, il n'y a donc pas de "vraies" globales qui affectent l'ensemble du programme - ce qui les rend moins nocives. Autre point : il n'y a pas de const
Ainsi, 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 s'il n'y a pas de nécessité technique, comme dans :
cache = {}
def foo(args):
global cache
cache[args] = ...
Les manipulations des globaux sont ainsi plus faciles à repérer.
Mon opinion personnelle sur le sujet est que l'utilisation de variables globales dans la logique d'une 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 les tests également.
En outre, 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ù elle a été modifiée et ce qu'elles peuvent attendre de cette variable globale, contrairement à une fonction isolée dont la fonctionnalité peut être déterminée en lisant la définition de la fonction elle-même.
(Probablement) Violation de la définition des fonctions pures
Je pense qu'un code propre et (presque) sans bogues devrait avoir des fonctions aussi pures que possible (voir fonctions pures ). Une fonction pure est celle qui remplit les conditions suivantes :
- La fonction évalue toujours la même valeur de résultat pour la même valeur d'argument(s) . La valeur du résultat de la fonction ne peut dépendre d'aucune information ou état caché susceptible de changer pendant l'exécution du programme ou entre différentes exécutions du programme, ni d'aucune entrée externe provenant de dispositifs d'entrée/sortie (généralement - voir ci-dessous).
- Évaluation du résultat ne provoque pas d'effet secondaire ou de résultat sémantiquement observable Il s'agit notamment de la mutation d'objets mutables ou de l'envoi de données à des périphériques d'entrée/sortie.
Le fait d'avoir des variables globales constitue une violation d'au moins l'un des points ci-dessus, si ce n'est des deux, étant donné qu'un code externe peut probablement provoquer 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 tous ses résultats en tant que résultats explicites ." [1] . Le fait d'avoir des variables globales viole l'idée de fonctions pures puisqu'une entrée et peut-être une des sorties (la variable globale) n'est pas explicitement donnée ou renvoyée.
(Probablement) Violation du principe F.I.R.S.T. des tests unitaires
Par ailleurs, si l'on considère les tests unitaires et le principe F.I.R.S.T. ( F ast tests, I ndependent tests, R epeatable, S elf-Valider et T imely) violera probablement le principe des tests indépendants (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 dans ce que j'ai vu jusqu'à présent), c'est préparer et passer des 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 la fonction X à l'unité, vous devez d'abord exécuter la fonction Y.
Les globales comme constantes
D'autre part, et comme d'autres l'ont déjà mentionné, si la variable globale est utilisée comme une variable "constante", cela peut être légèrement mieux puisque 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 membres de la classe et ne pas utiliser de variable globale du tout. Si vous avez un code dans lequel deux classes différentes doivent partager une variable globale, vous devez probablement remanier votre solution et rendre vos classes indépendantes.
Je ne pense pas que les globaux ne doivent pas être utilisés. Mais s'ils sont utilisés, les auteurs devraient prendre en compte certains principes (ceux mentionnés ci-dessus, peut-être, et d'autres principes de génie logiciel et de bonnes pratiques) pour un code plus propre et presque sans bogues.
Ils sont essentiels, l'écran en est un bon exemple. Toutefois, dans un environnement multithread ou avec de nombreux développeurs impliqués, la question se pose souvent dans la pratique : qui l'a défini ou effacé (de manière erronée) ? En fonction de l'architecture, l'analyse peut être coûteuse et s'avérer nécessaire à plusieurs reprises. Si la lecture de la variable globale peut se faire sans problème, son écriture doit être contrôlée, par exemple par un seul thread ou une classe threadsafe. C'est pourquoi les variables globales suscitent la crainte de coûts de développement élevés en raison des conséquences pour lesquelles elles sont elles-mêmes considérées comme néfastes. C'est pourquoi, en général, il est bon de limiter le nombre de variables globales.