A few days ago I made a code review and I noticed that several static
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 static
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 disagree here. Despite the fact that there are many static
methods which cause side effects (just have a look at System
), static
methods often (not always) lead to problems, for instance during testing.
However, static
isn't bad per se and I know every day is a school day. Is this a pattern I'm missing? What is the advantage of making a side-effect free method static
?
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:
this
?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.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With