Jump to content

Global Variables

Wictorian

Why does everyone hate global variables? As far as I understand in some languages you dont have to import the variables into functions unlike in python and this causes name confusion.

Link to comment
Share on other sites

Link to post
Share on other sites

What happens in the function should generally stay in the function. A function takes an input, does something with it, and returns an output. Global variables can be read by any part of the code or changed by any part of the code, which may not be what you want. It can also confuse you as to why something is going wrong, because you forgot x was already defined on line 32 and now a function on line 14834 modifies it due to you accidentally/unknowingly using x as your throwaway iteration index, for example. It can also make it hard to decouple general functions or tasks from your code.

 

There may surely be cases where you do want to use them, but in my experience there is very often a better neater solution.

Crystal: CPU: i7 7700K | Motherboard: Asus ROG Strix Z270F | RAM: GSkill 16 GB@3200MHz | GPU: Nvidia GTX 1080 Ti FE | Case: Corsair Crystal 570X (black) | PSU: EVGA Supernova G2 1000W | Monitor: Asus VG248QE 24"

Laptop: Dell XPS 13 9370 | CPU: i5 10510U | RAM: 16 GB

Server: CPU: i5 4690k | RAM: 16 GB | Case: Corsair Graphite 760T White | Storage: 19 TB

Link to comment
Share on other sites

Link to post
Share on other sites

15 hours ago, Wictorian said:

Why does everyone hate global variables? As far as I understand in some languages you dont have to import the variables into functions unlike in python and this causes name confusion.

Globals are often hated because it's often misused by those learning (or used as a crutch).  It also messes with things when you have threaded applications.

 

That isn't to say global variables don't make sense...if used wisely or knowing the limitations they can be acceptable...but usually there are better options.  I know you mentioned python, but I'm going to use c style code to show a potential danger of it that many novices make

 

char buffer[1024];

int main(...) {
	printf("%s", strInt(123));
	printf("%s", strInt(1234));
	printf("%s", strInt(12345));
    
    //So far the output is okay
    
    for(int i = 0; i < 128; i++)
    	startThread(threads, threadFunc, i);//Okay not really thread code, but more of c pseudo code at this point
        
    //Assume startThread takes in something like the above, so you have 128 threads each that will call threadFunc...what happens?
    //You might get the printed output as 0 - 127...but you might also get 111222444
    //The reason is that you are writing to a global variable with multiple threads so at any given time it might actually be written to by multiple threads before printing
    
    //Another example
    printf("%s %s", strInt(123), strInt(1234));
    //So this will be how the compiler actually optimized things, but most likely you will get the output as
    //1234 1234
	return 0;
}

const char* strInt(int integerToString) {
	snprintf(buffer, 1024, "%d", integerToString)
	return buffer;
}

void threadFunc(int i) {
	printf("%s", strInt(i));
}

 

So that is why globals can be hated.  Lots of opportunities for misuse.  If used properly though, it can be good.

 

e.g. settings that you know the entire program will take on, or lets say in a game engine having the primary game object.  Or when it's data that is utilized in multiple areas and creating separate instances of it would be wasteful  (e.g. no point in creating a Wordle object that has the entire word list...even if you have 3 or 4 games running at once...but at that stage you just would keep it "global" for the class itself.)

 

If possible though, usually it's better just creating an instance of an object.

 

In general the thinking about global variables should be this.

Is this needed to be accessed globally or from multiple functions?  If not, then maybe putting it at least as a static inside a function/method.

Can I put this data inside a class?  If so put it there (e.g. Wordle can have a words variable...but words is "global" inside of the wordle class)

 

The above 2 cases probably cover most cases why you shouldn't use global...in that there are better cleaner ways of doing it.

 

3735928559 - Beware of the dead beef

Link to comment
Share on other sites

Link to post
Share on other sites

11 hours ago, wanderingfool2 said:

Globals are often hated because it's often misused by those learning (or used as a crutch).  It also messes with things when you have threaded applications.

 

That isn't to say global variables don't make sense...if used wisely or knowing the limitations they can be acceptable...but usually there are better options.  I know you mentioned python, but I'm going to use c style code to show a potential danger of it that many novices make

 

char buffer[1024];

int main(...) {
	printf("%s", strInt(123));
	printf("%s", strInt(1234));
	printf("%s", strInt(12345));
    
    //So far the output is okay
    
    for(int i = 0; i < 128; i++)
    	startThread(threads, threadFunc, i);//Okay not really thread code, but more of c pseudo code at this point
        
    //Assume startThread takes in something like the above, so you have 128 threads each that will call threadFunc...what happens?
    //You might get the printed output as 0 - 127...but you might also get 111222444
    //The reason is that you are writing to a global variable with multiple threads so at any given time it might actually be written to by multiple threads before printing
    
    //Another example
    printf("%s %s", strInt(123), strInt(1234));
    //So this will be how the compiler actually optimized things, but most likely you will get the output as
    //1234 1234
	return 0;
}

