Most programmers who use exception handling use it at the local level; preventing errors from propagating out of a method or class, or preventing the premature termination of a loop when one iteration’s operation fails.
But every program needs a more cohesive approach to errors than simple local error trapping. The typical program consists of several levels, each of which has its own needs for error handing and for passing error information to higher layers. Those layers are:
1. Hardware and operating system
2. VCL and third party components
3. Generic components developed at your installation
4. Application-specific components developed at your installation
5. Application data modules
6. Application user interfaces
Of these levels, only level 6 can safely and reliably decide how to report errors and exceptions to the users. Therefore, the key focus of error management must be to promote errors up to level 6, or to at least up to where they can be logged to databases or files at level 5. However, it is best to let level 6 decide to use the resources of level 5 for logging as needed.
From a support perspective, errors must be managed so that when a user reports an error to support, the support personnel can quickly determine the cause, location, and context of the error. This can be managed by a simple strategy.
It is important to remember that the meaning of an error at level 3, the first level over which you have any control, is quite different from the meaning of the error at level 6. At level 3, the error may be EListError, but at level 4 it is “Attempt to insert a service type in the service type list failed”, at level 5 it is “Update of Package record failed”, and at level 6 it is “Unable to ship package.” To the user, the level 6 perspective is the most relevant, and it is usually the message which is displayed. The problem is that the support person needs to know more, and the programmer needs to know even more to fix the problem.
The solution to this problem is to cascade the exception up through the levels, with each level adding its context to the front of the message. For instance, if all the levels were in one method, they would look something like this:
try // Level 6
{
try // Level 5
{
try // Level 4
{
try // Level 3
{
DoSomethingWithList();
}
catch (Exception &VCLException)
{
throw new Exception(“Unable to “
DoSomethingWithList due to: “+
VCLException.Message);
};
}
catch (Exception &VCLException)
{
throw new Exception(“Attempt to “
“insert a service type in the “
“service type list failed due “
“to: “ + VCLException.Message);
};
}
catch (Exception &VCLException)
{
throw new Exception(“Update of “
“Package record failed due to: “+
VCLException.Message);
};
}
catch (Exception &VCLException)
{
Display(“Unable to ship package due ”
“to: “ + VCLException.Message);
};
Note that the final level actually displays the message. The resulting message looks something like:
Unable to ship package due to: Update of Package record failed due to: Attempt to insert a service type in the service type list failed due to: Unable to DoSomethingWithList due to: EListOutOfBounds (-1)
The first part of the message is what is most important to the user, but all of the information needed by support and the programmer is present as well.