views:

1459

answers:

20
+20  Q: 

Static methods

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?

+27  A: 

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.

sharptooth
If the business logic is these methods is complicated, you'll never be able to mock it if you want to unit test. Other tests in your suite may fail if there is an issue in CalcService.
cliff.meyers
+1, but I agree with brd6644 as well.
MatthieuF
+2  A: 

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.

Raibaz
how do you propose an implemntation is provided if the class is turned into an interface?
Jack Ryan
whops, huge mistake...corrected.
Raibaz
In c# you could also declare it as a static class; "public static CalcService {"
bstoney
Abstract classes can be subclassed and constructed: `new CalcService(){}`. Better to make the class final and add a private constructor (that throws Error).
Tom Hawtin - tackline
+4  A: 

I would make the whole thing static.

Otávio Décio
+21  A: 

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

Eric Petroelje
I concur. Completely.
Inferis
Sometimes the objects are generated - e.g., from a WSDL/XSD that will change in the future. Sadly this means that putting the methods on the object itself isn't always an option. However where it is, it should be, definitely.
JeeBee
Or you could have the WSDL/XSD/CodeGen generate your Trade object, and have your class methods on a class that extends that... OurTrade extends Trade, and use OurTrade throughout the application.
JeeBee
Indeed the real issue is the procedural programming style promoted by such "services", be their methods static or not. You can smell the anemic domain model beneath.
springify
How would you propose an application-wide preference/configuration service be implemented without using such static methods?
PintSizedCat
Using dependency-injection to supply that config service to the object that needs it.
cliff.meyers
what if dependency-injection isn't an option?
PintSizedCat
Why wouldnt dependency-injection be an option? You don't need a DI framework to do DI
MrWiggles
Sometimes DI just isn't plausable, if you have say a factory framework and a DI framework the DI won't work alongside the factory in some cases. (This is the case with some of the stuff my company has at the moment)
PintSizedCat
A: 

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

jassuncao
+14  A: 

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.

Jack Ryan
See this is partially the reason my colleague gave for not making it static, I can see the reason but we're writing a very customer specific thing and I really don't forsee it being changed. He also gave the reason that it's very c'like programming but is that really a concern?
PintSizedCat
+1 not making them static does give you some advantages and the cost of doing it is next to nothing if you're using a DI framework
MrWiggles
But isn't this scenario exactly the reason static classes exist?
If it becomes necessary later to have flexibility in how a price is calculated, refactor at that time. If, as you say, this is unlikely, then all the more reason not to do it. KISS :-)
Galghamon
Depends on your point of view, I view statics as nothing more than globals, just tied to a particular namespace. OP said he cant foresee it being changed, but that doesn't mean it won't, and if it costs nothing to do it now, why not?
MrWiggles
+1 You can't mock these methods to test OTHER classes that use this class
MatthieuF
A: 

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.

James Van Huis
+2  A: 

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.

Pete Kirkham
You mention there's no runtime cost. Are you saying that "StaticClass.calcPrice()" is equivalent to "new NormalObject.calcPrice()" ? If so is that true for C# or just Java?
You should create a provider as part of initialisation, as is done with javax.lang.model.util.Elements. If that class is the only implementation of that interface, then calls to its methods are inlined as static calls by the JVM. I've no idea whether C# does the same.
Pete Kirkham
+2  A: 

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.

Steve B.
+1  A: 

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.

Daniel
+3  A: 

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?

Magnus
+1  A: 

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?

taglius
+5  A: 

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.)

Brian Agnew
+3  A: 

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.

Stephan Schmidt
+2  A: 

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.

Antonio
A: 

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.

OscarRyz
+1  A: 

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)

michel.iamit
Michel, You can't mock static methods. In your test if you need to mock it, you are left with no choice
Sheraz
Ok, thanx, so the conclusion is, if there is no reason using mocks, you can make them static, otherwhise do not make them static. right?
michel.iamit
+1  A: 

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.
Sheraz
+2  A: 

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.

Julien Chastang
A: 

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.

bagheera
I wish whoever marked this down would care to explain why.
bagheera
Miško Hevery of Google Testing Blog expresses similar sentiments.How to think about OO - http://googletesting.blogspot.com/2009/07/how-to-think-about-oo.htmlStatics hinder testability - http://misko.hevery.com/2008/12/15/static-methods-are-death-to-testability/
bagheera
I'm not the one that voted you down, but your post seems to reflect your personal bias against static members without giving any objective reasons. You address performance as an invalid argument, but the arguments was not really been presented. And your comment about IDE behavior more or less expresses your _own_ preferences about IDEs.
Steen
Oh man, I really wish I could edit my comments, sorry about the typos and the language errors.
Steen