Should all methods be static if their class has no

2019-01-10 15:13发布

问题:

I've just had an argument with someone I work with and it's really bugging me. If you have a class which just has methods like calculateRisk or/and calculatePrice, the class is immutable and has no member variables, should the methods be static so as not to have to create an instance of the class each time. I use the following example:

public class CalcService {
  public int calcPrice(Trade trade, Date date) {
    ...
  }
  public double calcRisk(Trade trace, Date date) {
    ...
  }
}

Should those methods be static?

回答1:

The class you describe is simply just a set of functions that operate on inputs only. It's perfectly reasonable to make such functions static methods of a class. Doing so groups them logically and eliminates possible name conflicts. The class in fact acts as a namespace and nothing more.



回答2:

I would say yes, but an argument could also be made in this case for just putting those methods on the Trade object.



回答3:

There is a general feeling against static classes these days, for testability reasons.

This is because static classes cannot implement an interface and so cannot be easily substituted for test classes if needed. I think that cases like this that deal with price are an excellent example of this. It is possible in future that there may be multiple ways of calculating a price, and it is nice to be able to substitute these calculators for one another as the need arises.

It may not be useful now but I see more advantages in not using a static class than using one.



回答4:

I would avoid making these static. Whilst at the moment that may make sense, you may in the future want to add some behaviour. e.g. at the moment you would have a default calculation engine (strategy):

CalcService cs = new CalcService();
cs.calcPrice(trade, date);

and later on you may want to add a new calculation engine:

CalcService cs = new CalcService(new WackyCalculationStrategy());
cs.calcPrice(trade, date);

If you make this class instantiatable, then you can create different instances and pass them around, instantiate on the fly etc. You can give them long-running behaviour (e.g. how many calculations involving trade X has this object done ? etc.)



回答5:

It is a tough call. Remember what Josh Bloch says about APIs:

APIs, like diamonds, are forever. You have one chance to get it right so give it your best.

(This may not be a public API, but if you have colleagues that are going to use this code, it effectively is an API.) If you declare those methods static, you constrain their future evolution, and incorporating state in the class will be difficult or impossible. You are going to have to live with those static method signatures. If you decide to make them non-static down the road because you need state, you are going to break the client code. I would say, when in doubt, don't make them static. That said, there is a place for static utility classes that contain a bunch of functions (e.g. calculate the area of a circle.) Your class may fall into that category.



回答6:

I would make the whole thing static.



回答7:

While you could use JMockit or any similar tool to mock out the static methods, my own personal choice would be to avoid statics where possible since static methods often increase coupling.

Some of the answers implies that the method is stateless, but I don't really want to see it that way. The method accepts state in form of method parameters. What if those parameters were state in an object instead?



回答8:

I clearly would say no.

It's much harder to change out in the future if you call static methods instead of instance ones. With instance methods it's easy to inject your service, e.g. in Java with an IoC/DI container like Guice or Spring.



回答9:

The answer is yes and no. It all depends on the purpose of the method behavior. For example:

  1. if these methods are simply utility methods then it makes perfect sense to make them static.

  2. If the methods represent some sort of business logic of your application (let's say... a web application) then you may want to make them as flexible as possible. In this case, they would become a simple POJO class, as instance methods. This has the not so obvious benefit that they can be converted to Spring transactional beans, or even EJB3 session beans with very little effort. It also makes the methods easier to test. You can also create interfaces for this bean and add additional aspects to it the way you need.



回答10:

If you make it static, you can't inject a different implementation easily.

There is no longer any runtime cost to calling non-static methods, so for new code avoid static as far as sensible.

OTOH, refactoring tools can replace all calls to a static method fairly easily, so it's not critical one way or another.

I don't know whether the calculation of prices or risks can vary in your domain. If there are different strategies, passing a stateless strategy implementation around may have benefits. But it's more code, and there's a good chance that YAGNI.



回答11:

Imo, they should be static. I see no reason why they shouldn't be, since instance objects would have no state, and calling the methods without instantiating would require less code and thus improved readability.

Actually, i would probably make sure the class won't be instantiated by making it abstract.



回答12:

I believe that stateless methods should generally be static.

  • It's clear in the code that no object is involved
  • It avoids a meaningless constructor invocation

I can see breaking this rule for a strategy-pattern implementation, as a number of people have noted here.



回答13:

It depends what your goal is:

If your goal is to write as few lines of code as possible, the static approach would be the best.

If your goal is testability, we've discovered that static methods are a bugger to mock out. We, sadly, end up writing an interface, and a class for some of these just to be able to mock them out easily.



回答14:

if the methods need information in a Trade instance to do their work, then why aren't these methods non-static members of the Trade class?



回答15:

If it is not a clearly requirement to have it as "static" I would recommend you to make them instance.

Not only because this would generate a healthy practice, but, if you're using this in production code that might change in the future, it may happen that some day you really need to change the implementation for an specific module and don't want to break the whole application only for this reason.

Again, this might not happen with your specific code, but I was once in this app with tons of classes like this ( 40 - 60 or more )

A lot of times, having these classes as statics, prevent us from changing some modules easily and causes a lot of misery and tears.

It would've been easier if I could have inject new implementations for those specific parts.

The lines of code of this app in 500k and not all of them were in java which make the refactoring harder.

If you're using this in a 1k line project, then it doesn't matter at all.



回答16:

In above answers i read the argument of not making it static for testing reasons. I do not see why, but I am not familiair with the test procedure you're using.

In our company we use unit and system testing with Junit. (org.junit) There it's no problem at all to test static methods with this test package.

So I would say: yes make them static.

(With the remark that I do not know the test procedure where testing static methods is a problem)



回答17:

I recently came across same problem. I was usnig static method. This method basically returns the folder path I need to save all the user defined settings. Now the problem is that I need to write a test case that basically wipes out everything from the folder. I'd definitely not want to delete actual files and therefore I'd want that method to return something else. Yakes .... I can't casue I can't mock the method as it's static. Left with no luck but to change it to a not static method and have the class implement the interface with that method. Then I can easily mock that interface and have the method return any path I want.

End result. Making it a not static gives you more functionality. Make class Singleton and you have everything a static does for you plus loosely coupling.


回答18:

In my opinion they should be static. You might even get performance improvements because the compiler/jit might inline the methods



回答19:

In this case, I would probably make a couple of static methods. I would assume that the calc function does not depend upon other resources to calculate the values, and it is generally segregated from the rest of the code.

In general, however, I tend to shy away from doing overly complicated things in static methods. If you were unit testing and wanted to swap in a MockCalcService, having the static calls spread out across your code would make it very difficult.



回答20:

Statics smell

In most cases, a static method is an example of behavior divorced from data. It indicates something is not encapsulated. e.g. if you see validate methods for phone number, email etc in util classes, ask why they aren't these fields don't have their own classes. Even library classes can be extended to accommodate custom behavior. Finally in special cases like java.lang.String (which is final) you could use a custom myproject.String (with additional behavior) that delegates to java.lang.String

Objects are the way to access behavior in OO languages. It is not useful to worry about the cost of object instantiation and use statics instead. For most business software, this is a 'penny wise pound foolish' approach to performance.

Sometimes, you use functors (methods that don't use object state) for expressing intent. Doesn't mean they should be made static. IDE warnings that suggest "method can be made static" should not be taken seriously.



标签: java static