Reputation: 2604
After reading some SO threads on this topic: I've come up with these reasons for why global variables/singletons are bad.
I want to make a game in C++, and there will be a "heightmap object" that represents the landscape of the world in my game as heightmap. This heightmap can change. I want to use a global object for it. (I don't expect to run into static initialization order issues, as there won't be any other static variable that references this heightmap object).
Now, I know global state is bad, and global mutable state is even worse, for those above reasons. But it seems really, really cumbersome to do the alternative: Create a heightmap object at main()
scope, and pass that heightmap object to every single function that wants to use it.
What if I'm 100% sure that there will only be one heightmap in my application? Also, since this is a small, solo project, I have faith that I will be able to understand what each function is doing to the global state? And I don't see how the use of a global variable in this this case hurts unit testing. If I want to use a mock heightmap, couldn't I just do globalHeightmap = generateMockHeightmap();
before calling the function that I want to test?
Upvotes: 1
Views: 159
Reputation: 96241
As certain as you may be about the characteristics of your project right now, I can pretty much assure you that at some point in the future you'll need to modify the code that relies on this global variable. At that point the global variable will likely come back and make it harder for you to figure out the needed changes because state isn't hidden (for example what if you accidentally change the state instead of reading from it - then the entire program is affected at some random point in the future). I can't overstate how important it is for program maintenance and debugging to minimize state mutation points and global variables are pretty much the antithesis to that goal.
Just overriding the global state map for your unit test seems fragile. What if you need to restore the old state, or mutate between states in the test? Then you wind up with a bunch of save/set/restore code.
What if you ever want to add a threading model to your application? Using global state will make that transition that much more complicated.
What if someone else helps you out with the project a year from now? Will they be able to understand the code? Will you be able to understand it a year from now (I know that I always try to write obvious code and add comments where it's not specifically because I might be the person that comes back a year later and no longer remember a thing about the mechanism).
Finally, if a non-global-variable approach seems like too much work or too complicated that probably means your alternate approach is too complicated or needs another idea/rework. There's no reason that you can't stash the heightmap into an object that's created at the appropriate high-level game object and passed/stored in lower level objects as needed.
Upvotes: 1