Stages of Transformation

When you're untangling spaghetti code, there is always a danger that your changes will have unintended consequences, because the flow of control may not be obvious.

One problem is that a variety of COBOL constructs may invoke any given paragraph:

You can identify these constructs by searching for the paragraph name.

More insidiously, a paragraph may receive control directly from the preceding paragraph without being invoked by name. In order to know how a given paragraph receives control, you need to know how the previous paragraph receives control -- and so forth recursively all the way to the top of the PROCEDURE DIVISION.

Likewise you need to know what receives control when execution reaches the end of the paragraph. Depending on how the paragraph received control in the first place, control may or may not fall into the following paragraph.

Until you have eliminated or at least identified all the cases where control falls directly from one paragraph into the next, it is dangerous to rearrange paragraphs or add new ones. Such a change may disrupt the flow of control in unexpected ways.

It is essential to eliminate all such fall-through logic as soon as possible.

Coping with Sections

The use of both sections and paragraphs in the same program adds more ways to obscure the flow of control.

While we can suggest a few coping strategies, the rest of this discussion ignores the possible existence of sections. Otherwise the issues would be just too complicated to address in a general way. The most we can recommend is an ad hoc approach. If your program has sections and you can't get rid of them, muddle through as best you can.

The Stages

The following stages represent a logical series of transformations. Each stage makes the later stages safer and more manageable.

These stages will not solve all your problems. You will probably have to exercise some ingenuity at some point (and ingenuity is always error-prone). Rather, the stages provide a conceptual framework which will reduce the need for ingenuity.

It is neither necessary nor desirable to follow these steps in a rigid sequence. Use your judgement. Be opportunistic. In particular, applying one of the later transformations may create a new opportunity to apply one or more of the earlier ones. That's normal. You may be working at several different levels in different parts of the program.

Eliminate ALTER

In later stages we will get rid of GO TOs. Those techniques won't work with GO TOs which are subject to ALTER.

Eliminate GO TO DEPENDING

Transform each instance into a case structure with ordinary GO TOs, to which we can later apply the standard techniques.

Eliminate trivial THRU clauses

Be greedy and knock off the easy ones first.

Eliminate serial THRU clauses

These are more tedious but still easy.

Eliminate trivial GO TOs

More easy ones. This step may render some THRU clauses trivial (or serial). If so, eliminate them.

Establish a single exit point for each entry point

This transformation makes it easier to apply the next one.

If you can't apply this transformation immediately in an obviously safe way, just be patient until the opportunity arises, as it surely will.

Whenever possible, transform fall-through logic into GO TO logic

What??? You should add more GO TOs??? Relax. It will all work out.

Mark all remaining instances of fall-through logic

Tend to them later, as opportunities arise. For now, insert big prominent comments so that you won't disrupt the fall-through by accident.

From now on it's safe to add or rearrange paragraphs, as long as you don't disrupt the remaining fall-through logic.

Eliminate GO TOs by adding new paragraphs

On an ad hoc, case-by-case basis you may be able to pull chunks of code out into separate paragraphs, so that you can eliminate some GO TOs more easily.

Consolidate common GO TOs

If a paragraph always exits by one of several GO TOs, and they all GO TO the same destination, combine the GO TOs into a single unconditional GO TO at the end of the paragraph. Then you can apply the next transformation.

Let GO TO's percolate upwards

If a paragraph has a single unconditional GO TO at the end, move the GO TO out of the paragraph and into whatever code invokes the paragraph. This transformation may create an opportunity to apply the previous one.

Transform loops to use PERFORM UNTIL rather than GO TO.

These transformations are potentially more complex and more error-prone than the rest. Proceed with caution.

Keep going until the GO TOs and THRU clauses are gone.

There may be a few spots which don't fit the simple patterns, and you can't readily transform them mechanically. Often, by rearranging the code, you can transform part of the code into a simple pattern, and work on the rest in a later step. If all else fails, figure out what the code is doing.

Eventually all GO TOs either disappear or percolate to the top. Finally you might have GO TOs whose destination ends in a GOBACK or similar construct. Let the GOBACK percolate upwards as if it were a GO TO; then the last GO TOs can disappear.

Restructuring

Your program is now structured in a formal sense. That is, it has no GO TOs or PERFORM THRUs.

However, it probably isn't well structured. It probably uses cryptic flags and switches to control loops and case structures. Some of your paragraphs are probably not very cohesive, or they don't have very good names. Even if you have been fixing some of these problems along the way, the job is probably not complete.

By the time you get this far you have reached a better understanding of what the program does. You are in a good position to:

Whatever changes may be appropriate, neither you nor anyone else need be afraid to make them. You have transformed spaghetti into ravioli.
[style forum]COBOL Style Forum [spaghetti]Spaghetti code [stage]First stage
[home]COBOL Home