24

Recently I started programming in Groovy for a integration testing framework, for a Java project. I use Intellij IDEA with Groovy plug-in and I am surprised to see as a warning for all the methods that are non-static and do not depend on any instance fields. In Java, however, this is not an issue (at least from IDE's point of view).

Should all methods that do not depend onto any instance fields be transformed into static functions? If true, is this specific to Groovy or it is available for OOP in general? And why?

1
  • Do these methods call other instance methods? Or do they literally have nothing to do at all with an object of that class? Can you give an example?
    – Ray Toal
    Oct 29, 2013 at 8:27

4 Answers 4

29

Note that IDEA has this inspection for Java as well, it is called Method may be 'static',

This inspection reports any methods which may safely be made static. A method may be static if it doesn't reference any of its class' non static methods and non static fields and isn't overridden in a sub class...

Thing is though that for Java code, this inspection is turned off by default (programmer can turn it on at their discretion). The reason for this is most likely that validity / usefulness of such an inspection could be challenged, based on a couple of quite authoritative sources.

To start with, official Java tutorial is rather restrictive on when methods should be static:

A common use for static methods is to access static fields.

Given above, one could argue that turning on by default mentioned inspection doesn't comply with recommended use of static modifier in Java.

Besides, there is a couple other sources that go as far as suggesting a judicious approach on using ideas that lie behind this inspection or even discouraging it.

See for example Java World article - Mr. Happy Object teaches static methods:

Any method that is independent of instance state is a candidate for being declared as static.

Note that I say "candidate for being declared as static." Even in the previous example nothing forces you to declare instances() as static. Declaring it as static just makes it more convenient to call since you do not need an instance to call the method. Sometimes you will have methods that don't seem to rely on instance state. You might not want to make these methods static. In fact you'll probably only want to declare them as static if you need to access them without an instance.

Moreover, even though you can declare such a method as static, you might not want to because of the inheritance issues that it interjects into your design. Take a look at "Effective Object-Oriented Design" to see some of the issues that you will face...

An article at Google testing blog even goes as far as claiming Static Methods are Death to Testability:

Lets do a mental exercise. Suppose your application has nothing but static methods. (Yes, code like that is possible to write, it is called procedural programming.) Now imagine the call graph of that application. If you try to execute a leaf method, you will have no issue setting up its state, and asserting all of the corner cases. The reason is that a leaf method makes no further calls. As you move further away from the leaves and closer to the root main() method it will be harder and harder to set up the state in your test and harder to assert things. Many things will become impossible to assert. Your tests will get progressively larger. Once you reach the main() method you no longer have a unit-test (as your unit is the whole application) you now have a scenario test. Imagine that the application you are trying to test is a word processor. There is not much you can assert from the main method...

Sometimes a static methods is a factory for other objects. This further exuberates the testing problem. In tests we rely on the fact that we can wire objects differently replacing important dependencies with mocks. Once a new operator is called we can not override the method with a sub-class. A caller of such a static factory is permanently bound to the concrete classes which the static factory method produced. In other words the damage of the static method is far beyond the static method itself. Butting object graph wiring and construction code into static method is extra bad, since object graph wiring is how we isolate things for testing...


You see, given above it looks only natural that mentioned inspection is turned off by default for Java.

IDE developers would have a really hard time explaining why they think it is so important as to set it on by default, against widely recognized recommendations and best practices.

For Groovy, things are quite different. None of arguments listed above apply, particularly the one about testability, as explained eg in Mocking Static Methods in Groovy article at Javalobby:

If the Groovy class you're testing makes calls a static method on another Groovy class, then you could use the ExpandoMetaClass which allows you to dynamically add methods, constructors, properties and static methods...

This difference is likely why default setting for mentioned inspection is opposite in Groovy. While in Java default "on" would be source of users confusion, in Groovy, an opposite setting could confuse IDE users.

"Hey the method doesn't use instance fields, why didn't you warn me about it?" That question would be easy to answer for Java (as explained above), but for Groovy, there is just no compelling explanation.

4
  • By the way, ReSharper (made by JetBrains for C# / Visual Studio) suggests the same thing Apr 1, 2014 at 15:09
  • 6
    There is an important distinction between static methods with and without side effects. The Google extract really addresses the former.
    – assylias
    Apr 1, 2014 at 22:43
  • @assylias It does, but it also discusses how factory methods can make testing harder (since it tightly couples dependencies in the application). Using a dependency injection framework is one of the best workarounds for this, and it also solves many other problems as well. Dec 27, 2018 at 11:06
  • For the curious, the blog author does indeed use the word "exuberates". web.archive.org/web/20210117132451/https://dzone.com/articles/… Presumably they had in mind the word exacerbates.
    – mleonard
    Sep 2, 2021 at 10:58
5

It's hard to imagine that this would make any discernible effect on performance. The only benefit that I can see to making them static is that it provides a visual indication that instance state is unaffected. In other words, it tells the person reading the source code something... "interesting" about that method, just by virtue of it being there. The real question is, does it clarify or confuse? "Why is this method static? Is it a factory method? Is the ability to call it without an object instance needed?"

In addition, some folks don't like static methods, because they claim that you cannot mock them, and therefore they are not testable, or something along those lines. Certainly, if you are making it static for any of the usual reasons, like providing a factory method for example, then I'm all for that. I'm just not quite sure that making methods static just because they don't touch instance state is a mandate.

2
  • 5
    Do consider that (within Java) a static method can't be overridden. While not often an issue, it means some subclass later can't change that implementation. This isn't to say that a static method isn't the right answer but rather part of the design considerations.
    – user40980
    Oct 29, 2013 at 17:43
  • 2
    @user40980 it's worth considering, true, but it's also worth considering that inheritance can be a clumsy tool that is often misused, and several prominent figures argue that all classes should be final or specifically designed with inheritance in mind.
    – sara
    Jun 19, 2016 at 14:25
4

I think it is to enable possible refactoring to be spotted.

Once the method has been made static, it is clear that it can be moved out of the class, say to an unity class.

It is also easy to transform it into an instance method of one of its parameters, often this is where the code should be.

-1

Note that you may have stateless classes that implement some interface (e.g. java.lang.Runnable - you can't make their methods static. Some patterns (e.g. Strategy) also can produce stateless objects that may even have several methods.

Statics are first cousins of the singletons. It will be really hard to move from statics to non-statics at a later point - so when you will need to add state you will be tempted to start introducing static variables.

2
  • how does this answer the question asked?
    – gnat
    Oct 30, 2013 at 7:21
  • 1
    why is it hard to go from no state to some state? I'd say it's the other way around. it's easier to contaminate something pure than to purify something contaminated.
    – sara
    Dec 5, 2017 at 16:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.