Is it better OO design to catch an exception at the the user interface level of code, or in a lower level class?
E.g. I read data from a user, then send it to a lower level class which validates it. I can either throw an exception back up the call stack or handle it in the code. But I want to know whether one solution is condidered better than the other in terms of object orientated design.
I believe there is not a magic bullet answer to that question.
Mr Joshua Bloch in his book, Effective Java, (a master piece, by chance) gives a few advises, and I indeed recommend you to read it.
A bit of what I remember:
You should handle your exceptions in the specific place that you know you can do something about them, although all you can do is log the exception, if you cannot do anything, then you better declare them in the throws signature of the method or wrap them in other more specific exceptions.
For instance, if you are writing a library that connects to a database and , what can you do with the checked SQLException?
Many would say that there is nothing to do if the connection fails. However, if you have a set of different database servers to which you can connect, if the connection with the first server fails, you can try a second one, or a third one. This is an example of a place where it might be a good idea to handle the exception.
But there are cases where you can do nothing in the specific context where the exception is to be handled. For instance, you tried to update a record of the database and it failed, that throws an SQLException, and what can you do?.
If you are writing a library, you cannot throw a message box, or simply ignore the exception and make the user of the library believe that everything went all right.
In those cases you may consider to declare the method signature to throw the exception instead of handle it.
Bloch also explains that some exception names are not specific of the context of your application and some people prefer to wrap this kind of low level exceptions into more context specific exceptions.
For instance, if you are writing a Stack class that uses an array to hold the elements. If you try to push an element when the stack is full you would get an ArrayIndexOutBoundsException. But that is out of context and actually violates the encapsulation principle, because you do not need to know the way the stack was implemented.
In this case it could be better to wrap the ArrayIndexOutOfBounds exception into a customized exception like a StackOverflowException and StackUnderflowException, which is more specific to the context.
I believe that one the biggest errors is to write the try...catch and do nothing to handle exception.
While writing the code I prefer to do a throws first. That way I concentrate on the logic and definitely will not forget about the exception, because when I use method I will have to see about them.
Most of the times I follow Bloch's advise and wrap lower level exceptions into more specific exceptions. If the exception is a condition from which, I believe, the program can recover, then I use a checked exception. On the other hand, if I believe the condition happens because a program error I use unchecked exception.
In that way you can transform many checked exceptions into unchecked ones. For instance, reading a file may throw a FileNotFoundException, however, if you check to see if the file exists first, then you can throw a context specific RuntimeException or reuse one the typical RuntimeExceptions, like IllegalArgumentException.
Whatever the case, if your exceptions scale up to your user interface, maybe it is because that is the best place to handle them. Although this "handling" implies just showing a message box or simply logging the exception for future analysis.
No matter what you do, never, never ever just catch the exception in an empty block, for you will regret it no longer after that. [ June 09, 2006: Message edited by: Edwin Dalorzo ]