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.