| iMatix home page
| Libero home page | Libero documentation
| << | < | > | >>
Libero Libero
Version 2.32

Using Exceptions

Exceptions are basically a tool to reduce the size of a dialog. Instead of defining an extra state to handle a decision (typically the Ok/Error outcome of some work), you assume it's Ok, and carry on with the next action module directly. If it's Error, you raise an exception, which is like a jump to that event in the same state. Any module in progress is completed, but any further modules are not executed by the dialog manager. It's often useful to put exception events into the Defaults state, since certain kinds errors can occur in any state. So you can raise an exception in any code, and know that it will be handled the same way, in the Defaults state. Sometimes we override such central handling by defining specific handling for an exception event in a specific state. Exceptions are thus used to make small control steps within a state (error handling is just one specific example). Such control steps can be used for any purpose. Overusing exceptions leads to impenetrable dialogs.

Exceptions are a powerful technique that make your dialog leaner and meaner. In a typical dialog many actions do some work that may result in an error condition. For instance, an action that reads some data from a file may discover that the file is no longer accessible due to a 'hard' error (protection, disk crash, insufficient memory,...). Without exceptions, the only way to handle such possibilities is to define additional states - for instance, 'after-reading-data', that check the outcome of each action with a questionable outcome.

This quickly leads to dialogs with dozens of states that serve only to keep track of these minority cases. In the majority of cases, the errors never happen. This means that the main logic of the dialog can get diluted by all the extraneous states. With exceptions, you write the dialog as though errors were incidental. When an error happens, you treat it as a special case, as an 'exception'. Otherwise, the dialog carries on normally.

Most real dialogs use exceptions, sometimes heavily, for two reasons:

  1. Exceptions are a good way to handle errors.
  2. Exceptions can make a complex dialog simpler.

A module raises an exception by setting the variable Exception-Raised to a 'true' value. The module then supplies an event in The-Exception-Event. Quite often I use an event called 'Exception' when I use an exception event to handle fatal errors. This is how we raise an exception using an event called Exception-Event in various languages:

C and C++:

    exception_raised = TRUE;
    the_exception_event = exception_event;

80x86 assembler:

    mov exception_raised,1
    mov the_exception_event,exception_event

Korn Shell:

    exception_raised=TRUE
    the_exception_event=$exception_event

COBOL:

    MOVE "YES" TO EXCEPTION-RAISED
    MOVE EXCEPTION-EVENT TO THE-EXCEPTION-EVENT

Visual Basic:

    exception_raised = True
    the_exception_event = exception_event

In most languages (except COBOL) Libero provides a function or macro 'Raise-Exception' that does the above. See the later sections on using Libero in each language for details.

The dialog normally executes all the action modules for an event-in-state, one by one, then switches to the next state for the event. An exception interrupts this flow. The dialog handles exceptions in two steps:

  1. It checks Exception-Raised after executing each module. It this variable has become 'true', it stops and checks the value of The-Exception-Event.
  2. It looks for The-Exception-Event in the current state (or Defaults), then executes the action modules for that event. These modules can in turn raise an exception.

When a module raises an exception, the dialog does not care what the next state was supposed to be. This is no longer important, since the exception event will determine its own next state.

Libero also allows a short-cut: if the exception event is the same as the current event, you don't need to supply it. If you just set Exception-Raised but not the event, the dialog loops back to the same event in the same state. Honestly, I don't use this very often. I prefer to separate exception events from 'normal' events.

Take the example of three actions which the dialog executes in series. First, it reads some data from a file. Then it parses and converts the data. Lastly, it writes the data to another file. Each of these actions has a normal outcome, and possible exceptional outcomes (error during reading, invalid data, error during writing, etc.). If we write the dialog without exceptions, we need these three states:

Before-Reading:
    (--) Ok                         -> After-Reading
          + Read-Data-From-Input
    (--) Error                      ->
          + Terminate-The-Program

After-Reading:
    (--) Ok                         -> After-Parsing
          + Parse-and-Convert-Data
    (--) Error                      ->
          + Terminate-The-Program

After-Parsing:
    (--) Ok                         -> Another-State
          + Write-Data-To-Output
          + ...
    (--) Error                      ->
          + Terminate-The-Program

In this case, Read-Data-From-Input does something like this (I use C as the language):

MODULE read_data_from_input (void)
{
    if (read_from_file (file, input) != NULL)
        the_next_event = ok_event;
    else
        the_next_event = error_event;
}

By using an exception event (here, Error), we can collapse the three states into a single state:

Before-Reading:
    (--) Ok                         -> Another-State
          + Read-Data-From-Input
          + Parse-and-Convert-Data
          + Write-Data-To-Output
          + ...
    (--) Error                      ->
          + Terminate-The-Program

Read-Data-From-Input now does this:

MODULE read_data_from_input (void)
{
    if (read_from_file (file, input) == NULL)
        raise_exception (error_event);
}

Some hints about using exception events:

  1. Don't over-use exceptions. What you gain from a more compact dialog you can loose in unclear logic. Remember that exceptions should be used for error handling and special cases, not for primary logic.
  2. Choose good names, and use one exception event for the same purpose everywhere. For instance, use an exception event Fatal-Error to indicate a fatal i/o error that causes the dialog to halt.
  3. The Defaults state is an ideal place to handle exceptions which may occur in many places. However, do place specific exception handling in any state where it is useful.


| << | < | > | >>
| Using Libero | The Dialog File Syntax | Libero Options | Using Exceptions | Using The Defaults State | Using Sub-Dialogs | Using Super-States | Using Templates | Using Get-External-Event | Efficiency | Care and Feeding of Dialogs | When To Use Libero
iMatix
Copyright © 1996-97 iMatix