A conversation Clinton was having...

Monday, February 25, 2008

Party like it's 2002

Anyone who thinks that I'm a notorious Java hater might be interested in this whitepaper. I wrote it back in 2002 and released it to the public in response to Microsoft's globally loathed .NET PetShop whitepaper. For what it's worth, I didn't simply spew up an unpolished blog. Back then I took the time to write a full example application and an 18 page document detailing how Java was "better" than .NET 1.0

http://www.clintonbegin.com/downloads/JPetStore-1-2-0.pdf

Sun even hired me to speak on the topic at their (now defunct?) Sun Developer Days in various cities.

I'm just calling a spade a spade -- in both cases.

Clinton

Thursday, February 21, 2008

Backward Compatibility...be damned

So my humble little Java 5 Rant created a bit of a stir. Good. One thing Java still has is the best community in the business. I love the energy.

The responses to my post have been very positive and even the dissent was kindly worded. Mostly it can be chalked up to a difference of opinion. After all, what else is there? Facts? Right.

But there's one common rebuttal I will address, and it is this:

>> you can't just stop supporting backward compatibility.

Oh yes you can. And sometimes you should...

Apple took a big risk and made a big change by introducing OSX. How many of their customers are begging to go back to OS 9? Or how many wish they had just kept adding onto OS 9 for the sake of backward compatibility? How many of you fashionable-Mac-geeks would still be toting your shiny silver monolith of aesthetic goodness if it was running OS9, or some derivative of it?

Microsoft took a huge leap when they swapped out MFC and Visual Basic for the .NET Platform. Their customers didn't fault them for doing so, and their community welcomed the the change. Find me a person begging to work with MFC or VB6 instead of .NET.


Not only did Apple and Microsoft make current customers happy, I'm pretty sure they gained new customers in the process. I wonder how many holdouts finally switched to Java 5 now that it has ...generics? ...annotations? Surely some switched when the new logo was presented with Java 6! Help me out here.

It takes a bit of guts to admit that perhaps Java would have been better off if it hadn't evolved in this way. It takes guts to plan for a larger step forward that would truly take the Java platform where it needs to be.

Backward compatibility is no excuse. JRuby and Groovy are managing to be compatible with Java... so why should we think that "Java++" can't? In many ways, working with existing Java code with JRuby and Groovy is nicer! It's amazing how successful they've been in that regard.

I believe the same would have been true if Sun had built something truly new and innovative. Java 5 was a big change, it did impact some code and your environment. Hell, your fancy IDE with code completion probably needed a major upgrade at a significant cost... except for you Eclipse and NetBeans users I suppose. :-)

But for all of the imposition, you got very little for it. Java 5 was like moving to a new house that had the same number of rooms, but more hallways.

Clinton

Thursday, February 14, 2008

Java 5 Rant

Anyone who knows me has already knows that I'm no fan of Java 5. Since Java 5 was released, Java has dropped from 1st to 4th on my list of languages that I consider when starting a new application. It was such a disappointment to me, both because of the poor implementation of the new features, as well as the omission of some fairly basic features.

This is obviously an old rant. Java 6 is out and Java 7 is near. But Java 5 is where I feel the ball was dropped and the language took a tumble downhill. It's a bit of history and just my opinion. Don't take it too seriously.

DRAFT: There's a lot to this topic. I need to do a lot of clean-up and add some code examples to finish it off. I'll likely remove some of the exaggerated frustrations, but as I was typing it the first time, it's hard not to get excited. :-)

The Rant

Generics

There isn't much to say about Generics, as their failure is well documented. So, I'll simply say: they don't work. They don't offer any type safety whatsoever. At most, they offer useful information to frameworks about collection types via reflection. Otherwise, they're a more verbose, less helpful form of casting.

They really are verbose, especially when dealing with nested collections. The worst part is that it all has to be typed two or more times: once for the declaration, once for the instantiation and once for every method parameter you pass it into. If I'm going to do all of this extra typing, should it not at least be better than simple type casting?


The brilliant [sarcasm] part about it is that if you simply leave off the generic parameters at any point in your code, the code will compile anyway -- but suddenly without type checking. I fully understand this was done for backward compatibility, but this implementation is half-baked. I personally would not have bothered. I'd rather just live with untyped collections and casting. In the good old days, if I made an error by casting the return value of list.get(1) to something inappropriate, I would get an error right there, where I made the mistake. With generics, it's fully possible to type a list of Dates as a list of Strings in an attempt to use it in a for(:) loop, where the error will be reported. But the mistake I made could be far, far away from where the runtime reports it. Horrible, more verbose and less helpful.

But that's just the beginning. Google "Java Generics type erasure" and/or "Java Generics wildcards" for more fun times. It should not be easier to learn an entirely new language than it is to understand Java Generics in their messed up entirety.


Annotations

