this is totally gonna work… » Java

Proportional Code

October 26th, 2008

Few things are less sexy than command-line parsing. It is one of the most mundane tasks a programmer has to execute in their career. But, it surprises just how much code is required to do basic command-line parsing in a lot of languages, including Ruby. So I got to thinking, why does this bug me so much? I think the answer is that requiring so much code for such a relatively trivial task violates my sense of proportionality in the code. I hate having to say so much more about this teeny little task than I do about the “theme” of my code. I think it distorts the narrative of the code.

Let’s say that the processing of writing your program is like launching spacecraft. Ideally you would like to get from launch to cruising around in space as quickly as possible. The Star Trek universe solves this quite elegantly with the transporter. We don’t put you in a box and launch it, we break your atoms apart and transmit them to another location! That’s pretty cool, but maybe we’re just not quite that cool yet. Another solution is one proffered by the Star Wars universe. A ship like the Millenium Falcon can leave just about any planetary atmosphere any time it damn well pleases without the use of special equipment. It just flies away. Not bad.

Atlantis (STS-125)

However, here on earth, our primitive space craft need a tremendous amount of disposable apparatus to reach escape-velocity. The proportion of useful vehicle (the shuttle) to the orbit-busting mechanism (the rocket boosters and fuel tanks) is a staggering 5.4:1 (based on liftoff weight).

Command-line parsing in code exhibits a similar disproportion. The interesting part of your app isn’t the command-line parsing. Why should it take up such a disproportionate amount of space in your code? Those boosters quickly become “space-junk”, once the launch vehicle has left Earth; expensive trash that is never to be used again.

Space-junk is dangerous for the next guy that wants to launch into space. It’s also dangerous for the folks on the ground as it may decide to come crashing back down to earth. And those boosters have also been responsible for one of the worst disasters in NASA’s history. If we could only get rid of those damn things the whole space program just might be a little better off. Unfortunately physics, and our current space-flight capabilities currently require them.

But our code is a different story. We don’t have such physical barriers that handicap us. Any barriers we run into are usually of our own making. So why not try to reduce those as much as possible? Why say in more code, what you could say in less? Wouldn’t that cut down on bugs? Wouldn’t that ease the burden of maintenance? Wouldn’t that reduce the amount of information overhead you have to maintain each time you revisit that code?

Command-line parsing is a stupid, menial task that should require very little attention. By extension, it should only be given a stupid, menial amount of code to make it work. We have big ideas! They shouldn’t get bogged down by handling command-line options!

This is why I wrote Clip. Clip is an expression of the need to make the simple things simple, but no simpler. If you have modest command-line parsing needs, Clip rewards you with minimal investment. If you need something trickier, Clip allows you to say a little more to it and gain more benefits from it. You get to decide how much you want to engage—not the library.

This is one of the things I like about Ruby. The language is extremely flexible which gives me a lot of ways to “pack” ideas into code in a variety of ways. Having more than one way to do things isn’t all that useful by itself. But it’s essential when you want to write expressive code. Things like object literals, or one-line control-structure alternatives help me keep the lines of code proportional to the ideas they express.

This is also something I find challenging to do in Java. In languages like Java, even just creating a collection of objects requires quite a bit of code:

    1 import java.util.*;
    2
    3 public class Designer {
    4   public void makeItWork(List<Trash> trash) {
    5     // today's challenge: convert trash to wearable garments
    6     List<Garment> garments = new ArrayList<Garment>(trash.size());
    7     for (Trash t : trash) {
    8       Garment g = new Garment(t.getName());
    9       garments.add(g);
   10     }
   11
   12     submitToJudges(garments);
   13   }
   14 }

In Java we often solve this by pushing all of that code into a private method that is named something meaningful. This works pretty well, but does tend to result in an explosion of “helper methods”. Sometimes folks take the “cheap” route and simply prefix these riffs with explanatory comments like “convert each Trash into a Garment”. I’m not a real big fan of this. Generally I don’t care about the object conversion in the first place because the rest of the code is presumably doing something interesting with the Garments and I don’t give a damn about the Trash.

So let’s look at it in Ruby:

    1 class Designer
    2   def make_it_work(trash)
    3     submit_to_judges(trash.map { |t| Garment.new(t.name) })
    4   end
    5 end

By my count there are five lines in the Java example (including the comment) just to convert trash to garments. In contrast I boiled that down to one line in Ruby. OK I could have done this in two lines if you think that’s too much of a long-train. But I think there are couple of important points here:

  1. The importance of the concept being expressed diminishes from left to right
  2. The attention-span of the reader diminishes from top to bottom

The Ruby example beats Java on both counts. I don’t waste a lot of the reader’s attention span up-front on book-keeping details (in the vertical space) and I state the important thing I’m trying do (submit my top Foos) quickly (on the left). The details of which Garments I’m dealing with are merely a qualification of what I’m trying to do.

How you handle these two dimensions is greatly affected by both the language you use and the APIs you deal with. This is one of the reasons that I do not find the use of scripting languages for Java’s Swing API all that compelling. Scripting languages like JRuby or Jython help me with the horizontal space, but don’t do a damn thing for the vertical requirements. With an awful API like Swing I have to say a lot of words to make it go, regardless of the language I do it with.

Getting back to my dumb example, being on such a small scale this may not seem like a large impact. But multiplied several times over to match the size of most projects, this kind savings can really pile up. The difference in the amount of code required by these two approaches is manifested in a savings in cognitive investment required to grok these projects. This is the very essence of maintainability and sustainability. Anytime you can do more with less, you come out ahead.

At great peril to my own geek cred, I will say that this is why I find The Lord of the Rings to be such an awful piece of writing. It is so full of peripheral and non-essential information that finding the real story or characters requires extraordinary patience and concentration on the part of the reader. If Tolkien had been more concerned with the story and less with “world-building” I’ll bet he could have gotten that story boiled down to a single book.

Now I realize that a lot of folks love the Tolkien books for the very reasons I criticize it. That’s fine, that is an argument about aesthetics, not facts. However I would strongly argue that “world-building” in your code is a bad idea. I think you’re much more likely to build a decent piece of software if you pack your ideas tightly like a William Gibson novel than as a sprawling “trilogy” of epic code. Go ahead, prove me wrong. I double dog-dare ya.

OK, so by this point any credibility I may have had is gone. Look at the size of a post about saying more with less. In the hope that you might be lazy and like to skip to the end:

Do as much as you can…with as little as possible.

The Java Conundrum

December 30th, 2007

Steve Yegge’s latest blog post was one that really struck a chord with me personally. I think he hit most of the nail right on the head in describing a common frustration with the Java language. It seems like every attempt to refine the language ends up as some controversial, inelegant hack that often reduces the readability of the code. The same day I read that post I came across Josh Bloch’s presentation on Java closures. This was my first introduction to closures in Java-land and my first reaction was one of horror. This is supposed to enhance the expressiveness of the language? Sheesh, not as far as I can tell…

Steve talks about the size of your Java codebase and just touches on IDEs, but I’d like to explore that aspect a bit. I’ve been a dedicated Eclipse user for about five years. Before that I used NetBeans and before that Emacs. These days I think the three major IDEs (Eclipse, NetBeans and IntelliJ) are essentially equivalent. They all have great code completion, integrated refactoring tools and built-in unit-testing support. By the time I switched to Eclipse my Java projects were reaching a magnitude that required these sorts of tools. Switching back to plain old Emacs would have been possible, but a very counter-productive move. In essence, our projects mandate a certain set of tools in order to achieve some minimal baseline of productivity. There is no going back.

Maybe this isn’t a bad thing. I’ve certainly dismissed my fair share of kooks who live by the “desert-island” coding theory where any developer should be prepared to have to work on thirty-year old servers with no UI system and where only edlin is available. That’s nuts. We have evolved. BUT…is Java requiring additional evolution that we otherwise wouldn’t need? Like Steve’s point about dependency injection, are we creating new sacred cows whose existence is justified only by the requirements of working with Java?

I’m a big fan of dependency injection, but when I started working more seriously in Ruby I realized that it was a concept that had much less worth simply because of how the language works. So while the concepts behind projects like Spring are admirable, the amount of knowledge required to use these tools (all in the name of finding a shortcut around a bunch of manual work), seems to exceed any benefit as far as I can see. It seems that the evolution of Java has required additional complexity to manage the previous rounds of complexity we were trying to get around in the first place. A conundrum indeed.

