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.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s