2

Consider the following code snippet:

class Foo {
  Baz baz;
  // ...

  void bar() {
    int p = this.baz.doSomething();

    if (p == this.x) {
      throw new FooException('Invalid values', FooException::INVALID_VALUES);
    }

    this.x = p * this.y;
  }
  // ...
}

Baz::doSomething() can throw exceptions of the BazException type.

This causes Foo::bar() to throw both kind of exceptions, of the type FooException and BazException.

Is it acceptable to have these kinds of methods, or should methods of an exception throw its own exception type only? An example of this with the barfunction rewritten is as follows:

void bar() {
  try {
    int p = this.baz.doSomething();
    if (p == this.x) {
      throw new FooException('Invalid values', FooException::INVALID_VALUES);
    }
  }
  catch (BazException be) {
    throw new FooException('Invalid values', FooException::INTERNAL_ERROR);
  }
}
  • What language are you using? I recognize this is likely meant as a language generic question, but I'm not sure all languages with exception handling of this form include "child exceptions" which would be what you're after (c++ I don't think has child exceptions inherently where C# does) – Assimilater Sep 30 '16 at 5:33
  • 1
    If every class had its own exceptions it would be impossible to keep track of what might throw what. – whatsisname Sep 30 '16 at 6:11
  • The try/catch to change the exception is just make-work. The whole point of exceptions is to not handle/catch them unless there's some useful course of action you can undertake. – Erik Eidt Sep 30 '16 at 16:13
4

Why do we use different exception types? We could just as well use a single type for all exceptions, e.g. Java's RuntimeException.

The point is that we can filter exceptions in a catch clause so that we only catch those exceptions which we can handle. It is not reasonable to catch logic errors, they can only be fixed by changing the program. It is not reasonable to catch argument validation errors, unless they were caused by user input. It seems that the type tag INVALID_VALUES and INTERNAL_ERROR should be the exception type, not FooException. In particular, prefer standard library exceptions where handling the standard exception would also make sense for your error.

Catching exceptions to re-wrap them in another exception type is only OK if you are able to add context, e.g. “error while updating Bazzes”. However, the exception type or message should not be used to pinpoint the exact source code location of the error – that is what stack traces are for. We have to take great care to keep the original exception and stack trace. Java's standard library exceptions can take a Throwable cause in their constructors. If you create custom classes, you should do that too. Currently, you are throwing all that valuable debugging information away.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.