Avoiding Globals?

Monkey Forums/Monkey Programming/Avoiding Globals?

zoqfotpik(Posted 2014) [#1]
How important is it to avoid global variables, in the scale and scope of small-to-medium-size apps?

It seems to me that the ease of use for a relatively small number of global variables outweighs headaches associated with them, many of which aren't likely to crop up for our applications (multithreading, etc.)

This is just something I've been doing for 35 years now and it doesn't really seem like the end of the world that a lot of people have claimed it to be. Obviously you don't want all of your variables to be global, but for variables that are accessed by almost everything, what is the harm really?


therevills(Posted 2014) [#2]
For a personal project, globals IMHO aren't an issue, but for a shared API or business app you want your modules to be self containing as much as possible with best OO practice.


zoqfotpik(Posted 2014) [#3]
That's pretty much what I thought. I know enough about software engineering to be very concerned about breaking Great Edicts like that one, but as we know, a lot of the things they teach in the Ivory Tower are unhelpful, unnecessary or worse down in the trenches. For me this seems to be a production speed thing. Any suggestions for how to manage variables better?


therevills(Posted 2014) [#4]
You could use a class full of static (global) fields, or an interface (not sure if that would work in monkey).

[Code]Class Globals
Global gravity: Float = 9.81
End [/code]


Paul - Taiphoz(Posted 2014) [#5]
I tend to abuse globals a fair bit, I work solo so no need for me to worry about other programmers messing things up, having a global class could be handy tho.


zoqfotpik(Posted 2014) [#6]
I have been thinking of setting up some sort of variable repository for other reasons (the tweaking interface I mentioned a week or so ago...) Lots of people use repositories but it's something I don't entirely understand the reasoning for, except for decoupling and recoupling between different data items.

Yes, Monkey does allow interfaces but I haven't gotten around to figuring them out yet.

Isn't a globals class just brushing the problem under the carpet? You're still using globals.

What I've been playing around with is making a boxed int class, on the Create method using reflection to find out the variable name, then adding the variable to a map full of boxed variables. That's massively hairy but I'm messing around with it for the variable tweaker and other reasons.


ElectricBoogaloo(Posted 2014) [#7]
I'm a self-confessed Global-a-holic...
I have a lot of terrible habits, and Globals are one of them.
If Monkey did GOTO, I'd still be using that, too.

Like Revills said, if you're coding for yourself you aren't expecting to reuse too much, and nobody's ever going to see it, it's not really important.
The important bit is that it works, and that you keep an eye on things.
Using Globals means more things can go wrong, when you accidentally reuse them. Goodness knows how often I've stumbled upon stuck-loops because I constantly keep reusing "n"!!!

Take care, double check, and you'll be fine.
Commands, keywords, types and functions are all there to be used. If it was DANGEROUS, it wouldn't be in.


darky000(Posted 2014) [#8]
I tend to shy away with global variables unless it is used for everyone like scales, default device width and height and they are mostly constants or changed rarely. My problem is I usually forget small things I implement on my code so I always generalize my code and encapsulate them as much as possible so when I proceed the next day or two, I don't have to worry about changed values besides the things I am currently working on. It is a matter of setting your own rules I guess.


Arjailer(Posted 2014) [#9]
"you aren't expecting to reuse too much" - see that's the tricky bit. It's always the things you least expect that you end up wanting to re-use. That's why I now encapsulate everything in non-global classes and pass that state around and avoid globals at all costs - 'cos globals have a way of biting you in the most delicate places when you least expect it.


Gerry Quinn(Posted 2014) [#10]
I thought I responded to this earlier,

Personally I used to worry more about globals than I do now. Most things should be owned by classes, but there are certainly cases where too much encapsulation gets in the way.

In small to medium games, in particular, you tend to have several single-instance, tightly coupled classes, such as game logic, display screen(s), player character etc. Without globals, you can easily end with either an excessive amount of message passing, or classes with pointers to each other and exposed internals, which is really just a form of messy globalisation by the back door.

I do try to keep all globals pertaining to a single game in the same file.


zoqfotpik(Posted 2014) [#11]
I know after all the work I've put into my current game, I'm going to be reusing the current system a whole bunch of times. Hell, most of the 80s and 90s arcade games put out by given publishers reused the same graphics system numerous times with only incremental improvements.


wiebow(Posted 2014) [#12]
I work on my framework, but I use a class to create a namespace for all my globals and stats. Still, if you work alone, don't bother, unless you use a lot of modules from other authors. Then it might be sensible to use a class to ensure your globals are your globals.


muddy_shoes(Posted 2014) [#13]
Even with reuse the question is how you will reuse code. I suspect most people would end up essentially reusing a whole framework structure and that would include things like system globals. The problems only occur if you want to pull out a single system and discover that it's full of global references that you don't want to take too. To be honest that's really just a dependency issue though -- if all those global references were made non-global you'd still have a problem with extracting the system.

As with pretty much every software engineering principle there are cost and benefits and pragmatism needs to be applied. The internet is full of puritans, mostly fresh from a software engineering class taught by someone who has never created a large commercial software system, who will speak from a metaphorical pulpit on the one true way with no regard for the realities of any specific situation.

When talking about globals as "bad" we need to consider what sort of global usage we're talking about. I once worked on a system where they had somehow ended up with over a hundred shared global primitives. These were freely used by anyone who felt the need and the code contained multiple instances of people using a "rarely referenced" global as a temp variable completely at random. This was definitely bad and would be bad even if working alone. On the other hand mojo clearly has global state all over the place for things like the rendering colour, alpha, font etc. Is this bad? I'd suggest that the answer is "yes, in certain circumstances, but generally only if you want to use it in a way not intended".

If someone were to argue that avoiding globals has benefits with testability/modularity, I would agree. If they were to argue that you should therefore never allow global references of any kind, ban singletons and always use dependency injection in all code then I'd suggest they're being unreasonably dogmatic. You should certainly question shared writeable global state. You should also try to limit system dependencies of all kinds and it's better not to use a global where a dependency exists. However, sometimes things are genuinely global in nature and sometimes simple convenience is a factor for productivity. I wonder how many code purity crusaders seriously use dependency injection to pass a reference to their Logging class to everything they write for example.


wiebow(Posted 2014) [#14]
I couldn't live without singletons anymore... I agree muddy_shoes.


Samah(Posted 2014) [#15]
@muddy_shoes: I once worked on a system where they had somehow ended up with over a hundred shared global primitives.

Hey therevills, does this remind you of a certain class in the pn package? :)


Paul - Taiphoz(Posted 2014) [#16]
Global's like anything in programming are very powerful but like all things with power can easily be abused and misused, one thing I find that helps manage their use and prevent accidental use or abuse of a global is following a strict and simple naming convention, for people that are not used to following one it can be a bit annoying trying to get yourself into the habit, but its something I can strongly recommend as it will save you a lot of headache in the long run and it will make your code a lot easier to read.

Package/Imports : lowercase
Const : ALL_UPPER
Global,Methods,Functions,Keywords.... : PascalCase
Local: lowerCamalCase
Field : lowercase
Func/Method Params : _lowercase


ElectricBoogaloo(Posted 2014) [#17]
LMAO.. You guys would HATE my code!!!


Samah(Posted 2014) [#18]
My naming convention:
Const: UPPERCASE_WITH_UNDERSCORES
Global, Local, Field: camelCase
Class, Interface, Property, Method, Function, Keywords: PascalCase
Package names: lowercase

When you have an IDE that does variable scope syntax highlighting (Jungle) I see no reason to use different conventions for variable scopes.


Paul - Taiphoz(Posted 2014) [#19]
I use three Ide's at the same time, I have diddy or other modules open in Ted at all times so I can when needed have a look under the hood.

I use Mollusk for my ember module so I can tweak it in place while working on my project.

and of course where the grunt of the work is done, Jugnle for the game itself, so the second I boot jungle I also boot the other two, so keeping to a standard really helps me at least.

I do agree tho, Jungle does make life easier with it's highlighting, but I think even with that I will still continue to maintain my standard, it simply makes like easier in the long run and I am not always looking at code in jungle or an IDE with good highlighting.


Samah(Posted 2014) [#20]
I just use Jungle for everything. It's smart enough to jump to the Diddy source if I Shift+F2 on any Diddy identifier. Also I can view any number of files at the same time. Thanks ziggy! :)
All it needs now is a native OSX client...


Nobuyuki(Posted 2014) [#21]
I discovered the jump-to thing about a month ago and it's been indispensible for debugging the labyrinth of code that is our current project. Having 4-5 people's crap in a single Monkey codebase can be extremely hairy if everyone follows a different coding convention. I mostly have the same convention as Samah, though I avoid prefixing "I" to interfaces, and try to keep locals in all lowercase. (Also I avoid Strict because it's too anal about matching parenthesis to methods with no parameters)

Speaking of, Globals drive me batty. The aforementioned codebase has some 15-20 globals, whereas my framework's convention is to make all game components' toplevel stuff exist as a field of the App singleton unless absolutely necessary for external reasons. Worse, the globals don't have a consistent naming convention, so everything's all kinds of effed up. One of the people involved with the code at one point was clearly a C++ programmer, because he honored the code with a couple globals we can't get rid of that start with "g_", and some classes I managed to refactor out that had fields that started with "m_". Gross.

Just say no to Globals on the top level. All of my games call the App singleton "Game", so that global namespace vars are always prefixed with "Game." -- Do this and you'll never be confused where something lives.


Paul - Taiphoz(Posted 2014) [#22]
I can't really do that samah, my projects tend to be more than ten files and I like to have them all open in tabs at the same time, if I'm working on something and then have to add additional tabs it gets really annoying to deal with, even moving between tabs now is a bit annoying because I have so many open, so adding my module and diddy to that set of tabs would be a nightmare for me.

I actually have a good solution to this lot of tab problem, I blogged about my idea a while back, something that's based on how Ant's communicate and how it could be applied to IDE's Ant Ide Idea if something like that was applied to an IDE the raw data could then be used to sort the active tabs pushing the more active tabs to the left, the end result would be an automatically sorted set of tabs with the ones your working on the most readily available at the left and the others which your not working on so much off to the right.


Gerry Quinn(Posted 2014) [#23]
My convention:

Const: COLOUR_RED
Const inside class: RED
Global: theThing
Local, Field: camelCase
Class, Method, Function, Keywords: PascalCase
Parameter: camelCase
Interface: IName
Package (filename): lowercase

In major project classes (not always in utility classes):
*Non* Const Method: _PascalCase
Out Parameter: _camelCase
Parameters not marked with an underscore should not be changed by the method.

{Edit: I said that const methods get underscores but of course it is the other way round: methods that are non-const get them - and the fewer of those, the better.)


therevills(Posted 2014) [#24]
Yes, Monkey does allow interfaces but I haven't gotten around to figuring them out yet.

Yeah I know MonkeyX has interfaces, but I didn't know if you could have globals in them... like Java:
public class HelloWorld implements IGlobals{
     public static void main(String[] args){
        System.out.println("Gravity = " + gravity);
     }
}

interface IGlobals{
    public float gravity = 0.91f;
}

But I've just tried this with MonkeyX and you get "Error : Interfaces can only contain constants and methods." when compiling.

Isn't a globals class just brushing the problem under the carpet? You're still using globals.

Yes, but now it is a Class so its "cleaner" ;)

Hey therevills, does this remind you of a certain class in the pn package? :)

SystemStorageArea.java = orz


Samah(Posted 2014) [#25]
@therevills: Yeah I know MonkeyX has interfaces, but I didn't know if you could have globals in them... like Java

Yep, and Java 8 allows for default implementations in interfaces. That's something I'd love in Monkey!

@therevills: SystemStorageArea.java = orz

I just counted, and there are 107 public static non-final fields in SystemStorageArea.
Note to others: This is a class in the application therevills and I maintain for a living.

@Nobuyuki: The aforementioned codebase has some 15-20 globals

If you mean Diddy, blame therevills. He loves globals. :D


Goodlookinguy(Posted 2014) [#26]
I just counted, and there are 107 public static non-final fields in SystemStorageArea.

Sounds like a God object anti-pattern in the making.

Now, to chime in my opinion on the topic (which no one cares to hear, but I'll cram it down your throats anyways). I find it necessary to use globals whenever I have code like timers that are cached at every update. I have to keep a global list of all of the timers created and then update them accordingly as well as destroy them when they're finished. Same thing with fades and tweens so that I don't have to keep recalculating the interpolation between points.

For everything else I use the singleton instance of the App class with a bunch of fields to do all of the other global stuff. It avoids the idea of globals while still very much doing it.