Jump to content
  • Advertisement
Sign in to follow this  
shurcool

Avoiding Global Variables

This topic is 2366 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I was under the impression that if one had a lot of freedom and time to write high quality C++ code and follow best practices, then one could avoid having global variables altogether. After all, global variables often feel like quick hacks in order to code something up quickly, rather than "take your time and do it properly", and when a project gets larger they get in the way. Often, you'll need to replace a single global class instance with a list of properly maintained objects.

Anyway, if the general idea above is sort of true (that it's better code practice to avoid globals when possible, and it is possible to avoid them in all cases), what happens if...

Suppose you have a list of a lot of items. And each of these items needs to have some sort of connection to the outside world, i.e. for example to the list itself.

If you had a global variable, the problem would be solved trivially. But otherwise, would you have to specify that variable and add it to each instance of your item collection?


struct MyCustomContainer
{
int Whatever;
SomeGlobalClass * ConnectionToOutsideWorld; // This becomes a huge waste of memory because it's there in each instance, only to replace 1 global variable
}
std::vector<MyCustomContainer> LotsOfItems;


Please offer some advice.

Share this post


Link to post
Share on other sites
Advertisement
Why do all the object need that outside connection? That's the key here. They probably shouldn't. Perhaps they need it for some operation? In that case, pass that data to that operation instead.

Share this post


Link to post
Share on other sites
Here's some reference for advocating that global vars can/should be avoided: http://www.gamedev.net/topic/621707-singleton-template/

Basically, my question is this: Do I need to redesign my code so that the items in a huge list do not need a connection to the outside world... Or is there a better solution than to waste memory by padding each item with a variable (which could be replaced by 1 global variable or singleton).

Share this post


Link to post
Share on other sites
Ok, let me look up what exactly I was doing that required a connection to the outside. I'm pretty sure it seemed hard not to require it.

Share this post


Link to post
Share on other sites

Why do all the object need that outside connection? That's the key here. They probably shouldn't. Perhaps they need it for some operation? In that case, pass that data to that operation instead.

Okay, you were right. They need it for a few operations, and in theory I could be passing the outside-connection variable as a parameter to those functions. But I'll have to start passing it in oh-so-many places which is annoying given how much less typing it'd be to just have a reference.

Basically, I have a WidgetManager class that contains a bunch of instances of classes derived from a Widget class.

The Widget class has functions like CheckHover(), CheckActive() and CheckAnyActive() that return true if the currently hovering/active widget (info available in parent WidgetManager class) happens to be _this_ widget.

bool Widget::CheckHover()
{
return (this == m_WidgetManager.m_HoverWidget);
}
bool Widget::CheckActive()
{
return (this == m_WidgetManager.m_ActiveWidget);
}
bool Widget::CheckAnyActive()
{
return (nullptr != m_WidgetManager.m_ActiveWidget);
}


The classes that derive from Widget (e.g. ButtonWidget and whatnot) use those methods from Widget to do their jobs.

So it looks like I'd have to rewrite those functions as Widget::CheckHover(WidgetManager & WidgetManager), etc. if I want to avoid storing a WidgetManager & m_WidgetManager; variable in each instance of Widget. Of course, in this case there's probably not that many of them, but I just felt it was unnecessary duplication of memory in order to avoid globals...

Share this post


Link to post
Share on other sites

What about:


Widget::SetHover(bool hovered)


which is called by the window manager.

A WidgetManager will contain many Widgets. By design, there will at all times be 1 or no hover objects. So it makes sense to have one variable that represents which Widget (if any) is hover.

If each Widget has a bool hover, then:

1. It wastes memory.
2. Due to bugs or memory errors, it may be the case there will be more than 1 Widget with hover set to true, causing further bugs.

I want to follow the DRY principle. If some concept requires only one variable to represent it, I don't see any compelling reason (other than ease of writing code) to use more memory than that to represent it.

Share this post


Link to post
Share on other sites
Why have a variable at all? Use the mouse-move event to search for the widget under the cursor and tell said widget to do whatever it needs to do due to the on-hover condition.

Share this post


Link to post
Share on other sites
There is some state that needs to be kept track of from the past. Current mouse event isn't enough. For example, when releasing the mouse button, it matters where it was clicked to begin with. But this is off topic.

What I'm more interested in knowing is this:

If you have a large list of custom structs that needs an "outside world" connection, there two solutions that use no more memory than is least required:
1. global variable/singleton
2. pass in the variable as a parameter to functions that need it, every time

Any other solutions?

Share this post


Link to post
Share on other sites
Does the widget need to know that it's hovering? Probably not -- A widget should be concerned only with being a widget, not with how the application presents the widget. If the widget type itself has many states, then track the state internally -- if a collection of widgets can share in some mutual (or mutually-exclusive) state, as in your example, then the widget container is probably the appropriate place to hold that state.

An alternative solution to your problem would be to replace the widget to be hovered with a widget that is inherently hovering, and then to replace the old widget when it looses the hover status.

OOP doesn't state that you should push all state down into the lowest levels that you can, it states that state should exist at the lowest level that is reasonable in order to reduce the visibility of that variable -- its that act that reduces coupling, encourages SRP, and promotes reusability, among other OOP design goals.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!