I’m a naughty programmer, and until now I haven’t handled errors properly (e.g. just catching a java.lang.Exception, printing a debug message, and moving on). When I do “handle” them, it’s simply been to shut the compiler up.
I’ve recently learned the error (haha) of my ways, and would like to start doing it right. So I’m researching it here and other places (via Google searches).
Suppose I have a block of code which does the following:
...
x.method1(); // throws ExceptionTypeA
...
y.method2(); // throws ExceptionTypeB
...
z.method3(); // throws ExceptionTypeC
...
x.method4(); // throws ExceptionTypeA (again)
...
From what I’ve gathered, the proper way to handle this is:
try {
...
x.method1(); // throws ExceptionTypeA
...
y.method2(); // throws ExceptionTypeB
...
z.method3(); // throws ExceptionTypeC
...
x.method4(); // throws ExceptionTypeA (again)
...
} catch (ExceptionTypeA e) {
// do something about condition A
} catch (ExceptionTypeB e) {
// do something about condition B
} catch (ExceptionTypeC e) {
// do something about condition C
}
This seems pretty straightforward to me, but it seems to get messy when I have a long block of code which throws various errors throughout. I seem to wind up with just one giant try/catch around my whole method! The alternative seems to be:
try {
...
x.method1(); // throws ExceptionTypeA
...
} catch (ExceptionTypeA e) {
// do something about condition A
}
try {
...
y.method2(); // throws ExceptionTypeB
...
} catch (ExceptionTypeB e) {
// do something about condition A
}
try {
...
z.method3(); // throws ExceptionTypeC
...
} catch (ExceptionTypeC e) {
// do something about condition C
}
try {
...
x.method4(); // throws ExceptionTypeA
...
} catch (ExceptionTypeA e) {
// do something about condition A
}
This looks really nasty. In cases like this, I’ve considered doing something like the following:
private void doSomething() throws exceptionTypeA, exceptionTypeB, exceptionTypeC {
...
x.method1(); // throws ExceptionTypeA
...
y.method2(); // throws ExceptionTypeB
...
z.method3(); // throws ExceptionTypeC
...
x.method4(); // throws ExceptionTypeA (again)
...
}
public void doSomething_andHandleErrors() {
try {
this.toSomething();
} catch (ExceptionTypeA e) {
// do something about condition A
} catch (ExceptionTypeB e) {
// do something about condition B
} catch (ExceptionTypeC e) {
// do something about condition C
}
}
… and then just calling doSomething_andHandleErrors(); from outside. Is this a ‘good’ practice? Am I falling into some anti-pattern?
Thanks!
The main difference between your first and second example is how you handle the error itself. Is it transactional? In your first example, y.method2() will not run if x.method1() throws an exception. In your second example, it is possible depending on what the error handling does.
Both of those are decent patterns, it’s a matter of the business case required here. Do you want the exception to get passed to the caller so they can handle it? Do you want to do something else because of the error?
Also, do not forget the finally block. You’ll want to make sure you use one if you’re dealing with resource management (IO Streams, database connections, for example) so that you can do cleanup if necessary.