问题
Other than logging, what constitutes handling an exception? I ask as people say only catch an exception you can handle.
For example, I wrote a tool to interact with Active Directory. I run it on the domain controller. As I have intimate knowledge of AD, an otherwise-exceptional case I can handle (eg I can raise a prompt to ask for another domain name) and go from there. But if there is a problem with the domain on a production server so critical, would this not be exceptional?
So in this case, a problem with the environment should be exceptional (given that is production and AD etc), yet this is something I can handle. I think handling an exception depends on the program audience (agree)?
Anyway, the main question: to deduce if I can "handle" an exception, I need to know what handle entails - other than logging and presenting the user with another choice (in which case I avoid exceptions by using if file exists etc).
For the above case (AD), I structured my code as:
if (adIsAvailable)
// do whatever here
else
raise exception and ask for action
this is then caught in the gui
Any thoughts on the validity of that design?
回答1:
Great question. Remember that you can handle only specific types of exceptions and propagate the really critical ones up the stack and into oblivion.
One type of usage of exception handling is interacting with the user, of course, as you said, the best way is to check a precondition that if violated (file does not exist) will throw an exception, rather than performing the actual task and relying on the exception mechanism for notification.
Another usage of exception handling is retry. For example, you are sending a query to a DB and receive a TimeOutException, or another error that indicates that the connection is temporary unavailable. In this case you might want to wait a bit, and try another time. And only if you fail to reach the Db after, say, 3 times- propagate the exception to the upper layers.
Another way of handling an exception is adding data to the exceptionor changing its type. You might want to catch a TimeOutException but throw a MyApplicationException that contains, for example, the SQL that you tried to execute (the original exception being the inner exception).
Furthermore, you might want to do the opposite- remove data from the exception, such as the stack- trace, this from security reasons (it is not wise to expose the inner workings of the applications to the malicious user)
In your case by the way, you might want to format a user friendly message that clearly states the nature of the problem, instead of presenting the user with a stack trace and an obscure message. This is another example for a transformation that can be done during exception handling.
Not long ago, I had an exception thrown from my app that rose from insufficient space in a table space on a DML operation. The user got a horrible exception with an error code. What I did is add a handler that inspected the exceptions thrown from the invocation of the command, and added special handling for this error code- it now tells the user exactly what the problem is!
回答2:
You have a few different issues combined, here.
- How to handle (and decide when to handle) exceptions that are thrown by underlying code
- When to throw exceptions yourself
- Whether production code should treat 'exceptional' situations differently from dev. code.
Regarding point (1):
This can be a bit messy and hard to decide - different APIs might use exceptions differently, even inside the same language.
In C#, for instance, I prefer to use int.TryParse()
rather than int.Parse()
and catching a FormatException
if I expect my input to maybe fail parsing, and I want to write code to handle that case.
If I don't want to handle bad input, I will use int.Parse()
, and let the exception propagate.
It depends on the situation, alas.
Regarding point (2):
Exceptions basically mean "I give up". They mean something went wrong, but you aren't going to handle it yourself right there.
Regarding point (3):
I think this is almost always a bad idea.
Aside:
I disagree with part of Vitality's answer, where it says:
the best way is to check a precondition that if violated (file does not exist) will throw an exception, rather than performing the actual task and relying on the exception mechanism for notification.
If you write code like:
if (file_exists(x))
{ /* do something */ }
else
{ /* whatever */ }
Then you open yourself up to race conditions.
Maybe the file was deleted in between the file_exists()
check, so your code will throw an exception anyway.
Or maybe the file got created just after you entered the else
section.
In a case like this, I think it is better to do what you are trying to do, and if something goes wrong, deal with the exception.
来源:https://stackoverflow.com/questions/11658708/ways-to-handle-exception