fredag 28 december 2012

Five things that make Java painful (and some remedies)

I figured I'd present a list of the five things that disturbs me the most with Java as a language. Just give me nice standardized solutions to the following issues and I promise not to ask for more... ;-)

I will also present some third party libraries that will remedy some of the pain that these problems cause.

No closures or lambdas

No one on earth has missed the fact that clojures and lambdas are _the_ big thing these days (and have been for quite a while, even C++ has them in the latest version of the standard). Without them many of the nice "functional" (although one can argue about how functional they are) constructs that are present in quite a few modern languages (and old, Lisp for example) are ugly or impossible to implement.
I'm really not asking for that much more than what is already in the language today in the form of anonymous classes toay. It's just that the code gets so damn bloated when using these anonymous classes that you want to rip your eyes out when you look at it a week later.
Hopefully Java 8 will include closures through project lambda and hopefully it will be delivered on time 2013 as planned and hopefully it will be adopted as the industry java standard version really soon thereafter... Too many hopefully in that sentence to be really truthworthy.

Remedy until then

Check out JPropel. It is library that (among other things) can transform static functions into anonymous classes that implements a Function iterface by a simple annotation. This allows you to pass them around as objects. It ain't closures but it reduceds some of the boilerplate needed to pass function objects around. This actually mimics the way lambdas are implemented in Scala quite closely.

Setters and getters

What a pain to write all those setters and getters. Ok, they can be generated by your IDE... But what a pain to read all those setters and getters! Some claim that getters and definitely setters are a design smell. I can agree in some situations but in situations they may actually be required or at least useful. But I don't want to see all that noise they should just be there. Again, check out Scala. Getters can be automatically generated from the constructor parameters or we could just use public members and later replace these with methods as needed without breaking the interface.
As far as I know there is no short term remedy planned for this in Java.

Possible remedy

Project lombok has a couple of annotations that let you annotate the classes and fields for which setters and/or getters should be generated. Based on this lombok will then generate the necessary code. Check out the @Data annotation for example.


Painful declaration of variables

Declaring variables in java is a pain, especially when generics are involved. Up until Java 7 it was (is) a real pain with a previously unseen level of verbosity. Look at this:
final Map<String, List<Integer>> cpuLoad = new HashMap<String, List<Integer>>()

In Java 7 this was somewhat improved:

final Map<String, List<Integer>> cpuLoad = new HashMap<>()

So, what do I actually want? Pretty much what's in Scala today actually. A more powerful type inference system. We all know the compiler knows the types. Why can't it just infere them for us and let us focus on other things?
The other thing that annoys me about java reference declarations is the extra final keyword needed to make a variable immutable. I'm a big fan of immutable data. It makes the code easier to reason about and more maintainable. But even I cannot force myself to make the input parameters and local variables in a functions final because of all the clutter.
Also here I think Scala is a language to look at. Mutable variables are declared using the var keyword. Immutable "variables" are declared using the val keyword. The exact same number of letters!


A pain killer

At least when using Java <= 1.6 is the Guava library that removes some of the boilerplate in declaring generic collections. To my knowledge there is no  ongoing effort to make the type inference system in Java any better than it currently is. Guava is worth investigating for other nice features as well!

No persistent collections

No persitent collections exist in the standard java API. By persistent I mean collections that are immutable but supports efficient "modification" by returning a copy of itself with the applied changes. Since structural sharing is used most of the data stored in the new and old can often be shared between the two collections hence unnecessary copying is reduced.
The persistent collections bring with them all the good of immutable data (easier to reason about, thread safe, ...). They are used by default in JVM languages such as Clojure and Scala.

Librabries do exist that provide these type of collections for Java as well, and this may not be considered a big deal by some. The fact that they are not part of the standard library will limit their use though and most of the Java code written today does not utilize these lovely collections (I dare say) even if, in most cases, it would be benificial.

I don't know of any initiative to introduce a standardized alternative for persistent collections.


An option

The pcollections library is a nice player. Play with it!

No for comprehension

The lack of for comprehensions (as implemented in Python or Scala for example) is a shame. Although the for comprehension is just a syntactic sugar built with higher order functions such as map and filter it's a very sweet sugar that can lead to some beautiful solutions. It also makes it possible to introduce constructs close to those of Microsofts .NET LINQ to dig for data in collections. I don't know if there will ever be anything similar in Java but the introdution of lambdas and higher order functions will allow java to move one step closer to it.


An alternative

JPropel (light) has a really nice alternative here as well. Check it out!

Concluding thoughts

So in the end I think this was mostly a rant showing some of my frustration on the (non moving) state of Java. To me it seems like the biggest problem in the java development process is that there's to much focus on keeping things backward compatible. Of course you want your old Java 2 code to compile and run on a Java 8 JVM but do we really have to retro fit the massive API to make use of new features in the language? Can't it just rest in peace? The collections API for example, how about leaving that behind (maintenance should be minimal given it's maturity) and go for a new more up to date collections API?
In the case were interwork between old and new collections (or other APIs) are actually needed some adapter code could be introduced.

So, seems like there are a bunch of other languages running on the JVM that already include most of the stuff I'm asking for. Why not use them? Well, maybe I would in my day to day job but language mixes (no, I'm currently not on a green field project) often come with their own problems. Languages such as Scala also come with their own weak points (not always directly related to the language). IDE support that still lags behind compared to Java (although improving), slow compilation, some overly academic features, ...
Still, I would happily try out an alternative JVM language in a real world project! Given todays Java development pace it might just be the only way out.