The way we log information provides a good hint for the way we can handle exceptions. Although there are many schools for the classification of log information, I will show one that seems to make sense from the point of view of exception handling.

Level Meaning
Information

Nothing has been found to be unexpected, but information about progress of the program will be logged anyway.

Warning

The function was able to perform the expected procedure, but it is likely that there is something wrong.

Recovered Error

An error occurred. The function was not able to perform its process, but the function recovered the state of the system to the point when the function was called (as if the function was not called).

Fatal Error

An error occurred, and the system is in an undefined or inconsistent state.

Let’s look at each of these one by one.

Information

This kind of log is just used to record information about the progress of some procedure. It doesn’t necessarily imply any problem. Such information should not be passed to the caller with the use of exceptions, since raising an exception causes loss of the returned value and disruption in control flow.

Warning

This kind of log implies that there might be a problem in the system. The function, however, was able to do whatever it needs to do. Such warnings may be logged in the following situations:

  • the function was passed unusual argument values;
  • there was unexpected data in a file;
  • etc.

Such information should not be passed to the caller with the use of exceptions.

Recovered Error

For a system to continue to be reliable in the event of an error, it is preferable for a function to restore the state of the system to the point when the function was called. For example, if a function writes to a file, it should keep the original file, so that the file can be restored when an error occurs. If the function uses a database, it should use transactions, so that the database can do the recovery for you. Whatever the function modifies should be put back to its original state.

A recovered error can be propagated to the caller with the use of exceptions.

Fatal Error

In some cases, a function may not be able to restore the system’s state. Or, the system might already be in an inconsistent state even before the function was called. Many assertions indicate fatal errors.

Fatal errors can be propagated to the caller with the use of exceptions. In some cases, the system may be in such a hopeless state, that it may choose to crash to avoid any more damage. This behavior might be chosen, if recovery is too expensive considering the likelihood of an error. In many implementations, OutOfMemoryError causes crashes, be it unintentionally [i].

In any case, as a rule, errors should be logged as well as thrown, since they could be lost during propagation.


[i] Despite conventional “wisdom” not to catch OutOfMemoryError, there are cases when such error is recoverable, as in the case when a function tries to allocate a very large amount of memory.

Contents

Background

Review of Exception Handling Basics

The Requirements

The Three-tiered Exception Handling Architecture

Summary