Best Practices for Exception Management in Java or C#

Best practices for exception management in Java or C#

It seems odd to me that you want to catch exceptions and turn them into error codes. Why do you think the caller would prefer error codes over exceptions when the latter is the default in both Java and C#?

As for your questions:

  1. You should only catch exceptions that you can actually handle. Just
    catching exceptions is not the right thing to do in most cases.
    There are a few exceptions (e.g. logging and marshalling exceptions
    between threads) but even for those cases you should generally
    rethrow the exceptions.
  2. You should definitely not have a lot of try/catch statements in your
    code. Again, the idea is to only catch exceptions you can handle.
    You may include a topmost exception handler to turn any unhandled
    exceptions into something somewhat useful for the end user but
    otherwise you should not try to catch each and every exception in
    every possible place.

How using try catch for exception handling is best practice

My exception-handling strategy is:

  • To catch all unhandled exceptions by hooking to the Application.ThreadException event, then decide:

    • For a UI application: to pop it to the user with an apology message (WinForms)
    • For a Service or a Console application: log it to a file (service or console)

Then I always enclose every piece of code that is run externally in try/catch :

  • All events fired by the WinForms infrastructure (Load, Click, SelectedChanged...)
  • All events fired by third party components

Then I enclose in 'try/catch'

  • All the operations that I know might not work all the time (IO operations, calculations with a potential zero division...). In such a case, I throw a new ApplicationException("custom message", innerException) to keep track of what really happened

Additionally, I try my best to sort exceptions correctly. There are exceptions which:

  • need to be shown to the user immediately

  • require some extra processing to put things together when they happen to avoid cascading problems (ie: put .EndUpdate in the finally section during a TreeView fill)

  • the user does not care, but it is important to know what happened. So I always log them:

  • In the event log

  • or in a .log file on the disk

It is a good practice to design some static methods to handle exceptions in the application top level error handlers.

I also force myself to try to:

  • Remember ALL exceptions are bubbled up to the top level. It is not necessary to put exception handlers everywhere.
  • Reusable or deep called functions does not need to display or log exceptions : they are either bubbled up automatically or rethrown with some custom messages in my exception handlers.

So finally:

Bad:

// DON'T DO THIS; ITS BAD
try
{
...
}
catch
{
// only air...
}

Useless:

// DON'T DO THIS; IT'S USELESS
try
{
...
}
catch(Exception ex)
{
throw ex;
}

Having a try finally without a catch is perfectly valid:

try
{
listView1.BeginUpdate();

// If an exception occurs in the following code, then the finally will be executed
// and the exception will be thrown
...
}
finally
{
// I WANT THIS CODE TO RUN EVENTUALLY REGARDLESS AN EXCEPTION OCCURRED OR NOT
listView1.EndUpdate();
}

What I do at the top level:

// i.e When the user clicks on a button
try
{
...
}
catch(Exception ex)
{
ex.Log(); // Log exception

-- OR --

ex.Log().Display(); // Log exception, then show it to the user with apologies...
}

What I do in some called functions:

// Calculation module
try
{
...
}
catch(Exception ex)
{
// Add useful information to the exception
throw new ApplicationException("Something wrong happened in the calculation module:", ex);
}

// IO module
try
{
...
}
catch(Exception ex)
{
throw new ApplicationException(string.Format("I cannot write the file {0} to {1}", fileName, directoryName), ex);
}

There is a lot to do with exception handling (Custom Exceptions) but those rules that I try to keep in mind are enough for the simple applications I do.

Here is an example of extensions methods to handle caught exceptions a comfortable way. They are implemented in a way they can be chained together, and it is very easy to add your own caught exception processing.

// Usage:

try
{
// boom
}
catch(Exception ex)
{
// Only log exception
ex.Log();

-- OR --

// Only display exception
ex.Display();

-- OR --

// Log, then display exception
ex.Log().Display();

-- OR --

// Add some user-friendly message to an exception
new ApplicationException("Unable to calculate !", ex).Log().Display();
}

// Extension methods

internal static Exception Log(this Exception ex)
{
File.AppendAllText("CaughtExceptions" + DateTime.Now.ToString("yyyy-MM-dd") + ".log", DateTime.Now.ToString("HH:mm:ss") + ": " + ex.Message + "\n" + ex.ToString() + "\n");
return ex;
}

internal static Exception Display(this Exception ex, string msg = null, MessageBoxImage img = MessageBoxImage.Error)
{
MessageBox.Show(msg ?? ex.Message, "", MessageBoxButton.OK, img);
return ex;
}

Is it a good practice to throw exceptions?

I'm sure this question had been answered elsewhere. But here are a few other links for reading:

  • Best practices for catching and re-throwing .NET exceptions
  • When to throw an exception?

From the book "The Pragmatic Programmer", the big question relating to the usage of exceptions is "What is Exceptional?".

In that section, I quote:

... exceptions should rarely be used as part of a program's normal flow; exception should be reserved for unexpected events.

While it is debatable whether or not to use exception in your case, I would say no - because you probably need to capture all possible input errors in one request and reflect back on the form for the user to correct those values.

Now that I recall, yes you should use exceptions here. This is how you code defensively. If you already expected valid arguments to be passed into the Customer class, then the code should throw exception to guard against invalid usage of the class (say for example, by another programmer). In that case, you should have another input validator to validate user's input to the application before reaching the Customer class.

Best practice Error handling

Using error codes to identify exceptions is not a bad practice.

It can be very useful in a production environment to keep the log files shorter and also it can be used to internationalize error messages.

On the other hand, when developing, it can be annoying to received an error code instead of a full blown error message with meaningful description. A developer has to go and check what the error code is about.

In one of my projects (using Java) I have developed an hybrid approach. My root exception has a constructor that uses an Enum class. The Enum class contains a list of error codes + default error messages. Something like:

public enum ErrorCodes {

VALIDATION_ERROR(5001, "One of the objects cannot be validated"),
RESOURCE_NOT_FOUND(4004, "The requested resource does not exist"),

The root exception has also other constructors, so that a developer can override the default message:

public CoreException(ErrorCodes _errorCode, final String message, final Throwable cause) {
super(message, cause);
errorCode = _errorCode.getCode();
}


public CoreException(ErrorCodes _errorCode, final String message) {
super(message);
errorCode = _errorCode.getCode();
}

When the exception is caught the Exception handler can decide (based on some configuration setting) to log the error and the message or the error only.
A more sophisticated error handler could also look up a message in a specific language from a resource bundle based on the error code.



Related Topics



Leave a reply



Submit