Woozle Wuzzle
J2SE 1.5 mother lode

While doing my standard early morning web-walk I stumbled on a mother lode of J2SE 1.5 information. JDiff isn't necessarily 1.5 specific, but it allows you to see all changes that occurred in the API. JDiff is one of those thing you wish you stumbled on years ago. While perusing the diff on java.lang.Thread I noticed that setUncaughtExceptionHandler() and setDefaultUncaughtExceptionHandler() have been added. If you've ever used java.lang.ThreadGroups uncaughtException() then this addition to Thread will be old hat. Regardless, this is a welcomed change. Javalobby has a decent write up on these two new methods.

Polanski's The Tenant

I recently took the opportunity to see Roman Polanski's The Tenant at the Gene Siskel Film Center. I left the theatre completely speachless (and for those that know me, that's no small feat). For anyone that loves independent or avant-garde films, I would add this one to the list.

The Tenant reminded me at times of Marc Caro and Jean-Pierre Jeunet's Delicatessen, another wonderful film. I would love to see a modern indie director, such as Darren Aronofsky, do a remake of The Tenant with a Delicatessen flare. I'm adding "create remake of The Tenant" to the list of things that I should do once I'm rid of these shackels that bind me to my computer.

Interchangable cogs?

It is a common belief in the industry that programmers are just interchangable cogs. "Programming is programming", right? I believe that as SOAs, MDAs, RTIs and other "standard" architectures become more prevalent that this "interchangable cog" belief will initially become stronger due to perceived simplification of tasks. Unfortunately, this is exactly opposite from what the reality is.

As the nuances, scope and concerns of a specific architecture grows, developers become more and more specialized in that architecture. Specialization limits ones general knowledge (or just pushes it further down the stack) and therefore limits interchangability. This specialization trend can be seen in regards to development languages, platforms and applications. For example, interchanging a C developer fluent on Unix with one fluent on Windows is a recipe for disaster. The same can be true for Java and C#, or PeopleSoft and SAP.

I have recently tasked myself with determining how our universities are meeting the demands of greater specialization and addressing this interchangable cog paradox. At first glance it appears that there is little being done but I am only at an initial phase of my research. In a recent conversation that I had with a professor at my alma mater, I learned that most universities purposefully have more generic and abstract courses to separate themselves from trade or vocational schools.

I'm a man on a mission and I will post more information as I acquire it.

Does web programming make for lazy developers?

Given the plethera of "enabling technologies" such as J2EE, does web programming (specifically, tier two -- business logic) make for a lazy developer?

In the recent past, I was prototyping a web application using Spring, Struts, and a few other technologies sprinkled in for good measure. After a few weeks of stateless whos-its and whats-its, injecting transaction doo-dads, and so on, I moved on to a project involving NIO, wire protocols, and high degrees of concurrency. Getting back into the swing of worrying about multi-threaded issues, object creation weight, and the like was not a trivial excercise.

Let me stress that I'm not referring to API nuances. I'm speaking to the vastly different sets of skills that need to be employed. I felt that a much larger degree of care and awareness was needed when dealing with "systems programming". The web technologies on the other hand made me feel less concerned: "JTA will handle that for me so I don't need to worry."

Don't get me wrong, JTA, JMS, JNDI, etc are wonderful things that eliminate much of the tedium and start-from-scratch'ness that allows projects to get done are the current break-neck pace. (I admit that I am making the overgeneralization that enabling technologies and web development are synonymous.) But does all of this "simplification" provided by enabling technologies allow developers to go lax?

... or has all of the hype and marketing surrounding these enabling technologies simply obscured the diligence required?

Limit the scope of try-catch blocks

How many times have you seen the following?

public void myMethod(...)
    throws ...
{
    try {
        ... entire method is here ...
    } catch(SomeException se) {
        ....
    }
}

Consider when entire method is here is more than a dozen lines or so with a number of statements that throw SomeException lumped:

Limiting the scope of try-catch blocks forces the developer to think about each exception that can be thrown and how to appropriately handle them. I immediately associate a higher risk (as in QA) with a section of code that is in a single large try-catch block. It is likely that there are statements in that block that throw the caught exception that were never considered. This is a similar case as presented in That nasty java.io.IOException where unexpected exceptions bubble out due to a throws clause.

A common case to watch out for is one where a try-catch block surrounds a loop or vice-versa. The tendancy with a large try-catch block is to miss cases where the exception, if properly caught in a smaller try-catch block, would continue rather than break or vice-versa.

There are cases where a large try-catch block makes sense. Through comments it is a simple matter to indicate the reason why such a choice was made (see Code Comments for more information) thereby reducing the risk associated with the block.

That nasty java.io.IOException

I constantly run across code that looks like:

