Distinguishing between good and bad programming standards

A COBOL Techniques Quiz and Forum

by Conrad Weisert, October, 1999

COBOL remains a popular programming language, not only for so-called "legacy" systems but also for new applications. We know that there's a huge difference between good and bad COBOL, but just what is "good COBOL"?

Here are eight rules taken from textbooks, course materials, and organizations' in-house standards manuals. Look them over and for each one tell us whether you concur or disagree. Specifically is it:

  1. a good rule that will contribute to program quality and programming productivity?
  2. an unnecessary neutral rule that will have little effect one way or another?
  3. a bad rule that will do more harm than good?
and give your reasons. If the rule can be improved by modifying or qualifying it, propose a change.

Some of them are controversial; let's get a constructive debate going.

Results beginning in April.

We posed these proposed standards some time ago. We've gotten a few replies representing both sides of the arguments. We've summarized the "answers" below. So far, the consensus is that all eight of these "standards" are unnecessarily burdensome and even harmful! Does that mean that detailed COBOL programming standards are ill-advised? Not at all; just these particular standards, found in the handbooks of real organizations,

It's not too late to register your opinions, so let us hear from you. We're also looking for more COBOL programming standards, good or bad. Send us the ones you particularly like or particularly hate. -- October, 2003

Return to IDI Home Page

