Establishing Single Exit Points

Your COBOL program receives control in one or more places: It returns control at some other point, whether by STOP RUN, EXIT PROGRAM, or GOBACK. This point of exit should be as close as possible to the point of entry, so that it is immediately clear where the flow of control stops.

(We are not concerned here with abends. They do not return control, they terminate control.)

Example

Consider the following code fragments:

 PROCEDURE DIVISION
*
 0000-MAINLINE.
     PERFORM 1000-BEGIN-JOB.
     PERFORM 2000-PROCESS-RECORD
        UNTIL END-OF-FILE.
     PERFORM 3000-END-JOB.
*
 1000-BEGIN-JOB.
* open files, read header, get date and time, etc.
...
*
 3000-END-JOB.
* write trailer, close files, display record counts, etc.
     STOP RUN.
From looking at the first page of the PROCEDURE DIVISION, you can't tell what happens at the end of 0000-MAINLINE. Unless you look at the innards of 3000-END-JOB, you might wonder if control falls through into 1000-MAINLINE.

It would be better to move the STOP RUN up into the topmost paragraph where it is immediately obvious. Such a change would not affect the behavior of the program, but it would make it easier to recognize the flow of control.

Another example

The previous example is standard, boring code, and is not likely to confuse anyone even in its original form. Minor transgressions are tolerable in a program which is otherwise well structured.

However, we are concerned about cases where the flow of control is not so obvious. It may be tangled spaghetti code. Alternatively, it may be a subprogram where the structure is less standardized. There may be multiple entry points.

Suppose the top-level paragraph branches to one of seven different paragraphs, either by PERFORM or by GO TO, and that each of these paragraphs always exits with GOBACK.

Take the GOBACK out of each of these paragraphs and move it to the code which invokes the paragraph. For example:

     ELSE IF LINK-ACTION-INSERT
        GO TO 1700-INSERT-RECORD
becomes:
     ELSE IF LINK-ACTION-INSERT
        PERFORM 1700-INSERT-RECORD
        GOBACK
Once all branches contain a GOBACK, you can consolidate them into a single GOBACK at the end of the top-level paragraph.

Harder Examples

The main reason to move the exit point close to the entry point is to make it clear whether the first paragraph falls through into the second.

If there is no simple, easy way to meet this goal, don't worry about it for now. As you continue to untangle the rest of the program, it will eventually become easier to untangle this part.

Meanwhile, try to analyze the logic to determine if such a fall-through occurs. Document your conclusion, or maybe your inability to reach a conclusion, with a prominent comment at the bottom of the first paragraph. This comment will make it easier to apply the next transformation: changing fall-through logic into GO TO logic.

A Final Perversity

One way for a program to exit is to fall off the end. If control reaches the end of the last paragraph, and no PERFORM is active, then the program terminates.

If you can't prove that such a thing won't happen, then add an extra paragraph at the end of the program, containing nothing but GOBACK, EXIT PROGRAM, or STOP RUN.

This addition is guaranteed to have no effect. Either it is unreachable or it merely makes explicit what already happens anyway. In the first case you will eventually delete it. In the second case you will eventually make it the target of an explicit GO TO, which you will later eliminate.


[style forum]COBOL Style Forum [spaghetti]Spaghetti code [stage]Next stage
[home]COBOL Home