Global variables (again)

前端 未结 11 965
感情败类
感情败类 2021-01-21 16:31

I keep hearing that global variables should never be used, but I have a tendency to dismiss \"never\" rules as hot-headed. Ar

相关标签:
11条回答
  • 2021-01-21 16:34

    I'm also curious to hear the precise explanation, but I can tell you that the Singleton pattern usually works pretty well to fill the role of global variables.

    0 讨论(0)
  • 2021-01-21 16:36

    Global variables (and singletons, which are just a wrapper around a global variable) can cause a number of problems, as I discussed in this answer.

    For this specific issue -- blittable objects in a game kit -- I'd be apt to suggest a method signature like Sprite::drawOn(Canvas&, const Point&). It shouldn't be excessive overhead to pass a reference to the Canvas around, since it's not likely to be needed except in the paint pathway, and within that pathway you're probably iterating over a collection anyway, so passing it in that loop isn't that hard. By doing this, you're hiding that the main program has only one active screen buffer from the sprite classes, and therefore making it less likely to create a dependency on this fact.

    Disclaimer: I haven't used SDL itself before, but I wrote a simple cross-platform C++ game kit back in the late '90s. At the time I was working on my game kit, it was fairly common practice for multi-player X11-based games to run as a single process on one machine that opened a connection to each player's display, which would quite efficiently make a mess of code that assumed the screen buffer was a singleton.

    0 讨论(0)
  • 2021-01-21 16:43
    • Global variables can change in unexpected ways, which is usually not what you want. The state of the application will become complex and unmaintainable. Very easy to make something wrong. Especially if someone else is changing your code;

    • Singleton might be a better idea. That would at least give you some encapsulation in case you need to make extensions in the future.

    • One reason not to use global variables is a problem with namespaces (i.e. accidentally using the same name twice);

    • We do often use global (to namespace) constants at work which is considered normal, as they don't change (in unexpected ways) and it is very convenient to have them available in multiple files.

    0 讨论(0)
  • 2021-01-21 16:48

    If the screen buffer is shared between lots of different pieces of code, then you have two options:

    1) Pass it around all over the place. This is inconvenient, because every piece of code that uses the screen buffer, even indirectly, needs to be laboriously indicated as such by the fact that this object is passed through the call stack.

    2) Use a global. If you do this, then for all you know any function at all in your entire program might use the screen buffer, just by grabbing it from the global[*]. So if you need to reason about the state of the screen buffer, then you need to include the entire program in your reasoning. If only there was some way to indicate which functions modify the screen buffer, and which cannot possibly ever do so. Oh, hang on a second...

    This is even aside from the benefits of dependency injection - when testing, and in future iterations of your program, it might be useful for the caller of some function that blits, to be able to say where it should blit to, not necessarily the screen.

    The same issues apply as much to singletons as they do to other modifiable globals.

    You could perhaps even make a case that it should cost you something to add yet another piece of code that modifies the screen buffer, because you should try to write systems which are loosely coupled, and doing so will naturally result in fairly few pieces of code that need to know anything at all about the screen in order to do their job (even if they know that they're manipulating images, they needn't necessarily care whether those images are in the screen buffer, or some back buffer, or some completely unrelated buffer that's nothing to do with the screen). I'm not actually in favour of making extra work just to punish myself into writing better code, but it's certainly true that globals make it quite easy to add yet another inappropriate wad of coupling to my app.

    [*] Well, you may be able to narrow it down on the basis that only TUs that include the relevant header file will have the declaration. There's nothing technically to stop them copy-and-pasting it, but in a code base that's at all well regulated, they won't.

    0 讨论(0)
  • 2021-01-21 16:51

    Like any other design decision, using global variables has a cost. It saves you having to pass variables unnecessarily, and allows you to share state among running functions. But it also has the potential to make your code hard to follow, and to reuse.

    Some applications, like embedded systems, use global variables regularly. For them, the added speed of not having to pass the variable or even a pointer into the activation record, and the simplicity, makes it a good decision [arguably]. But their code suffers for it; it is often hard to follow execution and developing systems with increasing complexity becomes more and more difficult.

    In a large system, consisting of heterogeneous components, using globals may become a nightmare to maintain. At some point you may need a different screen buffer with different properties, or the screen buffer may not be available until it's initialized meaning you'll have to wrap every call to it with a check if it's null, or you'll need to write multithreaded code, and the global will require a lock.

    In short, you are free to use global vars while your application is small enough to manage. When it starts to grow, they will become a liability, and will either require refactoring to remove, or will cripple the programs growth (in terms of capability or stability). The admonition not to use them stems from years of hard-learned lessons, not programmer "hot-headedness".

    0 讨论(0)
  • 2021-01-21 16:51

    In this case a class that provides member functions for all methods that need access to the screen buffer would be a more OOP friendly approach. Why should everyone and any one have uncontrolled access to it!?

    As to whether there are times when a global is better or even necessary, probably not. They are deceptively attractive when you are hacking out some code, because you need jump through no syntactic hoops to access it, but it is generally indicative of poor design, and one that will rapidly atrophy inter maintenance and extension.

    Here's a good read on the subject (related to embedded programming, but the points apply to any code, it is just that some embedded programmers thing they have a valid excuse).

    0 讨论(0)
提交回复
热议问题