0

A topic is not so clear I will try to explain my question in an easy example. We know what all clients of a bank share money from a bank. So if the bank is bankrupt, no client could take a loan. Based on that point of view I will try to make a simple program.

Approach 1:

    class Client {
        private static int sharedMoney = 100;
        void takeLoan(int amount) {
            sharedMoney = sharedMoney - amount;
        }
     }

Approach 2:

class Client {
    private SharedMoney sharedMoney;

    public Client(SharedMoney sharedMoney) {
        this.sharedMoney = sharedMoney;
    }

    void takeLoan(int amount) {
        sharedMoney.setAmount(sharedMoney.getAmount() - amount);
    }
}

class SharedMoney {
    private int amount;

    public SharedMoney(int amount) {
        this.amount = amount;
    }

    public int getAmount() {
        return amount;
    }

    public void setAmount(int amount) {
        this.amount = amount;
    }
}

Of course, logic is not 100% covered, but I think I showed my point. Does anyone have a rule of thumb I should follow when coding? When should I use static when sharing something (money) and when should I pass reference in the constructor when again sharing the same thing (money)?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Stefan
  • 969
  • 6
  • 9
  • 1
    You use `static` when you want all instances of a `class` to share the same variable. All the instances can change this variable and the new value while be visible by all these instances. Conceptually it can be tempting to choose the `Approach 1`, as the `sharedMoney` variable should be shared by all your `Client` class instance. But for design principle, easy class testing and class responsibility principle, you should the `Approach 2`. – Harry Coder Oct 18 '20 at 23:12

1 Answers1

1

In almost all cases approach 2 is preferred. This has a number of significant advantages over approach 1:

  • It is much easier to test approach 2. You can pass in a mocked SharedMoney that behaves exactly as required for your test (such as having a specific amount of money).
  • It allows you to add methods to the SharedMoney class that are related to those objects rather than end up with static methods in Client that aren't really related to that class's responsibilities
  • Static variables contain global state. Global state is any program state that is potentially available to any code to access or change. Any time you have global state you introduce the possibility of an unrelated method changing that state with unexpected side effects which makes code unpredictable and prone to bugs that are difficult to detect. Try to avoid global state whenever possible. The alternative is generally dependency injection, of which your approach 2 is a good example.

These topics are dealt with at some length in the answers to Why are static variables considered evil? Note, however, that at lot of the discussion there is really about mutable static variables. Constant values (generally declared as private static final and, by convention, given uppercase names) don't have the same disadvantages as their values can be relied upon not to change.

sprinter
  • 27,148
  • 6
  • 47
  • 78
  • Thanks for the answer and reference, it really helped. What do you mean by term `global state`? I never heard about that term before. Before I google, what is global state in my example? :) – Stefan Oct 18 '20 at 23:09
  • @Markus, in OOP fields values represents the state (and methods the behaviors) of an instance. A global state means a fields that is visible and changeable by any other instance or class outside the class that own the fields. `public static` fields are global. – Harry Coder Oct 18 '20 at 23:20
  • @Markus I'll add a comment about global state to the answer for your reference – sprinter Oct 19 '20 at 00:58
  • @HarryCoder `static` fields do not need to be `public` to be global. They could be exposed via `public` class or object methods. – sprinter Oct 19 '20 at 01:00
  • I know what you mean, but what surprised me is that you said that `static variables contain global state` and I should avoid it. Both both static and instance variables can be made public. So I don't understand why it is a bad thing for static as the same problem can occur with instance variables as well. – Stefan Oct 19 '20 at 09:34
  • The only difference is that with instance variable I need instance of class to change their value (if they are public) and with static I can call directly with class name (again if they are public). But problem remains the same - they both have global access. So can you help me understand why you said that just 'just' static variables contain global state, please? :) – Stefan Oct 19 '20 at 09:37
  • @Markus The 'global' in the term 'global state' refers to the whole program having potential access to the state. That is true for class variables but not for instance variables. For instance variables you need a reference to the object to access the state. So it is very clear which objects could potentially change the state of other objects just by looking at the public methods / variables of that object. That is not true for class variables: without walking through the code it's impossible to know if they change some other class variable. – sprinter Oct 19 '20 at 10:08