Neomex
Neomex

Reputation: 1660

Should I use global variables here?

Why is it a bad idea to use global variables?

I want to make an array of variables available for all of the classes to use. It will store key states, so it can't be set as const (final).

Could you show me some other (proper) way of how to do this?

Upvotes: 3

Views: 4816

Answers (4)

Andreas Fester
Andreas Fester

Reputation: 36630

Why is it bad idea to use global variables?

Because it breaks encapsulation. All code can access them and modify them.

I want to make array of variables avaiable for all the classes to use

If there is only one instance to be used by all your code, you can use a singleton:

public class MyGlobalKeys {
    private static final MyGlobalKeys globals = new MyGlobalKeys();

    // disable construction outside of this class
    private MyGlobalKeys() {}

    public void getInstance() {
       return globals;
    }

    public void addKey(String key, bool state) { ... }
    public bool hasKey(String key) { ... }
    // and so on ...
}

Note that this sample is particularly not thread-safe - for improved implementation approaches, see Java Singleton Design Pattern

Upvotes: 7

Theodoros Chatzigiannakis
Theodoros Chatzigiannakis

Reputation: 29213

Why is it bad idea to use global variables?

Unless they are there to indicate known constants, global variables introduce what we call a mutable global state. This is contrast to what individual objects have when they have mutable data members - an object state.

Consider a method that takes some arguments, does something and returns a value.

The most desired scenario (from the perspective of analyzing code, debugging, testing, etc) is that this method will do the same thing if called on the same (or equal) object with the same (or equal) arguments. This is easily achieved for immutable objects (objects with immutable object state).

The most common scenario (in practice) is that a method's behavior will depend on the object's state and on the arguments, meaning that a method can behave differently for multiple calls with the same (or equal) arguments, if its object's state has changed (mutable object). This is less than ideal, but it's something one can still easily work with.

The most undesired scenario is when the method depends on the global state. Multiple calls to the same method with the same (or equal) arguments on the same (or equal) object can yield different results. Even if that object is in equivalent state across calls - or even if it's immutable! This is clearly very hard to work with, because if you suspect that a method doesn't do what it's supposed to do, you can't test its behavior anywhere you want. You have to test it at least for exactly the case you're working on (which may not be always as simple as it sounds) and then for every case you can think of it'll be used in and there will often be important cases that you'll miss. You just can't always trust such a method.

This is not an explanation of why you shouldn't use global variables, but why they're generally considered bad practice.

Another example I personally use is if you take a piece of code that initially was used to perform an operation once and have it perform it multiple times in the same session (say by sticking it to a GUI). In that case, every run of the operation other than the first will find the program in a usually unpredictable state. This would have the embarrassing effect that an operation in your program will behave correctly the first time it's executed and risk running incorrectly every other time until the program is closed and run again.

Yet another example I use (if the previous one doesn't persuade) is: What if the example of the previous paragraph was the case, but in parallel? In that case, multiple threads performing the same operation will change each other's states at wildly unpredictable points.

Could you show me some other (proper) way of how to do this?

In my opinion, the proper way to do structure a program is to pass the state that a method should work with as one or more arguments (and have it pass that state to the method it calls, if they require this information as well).

Upvotes: 2

cha0site
cha0site

Reputation: 10717

Global variables, of the non-constant variety, are bad design for numerous reasons that basically come done to the fact that they break encapsulation. Global variables ensure that you can't have two different instances of your class (singletons suffer from similar problems).

They'll make it harder to unit test your code, and they'll make it impossible to parallelize your code. Consider a scenario where you have code that processes an input file. Each input file is separate from other files. You want to process an entire directory, and in order to take advantage of your new multi-core server you decide to process 4 files at once using threads. Supposedly, this should be dead simple as the processing tasks are completely unrelated and thus don't need synchronization. However, since you used global variables, you introduced a global interdependency between different instances of your code, and thus the threads will muck with each other's internal state and lead to the code not working.

This is an argument against naive usage of global state. There are several legitimate uses of such, but each case must be argued on its own merits.

As for the proper way of doing this, I would create a State class and pass it to the constructors of all classes that require it.

Upvotes: 0

TobiMcNamobi
TobiMcNamobi

Reputation: 4813

My personal experience is this: If you start using global variables (or anything that behaves like a global variable) you will do it again and again. In the end you will find yourself in a pool of spaghetti code.

On the other hand I cannot imagine why all (!) other classes should make use of the key states.

I suggest to think of an expert for storing these states. This expert will be your key state class.

Upvotes: 1

Related Questions