Say I have 3 tier app- frontend domain and data access. I have read that it is a good idea to catch exceptions high in the call stack…so if I get a data-access exception, the domain layer merely does a finally, like so
try{
}finally{
//cleans up
}
and lets the data-access exception percolate to the frontend layer. Does this not break layering by making the front-end layer deal with the innards ? I think that each layer should either handler or wrap and throw exception that it cannot handle to its calling layer…
any thoughts ?
Lots of good feedback so far, I’ll give you my take.
Rule #1. ONLY catch exceptions you are going to actually handle. By handle, I mean handle in such a way that the client’s request can continue. You may catch things long enough to log information (don’t abuse this, usually the stack is enough information) or to convert to a different error that propagates easier (ala Runtime based). But, if you can’t handle it, don’t bother catching it. That’s just extra code that is useless and confusing. Even when you log or convert, you end up rethrowing.
Realize that most of the time, you can NOT handle an exception. Truly. Many fail to grasp this. But the reality is, if you get an IOException reading or writing to the disk, game over. That request cannot be completed for the user. If your network is flaky and you can’t talk to the database, same thing.
Rule #2. When you do get an exception that you cannot handle, the only thing you can do is try to fail in such a way that it is helpful to the user. This means, log it for later analysis (including original stack/cause), and then report something as helpful as possible to the user. Clean up whatever you must, so that the system remains in a consistent state.
Given that this communication with the end user happens at a very high level, that means you usually have to catch at that level. Most of the time, I find that there is very little value in any exception handling between it’s inception point and the top level where you catch it for logging and reporting to the user. I often convert to a form of RuntimeException, but that’s only done to ease propagation through the layers.
The biggest and most important thing is to realize that you usually can’t handle exceptions, so any code you write for them should be as simple as possible.