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!
As errors could be fatal, error handling is one of the crucial areas for application designers and developers, regardless of the application developed or programming languages used. In worst-case scenarios, the error handling mechanisms force the application to log the user off and shut down the system.
Error handling is important because it makes it easier for the end users of your code to use it correctly. Another important issue is that it makes your code easier to maintain.
Error handling refers to the routines in a program that respond to abnormal input or conditions. The quality of such routines is based on the clarity of the error messages and the options given to users for resolving the problem.
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.
The point of handling exceptions is that you should be able to proceed further even when you face an exception. The first way and the third way are basically the same. If an exception occurs in the method1()
you will directly exit the entire parent method without even an attempt at executing method2()
and others.. The second method may seem cluttered at first but is actually the way in which it should be done.
Even better than that would be to handle the exceptions that you expect it to throw in the method itself and return a sort of default value which will allow further execution without breaking business logic or cause inconsistency.
EDIT:
Example of advantage when using 2 method:
Suppose you're making a text parser and expecting a date
in the format DD-MM-YYYY
. But while parsing you find that you get date
in the format DD-MON-YYYY
. These type of parsing exceptions can be handled and still allow further execution.
This really depends on where (on which level) you want to catch
that exception.
A method that does throw an exception simply means that "I do not want to deal with this exception/problem, let anyone else catch" it. Clean code should come after this way of thinking; should I catch here or not...
In your last case if you throw again those exceptions, this would mean you will not need the objects x,y,z during error handling since they would most probably be out of scope.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With