Proposed COBOL programming standards

  1. Procedure names are to begin with a numeric prefix denoting the procedure's position on the hierarchical structure chart. For example, suppose:

    This one turned out to be surprisingly controversial. Several readers expressed enthusiastic support for this standard, reporting that their organizations had been following it for years. Others condemned it as an impediment to maintainability. I firmly support the latter opinion; this burdensome standard is indeed harmful and yields no obvious benefit.

    Procedures, like any kind of subroutine, should know as little as possible about their environment and about the context in which they're invoked. Restricting such knowledge facilitates not only future re-use but also modifications of this program.

    Embedding hierarchical position in the name is even worse, since the knowledge is scattered elsewhere in the program wherever the procedure is referred to. Programs often get restructured in the course of development and maintenance. What if we wanted to interpose a new procedure between the main program and 4-FILL-ORDER?

    Finally, the proposed standard assumes zero fan-in, that is that each procedure is invoked in only one context. Some readers also felt that the prefixes impaired natural code readability.

    A good way of coordinating a structure diagram and a long source code listing is to use the compiler-generated identifier listing. If your compiler doesn't produce one, then you can simply arrange the procedures in alphabetic sequence.

    Far better, of course, is to organize the COBOL program as separately compiled subprograms that don't have dozens of procedures in the same source code file. (The CALL verb was a late (1968) addition to COBOL, and by the time it was available many COBOL programmers had become accustomed to organizing their programs around one huge DATA DIVISION with parameterless procedures. Many experts attribute most of the difficulty in maintaining COBOL programs to that tradition.)

    -- CW, May, 2000, rev. March 2001

  2. All switches (or flags) are to be grouped together under the level-1 group item SWITCHES.

    Thank goodness, no one defended this silly proposal, which would force the programmer to put utterly unrelated data close together while spreading closely related data (e.g. TRANSACTION-COUNTER, TRANSACTION-END-SW ) apart over several pages.

    I have on my shelf a book called "Structured COBOL" (1986) that recommends this awful practice.

    -- CW, May, 2000

  3. Explicit name qualification is not allowed. Instead all data names are to be prefixed by the name of the level-1 record or structure in which they belong (abbreviated if necessary). For example:

  4. MOVE CORRESPONDING is not allowed.

    The above two standards are obviously related, since complying with standard #3 renders standard #4 irrelevant.

    Two readers wrote in support of these standards, but neither cited any benefit from complying with them. Actually, there are several huge benefits from not complying with them.

    • First, you have only one record description to maintain in your COPY library.
    • Second, you avoid those half-page (or longer) sequences of MOVE statements. (How many bugs have been the result of forgetting one of them?) When you add a new field to a record, all the procedural code that moves one copy of the record to another is automatically assured of being complete and correct if it uses MOVE CORRESPONDING. It's almost always easier and more reliable to change data rather than executable code, and it's certainly easier and more reliable to make one change than to hunt through a program making corresponding changes in many places. One line of code must be easier to understand and maintain than a half-page.
    • Finally, your code is just more readable. One of COBOL's design goals was to have English-like procedure syntax. No one says or writes "WS-" in front of every noun in English.

    I would not only not forbid the use of MOVE CORRESPONDING; I would recommend a standard requiring it wherever it makes logical sense.

    -- CW March 2001

  5. Every data name must describe the exact use of a data item in the real world of the application. Abstract or extremely general data names are not acceptable.

    While this practice makes sense in the context of huge monolithic programs, it breaks down as soon as we take a more modular approach to program structure. What a program module calls a particular piece of data depends upon the point of view of that program module. Abstract or extremely general names are, in fact, appropriate in a subroutine that performs a general, utility function, such as table look-up, display formatting, or data transformation.

    -- CW January 2002

  6. All tables must be maintainable by the end users through explicit table-maintenance transactions. Having to recompile a program to change a table entry is unacceptable.

    This is another well-intended standard that sometimes suffers in over-zealous enforcement.

    Of course a user-maintainable table is usually (but not always) preferable to a programmer-maintained one, but isn't any table better than a page and a half of IF statements comparing the same variable with consecutive constants?

    During a recent code-review walkthrough, someone pointed out that a table would simplify and shorten the program, only to have the programmer explain that the organization's standards prohibited him from using such a technique unless he also implemented a maintenance facility for the users!

    CW, June, 2001

  7. For any input file the program may contain only one READ statement; for any output file only one WRITE statement.
    At first this one generated less controversy than the above. Everyone thought it was a good idea to localize the program's interface to a file. Some pointed out that the most common structured code1 for processing a sequential input file uses a priming READ before the loop.

    On the output side, several readers pointed out that programs often need to write different records under different conditions.2 To move those records to a common area in order to invoke the unique WRITE operation with a PERFORM may be less understandable and more error prone than just doing the WRITE. Perhaps the prudent solution is to restrict output operations to a single subroutine.

    In one organization, this standard led to another one:

    1. Every WRITE must be by itself in a separate paragraph.
    2. The program may contain only one PERFORM of that paragraph
    They're still arguing about that one.

    -- CW, October, 2003

  8. No subroutine longer than 200 executable statements is allowed.
    No subroutine shorter than 10 executable statements is allowed.
    1. The 200-line limit was proposed to enhance readability by minimizing page turning on printed listings (or scrolling on the screen).

      Setting a fixed size limit fails to recognize legitimate situations that arise in implementing complex business rules, user interfaces, etc. Readers would prefer a guideline suggesting that the programmer question and carefully examine any routine that grows beyond this size to determine whether it lacks cohesion and consider dividing it into two or three well-defined functions. But one should never divide arbitrarily, e.g. "This routine does the first half of the inventory forecasting algorithm".

    2. The 10-statement floor was proposed in order to avoid linkage overhead for very small routines.

      It's easy to find counter-examples, i.e. shorter sequences of code that you wouldn't want to repeat every time you need them. For example:

      • Computing the greatest common divisor of two integers
      • Comparing two mixed-base quantities (e.g. year-month-day)
      • Converting temperature from Celsius to Fahrenheit.
      A programming language with a powerful macro processor (PL/I) or one with inline functions (C++) lets the programmer avoid linkage overhead while realizing the benefits of modularity. The COBOL programmer can try COPY . . REPLACING in some situations; otherwise a little overhead is usually preferable to a lot of repetition.

    -- CW, October, 2003

    1 -- Common enough that enlightened organizations package it for reuse as a COPY module.
    2 -- This need was especially common among programmers who used record output for printing reports, since heading lines, body lines, and totals lines had different format and data content. The "Report Writer" feature eliminated the need for that clumsy approach.

    Return to Technical articles
    IDI home page

    Last modified August, 2001.