Every once in a while I have a virtual fight with some Java programmer over refactoring tools. They are not available for C++, Python, whatever. How can you even use an IDE without refactoring tools? Do you know how much productivity you gain? The Java language is the best language in the world; it was designed to be "refactorable". Bullshit!
Let's see. Java is known to be a poor language from expressiveness' point of view. Tools save it somehow, and whenever I try to tell someone there are better languages out there, IDEs are thrown into my face and the refactoring tools they provide are the ultimate arguments for Java.
So I set out to prove that the most simple refactoring tool one can think of is not totally automatable, even in a language as simple as Java. Let's wait no more. I clicked Eclipse in my Applications/Programming menu, went and grabbed a cup of tea while it was loading, came back just to see it's asking about the workspace (first time use), grabbed another cup of tea while waiting, and set out to test my theory.
I entered this code:
import java.lang.Class;
import java.lang.reflect.InvocationTargetException;
public class MainClass {
public static void poorName() {
System.out.println("This is a stupid method.");
}
public static void main(String[] argv) {
try {
MainClass.class.getMethod("poorName", new Class [] {}).invoke(null, new Object[]{});
}
catch (NoSuchMethodException e1) {
System.out.println("there is no method with name poorName.");
}
catch (IllegalAccessException e2) {
System.out.println("there is an illegal access.");
}
catch (InvocationTargetException e3) {
System.out.println("invocation target exception.");
}
}
}
I was initially aiming at fewer lines of code, but then I decided to handle all the exceptions. Simply put, this program looks for a method called poorName in MainClass, using introspection. It then tries to call that method. If the method is not found or whatever, an error message is printed.
As I run this program, I get the nice message:
This is a stupid method.
Then, because I don't like the name of the method, I set out to rename it. Of course, what better way of renaming a method than right-clicking on it's name, and selecting "Rename" from the "Refactor" menu?
Tadam, no error message, method was renamed. Resulting code?
import java.lang.Class;
import java.lang.reflect.InvocationTargetException;
public class MainClass {
public static void goodName() {
System.out.println("This is a stupid method.");
}
public static void main(String[] argv) {
try {
MainClass.class.getMethod("poorName", new Class [] {}).invoke(null, new Object[]{});
}
catch (NoSuchMethodException e1) {
System.out.println("there is no method with name poorName.");
}
catch (IllegalAccessException e2) {
System.out.println("there is an illegal access.");
}
catch (InvocationTargetException e3) {
System.out.println("invocation target exception.");
}
}
}
When I run this code, guess what? It changed behavior. It now prints:
there is no method with name poorName.
which is true, but sad. There you go: method rename is not computable (anyone care for the mathematical proof?), even in a language as simple as Java (well, the language is not as simple as it used to be, but still).
To all Java refactoring maniacs out there: the next time you want to tell me you're not looking at another language because it doesn't provide automated refactoring tools, please think hard about why that happens in the first place.