Johannes Brodwall's Musings on Software Architecture and Programming

Quality code starts with the details of the language

The code I write in Ruby is higher quality than the code I write in Java. Why? Because the language supports better abstractions. It lets me express a problem once, and reuse it many places. The strength of an environment comes from the quality of the libraries, and the qualities of the libraries comes from the features of the language. In this post, I will review a proposal to make Java a better language: First-Class Methods. See how much better the code looks with it.

If you are like me, you often read data from a file or a database connection, and then you have to write boilerplate code in a finally block. This means lots of repeated code. To make the code correct, you actually need this monstrosity:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

/** Please don't read this code, it is just here to show how unfair life can be. */

publicstaticvoidtheOldWay(String[]args)throwsIOException{

BufferedReader reader=null;

booleandone=false;

try{

reader=newBufferedReader(newFileReader(newFile(args[0])));

Stringline;

while((line=reader.readLine())!=null){

System.out.println("This is a line:"+line);

}

done=true;

}finally{

if(reader!=null){

try{

reader.close();

}catch(IOExceptione){

if(done)throwe;

}

}

}

Having to write this sort of code once isn’t too much to ask. Having to repeat it for every time you want to read a file is an affront to sanity. The Spring framework introduced JdbcTemplate and similar constructs which really cut down on the room for error, but there’s still a lot of code. But look now: Here is how the code works with the First-Class Methods prototype:

Java

1

2

3

4

5

publicstaticvoidmain(String[]args)throwsIOException{

forEachLine(newFile(args[0]),#(Stringline){

System.out.println("This is a line:"+line);

});

}

I have implemented the forEachLine pretty much like the original, ugly code. The important thing to note here is that I only have to write it once. This allows us to hide more of our boilerplate code in libraries. This is the power of closures!

But wait, there is more. The #1 reason I prefer the FCM proposal over rival proposals for closures (BGGA, CICE) is the fact that it is simple to explain and works well within the expected behavior of the Java language. But in addition to this, First-Class Methods give us a much missed feature of the Java language: Compile time reflection.

To understand this, let me explain the name “First-Class Methods” first. The proposal is really to give Java Methods and Fields first class status in the language. The programming language geek term “first class” basically means something that can be passed to and returned from methods. What does this mean in practice?

// We now want to copy the "bar" property of OriginClass to the "foo" property of the TargetClass

Method fromMethod=OriginClass.class.getMethod("getFoo");

Method toMethod=TargetClass.class.getMethod("setFoo",String.class);

toMethod.invoke(target,fromMethod.invoke(origin));

System.out.println(target.getFoo());

}

Well, you should feel uneasy about it, because that code contains a typo! The comments says to use getBar, but the code mistakenly uses getFoo. Why can’t I get the compiler to check this? Well, with First-Class Methods, I can. This code gives a compiler error:

Java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

publicstaticvoidtheNewWay()throws

IllegalAccessException,InvocationTargetException

{

OriginClass origin=newOriginClass();

origin.setBar("origin mapped as property");

TargetClass target=newTargetClass();

// We now want to copy the "bar" property of OriginClass to the "foo" property of the TargetClass

Method fromMethod=OriginClass#getFoo();

Method toMethod=TargetClass#setFoo(String);

toMethod.invoke(target,fromMethod.invoke(origin));

System.out.println(target.getFoo());

}

This allows me to construct easy to use libraries for mapping properties between objects. For example, how do you like the following?

Java

1

2

3

4

5

6

7

8

9

publicstaticvoidwithLibrarySupport(){

OriginClass origin=newOriginClass();

origin.setBar("bar on origin");

TargetClass target=newTargetClass();

mapField(origin,OriginClass#bar,target,TargetClass#foo);

System.out.println(target.getFoo());

}

Pay special attention to the following fact: This code throws no checked exceptions. None! All error situations are already resolved compile time. See the companion source code in the appendix if you wonder how.

I’m really impressed with the First-Class Methods proposal. It solves the lack of closures in Java by letting you pass anonymous methods to other methods. This explains the initially strange syntax of forEachLine(new File(args[0]), #(String line) {.... #(String line) means a method without a name that takes a String parameter, just like I used TargetClass#setFoo(String) to refer to a named method. The # symbol is what’s being used for the same purpose in JavaDoc references, so it should be easy to remember. And in addition to giving us closures, this proposal also solves the problems of compile time reflection.

I have just scratched the surface of what kind of libraries can be created with this technology, which solves real problems without adding much weight to the language. Compared to the monster that is BGGA (“Bracha, Gafter, Gosling and Ahé” closures) and the fart that is CICE (Consise Instance Creation Expression), First-Class Methods is a simple, yet powerful proposal for closures. This is what I want.

Appendix: Trying out FCM for yourself

There is currently a prototype available for FCM. Here is how to use it: