Java development with an iPhone touch pad for the Atari 2600 from an urban hip-hop perspective

Day: April 29, 2008

You need to open a web connection to some site and post some binary data from a local file. You need to validate that the site returns data that matches byte for byte the contents of another file stored on your hard drive. You need to return pass or fail depending on whether or not the data matched. Sounds simple enough, right? I’m setting my stop watch… you have 10 minutes to scroll to the comment section below and code the logic in Java… Ready? Go!

What does it look like? (Did you hit the submit button when you were done?) Did you get it right on the first go? No, we don’t have a back-end compiler and test engine on this site so you wouldn’t get a green bar when you hit submit. The point here is to find the bug. You got a bug somewhere in that logic! First ask yourself, what’s it doing with the streams? Are you closing them all properly or leaving them to Roc, the garbage collector? Did you side step all of the try/catch ugliness with the big oogly try/catch generic Exception that squelches your NullPointer issues? That’s a big bug, believe it or not, because it hides the real problems for you and sends you on wild goose chases. (Who chases wild geese anywayz? What happens when you catch one? Is there a prize? Do you become a wild goose in turn with other hungry savages chasing your tail wielding fork and knife?)

The other point is why bother? Look at the code. I bet there’s a lot of bloat, unless you’re reaching out to some 3rd party API or framework. If you are then you get an F for cheating cuz you can’t submit binary jar includes in the comment section which means you stuff won’t run anyway. Here’s a breif snip of the very same requirement using Groovy:

While there is a dangling close on the input stream the entire thing could be written without explicitly calling to close anything. The magic comes from the callback pattern as you’ll see in this walk through.

But that’s not Java!
Look again. We are using standard Java API objects URL and File.new URL("http://myremotesite.com")
new File(resourceDir, "typicalRequest.bin")
We just didn’t have to import them. Our variables are untyped and we dropped semi colons because it’s unnecessary.def con = url.openConnection()
All of our get/set methods become accessible using properties syntax. We also have auxiliary helper methods, more on that below.

Decorated Objects
Groovy comes as the Amaretto creamer in your cup of Java. It decorates standard Java objects with additional capabilities. For example, there’s an execute method added to java.lang.String that turns any string into an instant command line. You can do stuff like:"cmd /c explorer C:\\myscreenshot.png".execute()
to open up an image on your hard drive. They’ve also added goodies like plus(int days) to the java.sql.Date object. All of the stuff you would normally break out into a util component has been tucked neatly inside the Groovy enhanced Java API.

New Style
If you’re still for looping and switch casing your way through development you need to get with the program. There’s a new style of programming and either ya’ with it or yer’ slackin’! My example shows off the power of closures and call backs. Let’s talk about what they are and the things they bring to the table. Typical programming requires iteration which results in the loop. In tasks like the example above you need to acquire some resource iterate and dispose of the resource. Since Java uses checked exceptions in a lot of it’s low level API calls you’re forced to deal with them at every turn. The actual thing you are trying to accomplish gets lost in a flurry of noise code dealing with the state of indexes or counters, loop constructs and exception handling. With the callback pattern (which is also possible in pure Java) the iteration, state management, and exception handling is dealt with by some object that you call. This object calls back the code that invoked it on each step of iteration. (You can use callbacks for more than just iteration.) You write logic that looks like so:networkThingIterator.iterateNetworkThings(this);
instead of:

We do this in plain old Java but we have to implement an interface which many would inline turning the above example to:networkThingIterator.iterateNetworkThings(new NetworkThingHandler() {
public void handleNetworkThing(NetworkFooBar foo) {
//The innards of your for loop goes here!
}
});

Not too bad but there’s a little bit of noise here. The syntax of Anonymous inner classes mandates you write an entire class definition where all you really want to write is the method to handle the iteration.

Enter closures
With closures you write what looks, works, and smells like a method but can be grabbed hold of like an object. It removes the cruft of anonymous inner classes and adds the ability to pass a method or an action, or a thing to do (i.e. verb) to an object that does callbacks. Our above networkThing iteration would look like:networkThingIterator.eachNetworkThing( {
//handle network thing here
}//End of closure defitnition
);//end of method call

Back to the example
In our initial Groovy snip we see closures being passed to what looks like magic methods added to the OutputStream and File objects. These withStream methods contain callback logic that opens the stream, passes it to the closure, and closes the stream. We also have another piece of magic in the left shift operator [<<] that pipes or reads the contents of an InputStream to an OutputStream. The net result is code that focuses on the real task of connecting to streams without the noise of try to open, catch exception, blibbidy-blobbidy, try to close. Look closer. There’s another call back decorated onto InputStream that performs iteration on eachByte and passes it to the given closure. It’s named eachByte. Self explanatory enough? I’d write more but I’ve become way to verbose on the topic so hit me up with any finer details or points of interest.

The source of all code that’s fun

Code like a girlMy Page RankWho links to me?
The opinions expressed here are my own and are not borrowed, stolen, shared, or necessarily understood by my current employer.