views:

546

answers:

6

I've been mulling about a post by Misko Hevery that static methods in Java are a death to testability. I don't want to discuss the testability issue but more on the concept of static methods. Why do people hate it so much?

It's true that we don't have closures (but we have a slightly awkward anonymous functions), lambdas & functions as first class objects. In a way, I think static methods can be used to mimic functions as first class objects.

+3  A: 

Static methods make testing hard because they can't be replaced, it's as simple as that.

How can static methods "mimic" functions as first class objects? Arguably they're worse than anything else on this front. You can "mimic" functions as first class objects by creating single-method interfaces, and indeed Google's Java Collections does exactly this in a number of places (for predicates, projections etc). That can't be done with static methods - there's no way (other than with reflection) to pass the concept of "when you want to apply a function, use this method.

No, I can't see how static methods help here. They discourage state-changing (as the only state available is the global state and any mutable state passed in via the parameters) but they don't help on the "functions as first class objects" side.

C# has better support for this (with lambda expressions and delegates) but even that's not as general as it might be. (Compare it with F#, for example.)

Jon Skeet
Why would you ever want to replace a method for testing? I want to test the method not the replacement!
ThomasD
What if the method goes to a webserver on the opposite hemishpere and you don't really want that, since you'd be better off with static mock data.
Anton Gogolev
+1 to Anton's comment. If you can't replace your dependencies, your "unit" tests will be testing those dependencies as well as the method they're really trying to test.
Jon Skeet
A: 

My biggest objection against static methods is that they are not polymorphic and that they are not used in an object-oriented way, instead one has to you the class (not an object) to access them.

Frank Grimm
+3  A: 

Functional != function, and for the record I will claim that a method != function...

Java is a statically typed, object oriented language. Java has also maintained a relative purity in that manner but it's no where near a functional language.

While it's true that you can mimic the behavior of functional programming with imperative programming you're never gonna get that tidy syntax which you'll wanna have for lambda calculus. In a way, if the language doesn't support proper lambda calculus it's not a functional programming language.

C++ has functions, but C++ also have classes. C++ therefore have two type of functions, member functions and functions. When you say method you mean a member function. Because the method is invoked on an instance of an object. But when you say static method you mean just function (in the C/C++ sense). This is just a vocabulary for referring to elements of your code. And in Java code can not exist outside a class, a method would imply that it belongs to some class i.e. type.

So far nothing of what I've said relates to functional programming but I think you get the point where you wrong.

I suggest you look at pure functional programming languages such as Haskell or Erlang. Because functional programming languages generally don't have closers either.

Your claim that static methods can be used to mimic functions as first class objects sounds really bizarre to me. It sounds more like a dynamic programming language than functional programming.

John Leidegren
+1  A: 

If you only use static methods then you are programming in a procedural, non-object-oriented style.

However, the only context I can think of where this would be OK is during the first programming lessons before object orientation is introduced.

starblue
+1  A: 

In Java, you can't give a function as an argument to another function.

In a functional language, if you have a function

def addOne(i) = i + 1

you can pass that to another function that eg applies it to all elements of a list.

In Java, with

public static int addOne(int i) { return i + 1; }

there is no way to do that.

Zarkonnen
+1  A: 

One characteristic of functional programming is immutability of data. static does imply that you don't need an object (instance) representing state, so that's not a bad start. You do however have state on the class level, but you can make this final. Since (static) methods aren't first-class functions at all, you will still need ugly constructions like anonymous classes to approach a certain style of functional programming in Java.

FP is best done in an functional language, since it has the necessary language support for things like higher-order functions, immutability, referential transparency and so on.

However, this does not mean that you can't program in a functional style in an imperative language like Java. Other examples can be given as well. It's not because you are programming in Java that you are doing OOP. You can program with global data and unstructured control flows (goto) in a structured language as C++. I can do OOP in a functional language like Scheme. Etc.

Steve McConnell mentions the difference of programming in a language versus programming into a language in Code Complete (also a very popular reference on SO).

So, in short, if you say that "static methods mimic first-class functions", I do not agree.

If, however, and I think that this was more the point you were trying to get across, you would say that "static methods can help for programming in a functional style in Java", I agree.

eljenso