views:

584

answers:

8

When I first started programming in .NET I used try/catches all the time. I am finding lately though I rarely ever use them for web applications. My exception (no pun intentended) is unmanaged code that could potentially create a memory leak such as com objects. Are they really needed anymore or do they just clutter things up?

UPDATE: Assume custom errors are being used to take care of the ugly stack trace page.

+18  A: 

Here's the answer in the form of a question

How do you expect to do error handling if you don't catch exceptions?

Exceptions (rightly or wrongly) are the error mechanism of the .Net language. You simply cannot write an application which both ignores exceptions and has sufficient error handling. It's ingrained into the framework and cannot be avoided

JaredPar
Event log records the error and custom error page gives a friendly message. LINQ commit function makes sure that the transactions go across the line in a batch, and roll back on failure. Where is the issue?
Al Katawazi
Does the Event Log record enough information? You using AJAX at all? The custom error page doesn't work very well with Ajax last I checked
JoshBerke
+1 well said Jared
JoshBerke
@Al The issue is that you are completely ignoring the ability to FIX the program. Your program is offloading all of its error handling onto the environment, which means you could be leaking memory like a sieve, and never be able to catch that.
Awesome answer! Is there something like "vote as best answer"? :-)I was also thinking like WTF when I first saw the question...
ionut bizau
@JaredPar: Yes, they're the error mechanism, but if you can't actually _handle_ the error, then don't catch it. Usually, the existing mechanisms (ASP.NET Health Monitoring and Custom Error Pages) will handle the exception better than the developer can. Only when the developer can do better should exceptions be caught.
John Saunders
Agree: oyu must handle somewhere. Disagree: please do not encourage programmers to try/catch all the time. Ben Scheirmans answer is better advise. Most programmers throw too little and catch too much.
Teun D
+2  A: 

Exception handling logic is still plenty useful in the web domain when used in the right places. Your back-end code may need to connect to a database, communicate with a different service, or call your own exception-throwing logic. In any of these cases, you'll want to catch an exception and communicate that to the user.

For instance, let's say you need to communicate with a database that is down. You'll want to send that information back to the client page to inform the user your site is currently down or experiencing problems. Unless ALL of your external calls return friendly status codes (which is highly unlikely and cumbersome), you'll need to rely on exceptions.

j0rd4n
+3  A: 

Try catches are an important aspect of programing and should not be ignored; however you don't need to have every statement wrapped in a try catch block. Generally I use the following rules:

  1. If this is a windows application, then the entry point should always have a try catch as a last ditch attempt to catch any exceptions. In asp.net this is done using the OnError of the Application objects.

  2. If I know that a specific exception can be thrown and I want to handle it. For example if you try and send an email with an invalid format for the send to email address you'll get a format exception. I might catch that specific exception and notify the user that the email they are using is not valid.

  3. If you have additional contextual information that you want to log that would be useful for troubleshooting. For example, while my global asp.net error handler might log all the form variables, perhaps I want to capture values of certain objects.

  4. If you want to modify the flow of the application, for example in ASP.Net if I want to display an error message when my ajax call fails, I shouldn't let the error bubble to my unhandled exception routine.

  5. If there are resources which need to be cleaned up, then I use a try catch finally, or a try finally block to ensure my resources are closed up.

JoshBerke
+3  A: 

use Finally

That way you can use try-catch and still clean up your unmanaged memory.

And, while it is true that you should avoid try-catches when they aren't necessary, (i.e. check if x == null instead of letting x throw NullReferenceException) You will find that especially on web applications, there are tons of times were try-catch statements are absolutely required because sometimes you will lose connections, or the user will do the wrong thing, and exceptions will be thrown whether you like it or not.

In those cases, you want to catch them, bundle them up in some logging, and then either gracefully continue, or release your resources and rethrow.

+21  A: 

I find that junior programmers use try/catch WAY too heavily. The decision to use try/catch should boil down to these simple rules:

  • can you handle the error? (perhaps this means to try again, or use different settings, return substitute values, etc)

  • can you provide a better error message (more detail) ?

  • do you need to log this specific error? (keep in mind that all errors should be logged at the highest level -- for example in the global.asax file in Application_Error method)

  • do you need to clean up/dispose resource used within an operation, such as a database connection or transaction?

If you answered yes to any of these, then sure, use try/catch. If you said no, then you can safely just allow an error page to be displayed and have the global error handler log it.

If you do intend to log or clean up resources, but still let the exception pass through, make sure you use throw; and not create a brand new exception. Doing so will eliminate your stack trace and basically give the error no context.

Just found this excellent quote from Ayende that seems to put it very nicely:

Exception handling should appear in exactly two places:

  • When an error is expected (making a web request call, for example) and there is some meaningful behavior to be done in the case of a failure (such as retrying after some delay)
  • On a system boundary, in which case you need to make a decision about how you are going to expose the error to the outside world.
Ben Scheirman
I completely agree
Al Katawazi
If you are just cleaning up resources, you probably shouldn't use catch at all, just use finally instead.
recursive
Another good rule of thumb: if you cannot think of a more specific type than Exception, you probably shouldn't catch at all.
Teun D
A: 

You should have a try/catch around any statement that might throw an exception that you can reasonably handle. By reasonably handling, I mean logging, cleanly closing down the application, sending an email, fixing the problem if possible, alerting the user, adding information to the exception and rethrowing, etc. If you can't do any of these things in a way that makes sense, then why catch it? With that said, there are times I delegate catching an exception to a higher level function, but rarely do I ever let an exception go completely uncaught. At the very least I can usually log an error, alert the user, and close the application.

Brad Barker
A: 

I would add that one of the key reasons for having exceptions is to enable your application to handle errors at the most appropriate level in the code to do something sensible with it. Exceptions provide a clean way to pass information back up the call stack to enable this.

Deciding on what layer to handle various exceptions is a key decision in your application design. The type of application your are developing will affect the decision.

E.g. When developing a web or desktop application, it may be totally acceptable to handle the majority of exception types at a very high level only. This technique can save a lot of code when your application really cannot do much about the error anyway, and just needs to tell someone and log it.

However, in a mission critical, multi-threaded server application, you are likely to need fine grained control over exceptions in order to deal with them appropriately and keep the threads spinning no matter what.

saille
A: 

Only use Catch(SomeException ex) if you are willing to handle SomeException. Exceptions which you are not willing to handle are counted as unexpected. Use unit tests to exercise your code and find the expected exceptions.

The following example is wrong because you're not doing anything with the exception

try
{
    // Some code that throws a exception
}
catch(Exception ex)  // Only handle this type of exception in the User interface.
{
    throw;     // Incorrect, throwing exception for no reason
}

This is better:

try
{
    // Some code that throws a exception
}
catch(System.Data.UpdateException ex)
{
    LogException(ex);
    string message = DecipherException(ex);
    throw new MyException(message, ex);     // Incorrect
}

And follow up with (in the user interface)

try
{
    // Code that throws a exception
}
catch (MyException myEx)
{
   // Use a nice dialog which shows the user how to fix the error
}
catch (Exception ex)
{
    // Unhandled scenario - usually fatal because you didn't expect it to happen.
}
Matt Lynch