beatngu13 beatngu13 - 29 days ago 5x
Java Question

Making side-effect free methods static

A few days ago I made a code review and I noticed that several

methods have been introduced. When I talked to the colleague who opened the pull request, he told me that he makes side-effect free (not pure) methods
as it would help to deal with side effects. He stated that this way you easily see which methods lead to side effects and which don't.

Personally, I strongly disagree here. Despite the fact that there're quite a lot
methods which cause side effects (just have a look at
methods often (not always) lead to problems, for instance during testing.

isn't bad per se and I know every day's a school day. Is this a known pattern I'm missing? What's the advantage of making a side-effect free method


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:

  1. Does the method dereference this?
  2. Is the method subject to dynamic dispatch on the type of this?

If the answer to both questions is "no", then the method can safely become static.

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.