public class FileReader {
    ...
    /**
     * <p>Reads the file with the specified name and returns the 
     * contents in a {@link java.nio.ByteBuffer buffer}.</p>
     * 
     * @param  filename the name of the file to read
     * @return an allocated (not direct) <code>ByteBuffer</code> 
     *         with the contents of the file
     * @throws IOException if an I/O error occurs
     */
    public ByteBuffer readFile(final String filename)
        throws IOException
    {
        ...
    }
    ...
}

What's wrong with that? you're probably asking yourself. It's even got comments! The title of this entry should give you a little clue. I will spare you the rant and soap box about the proper use of exceptions and attempt to appeal to your common sense: If you, as the developer of the function, couldn't handle or recover from the IOException, what makes you believe that someone calling the function (someone that has little notion of what's actually going on in the function) can do something with it?

The interface or contract that you expose should not break encapsulation. The fact that you (as the developer) have I/O issues to deal with doesn't need to be exposed out to the user. What the user cares about is: did the function succeed or not, and if not, are there cases that they can possibly recover from. A more sane interface might look like the following:

public class FileReader {
    ...
    /**
     * <p>Reads the file with the specified name and returns the 
     * contents in a {@link java.nio.ByteBuffer buffer}.</p>
     * 
     * @param  filename the name of the file to read
     * @return an allocated (not direct) <code>ByteBuffer</code> 
     *         with the contents of the file
     * @throws NoSuchFileException if there is no file with the specified
     *         name
     * @throws ReadFailedException if there was any unrecoverable
     *         problem while reading the file
     */
    public ByteBuffer readFile(final String filename)
        throws NoSuchFileException, ReadFailedException
    {
        ...
    }
    ...
}

This interface throws two exceptions: NoSuchFileException and ReadFailedException. The former is "recoverable" by the user in that they may have specified the filename incorrectly and they can do something about that. The latter tells the user that it just didn't work and there's nothing that they can do about it.

What's more is that by not throwing IOException the developer is forced to look at each case explicitly and determine how each one should be handled. How many times has a handlable IOException bubbled out of an interface unexpectedly due to the throws clause? Personally, I will leave off the throws clause (or comment it out) while I'm developing a function to ensure that I'm not letting anything slip by. In the later Eclipse milestones you can now select an exception in the throws clause and it will mark each occurrance in the function that throws that exception. This is invaluable.

The next time that you are developing an interface, think about how a user will use that interface. Get into their shoes and think about their concerns. And most importantly, make sure that you're not breaking your own encapsulation.

Perforce and change lists

If you use Perforce I find it best to start off a new change with "New Changelist" and a rough outline of what I intend to do. This is a nice way of informing others (especially in a decoupled work environment) what you are going to be working on. As I begin to make changes I will "Edit spec" to keep the change list description up to date. This ensures that not only will others be aware of what I am doing but I wont run into the dreaded situation where I don't actaually remember all of the changes that I made.

Don't forget to add the added, updated, or deleted files to this changelist as you go.

ByteBuffers, String, and C

I end up doing a lot of marshalling between Java and C over the wire. ByteBuffers are a natural fit for this situation given ByteBuffer.order(ByteOrder) and NIO's selectors.

The problem comes in when dealing with Strings.

There's no ByteBuffer.put(String) but that's OK because there's CharBuffer.put(String). But wait! In Java a char is two bytes. So CharBuffer.put(String) on "bollocks" will return:

0062006f 006c006c 006f0063 006b0073  .b.o.l.l.o.c.k.s

This is all fine and dandy if you're going to another Java application (or something that's commonly double-byte) but when going to vanilla C you're looking for single byte characters.

Your next bet is to try:

final String string = "bollocks";
final ByteBuffer buffer = ByteBuffer.allocateDirect(string.length());
buffer.put(string.getBytes());

This is fine and dandy for most applications. (It should be noted that the default character set is used in the transformation and that unless this code is used in a controlled environment, you may end up getting BufferOverflowException. So it's better to do:

final String string = "bollocks";
final byte[] stringBytes = string.getBytes();
final ByteBuffer buffer = ByteBuffer.allocateDirect(stringBytes.length);
buffer.put(stringBytes);

Or even better yet, explicitly put the charset in String.getBytes(String charsetName).)

So what am I complaining about? Everything seems fine. That's true up to this point. But what if you need to chunk up the string? CharBuffer provides CharBuffer.put(String src, int start, int end) which is ideal except for that problem of double-byte chars. What you actually end up doing is String.getBytes() and then walking over the resulting byte array. This may seem all fine and dandy except for the fact that the whole reason for doing the chunking in the first place is that the string is very large. Using String.getBytes() will cost you about three times the memory (the original string, the string as a byte array and the ByteBuffer into which you are writing).

