The Hugeness

Most of what I'm going to ramble about here was covered much more eloquently and in far greater depth in Beyond Java. These are my personal feelings and anecdotes on Java and it's history. I should also note that despite what appears to be a moderately negative tone, I still do use Java extensively and used it to build the product of the rather short lived startup I co-founded.

I first encountered Java way back in 1998. This was effectively my first programming language, though I had done some C++ in high school. That wasn't formally, mostly self taught and pretty much purely due to laziness. At one of the computer shows in Vancouver, (which might have been Comdex, did that show travel around?) I talked my father into buying me a C++ compiler and toolchain. It was definitely Borland, I'm fairly certain it was one of the Turbo C++ packages, though I have no idea which version now. Regardless, my main goals were to ease my physics and math homework by writing programs to do various tedious calculations for me. That was more or less a success, I still recall the joy at punching 3 numbers in and getting the solutions to the quadratic equation back. I learned about loops, variables and if statements, but nothing else really. But I digress.

At Carleton University, the first programming course I took was in Java, at this point in time, we're talking Java 1.1 for the most part, the entire API was a couple of hundred classes at most. Supposedly it was kind of exciting because it was object oriented, but that was way beyond me for at least a semester. Mostly what I recall from my entrance to the world of programming was my epic battles with the compiler. I hated javac. There was perfectly valid... things in my file, at least as far I could tell, but javac would tell me that in no uncertain terms that I could not go so far as to call that text 'code'. Eventually, the program compiled and joy was felt throughout the lands. Immediately thereafter, I would run the program, which would crash with a NullPointerException or some other fun error case. This was before the time of decent debuggers, at least to a novice programmer, so with a liberal smattering of System.out.printlns, eventually I could figure out where I had a mistake. Then change the code, fight with the compiler and the scenario would repeat itself until I could run the test cases provided in the assignment.

All in all, though, Java in those early days was a pretty simple language. You would make an array, do stuff with it and be happy about it. Or, once you started to grok how this object oriented stuff worked, you'd make a Vector and stuff things inside of it and you would never worry about resizing the array again. I mean, there wasn't much to the language, check out the 1.1.1 API I just googled for. There were a couple of weird features for a novice to see, anonymous inner classes are a great example, it took me years to really understand how to effectively use those things.

Java 1.2 was introduced in December of my first year and included a number of things, the only ones that actually mattered to me as a fledgling programmer was Swing and the Collections library. Swing because the winter term had a Java graphical user interface (GUI) course and the collections library because I could now cheat and use LinkedList instead of always having to write my own for each assignment. Maybe it wasn't every assignment, it just seemed that way, still.

Java 1.3 did not really add anything of use to me and stayed out of my awareness. Java 1.4 added a few more things and I wrote a fair bit of code with that version. Still though, Java was still the same old Java as I had used back when I started with it. There were new libraries, and that was nice, Java was growing with me as I needed to do more with it. There wasn't any real new syntax that had to be learned, if you hadn't seen regular expressions before, it was a bit of a shock to see Perlish things in Java 1.4 but for those of us who had used them, it was nice to have the power of regular expressions in Java.

By this time I was working in the industry, specifically on a rather interesting Java application that was officially using 1.3 Java when I first showed up on the scene, 1.4 shortly after I started writing code for it. I should  note that I mean interesting in terms of the curse, "May you live in interesting times". Not as in, "That book is great, some really interesting points." The system was the definitive legacy but business critical application, so arbitrarily going to a new Java version wasn't going to happen until the powers that be had given it the official green light. At the time I was happily drinking the generics kool- aid, helped in no small part by the .NET team at the company who was gushing about how much the .NET generics implementation had helped them. I pushed for the migration and eventually we had migrated to a 1.5 JVM and all was good.

I learned the new syntax for the generics and for a while it was great, but a few things were beginning to bug me. In the entire time I had worked at this company, I hadn't actually seen a ClassCastException in the wild. This appeared to be the main thing that the generics were attempting to fix. The syntax was a bit clumsy and fairly verbose, especially if you had descriptive class names. Making a generic class was an exercise in pain. Enough so that after one serious attempt, I nixed it in favour of a single purpose class that could only take instances of a given interface. Most grievous in my mind was that after going through all of this anguish to get a generic class, as soon as you hit run time, you could not use reflection to actually figure out what should be in the container. I remember being shocked when I found this out and needing a coffee break to reassess.

From what I could tell, all of this extra syntax was being entirely tossed out before run time, which meant all that extra typing and 'safety' was a merely a compile time check. One of the first lessons learned in programming was that just because something compiles does not mean it works. So while getting a bit of extra information at compile time is nice, I couldn't help but think the benefits of the check was not worth the cost of the extra time spent typing and managing the syntax. (Side note, no, it's not 'just typing', it is the most fundamental skill a programmer needs to have and should be taken very seriously. Arguments here and here.)

Regardless, I soldiered on and slowly encountered other 1.5 enhancements that made Java more complex. Annotations, which through a new syntax would allow you to add some extra meaning to a method, class or variable. Enumerations, which I do love using when the previous option was lists of static final integers or strings. That however, was done with a new keyword, 'enum', which by some entertaining coincidence was the exact variable name used throughout our codebase for Enumerations. (Enumeration enum = hash.keys(); Eventually I will write more on code quality in that entertaining project.) Never mind the fact that now you have to talk about Enumerations or enumerations, which is always entertaining. Then there is the varargs syntax, which just feels like a solution in search of a very specific problem. Seriously, I mean, have you ever needed this? Then there is autoboxing, a nice feature, but blurs the lines between objects and the Java primitive types, which can lead to a whole new way for developers to misunderstand what a block of code is doing.

I no longer feel that Java is a good language for a new developer to start programming in. It has it's advantages, but those are almost exclusively in the domain of large 'enterprise' systems now. Some of the changes appear to have been to keep maintenance costs down and to mitigate the damage a low quality programmer can do. Some of the changes appear to have been good ideas, but they were done at the cost of making the syntax more complex and complexity is the enemy of software development.