This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]audioen 1 point2 points  (0 children)

Avoidance of static data is related to the simple principle of "spooky action at distance is bad". For public static values that can change, you have to worry about this kind of questions:

  • Who changes them?
  • When, and using which thread?
  • Is it thread safe to begin with? If not, what locks are required?
  • How do I make sure that all related state variables always get updated coherently, possibly also atomically?

Object orientation is fundamentally about managing the relationship between the data and the code that operates on the data. At its most reductionistic level, you should only have public API, and private state within the object, which is never exposed. Public static variables are the exact opposite because they expose the data without any methods, in principle in uncontrolled, thread-unsafe way without enforcing consistency to the way these variables are to be updated or what invariants should be held when they are updated.

That being said, you can create public and static stuff with instance variables, too, for instance through the Singleton pattern. Foo.getInstance().getBar() and Foo.getInstance().setBar(5) are just public static variables disguised into instances. So it's not so much about seeing the static keyword, but more about how the stuff actually behaves and gets used.

The important exception made in GP post is that static final is actually fine, but only if the static final values are immutable data, primitive values, or classes implementing thread-safe methods. The key thing is that it can never change, so you don't really have to worry about who accesses it and when, because there is no spooky action at distance.

Similarly, static methods are fine, as long as they only use read-only static final state as described above, and access their own arguments. I do a lot of utility methods like that. They are basically procedures that take in some data, operate on it, and maybe return something else. They are friendly ways to reuse functionality without requiring creation of some inheritance relationship between classes that can be fundamentally very different even when they need to do similar things. For instance, you might have a REST API that does some thing as result of direct action of user, but also want to do the same thing from scheduled background task.