Should I catch exceptions only to log them?

The general rule of thumb is that you only catch an exception if you can actually do something about it. So at the Business or Data layer, you would only catch the exception in situation's like this:

try
{
    this.Persist(trans);
}
catch(Exception ex)
{
    trans.Rollback();
    throw ex;
}

My Business/Data Layer attempts to save the data - if an exception is generated, any transactions are rolled back and the exception is sent to the UI layer.

At the UI layer, you can implement a common exception handler:

Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);

Which then handles all exceptions. It might log the exception and then display a user friendly response:

static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
    LogException(e.Exception);
}

static void LogException(Exception ex)
{
    YYYExceptionHandling.HandleException(ex,
        YYYExceptionHandling.ExceptionPolicyType.YYY_Policy,
        YYYExceptionHandling.ExceptionPriority.Medium,
        "An error has occurred, please contact Administrator");
} 

In the actual UI code, you can catch individual exception's if you are going to do something different - such as display a different friendly message or modify the screen, etc.

Also, just as a reminder, always try to handle errors - for example divide by 0 - rather than throw an exception.


It's good practice is to translate the exceptions. Don't just log them. If you want to know the specific reason an exception was thrown, throw specific exceptions:

public void connect() throws ConnectionException {
   try {
       File conf = new File("blabla");
       ...
   } catch (FileNotFoundException ex) {
       LOGGER.error("log message", ex);
       throw new ConnectionException("The configuration file was not found", ex);
   }
}

Unless you are going to change the exception, you should only log at the level where you are going to handle the error and not rethrow it. Otherwise your log just has a bunch of "noise", 3 or more of the same message logged, once at each layer.

My best practice is:

  1. Only try/catch in public methods (in general; obviously if you are trapping for a specific error you would check for it there)
  2. Only log in the UI layer right before suppressing the error and redirecting to an error page/form.

Definitely not. You should find the correct place to handle the exception (actually do something, like catch-and-not-rethrow), and then log it. You can and should include the entire stack trace of course, but following your suggestion would litter the code with try-catch blocks.