Les variables globales sont-elles mauvaises? [fermé]


247

En C / C ++, les variables globales sont-elles aussi mauvaises que mon professeur le pense?


17
Je mordrai au cas où il essaierait de raconter une blague ... "à quel point sont-ils mauvais"?
Zach Scrivena

13
Je pense que cette question était assez intéressante! Le développement logiciel est toujours confronté aux mêmes pièges depuis le début et les programmeurs ignorent souvent que l'utilisation de variables globales, gotos, variable nommée courte N'EST PAS le problème. Un mauvais code est écrit tous les jours sans les utiliser. +1
Sylvain Rodrigue

69
Comment pouvons-nous éventuellement répondre? Il ne nous a pas dit à quel point son professeur pense qu'ils sont mauvais. :)
Steve Fallows

9
@Juan Mendes Je suis 100% d'accord avec vous! Le problème dont je parlais est que de nombreux développeurs savent qu'ils ne devraient pas utiliser de variables globales mais ils ne savent tout simplement pas pourquoi! Et j'ai donc vu de nombreux gros logiciels où chaque fonction a reçu la même méga-structure contenant +100 champs - Regardez maman, pas de variables globales! Même problème que les soi-disant «bonnes pratiques»: ce sont de bonnes pratiques dans CERTAINS contextes, pas dans tous les contextes. Leur utilisation PEUT créer un code non modifiable. À votre santé.
Sylvain Rodrigue

3
Il existe très peu de bonnes utilisations des variables globales. Une utilisation possible, mais discutable, serait un objet de "configuration" global, qui lit dans un fichier de configuration une fois au démarrage.
Siler

Réponses:


257

Le problème avec les variables globales est que, puisque chaque fonction y a accès, il devient de plus en plus difficile de déterminer quelles fonctions lisent et écrivent réellement ces variables.

Pour comprendre comment fonctionne l'application, vous devez à peu près tenir compte de chaque fonction qui modifie l'état global. Cela peut être fait, mais à mesure que l'application se développe, cela deviendra plus difficile au point d'être pratiquement impossible (ou du moins une perte de temps complète).

Si vous ne comptez pas sur des variables globales, vous pouvez passer l'état entre différentes fonctions selon vos besoins. De cette façon, vous avez de bien meilleures chances de comprendre ce que fait chaque fonction, car vous n'avez pas besoin de prendre en compte l'état global.


10
Cette réponse est vraiment bonne. Combinez cela avec la réponse «minimiser la portée variable» stackoverflow.com/questions/357187/…
bobobobo

17
Remplacez «classe» par «application» et «état d'objet» par «état global» et vous faites exactement le même argument pour ne pas utiliser de variables membres (ou champs) dans les classes. La vraie réponse est de les utiliser le cas échéant.
Ian Goldby

2
Quelques questions (peut-être idiotes): 1) Si vous voulez savoir quelles fonctions lisent et écrivent ces variables, ne pourriez-vous pas simplement utiliser la fonction "find" dans un éditeur pour repérer les cas où les valeurs de ces variables sont modifiées? 2) "Cela peut être fait, ... une perte de temps complète)." Pouvez-vous donner un exemple? 3) "Si vous ne comptez pas sur des variables globales, ... vous n'avez pas besoin de prendre en compte l'état global." Je ne comprends pas en quoi c'est un avantage. Peut-être qu'un exemple de cela fonctionnerait pour moi.
Andrei

2
@bobobobo lien cassé, pouvons-nous obtenir une capture d'écran de votre part, utilisateur 10k +?
noɥʇʎԀʎzɐɹƆ

3
@ noɥʇʎԀʎzɐɹƆ C'est parti! i.imgur.com/RwRgJLZ.jpg
Mateen Ulhaq

85

L'important est de se souvenir de l'objectif global: la clarté

La règle «pas de variables globales» existe parce que la plupart du temps, les variables globales rendent la signification du code moins claire.

Cependant, comme beaucoup de règles, les gens se souviennent de la règle, et non de ce que la règle était censée faire.

J'ai vu des programmes qui semblent doubler la taille du code en passant un nombre énorme de paramètres pour éviter simplement le mal des variables globales. En fin de compte, l'utilisation de globaux aurait rendu le programme plus clair pour ceux qui le liraient . En adhérant inconsidérément au mot de la règle, le programmeur d'origine avait échoué à l'intention de la règle.

Donc, oui, les globaux sont souvent mauvais. Mais si vous pensez qu'en fin de compte, l'intention du programmeur est rendue plus claire par l'utilisation de variables globales, alors allez-y. Cependant, rappelez-vous la baisse de clarté qui s'ensuit automatiquement lorsque vous forcez quelqu'un à accéder à un deuxième morceau de code (les globaux) pour comprendre comment fonctionne le premier morceau.


8
Suggérer d'utiliser un global au lieu de passer des variables est une recette pour rendre votre code non réutilisable et dangereux pour le multi-threading
Juan Mendes

16
Suggérer des globaux dans les bonnes circonstances est une recette pour un code plus clair et plus performant. "Passer" nécessite une allocation de mémoire dynamique de pile constante, et ce serait idiot pour quelque chose qui devrait être un global, comme un tampon global pour les données de socket entrantes. Par exemple, si vous avez une fonction qui lit Winsock recv (), pourquoi créer et désallouer constamment ce tampon à chaque appel? Faites du tampon un global. De multiples threads ne le liront pas de toute façon.
James

