Global variables are bad (2013)
wiki.c2.com
wiki.c2.com
If module global variables are considered truly horrible, the same can be said about instance variables inside classes. They are as good (or bad) as module globals in the sense that they represent shared state and can potentially be mutated by any method/member function in the class.
Of course the functional programmers among us will say that shared state of any kind is bad, and I agree. But we are not talking about that here, are we?
With all its upsides, Python has a problematic global state story; it's easy to shoot yourself in the foot.
Global mutable variables are also awful for multithreading. Thread-locals help, but even they breaks horribly as soon as you use something like a thread pool.
Same can be done with module level globals.
There's another point in favor of instance variables: it gives you the flexibility of multiple values in different parts of your code. As codebases grow, the danger of two unrelated places wanting different values for your global also grows.
Say a physics simulation has a global for gravity. This precludes, or at least unnecessarily complicates, the same process from having two separate simulations with different gravities (perhaps in different threads). This is especially bad in library code.
To be clear, I am not saying globals should be used everywhere. There are a programming construct just like any other. When used carefully, they can greatly simplify code — but also have the potential to horribly complicate the code when abused. And that is true about any programming construct.
One thing that irritates me is the tendency to paint things black and white — eg. goto, globals, multiple inheritance etc. are bad. So “modern” programming languages try to eliminate them in a misguided attempt to keep programmers safe from themselves. I agree that these things are often misused, but a bad programmer will figure out a way to misuse anything — or do you think it is impossible to write bad code in something like, say, Go? Dumbing things down doesn’t prevent bad programmers from messing up, instead it causes the rest to write horrible code because of the lost power.
Used to be you wouldn't use globals because it was difficult to figure out what code accessed or changed their values. Now that's a right click away.
Is making them properties and sticking them in a "GlobalVariablesByAnotherName" singleton and chucking that around better? Possibly. Possibly not.
I have found, however, that any code where someone has used global variables is hard to share with other developers. Maybe that's the crux of the matter.
> As with all HeuristicRules, this is not a rule that applies 100% of the time. Code is generally clearer and easier to maintain when it does not use globals, but there are exceptions.
For me, the root of the problem with them is that they introduce coupling (or to put it another way, they break modularity). When you introduce global state, you introduce it everywhere. In reality there are probably only a handful of places that it relates to, but "is the global state involved here?" becomes a question you need to ask yourself whenever you write/update any part of the code.
The same argument can apply at more fine-grained levels. If you introduce a module-level variable, you need to keep it in mind whenever dealing with any code in that module. Similarly for class-level and instance-level variables.
There is a trade-off: ease-of-access and clarity vs the extra cognitive load you are introducing to every part of the scope. In my opinion, that balance determines whether a variable is good or bad. For any non-trivial piece of code, the sum almost always works out on the side of reducing the cognitive load.
Assuming Python-like modules, module-level globals are worse for encapsulation.
1. A function can access module-level state without having been explicitly passed a reference to it.
2. You can't create additional instances of module-level state. For example, if your app server uses a module-level global for the server listening socket, you can't run two app server instances in the same process.
So a global variable should not be used for such cases. That doesn’t mean it is inherently bad. People writing the code are supposed to think about what constructs to use for a given scenario.
Yes, programmers have to be aware of what they're doing, but that's true of any programming construct. It doesn't mean that we shouldn't identify the dangers.
I've worked with a codebase where the global state was passed around as a configuration object, and that made heavy liberal use of dependency inversion. No other code base I've seen was so obtuse...it was nearly impossible to know what a line of code did but looking at it.
Dependency injection and configuration objects certainly can be useful, but the bad design they seem to encourage makes me think very carefully about using them.
If it is mutable, you have even more problems.
About the only way to deal with this is to strictly enforce contracts and completeness when using and implementing such a thing.
I'm developing a game in Unity, and the programming culture around it encourages globals and singletons to an unhealthy degree. I pushed back against them heavily in our project. As a result, it was very easy to add a previously unplanned split-screen mode one day, thanks to the codebase (e.g. the UI and input modules) not assuming that there's only ever one local player.
If you plan to "virtualise" stuff later, instantiation is certainly the way.
Also, if you have so many globals that passing them around as parameters / instance variables becomes truly tedious, that can be a valuable signal that the program is poorly structured.
Of course, none of this matters in small codebases, as long as they stay small.
Write code for the application you want, not the set of all applications you might hypothetically want someday. Incur the cost of new features after you decide you want them, not before.
As with any software engineering guideline, there are exceptions. E.g. Java-style loggers are so ubiqitous and "not that mutable", that it's generally good for them to be global.
Edit: also from experience, suddenly wanting two of something where before there was only one, is not that uncommon.
Coming from Java and its best practices it seemed really odd at first, but it makes state management and debugging so much easier.
Isn't properties for the globe by definition global?
Also, in most cases, would not the rotation speed of a world be a constant not a variable?
people are tired of guidance being turned into rules and then into dogma.
If you actually encounter a situation where more self-documenting constructs don't work, sure, but usually that only happens due to deficiencies in your programming language.
> Segmentation faults as the preferred error handling technique?
Actually you should use SIGABRT, not SIGSEGV; see self-documenting.
Considered harmful assertions considered harmful.
https://en.wikipedia.org/wiki/Coupling_(computer_programming...
I don’t know if this is “good” or not but it seems to work OK.
I've done alternatives and I've never really seen the benefit.
It seems like there’s simply a reasonable cognative “maximum” of global before it becomes unworkable. My gut tells me it’s between 1 and 4.
Of course, if you don’t need that, it’s not a gain, and a global is fine.
Globals also are fine if you are resource constrained (e.g. if you have a few kilobytes of RAM or even less) Getting your code running in it may trump everything else.
Compiler generated constants can still change, because registers and memory are mutable.
Global constants are fine. Something like pi is as global as it gets, and it's never a problem.
There's an intermediate case of "global config info" which is technically mutable but is only mutated during a program startup, and stays constant during execution.
Otherwise it is better to pass them in (via dependency injection or otherwise) encapsulated so that enhancing the code for them to become variable or have versions is easy.
(A) it makes the code "singleton" by default: you can't instantiate two objects of the same class with two different values for the global argument
(B) unless the global argument is declared in the same class, it slightly obfuscates the fact that a class depends on the argument (compared to all dependencies being constructor parameters)
(C) it makes testing, especially multithreaded testing, more awkward and error-prone: tests have to set and reset global variables
It's easy enough to refactor (A) where needed, as long as you have control of the code, and (C) can be worked around with good enough test helpers.
I think one can reasonably argue both for and against the convenience outweighing these downsides.
A bug can be extremely hard to replicate, because it only arises from a very specific sequence of events that step-by-step flip the globals into an overall invalid state. And it's virtually impossible to determine "whodunnit".
It's a perfect recipe for "the app sometimes crashes on Thursdays" scenario.
For most other uses of globals, I fully agree.
Of course this is a bit of a red herring anyway... As the original commenter remarked already, command line flags may be stored globally (eg. as read-only fields), but won't - and shouldn't - be variables.
They're only given once, and their values aren't going to change throughout the program's running time. So they're essentially constants, which is fine.
P.S. That doesn't mean there were no public/ global vars in legacy code. This practice started when code quality and system stability gradually started declining by their overuse
This is not a bad reason at all. I think this is the best and most used reason. And no alternative is provided in TFA.