Wednesday, December 31, 2008

Things to dislike about Java

Back in August I started working with Java the majority of the time. I still do a bit of Ruby, but the vast majority of my work these days is in Java. Java is good for a lot of reasons, but that is absolutely not what this post is about. This post is, in no particular order, the things about Java that I really dislike.

Closed Classes
I'm not sure if there's a term for this, but it's the opposite of what Ruby calls Open Classes. Open Classes allow you to define or redefine behavior on any class at any time. Java does not give me this ability. Let's look at a simple example, say I want to define a method that checks to see if a string is null or empty. In a language with Open Classes you can add behavior directly to the String class, so you could check to see if a string is null or empty by asking the string itself.


In an Object Oriented language, where objects are supposed to have appropriate behavior, I like having the ability to add the correct behavior to the correct class.

In Java, I'm stuck doing something very different. I could import some class defined in some library that has way more than I actually need, or, more likely, I'll just define my own StringUtils class and create a static method. In Java 6 I can static import this method, which makes my code procedural, joy.

If you are in the .net camp, don't laugh too loud. Your extension methods are flawed. Until you can override existing behavior, you're only halfway to the solution.

Lack of Closures, Blocks, Anonymous Methods
Whenever I manipulate a list of items I find Java severely lacking. In Clojure I can double each element in an array by simply calling the map method with an anonymous function and a list.

(map #(* % 2) [1 2 3])

In Java I'm stuck with iterating over the array, and adding the results to a temporary collection that is appended to with each iteration. I find that ugly, but it hardly compares to the absolute disgust I have for classes like Comparable and Runnable. An anonymous class instance that has one method is an obvious sign that the language is severely lacking in the area of closures, blocks, or anonymous methods.

Army of NNPPs
Java is currently the "one language to rule them all". This brings about several problems, one of which is the number of terrible programmers writing Java code. I'm lucky enough to work for a company that wants to "build the best software development teams in the world", so I don't work with a single person that writes code I find ugly. Unfortunately, that doesn't save me from the Java NNPP zombie army. Java NNPPs flood the forums and mailing lists with elementary questions and incorrect answers. The amount of signal to noise is so low that I find myself unsubscribing from every public mailing list, and avoiding all Java related forums. It's a shame that I generally have to stick to private mailing lists just to ensure I receive relevant answers.

Literal Arrays & Hashes
Arrays and Hashes are used so frequently, there's really no excuse for not having a literal syntax. In production code this is somewhat painful, but it really shows up in tests. Java does have a few solutions, two of them can be found in the following example.

asList(1, 2, 3, 4)
new Integer[]
{1, 2, 3, 4}

While these do offer "options" they both end up causing problems. The asList method works for about 75% of situations, but leaves me disappointed at least 25% of the time. Far too often there seems to be a method that doesn't like the return value of asList; therefore, I end up doing something significantly uglier to build a "correct" collection. The second example, the traditional Java array also works, but it's ugly to create and often to limited to work effectively with.

Command Line Execution for Snippets of Code
Sometimes you need to do something quick and simple. A command line interface (Ruby's IRB, Clojure's REPL) makes you more effective by seconds or minutes, millions of times a year. That wasted time adds up.

Java (the programming language) is so amazingly verbose (I'm talking about Java, the programming language)
Java forces me to repeat things all the time.

public class NewOrderHandler {
public void onNewOrder(NewOrder newOrder) {
// handle new order

In 2 lines of code I managed to type "NewOrder" 4 times. Even with a fancy IDE this gets very tedious. When writing Java code I don't actually write anything, I just keep hitting [Ctrl + space] and [Alt + Enter] all day long. When I'm writing code this tends to not be such a problem. I use IntelliJ for all my Java programming and I'm comfortable admitting that I can write Java code as fast as I was writing Ruby code.

The problem is, I don't spend all my time writing code. I spend a fair amount of my time reading code, code someone else on my team wrote, or code I wrote a few months ago. While I can write Java (or at least [Ctrl + Space] Java) as fast as I can write Ruby, it takes me at least 3 times as long to digest the responsibilities of a class written in Java as compared to Ruby.

These days I spend far more time trying to digest a class that takes 4 other classes as dependencies and each of those classes combine with the original class to solve one problem. Unfortunately it takes so much code to get something done that the simple behavior had to be split among 5 classes. To make matters worse everything has to be injected via the constructor because it's the only reasonable way to write testable software. So I end up reading pages of code to understand how each piece collaborates to do one simple task, awesome.

Extensive Tool Support Raises the Barrier of Entry for Tool Builders
I find the Java testing frameworks, much like Java itself, to be a generation behind. There have been steps forward elsewhere and the Java testing frameworks haven't yet caught up. I'm not one for complaining without providing a solution, so I started toying with building a testing framework. Does it integrate with IntelliJ? Of course not. Does it integrate with Eclipse? Absolutely not. Would anyone use it without integration? Emphatic No.

So now it's not good enough to create a good library, now I have to learn about IDEs also. Or (in my case anyway), drop the idea for more interesting pursuits, like finding the language I can replace Java with.

Java's not all bad. In fact, it might be the best tool for the work I'm doing these days. It's definitely tops in the areas that I need to be successful overall. But, I really do miss the things listed here, and all the other things that I've forgotten to write about but consistently swear about at work.

Happy New Year! Here's to a year where I find a suitable replacement for Java.
Post a Comment