A few days ago I made a code review and I noticed that several
static methods are only indirectly related to the concern of side effects. In the case of a private method, it can be made
static if it doesn't dereference
this. One of many consequences is that such a method does not mutate the object's state, which precludes one narrow class of side effects. Do not forget that the method may also accept arguments and mutate them; and even without that it can always access and/or mutate global state accessible over some static variable.
The real decision criteria are these:
If the answer to both questions is "no", then the method can safely become
The complaint that "static methods create problems for testing" is related to 2. above. In testing we sometimes have to provide mock overrides of a method. In that case the answer to 2. is "yes" and the method fails the criteria.
A private method should always be static if it can. In the split-second it takes to notice the
static marker you will have gained the following important knowledge: the method doesn't deal with the object's state and doesn't call any other instance methods.
If a public method satisfies the criteria to become
static, then it quite likely doesn't even belong to the class it's in because it has no coupling to it. In most cases such a method is a candidate for relocation into a static utility class.
Finally, the concept of pure functions (as opposed to just side effect-free) does matter here: pure functions are the least likely to ever need mocking. They are usually simple and fast to execute and their outcome can be controlled simply by supplying the appropriate input. Compare these two methods:
System.currentTimeMillis()—no side effects, but depends on global state and its output cannot be controlled. Often the fact that it's non-mockable means trouble in testing as the tests become non-repeatable.
Character.toUpperCase(char)—a pure function, performs a simple translation. You'll never have to mock this one.