Progress Programming Tips

By Rod Gaither (rdg@worldinfo.com)


PPT-19  Emulating exceptions in Progress - Part 1 of 3

Tip:

[Warning - another long topic]

Before we start I want to make a disclaimer or two.  You do not
have exceptions in Progress today.  The best you can hope for
is to achieve some or all of the benefits that exceptions provide with
hopefully a reasonable effort.  They key here is what you think is
reasonable effort given the resulting benefits.  Part 1 of this post
is the basic techniques.  Part 2 is how to handle the recovery/exit
portion.  Part 3 will (hopefully :-)) be a small, working, example.

The goals are -

1.  Create a structured, standardized, error definition set.

2.  Manage the process of catching errors with as little impact
as possible on the program flow.

3.  Minimize and centralize the code required to respond to and
report on errors of different classifications.

4.  Allow for layered recovery or exit options.


The error list -

To start with create an include file that contains all the
general error setup information.  Part of this setup information
is a (probably) long list of error type preprocessor definitions.
These definitions can act as they do in 3gl languages today. They can
map a mnemonic string to an error type number.

&GLOB  E_REC_LOCKED    100
&GLOB  E_REC_UNAVAIL   101

The error numbers point to a generic error type definition.
These definitions could be managed in any number of ways.  An
ascii file, in the db, loaded into a temp-table etc.  This
definition contains the classification information, the
message pattern or coded description.  An example might be -

100 "Info" "The selected  record is in use by another user."

The logic that responds to such an error could take specific
action based on the "Info" type of error - perhaps put up an
alert box with the description, after it was tailored with a
table name parameter.

Remember you now have standard Progress error descriptions
available to you via the ERROR-STATUS handle.  It may not be
necessary to provide custom descriptions for every kind of
error but rather point to the real progress error and use its
text.


Catching the errors -

To minimize the impact of error checking create a special
include file - perhaps err.i that takes as parameters the error
number and a parameter list.  An error check reference would
appear as -

{err.i &num={&E_REC_LOCKED} &list="Customer"}

This single line entry can be included without disrupting the
logic flow as most of the error raising logic is hidden and yet
the mnemonic provides enough information to know what kind of
error is being checked for.

Inside err.i would be code to make a call to the standard error
procedure passing the appropriate parameters.  It would also need to
include a return code and processing logic to respond to simple
signals such as - continue, error, return, retry, ...? For this to be
effective the program must be structured such that any err.i include
file reference can affect program control. Additional parameters could
be used for any context sensitive debugging information that needs to
be passed on to the error handler.


Managing the error lookup and handling -

This procedure needs to know how to look up an error entry,
respond with the appropriate alert message, write out any error
logging or debug info, and return an action code.

A few options spring to mind to locate the standard error
processing logic.

1. A special internal procedure in a standard persistent
library available to the whole application.

2. A trigger code block that is hooked to one of the developer
events - U1 - U10.  This code could be included as part of the
setup include file.  Using an event requires the parameters be
put someplace - local variables, private-data, etc. for the
trigger block to reference since passed parameters are not
possible.

3. A small internal procedure dedicated to this function and
again included in the setup include file.

The first option has the smallest footprint in every program
instance but makes getting some context information more
difficult.  Depending on the context information it could bloat
the err.i in setting up info to pass along for every error check. This
would then defeat the benefits of not having the error procedure local
to each instance.

The second and third options require the error handling code to
be in every procedure, which depending on what you put in there
could be considerable.  They do however make for a small err.i
for each individual reference and simplify the ability to collect
context information considerably.


Managing recovery and exit actions -

Of all of the parts this is the hardest.  The goal requires
that you be able to put {err.i} references wherever you like
and without having disruptive impact on the source code flow.
Since many pieces need to work together to make this possible
and the location of the {err.i} references impact the block
handling requirements this section of the topic will be covered
in detail in Part 2.

Wisdom:

Every development effort has a point of diminishing returns.
Recognizing this point and finding the balance between effort and
rewards is one of the lessons experience teaches.

Rod Gaither                  | rdg@worldinfo.com
World Information Systems    | (910) 333-2580  Voice
Greensboro, NC               | (910) 333-2584  Fax