Dealing with global variables properly?

Started by
7 comments, last by jpetrie 16 years ago
I'm just wondering what the professional standard is of dealing ( or not dealing ) with global variables? My application uses several libraries, and the globals ( shaderManager, resourceManager, directxStuff ) are needed thoughout the program at any level. Thanks for any advice! -Velik
Advertisement
Global variables are best avoided.

Quote:
My application uses several libraries, and the globals ( shaderManager, resourceManager, directxStuff ) are needed thoughout the program at any level.


What is really going on is that you think you need them at any level, where in reality it is only your current design that needs them at any level. Don't worry, I used to be the same. The only cure for it is disciple, do not allow yourself create global variables and you will come up with a design that does not require them.
Yeah, if you have it designed properly you should never really need globals. It's a bit of extra work, but it's worth it in the end. Good luck. [smile]
What the above posters said. Does your audioManager really need to talk to the renderer? Does your shaderManager really need to know about mouse input? You should instead consider passing the systems as variables down to where they are needed.
less lightbringer, thanks for all the useful advice. but yeah, I think theres got to be a better design then passing and replicating pointers everywhere.
Quote:Original post by Stellar Developer
less lightbringer, thanks for all the useful advice. but yeah, I think theres got to be a better design then passing and replicating pointers everywhere.


Passing pointers everywhere isn't a great substitution. Most of the time, you can partition large chunks of your application that do not need to talk to one another. Use this to cut down the number of pointers you need to pass.

Using a message system or signal/slot design can cut down on explicit dependencies, two subsystems can talk to each other without knowing about each other.
Everyone keeps saying avoid globals but rarely does anyone explain why you should be avoiding them.

Globals in themselves are not evil, what is evil is what people can do with your globals. If it is just a project you are working on for yourself, it is not a very big deal. If multiple people are working on your project then it becomes a much larger issue.

The problem with globals is that EVERY object in the game can have access to them. That means that at any time, anyone can change them at will. This can and most likely will lead to a debugging nightmare. We want to know, who is allowed to access which class, this means that if something gets changed we know the possible suspects. By passing a reference to a class you specify that that class is allowed access, thus you know it is a suspect if something goes wrong.

theTroll
Quote:Original post by Stellar Developer
I'm just wondering what the professional standard is [...]

[...] are needed thoughout the program at any level.


The professional standard is to avoid needing any mutable value throughout the program. This is usually done by assuming (when designing parts of your application) that the aforementioned mutable value does not exist.

Don't think in terms of "My program contains a resource manager, and this class needs to access it.", because this automatically implies global state (for which the better implementation is a global variable). Instead, think in terms of "This class works on a resource manager, but I haven't decided yet which resource manager it will work on, therefore I'll leave it as a function parameter and decide later." By delaying the moment when you bind the object-user with the object, you reduce the risk of an incorrect binding while allowing yourself the possibility to perform other bindings involving that object-user in other places in your program (thus reusing the object-user).
The "solution" -- or "better alternative" to globals (and singletons) is to not use them. What this doesn't mean is that you replace your global with a parameter in every function through which you pass the former global.

Think about it.

A rose by any other name... Globals and singletons are not "evil" nor generally considered malignant practice because they're called globals. The problem, as TheTroll points out, is that they are promiscuous. They can be touched from everywhere, by anything, with no consideration whatsoever as to the implications. Replacing a global with a parameter in every function does nothing for the health of your code (if anything it makes it worse).

Most people create a global because they figure, "I need this everywhere," but that isn't always the case. In a well-factorized design, you don't need to do all that much passing around of references to other subsystems. Pretend that it's impossible for you to create a global, and try to design your systems around that restriction. It's no different from designing around any other restriction (such as "you cannot write to the screen directly").

If you get stuck, ask for help. One of the real problems with "fixing" globals and the like is that the concrete solutions are often intensely domain-specific, and usually involve rather extensive redesign (which is why it's best to avoid them in the first place, if possible, since refactoring them out can frequently be too much effort against the gain in production code) -- in other words, it's difficult to provide a specific solution without specific code.

This topic is closed to new replies.

Advertisement