Java seems to be suffering from a serious case of feature-envy and lacks a firm hand to guide its future. Java 5 brought a few helpful (and sometimes controversial) features, but since then I’ve started to tune Java out. The JCP process seems to have devolved into feature-addition-by-committee process where, if any sort of quorum can be achieved, any features can make it as a JSR. As other languages have gained popularity and offered developers alternatives in expression, many have tried to evolve Java to “keep up”. I would put forth that this is both a disservice to the language and its users.

Right, wrong or indifferent, Java has a point of view of how the world should work. Everything in Java is an `Object` and every object is of some defined `Class`. There are almost no literal expressions in Java so just about everything you want to do in Java must be carries out as methods invoked on objects. Many of the new language extensions seem counter to this original design and show all the signs of a conceptual impedance mismatch. Extensions like closures are trying to act like anonymous functions where we don’t really care about the type. Oh, except that we do. Well, but we don’t want to. Yeah, but we have to.

As a result, Java has evolved from a relatively simple and consistent language (at least compared to C++) to one that requires programmers to understand Java’s entire Tale of Gilgamesh before they can be trusted with the language. I can’t imagine how they teach how Java 6 works in introductory programming classes. Instructors must be faced with innumerable choices where they trade completeness for clarity. Given the tome-like size of the Generics FAQ, I can’t see how anyone could feel comfortable sicking this subject on the young tender minds of new programming students.

It just seems to me that whatever stewards there are for the Java language have been fairly hands-off in setting or restricting the direction of the language. Perhaps Java would be better off accepting the fact that it will, at best, play the role of an equal among a number of peers and that it would best sustain itself by adhering to its core design principles and allow other languages to evolve their features to meet needs that Java can’t adequately satisfy.

To paraphrase Chico Escuela, “Java has been bery bery good to me.” Java has sustained a nearly decade-long career in a profession I love. For me though, I’m pretty sure that my current gig will be my last Java gig. My attention to and love for the language has waned. I’ve found alternatives that work better for the majority of problems I have to deal with. In short, the thrill is gone.

There are few tools in my toolbox that are timeless must-haves. I am a self-described “tool whore”. If I can find a tool that gives me a significant amount of productivity gain (one that exceeds the investment effort), I’ll gladly switch to them. I was a long-time dedicated Linux user, but switched to Mac when I found that the effort to maintain a Linux laptop exceeded the energy I was willing to put into it. I haven’t rejected Linux, I’ve simply put it in a place in my technical life where I can best take advantage of it.

I feel the same way about languages. While I have called myself a “Java developer” for a number of years, I’ve come to learn that I’m really a software engineer whose tool of late has been Java. Given the constant change within this field, it is simply self-destructive to assume that I can sustain a long-term career with the same set of tools and skills. I firmly believe that a good developer has to be aware of what else is going on in the world and must constantly evaluate and adapt new technologies and approaches. In short, we must evolve or face irrelevancy and, ultimately, professional extinction.

Today I’m doing more Ruby and I hope to be doing more Ruby professionally for a number of years. But I expect that in a few years some new language will emerge that will address the future shortcomings of Ruby. Who would assume that any one tool/language/operating system has really got it right? It’s never happened in the history of technology. At best, we’ve had systems that did better than their competitors. I’ll even go so far as to say that I don’t dismiss the possibility that Microsoft may come up with an operating system or development environment that beats the alternatives. It would require quite a lot to overcome my personal biases, but I won’t say it couldn’t happen.

Posted in Java | 4 Comments »

Ten Things I Think I Think

October 16th, 2007

In the spirit of Peter King’s Monday Morning Quarterback, here are ten things that I think I think:

10. Maven 2 Moves The Ball Down The Field (well, sortof): All Java build systems suck. They all suck in different ways and the selection of one over the other is largely dictated by what types of pain you are willing to tolerate. I’ve used Maven since it’s inception. It solved some things Ant didn’t but also came with its own problems. Maven 2 attempts to solve some of the problems with Maven Mark I (namely scripting in XML, yecch), but lacks coherent documentation and a clear roadmap for learning the tool.

That being said, it makes tasks like creating a WAR file and deploying to a web server relatively trivial when compared with the amount of Ant XML you would have to write to do the same thing. There’s still too much XML for my liking and god help you if you want to do something outside of the box.

