Kbase P25943: How to deal with Error Processing ?
Autor |
  Progress Software Corporation - Progress |
Acesso |
  Público |
Publicação |
  4/13/2005 |
|
Status: Unverified
GOAL:
How to deal with Error Processing ?
FACT(s) (Environment):
Progress 9.1x
OpenEdge 10.x
FIX:
Professional applications need to handle errors and unknown situations in a consistent and controlled manner. For the most part I am talking about application errors here while touching on some system error situations. Managing these problems such that the application can either recover or at least exit gracefully is what makes a robust application. Below are some areas for concern and some options for error processing. This is by no means an exhaustive list but gives a decent grounding in what error handling is about.
1. Error control for blocks in Progress
Before any effort at error management can be attempted you need to be aware of what Progress brings to the table to help you. These tools include error control options for block constructs - DO, REPEAT, FOR EACH, PROCEDURE/TRIGGER, the database transaction services, and your own programming efforts.
These block properties allow you to tell Progress to take specific block level actions - UNDO then RETRY, LEAVE, NEXT or RETURN when the Progress ERROR condition is raised. To use in combination with RETRY progress provides the RETRY function so you can test for the occurrence of a RETRY within a block.
For a complete discussion of these features see the Programming Handbook - Chapter 3 & 4 (v9) Block Properties, Condition Handling and Messages. In general, the Programming Handbook should be REQUIRED reading for all Progress developers. Also critical to this equation is the ON ERROR phrase. Related conditions are ENDKEY, STOP and QUIT which have ON phrases as well.
In addition to the error handling itself you need to be aware of the impact on transactions and subtransactions when an error occurs. It is the combination of error handling and transactions that enable you to write applications that maintain data and application integrity. An EXTREMELY simplified description is that the work done within the transaction scope is undone so that the data in the
database is returned to its previous state. For the moment lets just say that you need to use error and transaction processing to control what "Unit of Work" gets done or undone with regards to DB interaction.
The last category of error handling is handled by your own application logic. This is accomplished by using all that is presented above to control lower level language situations and your own programs/statements to verify and handle application based validations and processing control.
2. Using NO-ERROR and the ERROR-STATUS handle.
With the advent of version 7 Progress added the ERROR-STATUS system handle. This handle allows you to use the NO-ERROR option on (many) statements and then test the status of the ERROR-STATUS attribute ERROR. This in combination with the other attributes and methods of ERROR-STATUS allow you the developer to trap the default Progress errors and take control of the error management.
With the advantage of hindsight it seems obvious to me that having an ERROR-STATUS handle without having ERROR events or "Exceptions" (see below) is only a partial solution. As it is implemented today you must constantly scatter checks for errors if you want to manage the error conditions yourself rather than take the Progress default action.
3. Decision branch management
Statements such as IF and CASE that affect the control flow of your code need to have blocks/statements for handling errors. The CASE statement comes with an OTHERWISE construct to act as a catch all in case the variable used doesn't meet any of the WHEN selections. For the IF/THEN you can also specify an ELSE. Not every instance of these constructs requires handling the "other" condition but you should be very careful to be sure when it is acceptable to continue when the standard branch is not executed.
An example -
IF AVAILABLE(table) THEN DO:
...
END.R>ELSE ...
This else condition is often an error in the data being processed yet it falls into the "Never should happen" category. Often this else condition is left off with all the processing happening in the available block. This kind of silent treatment of error situations is very dangerous. If some other part of the application failed to create the appropriate records then areas that use those relations need to tell you things are not right. The same is true of CASE blocks. They often receive the data to be "switched" on from an external source. If new data has been used but the case hasn't been updated then usually the case statement needs an OTHERWISE so it can display a message or at least write an error log entry for later review.
4. Simple system error situations
Some error situations can be caused by problems external to the application. Many of these are unavoidable and cannot be managed within the application. Some however, such as not being able to find a file or access an output destination are situations you can detect and plan for in the application. When interacting with the environment outside of Progress it is wise never to assume an operation will be successful. Use the NO-ERROR option and test for the success/failure of the statement as needed to manage the processing. Also use the OS- commands to keep as much control within the Progress environment as possible.
5. Some basic error techniques
Categorize the error types. Use these classifications to help decide the severity of the problem - Fatal, Warning, Advisory... and respond accordingly.
Errors can be displayed as messages, entered into a db or text log file, or perhaps (in the future) even sent as an event to some administrative process or message center. Remember though that a db based log is going to be affected by the other transaction processing and data handling around it, causing potential conflicts and side effects.
Use include files to encapsulate error testing and responses to help standardize the way you manage the error control implementation.
Since V7 and higher the MESSAGE statement now has options to be viewed as a standard ALERT-BOX with types such as ERROR, WARNING, INFORMATION that can even return limited input from the user on what to do.
6. Exceptions
Some of the more modern language implementations are now supporting "Exceptions" as a method of error handling. This is a powerful capability that helps provide a structured way of handling error conditions without the constant check/handle
requirements of older language implementations. It allows you to define an error condition, give it a name, and "Raise" it similar to the Progress ERROR condition. The exception then propagates up through the layers of blocks until it is handled or the application terminates. A good example of a low level exception is a divide by zero math operation. You do not want to check every divide operation but you need to handle the error consistently. With such errors recovery may not be possible but at least proper cleanup and message display can be accomplished. Application exceptions are much more likely to be recoverable - No vendor terms available could even trigger processing to gather the information required and create the appropriate record without leaving the current context within the application..