If you're NIO Charset savvy then you may have said to do:

final String string = "bollocks";
final Charset charset = Charset.forName("UTF-8");
final ByteBuffer buffer = charset.encode(string);

This kills lots of birds with a single stone and is very tight code. ("UTF-8" must be supported by Charset so there's no need to check.) The parallel code for chunking is similar:

final String string = "bollocks";
final Charset charset = Charset.forName("UTF-8");
final CharBuffer charBuffer = CharBuffer.wrap(string, 0, 3);
final ByteBuffer buffer = charset.encode(charBuffer);

(where the loop over the remaining chars is not shown). Again, this is nice code that solves the problem. So what am I still complaining about? Well, it's better on the memory consumption but, even though I know the size of my chunking and can allocate a ByteBuffer of this size, I have to allow it to allocate the buffer for me.

If really know your java.nio.charset you would suggest:

final String string = "bollocks";
final Charset charset = Charset.forName("UTF-8");
final CharsetEncoder encoder = charset.newEncoder();
final CharBuffer charBuffer = CharBuffer.wrap(string, 0, 3);
final ByteBuffer buffer = ByteBuffer.allocateDirect(3);
final CoderResult encodingResult = encoder.encode(charBuffer, buffer, true/*no more input*/);

This is an "elegant" solution that allows for reuse of the ByteBuffer and fits the bill almost exactly! There is the extra CharBuffer in there that has to suck up space but at least it's limited in size.

Galileo's gedankenexperiment

Aristotle stated that heavier objects fell faster than lighter ones. Galileo stated the following thought experiment:

Imagine two unequal balls dropped from a height at the same time; according to Aristotle, the heavier ball would drop faster. Now imagine the same experiment with one difference: the two unequal balls are joined by a cable between them. If it was true that the heavy ball moves faster and the light one moves slower, then the light ball will hold back the heavy one. If Aristotle was correct the two balls tied together would not reach the ground as quickly as the heavy ball alone. But if we assume that the cable between the balls has the effect of turning the two balls into a single mass that is heavier than either one by itself, the joined balls should drop faster than either one by itself.

Another way of looking at this is the reverse:

A heavy object is dropped from a height. As it descends it cracks and splits into two objects, each of which is lighter than the original object. Will the two objects suddendly slow to half speed?

One can continue the above thought experiment and question what would occur if each of the two objects divided into two .... If the speed did in fact halve then one could imagine subdividing further to a point at which it appeared that the objects would fall very very slowly.

Virtual CD-ROM for XP

I was too lazy to get up and get a CD to burn an ISO to so I went searching for the next best thing: mounting an ISO as a virtual drive.

This ISO Recorder for Windows XP SP2 works well.

Transit of Venus

The Transit of Venus (where Venus will cross the face of the sun) will occur tomorrow, June 8th, 2004 in the early morning. I'm going to head to my local planetarium if I can get my sorry butt out of bed that early.

A little known figure in the history of the transit of Venus is Jeremiah Horrocks. He was a self-trained astronomer whose work Venus in Sole Visa influenced Issac Newton. Take the time to read about this facinating man.

When IDE's are too smart for their own good!

I was cleaning up some JavaDocs yesterday in a large, multi-project code base. The process was getting tedious so I enlisted the help of my old friend GSR (global search and replace). Since I wanted to update java files, text documents and package HTML files, I opted to use * as my wildcard rather than, say, *.java, *.html, *.txt. Boy what a mistake that was.

Everything was going well but then my IDE (Eclipse in this case) starting throwing a fit. I was getting AST creation errors all over the place and it seemed as though the world was caving in. I attempted the old tried-and-true technique of software; I restarted the IDE. No go. Same errors.

I was near the point of panic when I took a look at the IDE's log. The first thing I see is java.lang.InternalError and lots of them. Oh crap! I don't even know what that is, but anything that starts with java.lang and ends with Error isn't good. I scroll to the end of the exception line and see: invalid LOC header (bad signature). Egad!

To make a painful story short, it turns out that the GSR was doing replacement in JARs as well as text files. This was corrupting the header and java.util.zip.ZipFile was throwing exceptions to no end. After replacing the JAR files with fresh clean ones all was well.

I want to hand it to the Eclipse people for making the IDE tolerant to the stupidity of the average Joe out there doing his best to muck things up. Sure, I got errors up the wazoo but had I taken a moment to look at what they were really telling me I would have figured out the problem instantly.

Perhaps this should have been titled "When programmers are too smart for their own good!".

Creative Commons License Unless otherwise expressly stated, all original material of whatever nature created by Rob Grzywinski and included in this weblog and any related pages, including the weblog's archives, is licensed under a Creative Commons License.