Juste curieux, quel programme double la taille du code en passant des paramètres pour éviter les variables globales? D'après mon expérience, l'utilisation de variables globales peut résoudre les problèmes d'exposition des données, mais il y a généralement une logique complexe supplémentaire que vous devez ajouter afin de vous assurer que ces variables magiques se comportent correctement.
user2167582

3
Si quelqu'un passe environ 100 variables, il n'a pas appris ce qu'est un objet. Utiliser la référence à cet objet, c'est au pire contourner un pointeur. Je dirais que la règle n'est pas seulement la clarté, mais aussi la testabilité - et l'utilisation d'une approche non globale a tendance à rendre les choses beaucoup plus faciles à tester.
UKMonkey

2
"Si quelqu'un passe environ 100 variables, alors il n'a pas appris ce qu'est un objet." D'accord, mais tout le monde n'est pas orienté objet. Mon exemple personnel de doublement de la taille du code était un grand programme Fortran, vers 1986. En tant qu'employé fraîchement sorti de l'université, je l'ai "amélioré", en ajoutant environ 30 paramètres à chaque appel, éliminant ainsi tous les pays. Puis j'ai annulé mon amélioration quand j'ai réalisé ce que j'avais fait.
Tom West

64

Mon professeur avait l'habitude de dire quelque chose comme: utiliser des variables globales est correct si vous les utilisez correctement. Je ne pense pas que je sois jamais arrivé à les utiliser correctement, donc je les ai rarement utilisés du tout.


25
Tellement vrai. Ils sont comme des gotos, si vous ne savez pas quand les utiliser, ne le faites jamais.
David Holm

5
Dans ma société actuelle, ils utilisent staticbeaucoup de variables globales, le langage est C. Étant confinés à des unités de traduction relativement petites, ils commencent à ressembler à des variables de classe d'objets C ++.
Vorac