9: Maybe Static Imports Ain’t So Bad: When Java 5 first rolled around, I identified static imports as one of those features I would never use. Well, heh heh, never say never I guess. I have started to use static imports in a few places where I need something like the equivalent of a Ruby mixin. Interestingly enough the the only places I’ve felt comfortable with their use have been in unit-testing when I want to use EasyMock’s methods or JUnit 4 methods.

8: Java Annotations Are Curious Creatures: I can’t tell yet whether or not Java annotations are really all that great or not. If you’re a hard-core-no-good-thing-has-come-in-the-damn-JDK-since-the-collections-API kinda guy, you can make the argument that annotations are simply syntactic sugar for problems that could just as easily be solved with a proper object model or external configuration. In the old days (like the first version of EJBs) we wrote our configuration as actual code or, perhaps, as properties files. Then XML and Java went out on a hot date during the first dot-com bubble and spawned all sorts of illegitimate XML configuration children. I can’t tell you how many XML configuration systems I’ve seen that essentially reinvented properties files in XML (same configuration, twice the typing!)

Configuration via a pure object model can be, at times, extremely clunky (anyone remember writing EJB 1.0 deployment descriptors?) I think the evils of external file configuration have been experienced by just about any moderately experienced Java developer (Struts config anyone?) So it seems to me that annotations are simply a way to get some configuration closer to your code in something approaching a DSL (which most configuration files are attempting to be) without external files. I haven’t played enough with them to be totally sold, but the idea is intriguing…

7: I Couldn’t Code Java Without Eclipse: I say this not because Eclipse is just the greatest Java IDE of all time, but because I’ve invested so much time learning so many of its tricks. Really any modern Java IDE probably has equivalent functionality, so the issue is not so much that I can’t imagine coding Java without Eclipse, but rather that I can’t imagine coding Java with a plain ol’ text-editor. I don’t think this says as much about me as it does about the language itself. Does anyone doing Java professionally on a daily basis still use Vim or Emacs?

6: I Code Java, I Code Ruby. When Will I Use JRuby?: It’s funny that for as much Java and Ruby as I’ve done in the last eighteen months that I still have done no more than dabble in JRuby. The day can’t be far off, but I’m a little surprised that it hasn’t yet arrived.

5: I’m Tired of Algorithms: Well, that’s not exactly right. I’m tired of algorithms as the measure of one’s knowledge of software development. It’s important, but it’s not the most important. Apparently most of the software world doesn’t agree with me so it’s up to me to decide whether or not I want to continue swimming upstream or simply relax and go with the flow. Some little voice in my head tells that the latter is not a good idea…

4: I Think About Scaling All The Time: Aside from sustainable development, scalability is probably the most important thing I think about at my current position. I’ve worried about it before, but the scope of previous projects that I’ve worked on don’t approach the ambitions of this one. I’ve spent a lot of time in the last year reading up on all sorts of technologies around scalability. I’ve been pretty interested lately in things like the Spread Toolkit and Wackamole. I haven’t used them yet, but I’m keen to try them out. I’ve been using Jini lately…the jury’s still out on that one.

3: RDBMS Is Dead! Long Live RDBMS! Part of the result of all this scalability reading and thinking is coming to the realization that a relational database doesn’t work everywhere as the be-all, end-all of persistence. To that end I’ve been immersing myself in a number of different technologies. Inverted indices provided by the likes of Lucene or Ferret are fascinating alternatives to the traditional RDBMS approach. If you twist your brain the right way you can satisfy most requirements you would have of an RDBMS with inverted indices.

Similarly various key/value databases such as CouchDB and even Sleepycat make very sensible replacements for a general-purpose RDBMS. I find these interesting not so much because of their performance characteristics viz-a-viz RDBMS solutions—though that is certainly compelling—but rather because of their simplicity. For a lot of problems I really only care about storing and retrieving heterogeneous data via simple keys. Why make it any harder than that with a traditional relational column/row structure?

2: I’m Going To Ask Erlang Out On A Date: Erlang has gotten a lot of hype (and criticism) lately. Normally the simple churn of the blogosphere isn’t enough to get me interested in some johnny-come-lately, but Erlang strikes me as something with a little more staying power than the normal flavor-of-the-month technology. Perhaps it’s the track record as being “carrier-grade”. Perhaps it’s the move by some towards functional programming for solving particular problems. This, in particular, fascinates me. I’ve been an object-oriented guy for a long time, but there have been occasions when the OO approach seemed a little obtuse, but I didn’t really have a good alternative. I’m hoping that the process of learning Erlang will be a great foil to “get” functional programming.