const char* strInt(int integerToString) {
	snprintf(buffer, 1024, "%d", integerToString)
	return buffer;
}

void threadFunc(int i) {
	printf("%s", strInt(i));
}

 

So that is why globals can be hated.  Lots of opportunities for misuse.  If used properly though, it can be good.

 

e.g. settings that you know the entire program will take on, or lets say in a game engine having the primary game object.  Or when it's data that is utilized in multiple areas and creating separate instances of it would be wasteful  (e.g. no point in creating a Wordle object that has the entire word list...even if you have 3 or 4 games running at once...but at that stage you just would keep it "global" for the class itself.)

 

If possible though, usually it's better just creating an instance of an object.

 

In general the thinking about global variables should be this.

Is this needed to be accessed globally or from multiple functions?  If not, then maybe putting it at least as a static inside a function/method.

Can I put this data inside a class?  If so put it there (e.g. Wordle can have a words variable...but words is "global" inside of the wordle class)

 

The above 2 cases probably cover most cases why you shouldn't use global...in that there are better cleaner ways of doing it.

 

Ok so in python they are "finer" compared to languages like c.

Link to comment
Share on other sites

Link to post
Share on other sites

1 hour ago, Wictorian said:

Ok so in python they are "finer" compared to languages like c.

It's not that in one language they're fine and in another they're not. It depends on the case you are using them for. I use Python often, mostly in a science/data context, and I've used global variables in the sense of Python's global keyword like once in a blue moon and from what I remember it was as a quick and dirty "fix" and not the proper solution.

Crystal: CPU: i7 7700K | Motherboard: Asus ROG Strix Z270F | RAM: GSkill 16 GB@3200MHz | GPU: Nvidia GTX 1080 Ti FE | Case: Corsair Crystal 570X (black) | PSU: EVGA Supernova G2 1000W | Monitor: Asus VG248QE 24"

Laptop: Dell XPS 13 9370 | CPU: i5 10510U | RAM: 16 GB

Server: CPU: i5 4690k | RAM: 16 GB | Case: Corsair Graphite 760T White | Storage: 19 TB

Link to comment
Share on other sites

Link to post
Share on other sites

3 hours ago, Wictorian said:

Ok so in python they are "finer" compared to languages like c.

I mean I used c because it's a lot clearer to show what can go wrong.  Ever language has it's own nuances.

 

To an extent python has each file as a pseudo class almost.  I mean ultimately I think the goal would be to have a variable as local as possible, but that's just a rule of thumb.  Good code can have a balance between clean design/smart design/efficiency.  Sometimes you can get all of them together, but others you sacrifice a bit of clean code for more sensical design.

3735928559 - Beware of the dead beef

Link to comment
Share on other sites

Link to post
Share on other sites

11 hours ago, tikker said:

It's not that in one language they're fine and in another they're not. It depends on the case you are using them for. I use Python often, mostly in a science/data context, and I've used global variables in the sense of Python's global keyword like once in a blue moon and from what I remember it was as a quick and dirty "fix" and not the proper solution.

ok to avoid confusion I am talking about using variables without functions. or you have to store the output of the function somewhere in most cases.

Link to comment
Share on other sites

Link to post
Share on other sites

2 hours ago, Wictorian said:

ok to avoid confusion I am talking about using variables without functions. or you have to store the output of the function somewhere in most cases.

If they are variables that contain some information about e.g. input files, important constants etc. then they aren't hated. The disliked aspect is making variables that shouldn't be global global and modifying those, as the example above shows, because that can lead to confusing situations. It's fine to store a result on a more global level, but then subsequent function calls with it, for example, shouldn't modify it directly but return their own result that you then either use to overwrite the old one or store somewhere new.

Crystal: CPU: i7 7700K | Motherboard: Asus ROG Strix Z270F | RAM: GSkill 16 GB@3200MHz | GPU: Nvidia GTX 1080 Ti FE | Case: Corsair Crystal 570X (black) | PSU: EVGA Supernova G2 1000W | Monitor: Asus VG248QE 24"

Laptop: Dell XPS 13 9370 | CPU: i5 10510U | RAM: 16 GB

Server: CPU: i5 4690k | RAM: 16 GB | Case: Corsair Graphite 760T White | Storage: 19 TB

Link to comment
Share on other sites

Link to post
Share on other sites

On 7/15/2022 at 4:17 PM, Wictorian said:

unlike in python

Even in Python you can have global variables or from module import *  -- and both aren't in good codding style. And then there are constants (like a settings file) but also global mutable variables which are the biggest evil. Function starting to have side effects is not something you want to have in your code as it's hard to track and test properly.

Link to comment
Share on other sites

Link to post
Share on other sites

On 7/17/2022 at 1:41 PM, riklaunim said:

Even in Python you can have global variables or from module import *  -- and both aren't in good codding style. And then there are constants (like a settings file) but also global mutable variables which are the biggest evil. Function starting to have side effects is not something you want to have in your code as it's hard to track and test properly.

sometimes I like to use global variables for function inputs. 

Link to comment
Share on other sites

Link to post
Share on other sites

6 hours ago, Wictorian said:

sometimes I like to use global variables for function inputs. 

Yoda would have a quote for that but the short answer - you should not.

Link to comment
Share on other sites

Link to post
Share on other sites

They are okay if used as constants. If they are changed constantly, this is a problem, especially when working in a team and other developers mutate the variable in their parts of code leading to some unforseen side effect. 

Sudo make me a sandwich 

Link to comment
Share on other sites

Link to post
Share on other sites

Ultimately it all comes down to code design.  It's not an one size fits all kind of thing.

 

Passing parameters by globals is generally frowned upon as there aren't too many use cases behind a good reasoning behind it.  A key reason why is that it's absolutely not thread safe.  The second is if you modify a variable multiple times in different functions without realizing it  Python is apparently pass by reference so you don't really take a performance hit by passing by reference.

 

This is a bit of a contrived example, but similar to this:

global_example = ["Wandering", "Fool"]
remove_variable = []

def bad_example():
    global_example.append("Hello")

    global remove_variable
    remove_variable = global_example
    bad_example_add_remove()

    remove_variable = ["Hello", "World"]
    bad_example_add_remove()
    return

def bad_example_add_remove():
    global_example.append("add remove")
    remove_variable.pop()
    return


bad_example()
print(global_example)

 

3735928559 - Beware of the dead beef

Link to comment
Share on other sites

Link to post
Share on other sites

On 7/15/2022 at 10:17 AM, Wictorian said:

Why does everyone hate global variables?

Because people hate "bad code" or code that isn't easily understandable.

On 7/15/2022 at 10:17 AM, Wictorian said:

As far as I understand in some languages you dont have to import the variables into functions unlike in python and this causes name confusion.

Languages work differently and have different purposes.

 

 

Lot's of people like "local" variables and Object oriented design patterns.
Basically, you don't want people changing or adjusting things without knowing where it's being changed or adjusted.

IE, you have a video game and have a health variable.
If a weapon does 10 damage, and players receive 20 damage, something is obviously going wrong.
The less places I have to check to see what is going wrong, the better.

So if you're going to have a public or global variable (They are different but bring about the same issue) you best know what you're doing basically.

Some examples of global variables that make sense are like

bool isProgramRunning;
float deltaTime; //Might be best to still lock this in a Time object

Something that is used by everything and could make sense to be changed in a variety of locations.
Depending on the scale of the project, it could make sense to use more global variables to make it faster to develop.

Some programmers argue that if you're doing things properly, you should put some form of protection on every variable and use get/set to access things.

 

If you're making a project with up to 5 programmers, yeah sure, knock yourself out with globals since it's a smaller project and easier to keep track.
If you have a ton of people, the more you protect, the better.

Link to comment
Share on other sites

Link to post
Share on other sites

  • 2 weeks later...

copying this from when someone asked a similar question on reddit:

 

A large codebase will have thousands and thousands of lines, now imagine you want to create a variable to count something inside of a function, so you name the variable 'counter'. Well turns out that somewhere else in your code you already had a variable named counter, but you didn't remember it.

 

Fast forward a few weeks and you are wondering why your counter keeps changing unexpectedly, it turns out that the variable is being modified in two different places.

You might say, well just name it something different, and you can do that, but now everytime you want to create a variable that won't be messed up you need to check if that variable exists already somewhere else in the code, and if it does, you need to rename to something else. This will result in things that should be simple - 'counter' turning into 'counterLoopPacketsSentSensorOne' when something like that should be easily gleaned from context.

 

Introducing scope for variables prevents this, and let's you focus on writing good code instead of trying to figure out if you used this name somewhere else.

Of course namespaces, classes, etc also help with this, but they are effectively the same thing, encapsulation and preventing erroneous behavior from modifying the state of something you didn't know you were modifying.

 

There is also the issue of managing the lifetime of objects (or just memory in unmanaged land) globals will often stay in memory longer. You don't need var i on the stack anymore once your loop is over, so why keep it?

 

current project I am working on came up with 268 instances of "var i" when I searched for it, that would be 268 unique global variables for loop indices.

If your question is answered, mark it so.  | It's probably just coil whine, and it is probably just fine |   LTT Movie Club!

Read the docs. If they don't exist, write them. | Professional Thread Derailer

Desktop: i7-8700K, RTX 2080, 16G 3200Mhz, EndeavourOS(host), win10 (VFIO), Fedora(VFIO)

Server: ryzen 9 5900x, GTX 970, 64G 3200Mhz, Unraid.

 

Link to comment
Share on other sites

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×