1
Les variables statiques @Vorac ne sont pas des variables globales, ce sont des variables locales. Une variable globale est une variable disponible partout dans le programme (d'où "global", duh). À ne pas confondre avec les variables de portée de fichier , qui sont des variables déclarées en dehors de toute fonction. Une variable de portée de fichier statique n'est pas une variable globale.
Lundin

1
Pour me corriger, program lifetime, file scope variables. Et ils deviennent assez globaux une fois que vous passez un pointeur sur la variable vers le monde extérieur (ce qui est impossible avec les variables automatiques).
Vorac

@Lundin Je suis d'accord, staticles variables globales ont une portée limitée à la même unité de traduction. Mais ils ont une durée de vie jusqu'à la fin du programme comme n'importe quelle variable globale.
akhilesh1988

38

Les variables globales ne doivent être utilisées que si vous n'avez pas d'autre alternative. Et oui, cela inclut les singletons. Dans 90% des cas, des variables globales sont introduites pour réduire le coût de contournement d'un paramètre. Et puis le codage multithreading / test unitaire / maintenance se produit, et vous avez un problème.

Alors oui, dans 90% des situations, les variables globales sont mauvaises. Les exceptions ne sont pas susceptibles d'être vues par vous pendant vos années de collège. Une exception à laquelle je peux penser du haut de ma tête concerne les objets intrinsèquement globaux tels que les tables d'interruption. Des choses comme la connexion DB semblent être mondiales, mais ce n'est pas le cas.


2
La seule exception que j'ai vue au cours de mes années universitaires était les fonctions de rappel graphique. Dans XWindows, les rappels de souris n'avaient pas d'arguments de données void * qui vous permettaient de contourner des morceaux arbitraires de l'état du programme ... (pas que cela finisse par être BEAUCOUP mieux qu'un global de toute façon ...)
Brian Postow

10
+1 pour "Des choses comme la connexion DB semblent être mondiales, mais ce n'est pas le cas."
R .. GitHub STOP HELPING ICE

1
Les tables d'interruption ne sont pas globales, il y en a une par processeur - mais il y a aussi une instance de votre programme par processeur, donc elle "s'annule".
user253751

1
Quelqu'un peut-il m'éclairer sur les raisons pour lesquelles les connexions DB ne sont pas globales (et quelle serait une bonne alternative)? J'ai toujours pensé que les connexions étaient l'un des rares cas où les global étaient acceptables.
Floella

33

Le problème que les variables globales créent pour le programmeur est qu'il étend la surface de couplage inter-composants entre les différents composants qui utilisent les variables globales. Cela signifie que lorsque le nombre de composants utilisant une variable globale augmente, la complexité des interactions peut également augmenter. Ce couplage accru rend généralement les défauts plus faciles à injecter dans le système lors des modifications et rend également les défauts plus difficiles à diagnostiquer et à corriger. Ce couplage accru peut également réduire le nombre d'options disponibles lors des modifications et il peut augmenter l'effort requis pour les modifications, car il faut souvent suivre les différents modules qui utilisent également la variable globale afin de déterminer les conséquences des changements.

Le but de l' encapsulation , qui est fondamentalement le contraire de l'utilisation de variables globales, est de diminuer le couplage afin de rendre la compréhension et le changement de source plus faciles et plus sûrs et plus facilement testés. Il est beaucoup plus facile d'utiliser les tests unitaires lorsque les variables globales ne sont pas utilisées.

Par exemple, si vous avez une simple variable entière globale qui est utilisée comme indicateur énuméré que divers composants utilisent comme machine d'état et que vous apportez ensuite une modification en ajoutant un nouvel état pour un nouveau composant, vous devez ensuite suivre tous les autres composants pour garantir que le changement ne les affectera pas. Un exemple d'un problème possible serait si une switchinstruction pour tester la valeur de la variable globale d'énumération avec des caseinstructions pour chacune des valeurs actuelles est utilisée à divers endroits et il se trouve que certaines switchinstructions n'ont pas de defaultcas à gérer une valeur inattendue pour le global tout d'un coup vous avez un comportement indéfini en ce qui concerne l'application.

D'un autre côté, l'utilisation d'une zone de données partagée peut être utilisée pour contenir un ensemble de paramètres globaux référencés dans toute l'application. Cette approche est souvent utilisée avec des applications intégrées avec de petites empreintes mémoire.

Lorsque vous utilisez des variables globales dans ce type d'applications, la responsabilité de l'écriture dans la zone de données est généralement attribuée à un seul composant et tous les autres composants voient la zone comme constet y lisent, sans jamais y écrire. Cette approche limite les problèmes qui peuvent se développer.

Quelques problèmes de variables globales qui doivent être contournés

Lorsque la source d'une variable globale telle qu'une structure est modifiée, tout ce qui l'utilise doit être recompilé afin que tout ce qui utilise la variable connaisse sa taille réelle et son modèle de mémoire.

Si plusieurs composants peuvent modifier la variable globale, vous pouvez rencontrer des problèmes avec des données incohérentes dans la variable globale. Avec une application multithread, vous devrez probablement ajouter une sorte de verrouillage ou une région critique pour fournir un moyen de sorte qu'un seul thread à la fois puisse modifier la variable globale et lorsqu'un thread modifie la variable, toutes les modifications sont terminées et validée avant que d'autres threads puissent interroger la variable ou la modifier.

Le débogage d'une application multithread qui utilise une variable globale peut être plus difficile. Vous pouvez rencontrer des conditions de concurrence qui peuvent créer des défauts difficiles à reproduire. Étant donné que plusieurs composants communiquent via une variable globale, en particulier dans une application multithread, il est très difficile de comprendre quel composant modifie la variable quand et comment il modifie la variable.

Le conflit de noms peut être un problème avec l'utilisation de variables globales. Une variable locale qui porte le même nom qu'une variable globale peut masquer la variable globale. Vous rencontrez également le problème de convention de dénomination lors de l'utilisation du langage de programmation C. Une solution consiste à diviser le système en sous-systèmes avec les variables globales pour un sous-système particulier commençant toutes par les mêmes trois premières lettres (voir ceci sur la résolution des collisions d'espace de nom dans l'objectif C ). C ++ fournit des espaces de noms et avec C, vous pouvez contourner cela en créant une structure globalement visible dont les membres sont divers éléments de données et pointeurs vers des données et des fonctions qui sont fournies dans un fichier comme statique, donc avec une visibilité de fichier uniquement afin qu'elles ne puissent être référencées qu'à travers la structure globalement visible.

Dans certains cas, l'intention de l'application d'origine est modifiée de sorte que les variables globales qui ont fourni l'état d'un seul thread sont modifiées pour permettre l'exécution de plusieurs threads en double. Un exemple serait une application simple conçue pour un seul utilisateur utilisant des variables globales pour l'état, puis une demande provient de la direction pour ajouter une interface REST pour permettre aux applications distantes d'agir en tant qu'utilisateurs virtuels. Alors maintenant, vous devez dupliquer les variables globales et leurs informations d'état afin que l'utilisateur unique ainsi que chacun des utilisateurs virtuels des applications distantes aient leur propre ensemble unique de variables globales.

Utiliser C ++ namespaceet la structtechnique pour C

Pour le langage de programmation C ++, la namespacedirective aide énormément à réduire les risques de conflit de noms. namespaceainsi que classet les différents mots - clés d'accès ( private, protectedet public) fournir la plupart des outils dont vous avez besoin pour les variables encapsulent. Cependant, le langage de programmation C ne fournit pas cette directive. Cette publication stackoverflow, Namespaces in C , fournit quelques techniques pour C.

Une technique utile consiste à avoir une seule zone de données résidentes en mémoire qui est définie comme structayant une visibilité globale et dans laquelle se structtrouvent des pointeurs vers les différentes variables et fonctions globales qui sont exposées. Les définitions réelles des variables globales se voient attribuer une portée de fichier à l'aide du staticmot - clé. Si vous utilisez ensuite le constmot clé pour indiquer celles qui sont en lecture seule, le compilateur peut vous aider à appliquer l'accès en lecture seule.

L'utilisation de la structtechnique peut également encapsuler le global afin qu'il devienne une sorte de package ou de composant qui se trouve être un global. En ayant un composant de ce type, il devient plus facile de gérer les changements qui affectent le global et les fonctionnalités utilisant le global.

Cependant, même si namespacela structtechnique peut aider à gérer les conflits de noms, les problèmes sous-jacents de couplage inter-composants que l'utilisation de globaux introduit en particulier dans une application multi-thread moderne, existent toujours.


C'est la meilleure explication haut la main, explique tout ce qu'il y a à faire. Gloire!
johndoevodka

Votre langue doit avoir une règle de code pour vous empêcher d'utiliser trop de couplage de classes.
Melbourne Developer

19

Oui, mais vous n'encourez pas le coût des variables globales jusqu'à ce que vous cessez de travailler dans le code qui utilise des variables globales et commencez à écrire quelque chose d'autre qui utilise le code qui utilise des variables globales. Mais le coût est toujours là.

En d'autres termes, c'est un coût indirect à long terme et en tant que tel, la plupart des gens pensent que ce n'est pas mauvais.


19

S'il est possible que votre code soit soumis à un examen approfondi lors d'un procès devant la Cour suprême , vous devez vous assurer d'éviter les variables globales.

Voir cet article: Le code de l'alcootest buggy reflète l'importance de l'examen des sources

Il y avait quelques problèmes avec le style du code qui ont été identifiés par les deux études. L'un des problèmes stylistiques qui préoccupaient les examinateurs était l'utilisation extensive de variables globales non protégées . Ceci est considéré comme une forme médiocre car cela augmente le risque que l'état du programme devienne incohérent ou que les valeurs soient modifiées ou écrasées par inadvertance. Les chercheurs ont également exprimé leur inquiétude quant au fait que la précision décimale n'est pas maintenue de manière cohérente dans tout le code.

Mec, je parie que ces développeurs souhaitent qu'ils n'aient pas utilisé de variables globales!


6
Ce fut le meilleur rire que j'ai eu depuis un moment. Un vrai exemple de la raison pour laquelle le développement de sources fermées à but lucratif est mauvais, et un bon exemple de vars mondiaux qui ont mal tourné!
Evil Spork

Ce qui est établi ici, c'est que les variables globales sont vues avec mépris. Il n'y a rien ici qui montre que les variables globales étaient un véritable problème dans le code. SysTest a déclaré que bien que le code "n'ait pas été écrit d'une manière cohérente avec les meilleures pratiques habituelles de conception de logiciels", il continuerait à "produire de manière fiable des résultats de test cohérents". Donc, aucun mal des globaux n'a été réellement documenté. Comme je le vois, ils ont juste établi que, "Eh bien, ces développeurs ne pratiquent pas la même religion de codage que le reste du monde dominant."
LionKimbro

19

Les variables globales sont aussi mauvaises que vous les créez, pas moins.

Si vous créez un programme entièrement encapsulé, vous pouvez utiliser des globaux. C'est un «péché» d'utiliser les globaux, mais les péchés de programmation sont assez philosophiques.

Si vous consultez L.in.oleum , vous verrez un langage dont les variables sont uniquement globales. C'est non évolutif parce que les bibliothèques n'ont pas d'autre choix que d'utiliser des globaux.

Cela dit, si vous avez des choix et pouvez ignorer la philosophie du programmeur, les globaux ne sont pas si mauvais.

Gotos non plus, si vous les utilisez correctement.

Le gros "mauvais" problème est que, si vous les utilisez mal, les gens hurlent, le mars lander plante et le monde explose ... ou quelque chose comme ça.


17
Minimiser les problèmes d'utilisation des globaux à un étudiant confus n'est pas une bonne idée OMI.
GEOCHET

3
La philosophie du design n'est pas objective. Pas le moindre. Ce n'est pas parce que la plupart des programmeurs n'aiment pas quelque chose que l'on ne devrait jamais se pencher sur ce quelque chose. Il est facile de faire un usage général des globaux sans la fin du monde. Laissez-le faire, lutter (sachant qu'il le ferait) et apprendre comment.
user54650

7
Rich a raison. Cette réponse ne dit rien sur ce qui est / n'est pas mauvais (ou sur la façon dont les globaux peuvent être utilisés en toute sécurité), seulement que "ils ne sont pas aussi mauvais que tout cela. En tant que tel, cela minimise les problèmes.
jalf

4
Je ne suis pas d'accord pour dire que les variables globales sont aussi "mauvaises que vous les créez". Je pense que l'un des principaux problèmes, en particulier dans ce monde multi-développeur et interconnecté que la plupart d'entre nous vivent, travaillent et programment, est que les variables globales donnent à quelqu'un d'autre la possibilité de rendre votre code incorrect.
gariepy

@gariepy jusqu'à ce que je sache que la discussion porte sur la statique: D ok donc c'est ça ... et mon application n'a qu'une ou deux variables globales, celle-ci est livrée avec Visual Studio, DEBUG et TRACE que nous n'utilisons normalement pas: D
deadManN

17

Je répondrais à cette question par une autre question: utilisez-vous des singeltons / les singeltons sont-ils mauvais?

Parce que (presque tous) l'utilisation de singelton est une variable globale glorifiée.


11
J'étais sur le point de poster un commentaire intelligent disant: "Ils ne sont mauvais que si vous les appelez globaux au lieu de singletons", mais vous m'avez battu.
smo

J'essaie toujours de comprendre ce que les singletons de l'enfer sont LOL.
GeoffreyF67

1
@Geoffrey: voici quelques bonnes descriptions de SO - stackoverflow.com/questions/11831/… et pour quelques bons liens: stackoverflow.com/questions/11831/…
Gavin Miller

10
Pour mémoire, un singleton est une variable globale avec un nom de Design Patterns (tm) (lol) glorifié pour le rendre légitime. C'est tout aussi mauvais pour les mêmes raisons.
R .. GitHub STOP HELPING ICE

@GavinMiller Dites-vous que c'est OK si vous utilisez le simpleton ... ooops, euphémisme singleton?
Juan Mendes

14

Le problème est moins qu'ils sont mauvais et plus qu'ils sont dangereux . Ils ont leur propre ensemble d'avantages et d'inconvénients, et il y a des situations où ils sont soit le moyen le plus efficace soit le seul moyen d'accomplir une tâche particulière. Cependant, ils sont très faciles à mal utiliser, même si vous prenez des mesures pour toujours les utiliser correctement.

Quelques avantages:

  • Accessible depuis n'importe quelle fonction.
  • Accessible à partir de plusieurs threads.
  • Ne sortira jamais de la portée jusqu'à la fin du programme.

Quelques inconvénients:

  • Accessible à partir de n'importe quelle fonction, sans avoir besoin d'être explicitement glissé en tant que paramètre et / ou documenté.
  • Pas thread-safe.
  • Pollue l'espace de noms global et peut potentiellement provoquer des collisions de noms, sauf si des mesures sont prises pour éviter cela.

Notez, si vous voulez, que les deux premiers avantages et les deux premiers inconvénients que j'ai énumérés sont exactement la même chose, juste avec un libellé différent. En effet, les fonctionnalités d'une variable globale peuvent en effet être utiles, mais les fonctionnalités mêmes qui les rendent utiles sont à l'origine de tous leurs problèmes.

Quelques solutions potentielles à certains des problèmes:

  • Demandez-vous s'il s'agit en fait de la solution la meilleure ou la plus efficace au problème. S'il existe de meilleures solutions, utilisez-les à la place.
  • Placez-les dans un espace de noms [C ++] ou une structure singleton [C, C ++] avec un nom unique (un bon exemple serait Globalsou GlobalVars), ou utilisez une convention de dénomination standardisée pour les variables globales (comme global_[name]ou g_module_varNameStyle(comme mentionné par underscore_d dans les commentaires) )). Cela documentera à la fois leur utilisation (vous pouvez trouver du code qui utilise des variables globales en recherchant le nom d'espace / nom de structure) et minimiser l'impact sur l'espace de nom global.
  • Pour toute fonction qui accède aux variables globales, documentez explicitement les variables qu'elle lit et qu'elle écrit. Cela facilitera le dépannage.
  • Placez-les dans leur propre fichier source et déclarez-les externdans l'en-tête associé, afin que leur utilisation puisse être limitée aux unités de compilation qui doivent y accéder. Si votre code repose sur un grand nombre de variables globales, mais que chaque unité de compilation n'a besoin d'accéder qu'à une poignée d'entre elles, vous pouvez envisager de les trier dans plusieurs fichiers source, il est donc plus facile de limiter l'accès de chaque fichier aux variables globales.
  • Configurez un mécanisme pour les verrouiller et les déverrouiller, et / ou concevez votre code de sorte que le moins de fonctions possible aient réellement besoin de modifier les variables globales. Les lire est beaucoup plus sûr que de les écrire, bien que les races de threads puissent toujours causer des problèmes dans les programmes multithreads.
  • Fondamentalement, minimisez l'accès à ces derniers et maximisez l'unicité du nom. Vous voulez éviter les collisions de noms et avoir le moins de fonctions possible qui peuvent potentiellement modifier une variable donnée.

Qu'ils soient bons ou mauvais dépend de la façon dont vous les utilisez. La majorité a tendance à les mal utiliser, d'où la méfiance générale à leur égard. S'ils sont utilisés correctement, ils peuvent être une aubaine majeure; si elle est utilisée mal, cependant, ils peuvent et vont revenir à vous mordre quand et comment vous attendez le moins.

Une bonne façon de voir les choses est qu’elles-mêmes ne sont pas mauvaises, mais elles permettent une mauvaise conception et peuvent multiplier de manière exponentielle les effets d’une mauvaise conception.


Même si vous n'avez pas l'intention de les utiliser, il vaut mieux savoir comment les utiliser en toute sécurité et choisir de ne pas les utiliser, que de ne pas les utiliser parce que vous ne savez pas comment les utiliser en toute sécurité. Si jamais vous vous trouvez dans une situation où vous devez conserver du code préexistant qui repose sur des variables globales, vous pourriez avoir des difficultés si vous ne savez pas comment les utiliser correctement.


1
+1 pour le pragmatisme. Un singleton ajoute souvent juste un passe-partout pour transformer l'instance et le refactor en membres, et vous vous retrouvez avec ... des variables globales, simplement masquées sous un nom différent. Pourquoi s'embêter, sinon pour éviter le péché des globaux sur une simple technicité? Les espaces de noms sont sympa comme barrière, mais je trouve un simple g_module_varNameStyleparfaitement lisible. Pour être clair, je n'utilise pas les globaux si je peux l'éviter facilement - mot clé facilement , car depuis que j'ai cessé de croire qu'ils doivent être évités - ou plutôt obscurcis - à tout prix, je passe un bien meilleur moment, et mon le code est (choc!) bien plus ordonné
underscore_d

@underscore_d C'est principalement juste pour avoir un moyen de différencier plus facilement les variables globales et locales, et aussi pour faciliter la localisation des variables globales lors de la recherche dans votre code, dans le but d'éviter toute confusion quant à savoir si une variable est globale ou locale / un paramètre / un membre / etc .. Une convention de dénomination standard comme la vôtre fonctionne aussi bien, tant qu'elle est cohérente. Modification de ma réponse avec l'idée de convention de nommage standard, merci.
Justin Time - Rétablir Monica le

1
"Pour toute fonction ... documenter explicitement quelles variables" - rappelez-vous qu'il s'agit d'une relation transitive. Si la fonction A appelle les fonctions B et C, alors elle lit et écrit les variables écrites par les deux (plus celles directement dans son corps)
Caleth

11

Comme quelqu'un l'a dit (je paraphrase) dans un autre fil de discussion "Des règles comme celle-ci ne devraient pas être enfreintes, jusqu'à ce que vous compreniez pleinement les conséquences de le faire."

Il y a des moments où des variables globales sont nécessaires, ou du moins très utiles (travailler avec des rappels définis par le système par exemple). D'un autre côté, ils sont également très dangereux pour toutes les raisons qui vous ont été dites.

Il existe de nombreux aspects de la programmation qui devraient probablement être laissés aux experts. Parfois, vous avez besoin d'un couteau très tranchant. Mais vous ne pouvez pas en utiliser un avant d'être prêt ...


1
Je suis d'accord, si vous comprenez les conséquences, c'est OK d'enfreindre les règles, mais si vous vous surprenez à le faire souvent, vous faites quelque chose de mal
Juan Mendes

9

Les variables globales sont généralement mauvaises, surtout si d'autres personnes travaillent sur le même code et ne veulent pas passer 20 minutes à rechercher tous les endroits auxquels la variable est référencée. Et l'ajout de threads qui modifient les variables apporte un tout nouveau niveau de maux de tête.

Les constantes globales dans un espace de noms anonyme utilisé dans une seule unité de traduction sont fines et omniprésentes dans les applications et bibliothèques professionnelles. Mais si les données sont modifiables et / ou doivent être partagées entre plusieurs UT, vous voudrez peut-être les encapsuler - si ce n'est pour des raisons de conception, alors pour le débogage de quiconque ou pour travailler avec votre code.


9

L'utilisation de variables globales est un peu comme balayer la saleté sous un tapis. C'est une solution rapide et beaucoup plus facile à court terme que de se débarrasser d'un aspirateur ou d'un aspirateur pour le nettoyer. Cependant, si vous finissez par déplacer le tapis plus tard, vous aurez un gros désordre surprise en dessous.


métaphore paresseuse dépourvue de contexte! = réponse
underscore_d

1
@underscore_d: Je ne suis pas d'accord. Il s'agit d'une question de discussion, même si elle n'est pas étiquetée en tant que telle (probablement en raison de son âge), et donc des réponses comme celle-ci sont parfaitement valides, et cela fait un point qui répond à la question des PO.
gariepy

7

Les variables globales sont mauvaises, si elles vous permettent de manipuler des aspects d'un programme qui ne doivent être modifiés que localement. Dans la POO, les globaux entrent souvent en conflit avec l'idée d'encapsulation.


7

Je pense que votre professeur essaie d'arrêter une mauvaise habitude avant même qu'elle ne commence.

Les variables globales ont leur place et comme beaucoup de gens l'ont dit, savoir où et quand les utiliser peut être compliqué. Je pense donc que plutôt que d'entrer dans le vif du sujet, pourquoi, comment, quand et où des variables globales votre professeur a décidé de simplement interdire. Qui sait, il pourrait les interdire à l'avenir.


7

Absolument pas. Les abuser cependant ... c'est mauvais.

Les supprimer sans raison pour le plaisir est juste que ... sans raison. À moins que vous ne connaissiez les avantages et les inconvénients, il est préférable de rester clair et de faire ce que vous avez appris / appris, mais il n'y a rien de mal implicitement avec les variables globales. Lorsque vous comprenez les avantages et les inconvénients, prenez votre propre décision.


3
-1 Il existe de nombreuses raisons de mettre en garde contre les variables globales: la plus importante pour moi est que les dépendances cachées et globales rendent le test du code de toute manière prévisible extrêmement difficile. Sauf si vous n'appréciez pas la possibilité de tester votre code de manière automatisée, je suggère que les variables globales ne vous causeront que de la peine. Et en plus, dans un programme bien structuré, il y a toujours des alternatives.
jkp

1
ce que vous dites est une surgénéralisation massive, une utilisation prudente de l'état global n'empêche pas les tests automatisés - en fait, presque toutes les applications ont un état global, qu'il soit encapsulé comme des instances allouées dynamiquement d'objets bien encapsulés ou de données statiques qui sont totalement exposées. ne fait aucune différence conceptuellement, il existe encore des dépendances - il s'agit simplement de la façon dont elles sont codées.
jheriko

1
Exactement. Ils ne sont pas tellement "mauvais" qu'ils sont "facilement cassables". Si vous savez comment les utiliser sans casser quoi que ce soit et quand les utiliser au lieu d'une alternative, ils peuvent être utiles. Sinon ... pas tellement.
Justin Time - Réintègre Monica

4

Les variables globales sont bien dans les petits programmes, mais horribles si elles sont utilisées de la même manière dans les grands.

Cela signifie que vous pouvez facilement prendre l'habitude de les utiliser tout en apprenant. C'est de cela que votre professeur essaie de vous protéger.

Lorsque vous êtes plus expérimenté, il sera plus facile d'apprendre quand ils vont bien.


4

Non, ce n'est pas mal du tout. Vous devez regarder le code (machine) produit par le compilateur pour faire cette détermination, parfois il est bien pire d'utiliser un local qu'un global. Notez également que mettre "statique" sur une variable locale en fait fondamentalement une variable globale (et crée d'autres problèmes laids qu'un véritable global résoudrait). les "globaux locaux" sont particulièrement mauvais.

Les globaux vous donnent également un contrôle net sur votre utilisation de la mémoire, ce qui est beaucoup plus difficile à faire avec les locaux. De nos jours, cela n'a d'importance que dans les environnements embarqués où la mémoire est assez limitée. Quelque chose à savoir avant de supposer que l'embarqué est le même que les autres environnements et que les règles de programmation sont les mêmes à tous les niveaux.

Il est bon que vous remettiez en question les règles enseignées, la plupart d'entre elles ne le sont pas pour les raisons qui vous sont données. La leçon la plus importante n'est cependant pas que c'est une règle à transporter avec vous pour toujours, mais c'est une règle requise pour honorer afin de passer cette classe et aller de l'avant. Dans la vie, vous constaterez que pour la société XYZ, vous aurez d'autres règles de programmation que vous devrez finalement respecter afin de continuer à recevoir un chèque de paie. Dans les deux situations, vous pouvez contester la règle, mais je pense que vous aurez beaucoup plus de chance au travail qu'à l'école. Vous n'êtes qu'un autre parmi de nombreux étudiants, votre siège sera bientôt remplacé, les professeurs ne le feront pas, à un poste, vous faites partie d'une petite équipe de joueurs qui doivent voir ce produit jusqu'au bout et dans cet environnement, les règles développées sont pour le au bénéfice des membres de l'équipe ainsi que du produit et de l'entreprise, donc si tout le monde est du même avis ou si pour le produit particulier il y a une bonne raison d'ingénierie pour violer quelque chose que vous avez appris au collège ou un livre sur la programmation générique, alors vendez votre idée à l'équipe et écrivez-la comme une méthode valide sinon la méthode préférée . Tout est un jeu équitable dans le monde réel.

Si vous suivez toutes les règles de programmation qui vous sont enseignées à l'école ou dans les livres, votre carrière en programmation sera extrêmement limitée. Vous pouvez probablement survivre et mener une carrière fructueuse, mais l'étendue et la largeur des environnements à votre disposition seront extrêmement limitées. Si vous savez comment et pourquoi la règle est là et que vous pouvez la défendre, c'est bien, si votre seule raison est "parce que mon professeur l'a dit", eh bien ce n'est pas si bon.

Notez que des sujets comme celui-ci sont souvent débattus sur le lieu de travail et continueront de l'être, à mesure que les compilateurs et les processeurs (et les langues) évoluent, ce genre de règles évolue et sans défendre votre position et peut-être une leçon donnée par quelqu'un avec une autre opinion que vous ne connaissez pas Avance.

En attendant, faites tout ce que dit celui qui parle le plus fort ou qui porte le plus gros bâton (jusqu'à ce que vous soyez celui qui crie le plus fort et porte le plus gros bâton).


4
Est-ce juste une autre façon de dire "personne n'a jamais été licencié pour avoir acheté IBM"?
Gordon Potter

1
Bon point que pour certaines applications, l'utilisation de variables globales peut en fait faciliter le travail. En général, l'utilisation de variables globales est une source de problèmes avec les voies cachées de couplage entre les sections de la source. Cependant, avoir une zone de mémoire partagée référencée comme globale est utilisée pour un certain nombre d'implémentations telles que les interfaces de périphérique ou peut-être une table de paramètres globale contenant des constantes de différents types ou une table de saut.
Richard Chambers

4

Je voudrais argumenter contre le fait que tout au long de ce fil de discussion soit dit qu'il rend le multi-filetage plus difficile ou impossible en soi. Les variables globales sont un état partagé, mais les alternatives aux globales (par exemple en passant des pointeurs) peuvent également partager l'état. Le problème avec le multithread est de savoir comment utiliser correctement l'état partagé, pas si cet état se trouve être partagé via une variable globale ou autre chose.

La plupart du temps, lorsque vous faites du multi-threading, vous devez partager quelque chose. Dans un modèle producteur-consommateur par exemple, vous pouvez partager une file d'attente thread-safe qui contient les unités de travail. Et vous êtes autorisé à le partager car cette structure de données est thread-safe. Que cette file d'attente soit globale ou non est totalement hors de propos en ce qui concerne la sécurité des threads.

L'espoir implicite exprimé tout au long de ce fil de discussion que la transformation d'un programme d'un fil unique à plusieurs fils sera plus facile lorsque vous n'utilisez pas de globaux est naïf. Oui, les globaux facilitent la prise de vue dans le pied, mais il existe de nombreuses façons de se tirer une balle.

Je ne préconise pas les globaux, car les autres points restent valables, mon point est simplement que le nombre de threads dans un programme n'a rien à voir avec une portée variable.


3

Oui, car si vous laissez les programmeurs incompétents les utiliser (lire 90% en particulier les scientifiques), vous vous retrouvez avec plus de 600 variables globales réparties sur plus de 20 fichiers et un projet de 12 000 lignes où 80% des fonctions annulent, renvoient et fonctionnent entièrement sur l'état mondial.

Il devient rapidement impossible de comprendre ce qui se passe à un moment donné à moins que vous ne connaissiez l'ensemble du projet.


2

L'utilisation de variables globales dépend en fait des exigences. Son avantage est que cela réduit la surcharge de transmission répétée des valeurs.

Mais votre professeur a raison car cela pose des problèmes de sécurité, il faut donc éviter autant que possible l'utilisation de variables globales. Les variables globales créent également des problèmes qui sont parfois difficiles à déboguer .

Par exemple:-

Situations où les valeurs des variables sont modifiées lors de l' exécution . À ce moment, il est difficile d'identifier quelle partie du code le modifie et à quelles conditions.


2

Global est bon en matière de configuration . Lorsque nous voulons que notre configuration / modifications ait un impact global sur l' ensemble du projet .

Nous pouvons donc modifier une configuration et les modifications sont dirigées vers l' ensemble du projet . Mais je dois vous avertir qu'il faudrait être très intelligent pour utiliser les globaux.


1

Tôt ou tard, vous devrez changer la façon dont cette variable est définie ou ce qui se passe lors de son accès, ou il vous suffit de rechercher où elle est modifiée.

Il est pratiquement toujours préférable de ne pas avoir de variables globales. Il suffit d'écrire les méthodes d'obtention et de définition du barrage et de vous glander quand vous en avez besoin un jour, une semaine ou un mois plus tard.


1

J'utilise généralement des globaux pour les valeurs qui sont rarement modifiées comme les singletons ou les pointeurs de fonction en fonctions dans une bibliothèque chargée dynamiquement. L'utilisation de globaux mutables dans les applications multithread a tendance à entraîner des bogues difficiles à suivre, j'essaie donc d'éviter cela en règle générale.

L'utilisation d'un global au lieu de passer un argument est souvent plus rapide mais si vous écrivez une application multithread, ce que vous faites souvent de nos jours, cela ne fonctionne généralement pas très bien (vous pouvez utiliser des threads statiques mais le gain de performances est discutable) .


1

Dans les applications Web, une entreprise peut être utilisée pour conserver des données spécifiques à la session / fenêtre / thread / utilisateur sur le serveur pour des raisons d'optimisation et pour éviter la perte de travail lorsque la connexion est instable. Comme mentionné, les conditions de course doivent être gérées. Nous utilisons une seule instance d'une classe pour ces informations et elles sont soigneusement gérées.


1

En fin de compte, votre programme ou application peut toujours fonctionner, mais c'est une question d'être bien rangé et d'avoir une compréhension complète de ce qui se passe. Si vous partagez une valeur variable entre toutes les fonctions, il peut devenir difficile de déterminer quelle fonction modifie la valeur (si la fonction le fait) et rend le débogage un million de fois plus difficile


0

la sécurité est moindre signifie que n'importe qui peut manipuler les variables si elles sont déclarées globales, pour celle-ci pour expliquer, prenez cet exemple si vous avez le solde comme variable globale dans votre programme bancaire, la fonction utilisateur peut manipuler cela ainsi que l'agent de banque peut également manipuler cela pose donc un problème. Seul l'utilisateur doit se voir attribuer la fonction de lecture seule et de retrait, mais le greffier de la banque peut ajouter le montant lorsque l'utilisateur remet personnellement l'argent comptant au bureau.


-1

Dans une application multithread, utilisez des variables locales à la place des variables globales pour éviter une condition de concurrence.

Une condition de concurrence critique se produit lorsque plusieurs threads accèdent à une ressource partagée, avec au moins un thread ayant un accès en écriture aux données. Ensuite, le résultat du programme n'est pas prévisible et dépend de l'ordre des accès aux données par différents threads.

Plus d'informations à ce sujet ici, https://software.intel.com/en-us/articles/use-intel-parallel-inspector-to-find-race-conditions-in-openmp-based-multithreaded-code


Pour la postérité: c'est en partie correct au mieux. Les "variables locales" dans cette réponse se réfèrent aux variables locales de thread , plutôt qu'aux variables locales de portée les plus courantes auxquelles l'OP fait référence. Les effets secondaires de la modification des variables globales d'une manière non sécurisée pour les threads sont très différents de ceux de la modification de l'état global d'une manière non simultanée.
Jules
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.