Exceptions, part 2

This is part two in a series about using exceptions in both Java and .NET. You can find part one here.

When to throw exceptions

There are a lot of different opinions about using exceptions. Joel, of Joel on Software fame, thinks there are as evil as a goto. I disagree with Joel, but I do have two rules of thumb when it comes to throwing exceptions:

  1. Only throw an exception in exceptional cases.
  2. Make it possible to check for errors without necessarily catching an exception.
  3. Never throw an exception in a constructor.
Let’s go over these one by one.

Exceptional cases

I know that exceptional cases sounds kind of vague, but-to me-an exceptional case is a case that normally does not occur, and if it occurs, you’re pretty much screwed. For instance, when the computer runs out of memory, when a database connection drops underneath of you, or or when the filesystem is borked. In these cases, an exception is in place, because there is not much you can do anyway. It is not like you can force someone to purchase new memory chips if your malloc fails:

char* buf = (char*)malloc(100 * sizeof(char));
if (buf == NULL)
  GoBuyMoreMemoryNow();

Checking for errors without exceptions

The implication of the above is that it should never be required to catch an exception when you’re doing something normal. Suppose you have a user-provided string that should contains a date. In .NET, there is no easy way to check whether it really is a date, except for catching exceptions. So to check whether it’s a valid date, I have to do the following:

bool isValidDateTime = true;
try {
  DateTime dateTime = DateTime.Parse(someString);
} catch (FormatException fe) {
  isValidDateTime = false;
}

It turns out that the next version of the .NET framework will fix this, but until then, the only way to check for a valid string representation of a date is the above. Java does not have this specific issue, because its DateFormat class can return null as an error indicator.

Never in a constructor

Usually you don’t want to do anything that can fail in the constructor of a class. Instead, use a factory method, or an initialization method.

Comments are closed.