1: I Think The OLPC Project Is Brilliant: I can’t think of a project that embodies more of the things I value than the One Laptop Per Child Project. It’s about putting the right amount of technology in the hands of kids. It’s about giving them a sturdy playground where they are encouraged to learn through experimentation. It’s about building sensible collaboration so that students can learn how to achieve more together as a group than they could as individuals. It’s about choosing and using a tool that gets things done. It’s not about learning a particular platform and it’s not about market-share.

I signed up for the Give 1 Get 1 program, but I can’t really justify having my own OLPC laptop. However I may get one just to play with it for a few days and then find a worthy home for it. I can’t imagine a better way to empower a kid than to put a tool like this in their hands.

The Ache of Swing Programming

September 7th, 2007

As I type this post, I have to fight every urge to grab my hands in agony and cry out like a hurt child. This hand-ache is not unfamiliar. I realize that my hands have always felt like this anytime I’ve had to do some Swing programming.

Why does it have to be like this? Because Swing requires just so much damn typing. My lord my fingers are buzzing with a solid week of keyboard contact. Swing is a tremendously verbose API—it simply requires a lot of letters to make it go. I consider myself a pretty advanced Eclipse user who takes advantage of most of its features to let it write my code for me, but my hands still hurt. I shudder at the thought of having to code Swing like I did “back in the day” with good old Emacs.

I find it interesting that demonstrations of Java code being called from a scripting language (JRuby, Jython, Groovy, etc.) always include an example of rapid GUI prototyping with the Swing API. I say this because I think that while these scripting languages really beat Java in terseness, they don’t really help much when dealing with Swing. In other words, a scripting language may reduce the length of a line I might otherwise write in Java, but the sheer number lines I have to write is about the same. I don’t think this is an indictment of scripting-wrapped-around-Java so much as what it says about the Swing API itself.

The other reason Swing wears your hands out is that it is not a well-designed, intuitive API. You spend a lot of time experimenting to figure out the magic recipe that will make your app work. Despite the verbosity of the API docs and various Swing Tutorials, I find that I still have to play (nee fight) with the API to figure out how to get it to work.

Take, for example the juggernaut that is the JTable. I wanted to have a JTable instance update with new rows when the underlying model changed. I wanted to set a custom renderer for one of the cells to display a URI as a hyperlink and allow the user to click it and view the URI in their browser (via Desktop.browse(URI)). OK, let’s see here, let’s go to our IDE and put the cursor next to our JTable instance variable and trigger the autocomplete drop-down. Hmmm, what can we use here? Oh here, we go, setDefaultCellRenderer, hey that looks good. OK, let’s see, takes a Class and TableCellRenderer, yeah that looks good. Alright, let’s fire it up…wait for the VM to get warmed up…load our data model…click the table and…aw hell, a NullPointerException during table painting. OK, let’s go through the stack trace and look for one of my classes in there. I must be passing some null reference around. Hmmm, no…actually these are all Swing and internal classes. Great, now what?

Eventually I worked out that the problem is that despite the plethora of options for cell rendering, only one combination worked in my particular case. Only by trying every square in the Swing-API-matrix was I able to stumble upon a combination that worked correctly. Now I will admit that my Swing skills are a bit rusty and that I have to blame myself to a certain extent. However my big beef with Swing API is that it gives you so many ways to hurt yourself in spectacular and unintended ways. Looking at the API and its base-classes with 200+ methods, it’s pretty clear that the API was developed from the implementation on up. Any design with regard to usability seems to be an afterthought.

I feel like whenever I’ve had to work on a Swing project, I have to change my whole approach. It’s much more difficult for me to cull decent unit-tests out of the code. In part this is because it’s so easy to embed testable code inside of un-testable code (think of event handlers), but also because UI testing is difficult. Even the various UI-oriented unit-testing tools don’t really enable easier unit-testing so much as make it barely possible.

Despite all of this and the persistent ache in my digits, I can’t say I didn’t have any fun with this. I’ve always said that programming Swing is a bit like riding a mo-ped, it’s fun for a bit but you would never want your friends to catch you doing it.

Posted in Java, Rant | 2 Comments »