You would only know how bad they are if you've ever used anything else (e.g. C#). But they really are horrible.

  1. No extension of annotations. What? This is an object oriented language! Or at least it was. Now we have annotations based on what is essentially as limited as a C struct. I can't even begin to describe how horrible and limiting this is. There's no excuse. They simply ran out of time and decided to hammer it in however they could. See C# for a better implementation.
  2. No multiple annotations of the same type on a single target. Instead, we have to use collection annotations to group our annotations using a completely insane syntax. And yet this is one of the only places in the language you can use array shorthand! WTF. Seriously... again, see C# to understand what you're missing.
  3. No ordinal parameters (and only one messed up default "value"). Basically you should just never use the "value" default, as if you do, you've basically screwed yourself for all eternity. Since there's no way to depend on ordinal parameters to an annotation in the long term, you should just start using named params from the start. But that said, named parameters are horribly verbose. It would have been nice to have the option, but the definition syntax for annotations simply does not allow something like, oh I don't know, A CONSTRUCTOR!!! Why? Because they chose to use a bastardized interface as the definition for an annotation. And interfaces can't have constructors. I know why they used interfaces, I get it. But it's still stupid and they could have done far better. Again, they just ran out of time and decided to go with "finished" rather than "good". Which brings us to...
  4. The definition syntax. Look at the definition for an annotation. It doesn't even look like Java code. It looks like some other language created by Mork from Ork. Like what's with "default" suddenly being used to set the default value of a ... method? WTF! It's a bastardized interface. But remember, an interface is supposed to describe BEHAVIOR. But remember what I said earlier, annotations basically result in a C struct like thing attached to our class -- metadata (DATA!!!! not behavior). So why use an interface? Or @interface whatever the hell that is supposed to imply. This brings me to...
  5. Keywords. How the hell did enum get a keyword and not annotation? Let me tell you, I did have applications that had used the word "enum" as a variable name -- pretty much anywhere I ever used the Enumeration class! But I honestly had none that used "annotation". So why was there no keyword for annotation? But worse yet, why @interface? Why not @annotation if you needed to mangle it so that it didn't conflict with variable names? Or why not copy C#... hell, they copied Java enough -- AND DID A BLOODY FANTASTIC JOB OF IT. Just follow their lead and introduce a class, called Annotation that another class could extend... you know? It's really damn simple. I don't want to hear excuses. Watching the hoops that other teams have made Java jump through with Groovy and JRuby, and what Microsoft has done with C#, there are no excuses. Sun and the JCP ran out of time, money and the will to compete or something. This implementation is atrocious. I could literally go on, but that's enough about annotations.

Autoboxing

Integer a = 2;
Integer b = 2;
Integer c = 2000;
Integer d = 2000;
(
a == b) but (c != d).... nuff said. I'm not advocating using == on objects, but it's inconsistent. Autoboxing is simply incomplete and can never be fully or properly implemented without operator overloading.

for(:)

Again with the keywords... how do I even pronounce for(:)? Or type it in that sentence? Mostly the for(:) implementation is broken because generics are broken. But worse... why can't I iterate over an Enumeration or a damn Iterator?! If you want a perfectly good real life example, try using for(:) with anything that is returned from the Servlet API, like getParameterNames(). And contrary to popular belief (Ted Neward), there are APIs that return Iterators, that I would LOVE to use for(:) with, but I can't... because you have to give for(:) something (Iterable) that returns and Iterator, not an iterator directly. Why?! There's no good reason. Only academic ones.

A Note on Keywords and Compilers

There is really no excuse for not having keywords for annotations or foreach/in, as it's a simple compiler feature. A compiler can (nay, must) distinguish between different types of tokens in the code. C# 3.0 was able to make this work through simple pattern matching. Let's take the "annotation" keyword for example. Say you have code that uses variables called "annotation". What does that code look like?

public int annotation = 5;
annotation = annotation + 1;

Could you ever have a variable called "annotation" in the following position?

public annotation MyAnnotation {
...
}

Umm...no. The compiler can easily distinguish between that usage of "annotation" and member fields and local variables....easily. In fact, if you've ever had to name a variable "clazz", there's really no good reason other than that the compiler is lazy. C# managed to add LINQ and a number of keywords to the language without impacting other code, simply because it was easy to analyze the pattern that the code was used in, to distinguish between variables and keywords. I'm not suggesting that every keyword should be a valid variable name -- I agree, that could look a bit crazy after a while. But I think in the case of annotations and foreach/in we would have survived.

Enums

Enums are actually pretty good. They're well implemented, they got a keyword, and they are less verbose. Unfortunately they are also the least necessary and something I never really felt I needed. I've been using a type-safe enumeration pattern for a long time that basically does the same thing. But kudos, for making it less verbose. And the to/from string translations are nice too.

What's missing

Java 5 was missing some pretty simple, yet seriously nice things. Two that come to mind are:
  1. Multi-line strings. Come on guys! That's just a simple compiler change.
  2. Map and List literals... again, this is simply a compiler tweak. 99% of the time I use HashMaps and ArrayLists -- so just give me literal {} and [] blocks respectively.
  3. Type inference witha "var"-like keyword. Again, this would change nothing in the JVM, but would make generics far easier to deal with.
  4. The ability to reflect on parameter names. No it wouldn't require a change to the JVM. They could actually just automatically add annotations to the parameters at compile time, that carry the name forward in a runtime annotation. At least they'd get some use out of those bloody annotations.
The End.

And that's my rant. I could seriously keep going, and offer real world code examples of why this sucks super hard. But Java 5 is old news.

I'm looking to Ruby, Groovy and C# 3.0 before I look to Java. Not so much because those languages are better than Java 5, but more because Java 1.4 was better than Java 5. Java is going downhill at the hands of Sun and the JCP. Sad, sad, sad...

To end on a happy note, I'll still often choose Java where it makes sense. It still can't be beat for application integration, high performance web services or anywhere performance matters over all else (compared to Ruby, Groovy and Mono at least). But my choice is largely based on the JVM and the libraries available, and has nothing to do with the language.

Clinton