please verify me if I am right: when a program encounters a exception we should write code to handle that exception, the handler should do some recovery job, like rerun the program, but is not just telling us where we went wrong in real world application.
When you throw an exception you're saying:
"Something happened and I can't handle it here. I'm passing the buck!"
When you catch you say:
"Ok I can do something. Perhaps loop around and try again; maybe log an error message".
You can even choose to ignore the error but that's usually discouraged.
In general the thrower captures the state of the failure and the catcher acts on the failure.
In real life, exceptions don't always make error handling easier; but it helps keeps errors out of the main line code path. It's an alternate execution flow. You often hear this: "Exceptions should be used only for exceptional things."
This is a controversial topic, so I expect some to disagree with what I'm going to say.
Exceptions are for exceptional circumstances, namely, the following two classes of problems:
Program Bug
External Problems
In the former case, your program has gotten into a state it shouldn't be in. So you throw an exception and catch it at a level high enough where the program can gracefully continue. In general, this should be fairly high in your program. The reality is, if there's a bug in the middle of an operation, there's not much you can do to recover (after all, if you knew there was a bug, you'd fix it!). Best is to log it, let the user know and move on, if possible. Terminate the current operation, dialog, whatever, or even the whole program.
In the latter case, you are dealing with capricious and fickle universe. Things might go wrong through no fault of your own. In this case, you should try to detect errors as close to the source as you can and deal with them as best you can. If you sending an email to a flaky server results in an exception, it might be reasonable to try again (warning the user). If the database connection goes down, you could try again, but it might be better to give up and kill the current operation. It depends on how well you understand the external problems that might arise and what can actually be done about them.
If you have known error conditions, such as errors in user input or other data sources (e.g., XML parse error, user picked wrong choice on a form, etc.), it's probably best not to throw an exception, but instead gather and report the errors in a more structured fashion. In one project of mine, I have an error reporter class that can gather errors without interrupting program flow. Then those errors can be reported to the user, or logged.
Often times, I think the best approach is not to catch the error, especially if you don't have a specific response for the error. In general, I think the approach of "catch and try again" is flawed. The cause should be identified and corrected. You shouldn't just keep ramming into a brick wall.
Exceptions should be thrown when, and only when, a method/property/whatever is unable to fulfill its contract. The only time an exception should be caught without either rethrowing it or wrapping it in a new exception and throwing that is when the method that caught the exception can fulfill its contract despite the inner method's failure to fulfill its contract. While it may be hard to determine the optimal contract for a routine, once the contract is in place, deciding whether to throw an exception will be easy: do what the contract says.
It really depends on the error and how you want to handle it. In a lot of my automation systems, if something goes wrong, I want the program to send an email out with a specific error and then terminate. Other times I want to catch the error and run a different process to back out data that I had previously entered.
Sounds like you have the general idea down.
Related
I am designing a WinForms application.
At the moment, all my exceptions are being logged at the UI level.
However, for none of them, do I do anything other than logging. Is this indicative of a bad design?
Furthermore, in one method (.NET's method execute a command on a windows service), it can throw exceptions of type Win32Exception and InvalidOperationException.
With an exception like FileNotFound, I could prompt the user to provide another file (although .NET has methods built-in to check for the file's existence), but with exceptions like the above, they are down to low-level problems with the machine, so these can only be logged really.
Is this the right way to go with deciding which exceptions to catch? Also, should I catch or throw ArgumentNullException? It indicates a problem with the code, right?
(I'll use Eric Lippert's taxonomy of exceptions throughout the answer.)
If there is nothing you can do about it, then just log and bail out of the current operation, screen or the entire application, depending on the seriousness of the error. Just don't try to proceed in the face of fatal exceptions. In some extreme cases (like an AccessViolationException), just logging or even letting your finally blocks run may not be a good idea because you don't know what will happen if you run code in a corrupt process.
FileNotFoundException and other exogenous exceptions you should handle anyways. Even though you can check if a file exists beforehand, nothing prevents it from becoming inaccessible in between the check and its use. These exceptions depend on external conditions that you have no control over, so you should be prepared to handle them.
You should never catch ArgumentNullException or any other boneheaded exceptions. If it hurts when you do that, don't do it. If you pass a null argument when you shouldn't, then don't pass it. Fix the code so that it deals with the null reference beforehand.
I have always been of the belief that if a method can throw an exception then it is reckless not to protect this call with a meaningful try block.
I just posted 'You should ALWAYS wrap calls that can throw in try, catch blocks.' to this question and was told that it was 'remarkably bad advice' - I'd like to understand why.
A method should only catch an exception when it can handle it in some sensible way.
Otherwise, pass it on up, in the hope that a method higher up the call stack can make sense of it.
As others have noted, it is good practice to have an unhandled exception handler (with logging) at the highest level of the call stack to ensure that any fatal errors are logged.
As Mitch and others stated, you shouldn't catch an exception that you do not plan on handling in some way. You should consider how the application is going to systematically handle exceptions when you are designing it. This usually leads to having layers of error handling based on the abstractions - for example, you handle all SQL-related errors in your data access code so that the part of the application that is interacting with domain objects is not exposed to the fact that there is a DB under the hood somewhere.
There are a few related code smells that you definitely want to avoid in addition to the "catch everything everywhere" smell.
"catch, log, rethrow": if you want scoped based logging, then write a class that emits a log statement in its destructor when the stack is unrolling due to an exception (ala std::uncaught_exception()). All that you need to do is declare a logging instance in the scope that you are interested in and, voila, you have logging and no unnecessary try/catch logic.
"catch, throw translated": this usually points to an abstraction problem. Unless you are implementing a federated solution where you are translating several specific exceptions into one more generic one, you probably have an unnecessary layer of abstraction... and don't say that "I might need it tomorrow".
"catch, cleanup, rethrow": this is one of my pet-peeves. If you see a lot of this, then you should apply Resource Acquisition is Initialization techniques and place the cleanup portion in the destructor of a janitor object instance.
I consider code that is littered with try/catch blocks to be a good target for code review and refactoring. It indicates that either exception handling is not well understood or the code has become an amœba and is in serious need of refactoring.
Because the next question is "I've caught an exception, what do I do next?" What will you do? If you do nothing - that's error hiding and the program could "just not work" without any chance to find what happened. You need to understand what exactly you will do once you've caught the exception and only catch if you know.
You don't need to cover every block with try-catches because a try-catch can still catch unhandled exceptions thrown in functions further down the call stack. So rather than have every function have a try-catch, you can have one at the top level logic of your application. For example, there might be a SaveDocument() top-level routine, which calls many methods which call other methods etc. These sub-methods don't need their own try-catches, because if they throw, it's still caught by SaveDocument()'s catch.
This is nice for three reasons: it's handy because you have one single place to report an error: the SaveDocument() catch block(s). There's no need to repeat this throughout all the sub-methods, and it's what you want anyway: one single place to give the user a useful diagnostic about something that went wrong.
Two, the save is cancelled whenever an exception is thrown. With every sub-method try-catching, if an exception is thrown, you get in to that method's catch block, execution leaves the function, and it carries on through SaveDocument(). If something's already gone wrong you likely want to stop right there.
Three, all your sub-methods can assume every call succeeds. If a call failed, execution will jump to the catch block and the subsequent code is never executed. This can make your code much cleaner. For example, here's with error codes:
int ret = SaveFirstSection();
if (ret == FAILED)
{
/* some diagnostic */
return;
}
ret = SaveSecondSection();
if (ret == FAILED)
{
/* some diagnostic */
return;
}
ret = SaveThirdSection();
if (ret == FAILED)
{
/* some diagnostic */
return;
}
Here's how that might be written with exceptions:
// these throw if failed, caught in SaveDocument's catch
SaveFirstSection();
SaveSecondSection();
SaveThirdSection();
Now it's much clearer what is happening.
Note exception safe code can be trickier to write in other ways: you don't want to leak any memory if an exception is thrown. Make sure you know about RAII, STL containers, smart pointers, and other objects which free their resources in destructors, since objects are always destructed before exceptions.
Herb Sutter wrote about this problem here. For sure worth reading.
A teaser:
"Writing exception-safe code is fundamentally about writing 'try' and 'catch' in the correct places." Discuss.
Put bluntly, that statement reflects a fundamental misunderstanding of exception safety. Exceptions are just another form of error reporting, and we certainly know that writing error-safe code is not just about where to check return codes and handle error conditions.
Actually, it turns out that exception safety is rarely about writing 'try' and 'catch' -- and the more rarely the better. Also, never forget that exception safety affects a piece of code's design; it is never just an afterthought that can be retrofitted with a few extra catch statements as if for seasoning.
As stated in other answers, you should only catch an exception if you can do some sort of sensible error handling for it.
For example, in the question that spawned your question, the questioner asks whether it is safe to ignore exceptions for a lexical_cast from an integer to a string. Such a cast should never fail. If it did fail, something has gone terribly wrong in the program. What could you possibly do to recover in that situation? It's probably best to just let the program die, as it is in a state that can't be trusted. So not handling the exception may be the safest thing to do.
If you always handle exceptions immediately in the caller of a method that can throw an exception, then exceptions become useless, and you'd better use error codes.
The whole point of exceptions is that they need not be handled in every method in the call chain.
The best advice I've heard is that you should only ever catch exceptions at points where you can sensibly do something about the exceptional condition, and that "catch, log and release" is not a good strategy (if occasionally unavoidable in libraries).
I was given the "opportunity" to salvage several projects and executives replaced the entire dev team because the app had too many errors and the users were tired of the problems and run-around. These code bases all had centralized error handling at the app level like the top voted answer describes. If that answer is the best practice why didn't it work and allow the previous dev team to resolve issues? Perhaps sometimes it doesn't work? The answers above don't mention how long devs spend fixing single issues. If time to resolve issues is the key metric, instrumenting code with try..catch blocks is a better practice.
How did my team fix the problems without significantly changing the UI? Simple, every method was instrumented with try..catch blocked and everything was logged at the point of failure with the method name, method parameters values concatenated into a string passed in along with the error message, the error message, app name, date, and version. With this information developers can run analytics on the errors to identify the exception that occurs the most! Or the namespace with the highest number of errors. It can also validate that an error that occurs in a module is properly handled and not caused by multiple reasons.
Another pro benefit of this is developers can set one break-point in the error logging method and with one break-point and a single click of the "step out" debug button, they are in the method that failed with full access to the actual objects at the point of failure, conveniently available in the immediate window. It makes it very easy to debug and allows dragging execution back to the start of the method to duplicate the problem to find the exact line. Does centralized exception handling allow a developer to replicate an exception in 30 seconds? No.
The statement "A method should only catch an exception when it can handle it in some sensible way." This implies that developers can predict or will encounter every error that can happen prior to release. If this were true a top level, app exception handler wouldn't be needed and there would be no market for Elastic Search and logstash.
This approach also lets devs find and fix intermittent issues in production! Would you like to debug without a debugger in production? Or would you rather take calls and get emails from upset users? This allows you to fix issues before anyone else knows and without having to email, IM, or Slack with support as everything needed to fix the issue is right there. 95% of issues never need to be reproduced.
To work properly it needs to be combined with centralized logging that can capture the namespace/module, class name, method, inputs, and error message and store in a database so it can be aggregated to highlight which method fails the most so it can be fixed first.
Sometimes developers choose to throw exceptions up the stack from a catch block but this approach is 100 times slower than normal code that doesn't throw. Catch and release with logging is preferred.
This technique was used to quickly stabilize an app that failed every hour for most users in a Fortune 500 company developed by 12 Devs over 2 years. Using this 3000 different exceptions were identified, fixed, tested, and deployed in 4 months. This averages out to a fix every 15 minutes on average for 4 months.
I agree that it is not fun to type in everything needed to instrument the code and I prefer to not look at the repetitive code, but adding 4 lines of code to each method is worth it in the long run.
I agree with the basic direction of your question to handle as many exceptions as possible at the lowest level.
Some of the existing answer go like "You don't need to handle the exception. Someone else will do it up the stack." To my experience that is a bad excuse to not think about exception handling at the currently developed piece of code, making the exception handling the problem of someone else or later.
That problem grows dramatically in distributed development, where you may need to call a method implemented by a co-worker. And then you have to inspect a nested chain of method calls to find out why he/she is throwing some exception at you, which could have been handled much easier at the deepest nested method.
The advice my computer science professor gave me once was: "Use Try and Catch blocks only when it's not possible to handle the error using standard means."
As an example, he told us that if a program ran into some serious issue in a place where it's not possible to do something like:
int f()
{
// Do stuff
if (condition == false)
return -1;
return 0;
}
int condition = f();
if (f != 0)
{
// handle error
}
Then you should be using try, catch blocks. While you can use exceptions to handle this, it's generally not recommended because exceptions are expensive performance wise.
If you want to test the outcome of every function, use return codes.
The purpose of Exceptions is so that you can test outcomes LESS often. The idea is to separate exceptional (unusual, rarer) conditions out of your more ordinary code. This keeps the ordinary code cleaner and simpler - but still able to handle those exceptional conditions.
In well-designed code deeper functions might throw and higher functions might catch. But the key is that many functions "in between" will be free from the burden of handling exceptional conditions at all. They only have to be "exception safe", which does not mean they must catch.
I would like to add to this discussion that, since C++11, it does make a lot of sense, as long as every catch block rethrows the exception up until the point it can/should be handled. This way a backtrace can be generated. I therefore believe the previous opinions are in part outdated.
Use std::nested_exception and std::throw_with_nested
It is described on StackOverflow here and here how to achieve this.
Since you can do this with any derived exception class, you can add a lot of information to such a backtrace!
You may also take a look at my MWE on GitHub, where a backtrace would look something like this:
Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
I feel compelled to add another answer although Mike Wheat's answer sums up the main points pretty well. I think of it like this. When you have methods that do multiple things you are multiplying the complexity, not adding it.
In other words, a method that is wrapped in a try catch has two possible outcomes. You have the non-exception outcome and the exception outcome. When you're dealing with a lot of methods this exponentially blows up beyond comprehension.
Exponentially because if each method branches in two different ways then every time you call another method you're squaring the previous number of potential outcomes. By the time you've called five methods you are up to 256 possible outcomes at a minimum. Compare this to not doing a try/catch in every single method and you only have one path to follow.
That's basically how I look at it. You might be tempted to argue that any type of branching does the same thing but try/catches are a special case because the state of the application basically becomes undefined.
So in short, try/catches make the code a lot harder to comprehend.
Besides the above advice, personally I use some try+catch+throw; for the following reason:
At boundary of different coder, I use try + catch + throw in the code written by myself, before the exception being thrown to the caller which is written by others, this gives me a chance to know some error condition occured in my code, and this place is much closer to the code which initially throw the exception, the closer, the easier to find the reason.
At the boundary of modules, although different module may be written my same person.
Learning + Debug purpose, in this case I use catch(...) in C++ and catch(Exception ex) in C#, for C++, the standard library does not throw too many exception, so this case is rare in C++. But common place in C#, C# has a huge library and an mature exception hierarchy, the C# library code throw tons of exception, in theory I(and you) should know every exceptions from the function you called, and know the reason/case why these exception being thrown, and know how to handle them(pass by or catch and handle it in-place)gracefully. Unfortunately in reality it's very hard to know everything about the potential exceptions before I write one line of code. So I catch all and let my code speak aloud by logging(in product environment)/assert dialog(in development environment) when any exception really occurs. By this way I add exception handling code progressively. I know it conflit with good advice but in reality it works for me and I don't know any better way for this problem.
You have no need to cover up every part of your code inside try-catch. The main use of the try-catch block is to error handling and got bugs/exceptions in your program. Some usage of try-catch -
You can use this block where you want to handle an exception or simply you can say that the block of written code may throw an exception.
If you want to dispose your objects immediately after their use, You can use try-catch block.
I read several posts on exception handling/rethrowing exceptions on here (by looking at the highest voted threads), but I am slightly confused:
-Why would you not want the immediate catch block to handle an exception but rather something above it?
-Also, I read quite frequently that you should only handle exceptions which you can "handle". Does that mean actually doing something about it, such as retrying the operation?
You might want to catch an exception (e.g. file not found) and do some processing - e.g. if you open two files and the second file is missing, you will want to close the first file again before you continue, so that it isn't left open.
You might then want to tell the caller that an error occurred, so you re-throw the same exception or throw a new exception, describing the problem.
In some cases, if you get an exception, your code has no way of knowing if it is an error or not (e.g. if you are asked to load an XML file, but you get a File Not Found exception, is that an error, or should you return a blank XMl result?). In these cases you either want to re-throw the exception, or not handle it all all, and let the calling code decide how to deal with the problem.
Your second point is the answer to the first. Sometimes the lower-level functionality does not know enough about the context of the application to know what the right action should be. For example, if opening a file for reading fails because there is no file of that name, then the application might want to ask for a different file, or abort the whole operation, or whatever. At some level, some part of the application will take the responsibility to do the right thing, unless of course just having the program crash is an acceptable action to take.
Answering to your second question - you need to handle the exception in the immediate block only if can do anything about it: for example close connection to db, close streams, retry or retry with different params, log exception (if there will not be an exception generic handler on the higher levels). Probably only immediate block of code knows such details and can handle them. Calling blocks need to know that the error occurred they might know better what to do with exception.
For example immediate block works with a file. A caller might try to open a file from different locations(In the process of "probing") and ignore several errors as long as at least one succeeds. Another part of code might consider the very first failed attempt as an error. Caller block might chose to notify the user that an error is occurred, probably let her/him know some helpful info on how to fix the problem. Also it is nice to provide the means to notify support of the problem – some kind of dialog allowing user to ask for help, describe problem and send a message. In this message you might attach logs, some info about the environment like OS, versions of frameworks, programs, browser capabilities whatever you need to diagnose the problem (if user permits you to do so).
An exception is "handled" if the method which caught it can satisfy its construct. For example, the contract for a routine OpenRecentDocument which is called when the user selects an item from the "recent files" menu might specify that it must either (1) successfully open a document window, or (2) try unsuccessfully to open a document window, roll back any side-effects resulting from the attempt, and notify the user of the what happened. If OpenRecentDocument catches an exception while trying to open the file, but it is able to roll back any side effects from the attempt and notify the user, the routine will have satisfied its contract and should thus return without rethrowing the exception.
One unfortunate "gotcha" in all this is that there isn't any standard means by which routines which throw an exception can indicate whether their attempted operation has resulted in side-effects which could not be rolled back. There is no inherent way, for example, of distinguishing an InvalidOperationException which occurs unexpectedly while updating a shared data structure (which would imply that other open documents may have been corrupted), from an InvalidOperationException which occurs while updating the data associated with the document being loaded, even if one has anticipated the latter possibility and provided for it. The best one can do is either try to catch any InvalidOperationException which might occur in the latter situation near the spot that it occurs, encapsulate that exception in some other exception type, and throw that, or else have data structures maintain an "object corrupted" flag and ensure that if a data structure is found to be corrupt, all future operations on it will fail as cleanly as possible. Neither approach is at all elegant. The more common approach, which could probably be described as "hope for the best", usually works.
My VS just told me;
Warning 2 CA1031 : Microsoft.Design : Modify 'Program.Main(string[])' to catch a more specific exception than 'Exception' or rethrow the exception.
Why should I do that? If I do so, and don't catch all exceptions to handle them, my program crashes with the all-popular report-screen. I don't want my users to get such error-crap!
Why should I not catch all exceptions at once to display a nice warning to the user saying: "Something went wrong, don't care about it, I will handle it, just be patient"?
Edit: Just saw I have a dupe here, sorry for that Dupe
Edit2: To clarify things; I do exit the program after any exception has been catched! I just don't want my user to see that "report to microsoft" dialog that show up when an unhandled exception is raised in a console-application!
Swallowing exceptions is a dangerous practice because:
It can cause the user to think something succeeded when it actually failed.
It can put your application into states that you didn't plan for.
It complicates debugging, since it's much harder to find out where the failure happened when you're dealing with bizarre/broken behavior instead of a stack trace.
As you can probably imagine, some of these outcomes can be extremely catastrophic, so doing this right is an important habbit.
Best Practice
First off, code defensively so that exceptions don't occur any more than necessary. They're computationally expensive.
Handle the expected exceptions at a granular level (for example: FileNotFoundException) when possible.
For unexpected exceptions, you can do one of two things:
Let them bubble up normally and cause a crash
Catch them and fail gracefully
Fail Gracefully?
Let's say you're working in ASP.Net and you don't want to show the yellow screen of death to your users, but you also don't want problems to be hidden from the dev team.
In our applications, we usually catch unhandled exceptions in global.asax and then do logging and send out notification emails. We also show a more friendly error page, which can be configured in web.config using the customErrors tag.
That's our last line of defense, and if we end up getting an email we jump on it right away.
That type of pattern is not the same as just swallowing exceptions, where you have an empty Catch block that only exists to "pretend" that the exception did not occur.
Other Notes
In VS2010, there's something called intellitrace coming that will allow you to actually email the application state back home and step through code, examine variable values at the time of the exception, and so on. That's going to be extremely useful.
Because programs that swallow (catch) exceptions indiscriminately, (and then continue), cannot be relied upon to do what it is they are expected to do. This is because you have no idea what kind of exception was "ignored". What if there was an overflow or memory access error that causes the wrong amount to be debited from a financial account? What if it steers the ship into the iceberg instead of away from it ? Unexpected failures should always cause the application to terminate. That forces the development process to identify and correct the exceptions it finds, (crashes during demos are a wonderful motivator), and, in production, allows appropriately designed backup systems to react when the software experiences an "unexpected" inability to do what it was designed to do.
EDIT: To clarify distinctions between UI components, and service or middleware componentrs.
In Service or Middleware components, where there is no user interacting with the code component from within the same process space that the code is running in, the component needs to "pass On" the exception to whatever client component imnitiated the call it is currently processing. No matter the exception, it should make every possible attempt to do this. It is still the case, however, tjhat in cases where an unexpected, or unanticipated exception occurs, the component should finally terminate the process it is running in. For anticipated or expected exceptions, a velopment analysis should be done to determine whether or not, for that specific exception, the component and it's host process can continue to operate (handling future requests), or whether it should be terminated.
You should handle the exact exceptions you are capable of handling and let all others bubble up. If it displays a message to the user that means you don't quite know what you can handle.
Having worked on equipment used by emergency responders, I would rather the user see an ugly error message than to accidently swallow an exception that misleads the user into believing everything is "ok". Depending on your application, the consequence could be anything from nothing to a lost sale to a catastrophic loss of life.
If a person were going to catch all exception, show a better error dialog, and then quit the application, that's ok.. but if they are going to continue running after swallowing an unknown exception, I would fire a person for that. It's not ok. Ever.
Good coding is about practices that assume humans make mistakes. Assuming all "critical" exceptions have been caught and handled is a bad idea.
Simple answer: you are supposed to fix your bug. Find the place that throws the exception and unless it is beyond your control - fix it.
Also catching (without rethrowing) all kinds of exception violates exception neutrality. In general you do not want to do this (although catching exceptions in main does look like special case)
Since your warning message shows that this is in Main(), I'll assume that in lower levels, you do catch only more specific Exceptions.
For Main(), I'd consider two cases:
Your own (debugging) build, where you want all the exception information you can get: Do not catch any Exceptions here, so the debugger breaks and you have your call stack,
Your public releases, where you want the application to behave normally: Catch Exception and display a nice message. This is always better (for the average user) than the 'send report' window.
To do this nicely, just check if DEBUG is defined (and define it, if VS doesn't do this automatically):
#if DEBUG
yadda(); // Check only specific Exception types here
#else
try
{
yadda();
}
catch (Exception e)
{
ShowMessage(e); // Show friendly message to user
}
#endif
I'd disable the warning about catching general Exceptions, but only for your Main() function, catching Exception in any other method is unwise, as other posters have said already.
There is a way to suppress certain messages from code analysis. I've used this for this exact reason (catching the general exception for logging purposes) and it's been pretty handy. When you add this attribute, it shows you've at least acknowledged that you are breaking the rule for a specific reason. You also still get your warning for catch blocks that are incorrect (catching the general exception for purposes other than logging).
MSDN SuppressMessageAttribute
I am all for catching specific known exceptions and handling state...but I use general catch exceptions to quickly localize problems and pass errors up to calling methods which handle state just fine. During development as those are caught, they have a place right next to the general exception and are handled once in release.
I believe one should attempt to remove these once the code goes into production, but to constantly be nagged during the initial code creation is a bit much.
Hence turn off (uncheck) the warning by the project settings as found in Microsoft.CodeQuality.Analyzers. That is found in the project settings under Code Analysis:
All answers are good here. But I would mention one more option.
The intention of author to show some fancy message is understandable.
Also, default Windows error message is really ugly. Besides, if application is not submitted to "Windows Excellence Program" the developer will not receive information about this problem. So what is the point to use default runtime handler if it does not help?
The thing here is that default exception handler of CLR host ( https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2008/9x0wh2z3(v=vs.90)?redirectedfrom=MSDN ) works in a very safe way. The purpose of it is clear: log the error, send it to developer, set the return code of your process and kill it. The general way of how to change that is to write your own host. In this case you can provide your own way of handling exceptions.
Still, there is an easy solution which satisfies CA1031 and still most of your needs.
When catching the exception, you can handle it your own way (log, show the message etc) and at the end you can set the process result code and do the exit (using the mix of Thread.Abort and "Exit" methods, for example). Still, at the end of your catch block you can just put "throw;" (which will never be called because of ThreadAbortedException, but will satisfy the rule). Still there are some cases, like StackOverflowException, which can't be handled like that and you will see that default message box, for fixing which you need to fallback to custom CLR host option.
Additionally, just for your information, you application can run several threads (besides that one which execute Main method). To receive exceptions from all of them you can use AppDomain.UnhandledException. This event does not allow you to "mark" the exception as handled, still you can freeze the thread using Thread.Join() and then do the job (log, msgbox, exit) using another (one more) thread.
I understand all this looks a little tricky and may be not right, but we have to deal with the implementation of AppDomain.UnhandledException, ThreadAbortException, CorruptedState exceptions and default CLR host. All of this eventually does not leave us much of choice.
When you catch general exceptions, you get the side effect of potentially hiding run-time problems from the user which, in turn, can complicate debugging. Also, by catching general exception, you're ignoring a problem (which you're probably throwing elsewhere).
You can set up your try catch to catch multiple different behavior types and handle the exception based on the type. For most methods and properties in the framework, you can also see what exceptions they are capable of throwing. So unless you are catching an exception from an extremely small block of code, you should probably catch specific exceptions.
In VS you can setup a custom error page to show your users when something goes wrong instead of catching it in a try-catch. I'm assuming since you're using VS that you're using ASP .NET. If so add this tag to your Web.Config under the System.Web tag:
<customErrors mode="RemoteOnly" defaultRedirect="~/CustomErrorPage.aspx" redirectMode="ResponseRewrite" />
You can also catch all uncaught exceptions in the Global.asax file (if you don't have it already: Right-click on web project, select Add Item, and search for it). There are a bunch of application wide event handlers in that file like "Application_Error" that catches every exception that isn't caught within your application so you don't have to use Try-Catch all the time. This is good to use to send yourself an email if an exception occurs and possibly redirect them to your homepage or something if you don't want to use the customErrors tag above.
But ultimately you don't want to wrap your entire application in a try-catch nor do you want to catch a general Exception. Try-catches generally slow down your application and a lot of times if you catch every general exception than it could be possible that you wouldn't know a bug exists until months or years later because the try-catch caused you to overlook it.
At what point during development do you typically implement your exception handlers? Do you write them at the same time as you write the surrounding code, or do you write your code and then come back to "harden" it later?
I typically do the latter so that I can see exactly where and how my code fails, but I worry that my code isn't as resilient as it could be if I would have written the exception handlers right away.
At the same time, I don't want to spend a whole bunch of development time figuring out all the possible ways that my code could fail when there are other implementation details that I haven't settled on yet.
I'm curious as to how other developers do this.
Update: I just wanted to thank everyone for their answers!
I either write the exception handlers immediately, or I allow the exceptions to propagate upwards. I'm a big fan of what I call the "You're Not Going To Go Back And Fix It Later, Are You?" principle. You say you will, but honestly, once you get it working, you're not going to go back and fix it later, are you? Just get it right right now! Write your exception handlers right away, or add a throws clause and make it somebody else's problem. Do the right thing right now.
But you know what, sometimes you can't. Whatever you do, do not swallow exceptions with empty exception handlers! This is evil:
try {
connection.close();
}
catch (Exception e) {
// TODO Auto-generated code
}
I drop kick anybody on my team who checks that in.
If you really don't know what to do about an exception and cannot add a throws clause to propagate it upwards, at least do something halfway responsible. Print a stack trace, if nothing else. It's not ideal but at least you're not hiding errors.
catch (IOException exception) {
exception.printStackTrace();
}
Logging it via your application's logging system is better, though you shouldn't make a habit of it. It's supposed to be the caller's responsibility to handle these kinds of things.
catch (IOException exception) {
log.error(exception, "Unable to open configuration file %s.", fileName);
}
As a last resort, you can do an end run around your throws clause by wrapping your exception in a RuntimeException. At least you're giving somebody higher up the call chain a chance to handle the error, which is normally the Right Thing To Do.
catch (IOException exception) {
throw new RuntimeException(exception);
}
In my exception handler I usually raise a higher-level exception. For example, when parsing a file in Python, some string, list and dict operations may raise ValueError, IndexError or KeyError. These exceptions are usually not helpful for the caller, so I write an exception handler, which raises a descriptive MyParseError. I do this at the same time when writing the method, but later, when writing the test, I sometimes make the exception message more verbose.
If I am calling an API then I look at what exceptions can be thrown and decide based on the list. The exceptions that can be thrown generally fall into categories:
Improbable in my view this will get thrown - make sure that code fails nicely
Realistic that this will get thrown - what should I do if this gets called?
Certain that this will get thrown based on current inputs - add validation to inputs to stop it getting thrown
Could I raise a more relevant exception? - if an exception is likely to get to get called would it be clearer for other calling code if I raised a new/different exception
In general I think it is always good practice to have catch all try catch blocks high up in the call stack that can catch general exceptions (Throwable) and then report these nicely to the user - perhaps with an interface that will then email the error and stacktrace to the development team and ask for user comments.
Sometimes both. In some cases I know of the exceptions that can be thrown and I want to handle as I'm writing the code, and so I write the handlers right then and there. Other times I don't know of all of the exceptions and find them later, either through documentation, testing or both.
It's a combination of both. There are things that I know can go wrong like database connections, configuration settings, file read/writes as well as the red flags from the functional/tech specifications. I try to setup the try/catch for those ASAP.
As the application gets bigger over time I then start to see patterns and trends with either how the user is using the application and or how me and or the team has developed it and add those try/catches as needed.
It kind of depends on the nature of the project you are working on. In my case, if I'm familiar with the logic of the system, I should know where, and how, to handle exceptions even before writing code. On the other hand, I would write my stuff, test it and then write the handlers.
during development, when:
a unit test require it
when some presentation/persistence code require it
EDIT
in Java sometimes, you must take care error handling at very early stage (checked exceptions) and sometimes this is very annoying.
My approach is to address exception handling immediately, since it's not some aimless burden that you can happily postpone.
Just handle the exceptions that apply at the point that you write your code, propagate all those that do not matter, and only come back later to fix whatever is broken, saves you a lot of tears.
As a rule, not only do I write my exception handling when I'm writing the code, but I try to write the code to avoid exceptions in the first place. The advantages are that if I know I need to handle an exception I remember to and if I can avoid an exception that is always a plus. I also test my code after I've written it using boundary conditions to see if there's any possible exceptions that I may have missed.
Writing the handlers when you are writing the actual code is the best habbit i guess because you are very clear of the failures that may occur although you can add others when you discover it.
handling the exception may be tedious for the first time but it would save lot of time while debugging for some error i.e support.