COBOL STANDARDS AND CONVENTIONS
The standard programming language for the State of Hawaii Executive Branch's central computer site installation is IBM COBOL FOR MVS. Occasionally, a program, subroutine, or macro may be developed in another language, but only if the other language is more suited to solving the application problem.
These COBOL coding standards and conventions are meant to serve as a statewide directive to improve application program quality and computer programmer productivity. Prime consideration is given to the issues of program readability, understanding, ease of development and maintenance, ease of debugging, and program efficiency.
Good programming practices and established conventions and standards should always be followed. Changes to improve machine efficiency should never obscure organized structured program logic.
These standards, conventions, and guidelines will provide for uniformity in the development, construction, and installation of reliable COBOL application programs.
This section has specific conventions and guidelines for improving COBOL program performance. It is written primarily for a COBOL computer programmer who has technical skill and expertise in the COBOL language, grammar, syntax, and structure.
As a supplement, the IBM COBOL Compiler and Library Programmer's Guide's chapter on "PROGRAMMING TECHNIQUES" offers IBM's recommended techniques for increasing the efficiency of COBOL programs. These recommendations may be followed when they do not conflict with the State's standards.
The standard application development approach includes hierarchical structured design and programming with the strongly recommended use of a basic standardized skeleton program that is stored in the system library, "EDPD.PANVTEST," as XASA1A1HA1.
IMPORTANT DEBUGGING FACILITIES NOTES:
IMPORTANT CICS FACILITIES NOTES:
This division provides for the capture of all pertinent information concerning the program.
The eight character assigned mnemonic conforming to the statewide standard naming conventions will be provided by the data processing system analyst.
A one liner comment statement summarizing the major purpose or function of the program follows this line.
Example:
PROGRAM-ID. XLSA1A1L.
* EXTRACT LAST YEARS TRAINING TRANSACTIONS.
Both the data processing systems analyst and computer programmer's names will be included here. In addition to the application designer's name and the computer program coder's names, any vendor, consultant or contractor will also indicate the firm's name here.
The use of the INSTALLATION paragraph name is optional.
Use the format of "January 31, 2002" to reflect the date when the coding was originally developed by the computer program coder.
Enter only the paragraph name, DATE-COMPILED, because the operating system will insert the current system date after this paragraph name when the COBOL program source code is actually compiled.
This section will provide a brief narrative of the program function or purpose, and a summary of any revision made to the source code subsequent to the initial program implementation. This section will contain the following subsections:
A brief description of the main program purpose, function, or control logic, in 3 to 5 sentences. If the program is part of a system of programs, then explain how the program fits into the system. The following should also be included:
Example. *** External subroutines called: "CANCEL", "GREGRN".
Enter the name of each file used by the program indicating whether it is input, output or work-file (I/O) and its file organization (Physically Sequential, VSAM, etc.)
Any revision or modification to the program should be noted and dated. Data should include change request number, date change implemented, programmer's name, and summary description of the change.
Example of a completed "IDENTIFICATION DIVISION":
IDENTIFICATION DIVISION. PROGRAM ID. XASA1C1L. * DAGS/ICSD TRAINING EVALUATION REPORTS INSTALLATION. STATE OF HAWAII, DAGS/ICS DIVISION. AUTHOR. PROGRAMMER: JANE Q. DOE; ANALYST: JOHN R. SMITH. DATE WRITTEN. MARCH 3, 2001. DATE COMPILED. *REMARKS. * 1) GENERATES ANNUAL TRAINING STATISTICS * FROM MASTER STUDENT ATTENDANCE. * 2) PRODUCES THE FOLLOWING REPORTS: * a) XASA1C1R DETAIL COURSE STATS. * b) XASA1C2R SUMMARY BY COURSES. * c) XASA1C3R DETAIL DEPT. STATISTICS. * d) XASA1C4R DETAIL STUDENT STATS. * 3) TERMINATE JOB IF INPUT OUT OF SEQUENCE. * SORT ORDER: 01,41,CH,A SORT KEY * 66,04,CH,A TRAN YEAR * 62,04,CH,A TRAN MON-DAY * 4) COURSE CODES AND DESCRIPTIVE NAMES, * FOR MAXIMUM OF 90 COURSES. * 5) DEPT CODE AND NAME FOR 30 AGENCIES. * MODIFIED DECEMBER 2001 BY P. POTTER TO ADD SPECIAL * STUDENT PORTFOLIO REPORT XASA1C5R.
The function of this division is to define and specify the hardware configuration and requirements used by the program.
The SOURCE COMPUTER and OBJECT COMPUTER paragraph names are optional. If these paragraph names are coded, enter the phrase: IBM OS/390.
The use of the SPECIAL NAMES paragraph for any purpose other than to specify "TOP-OF-PAGE" or "NEW-PAGE", is discouraged.
Do not use the SPECIAL-NAMES paragraph to rename an input/output device, because the I/O functional name must already be as explicit as any mnemonic.
IMPORTANT NOTE:
EXAMPLE: 'ACCEPT ..... FROM CONSOLE'
EXAMPLE: 'DISPLAY ..... UPON CONSOLE'
The 'DISPLAY ..... UPON CONSOLE' sentence is primarily used to send messages to indicate the beginning and ending status of a program.
EXAMPLE: DISPLAY ' *** ' PROG ID ' *** '
'NORMAL TERMINATION ***' UPON CONSOLE.
NOTE:
3.2.2.1 FILE-CONTROL PARAGRAPH
For readability, and to allow the flexibility for name changes, each SELECT statement will begin on a new line with the ASSIGN and other options indented on the following line under the file name.
EXAMPLE: SELECT PAY XTRACT FILE
ASSIGN TO XLSA1A1D
KEY IS XTRT ID KEY
PASSWORD IS OPEN OKAY.
All file names will be descriptive ending with the word "FILE" and indicate the file's primary purpose or function, such as, input, extract, output, work, sort, or the project's PMS code.
EXAMPLE: OLD-MSTR FILE (Sample Input File Name)
NEW-MSTR FILE (Sample Output File Name)
TRAN DUP FILE (Sample Output File Name)
TRAN ERR FILE (Sample Output File Name)
OAB XTRACT FILE (Sample PMS File Name)
Device independence is encouraged. Programmers will not assign a data set to a particular storage device.
Reserve clause should not be specified but instead assigned at execution time via DD statements.
File status must be defined in the Data Division for all VSAM files. It is used to monitor the successful execution of each I/O request of the VSAM file.
3.2.2.2 I-O-CONTROL PARAGRAPH
This division describes each file, record, and data element used in the program.
The use of the 'COPY' statement is not allowed. The PANVALET ++INCLUDE command will achieve the same result.
The COBOL Report Writer Facility will not be used.
Data division members for all records used in more than one program should be designed and created in the project's library, copied into the PANVALET test library, and included in application programs when required. The design and creation of any shared PANVALET include module is the project systems analyst's responsibility.
The File Section contains a description of all externally stored data as well as each Sort Merge File used in the program.
3.3.1.1 File Description Entries
EXAMPLE: MSTR TAPE FILE.
EXAMPLE: PAYROLL MASTER FILE
OAB XTRACT MSTR FILE
3.3.1.2 Record Description Entries
Each record description will contain the following entries:
BLOCK CONTAINS.
RECORD CONTAINS.
LABEL RECORD.
DATA RECORD.
EXAMPLE:
FD MSTR XTRT FILE
BLOCK CONTAINS 0 RECORDS
.
.
.
DATA RECORD IS MSTR XTRT RECD.
IMPORTANT NOTES:
The COBOL compiler's de-blocking routine to get logical records from the physical block-size record is fast and does not require the massive number of housekeeping instructions required to get a new physical record of data.
Large blocks save I/O channel time and improves peripheral storage capacity, but requires more Virtual Storage for Buffer Management. The large physical block-size record may substantially increase the total region size for the program execution.
This section contains data description entries for temporary or non contiguous data items and/or records.
3.3.2.1 WORKING-STORAGE CONVENTIONS
Rules for recording data as stated in the FILE SECTION apply here unless specifically restricted.
3.3.2.2 WORKING-STORAGE ORGANIZATION
EXAMPLE: WORKING STORAGE SECTION.
01 FILLER PIC X(32) VALUE
'PGM=XLSA1A1L, WS BEGINS HERE'.
.
01 FILLER PIC X(32) VALUE
'PGM=XLSA1A1L, WS ENDS HERE'.
The names assigned to the fields within a major grouping should all begin with the same functional descriptive prefix. The fields within each major group should be alphabetized. But fields within major groups that may be printed should be listed in the same order as the output.
EXAMPLE: Counters or accumulators layout structures: 01 COUNTERS. 05 CNT-CLIENTS COMP-3 PIC S9(7) VALUE ZERO. 05 CNT-MASTER COMP-3 PIC S9(7) VALUE ZERO. 05 CNT-REJECT COMP-3 PIC S9(7) VALUE ZERO. 05 CNT-SELECT COMP-3 PIC S9(7) VALUE ZERO. 05 CNT-TRANSACT COMP-3 PIC S9(7) VALUE ZERO. 01 ACCUMULATORS. 05 CUM-AMT-PAID COMP-3 PIC S9(7) VALUE ZERO. 05 CUM-INTEREST COMP-3 PIC S9(7) VALUE ZERO. 05 CUM-SUBTOTAL COMP-3 PIC S9(9) VALUE ZERO. 05 CUM-MON-TOTAL COMP-3 PIC S9(9) VALUE ZERO.
Some recommended major groupings are as follows:
Input/Output Areas.
Control Fields.
Constants.
Counters.
Literals.
EXAMPLE:
05 ONE COMP-3 PIC S9(05) VALUE +00001.
05 FICA-RATE COMP-3 PIC S9(01)V9(04) VALUE +.0585.
Messages.
EXAMPLE:
05 MSG14 ERR IN SEQUENCE PIC X(42) VALUE
'TRANSACTION OUT OF SEQUENCE-ABORT JOB'.
Switches.
Names should be meaningful, self-documenting, and related to the condition being tested.
As an aid for future maintenance, the "88-level" condition data name will be used when defining any logical switch.
The "88" condition name will have the elementary variable topic it is describing as the prefix for the switch name.
EXAMPLE-1:
01 TEST-SWITCHES.
05 EOF-PAY-MSTR PIC X(01) VALUE 'N'.
88 EOF-PAY-MSTR ON VALUE 'Y'.
88 EOF-PAY-MSTR OFF VALUE 'N'.
COBOL-CODING-1:
IF EOF-PAY-MSTR ON
PERFORM 800-CHK-LAST-PAY-MSTR
THRU 800-CHK-LAST-PAY-MSTR-EXIT.
EXAMPLE-2:
01 TEST-SWITCHES.
05 EMPLOYEE STATUS PIC X(01) VALUE ZERO.
88 EMPLOYEE-IS-NEW VALUE '1'.
88 EMPLOYEE-ON-PROBATION VALUE '2'.
88 EMPLOYEE-IS-RETIRED VALUE '3'.
88 EMPLOYEE-UNCLASSIFIED VALUE '9'.
COBOL-CODING-2:
IF EMPLOYEE-IS-NEW
PERFORM 550-ADD-NEW-EMPLOYEE
THRU 550-ADD-NEW-EMPLOYEE-EXIT.
Pass Areas.
Print Formats.
Tables.
3.3.2.3 LEVEL NUMBER
All level numbers must have two (2) digits.
Except for level 01 items, all level numbers should initially be assigned to values in increments such as: 05, 10, 15. Other level numbers may come about as a result of maintenance, enhancements, or changes in requirements.
Level numbers should be indented in a consistent manner for each record. The COBOL coding form was designed in a manner that is convenient to indent four columns for each level, but to establish this indentation as a fixed standard may be unrealistic in a hierarchy that exceeds four or five levels. The main point here is consistency.
Align all level specifications and attributes of the same numeric-level rank in the same column position.
3.3.2.4 PICTURE
The PIC form is preferred. The PIC clause and the associated characteristics should be grouped and aligned in a method to facilitate summing field lengths. The following illustration requires a bit more clerical effort but has an excellent payoff during desk-checking and maintenance
05 FLD-A PIC X(02). 05 FLD-B PIC X(05). 05 FLD-C PIC 9(10). 05 FLD-D PIC X(22). 05 NUM-FLD PIC S9(05)V99.
For easy reference, PICTURE clauses will be aligned vertically whenever possible beginning in column 40.
When a REDEFINES clause is necessary, it should begin in column 30, and the PICTURE statements within the redefining area should be under the REDEFINES.
But the key point is consistency to visually associate COBOL key-words. Use the following formats for attribute descriptions:
EXAMPLE: 05 FILLER PIC ZZZ,ZZZ.99
3.3.2.5 OCCURS
The OCCURS command is used to define relational table data elements or repeating groups of data elements.
EXAMPLE:
01 TABLE-ITEM OCCURS 10 TIMES
05 FILLER PIC X(05).
Put the OCCURS...DEPENDING data at the end of the record, preceded by all fixed data elements. Extra overhead is entailed in accessing any fixed data element that follows the variable data group, because the relative position of the fixed data element is also varying.
When a program updates a file that has an OCCURS... DEPENDING record definition, the following technique is recommended.
Do not directly change the DEPENDING object, because that invokes expensive recalculation of record and group sizes and relative positions, every time the object value is modified.
3.3.2.6 VALUE
The VALUE clause must not be specified within the FILE SECTION.
Numeric data items should always be signed and have a signed value unless an absolute value is needed.
3.3.2.7 USAGE
Do not use DISPLAY data items for computations. Additional overhead is needed to convert the DISPLAY data items into an arithmetic type both before and after the computation.
If DISPLAY data items must be used in computations, using up to 5-digits is fast, however, from 5-digits to 9-digits is 15% slower, and from 10-digits to 13-digits is 50% slower.
3.3.2.8 COMPUTATIONAL
If arithmetic operations are performed on a numeric data item, it should have a usage of COMP-3 or COMP, as appropriate. Internal elementary numeric items should be tagged with the appropriate computational form whenever their primary use is in arithmetic operations.
Specify an odd number of digits for COMP and COMP-3 items, and use the fewest odd number of digits as possible. Specify S in PICTURE for COMP and COMP-3 items. The SYNC items are processed more efficiently. The SYNC clause is encouraged for computational items and must appear only at the elementary level.
Subscripts should be defined in the PICTURE with "S" and "COMP SYNC". Conversion to COMP will occur for subscripts unless COMP is specified. COMP results in the fastest arithmetic instructions.
3.3.2.9 RENAMES
Do not use the renames clause. REDEFINES can give the same result.
3.3.2.10 REDEFINES Clause
All redefining should refer to the originally defined statement regardless of the number of redefinitions.
All redefines entries must be of equal size and must have the same level numbers.
See the IBM COBOL reference manual's chapter on "Data Descriptions" when elements involved in the REDEFINE have the SYNC option.
3.3.2.11 ERROR-SWITCH
Use Procedure-1 below to handle validation or exception error test conditions in the application program.
Include an error switch variable named ERROR SW that is one byte, and a constant variable named PROG ID that is eight bytes.
ERROR SW will be initially set to zero. PROG ID will contain the value of the program's Program ID code.
PROCEDURE-1: HANDLING EXCEPTION CONDITION
RETURN CODE = 000 IF ERROR SW = ZEROS. RETURN CODE = 111 IF ERROR SW = "1". RETURN CODE = 222 IF ERROR SW = "2". RETURN CODE = 888 IF ERROR SW = "A".
For each exception condition, print an appropriate error message similar to the messages in the Control Report found in the standard COBOL skeleton program: XASA1A1HA1.
The LINKAGE SECTION is used to describe data made available from another program.
Data item description entries in the LINKAGE SECTION provide names and description, but storage within the program is not reserved since the data area exists elsewhere.
CICS/VS interface and storage control statements are found in the LINKAGE SECTION.
Example: LINKAGE SECTION. 01 DFHCOMMAREA PIC X(010). 01 DB PCB1 PIC X(100). 01 DB PCB2 PIC X(100).
NOTE:
The procedure division contains the algorithm for the application program. Ensure that the program is structured and modularized, uses structured-coding-constructs, avoids the use of the GO TO statement, and always uses the PERFORM ... THRU format.
Ensure that the data structures and data types are appropriate for the algorithm. As an example, consider two PERFORM ... VARYING loops, one with a DISPLAY data item for the loop variable, and the other with a COMP data item to control the loop. The DISPLAY data item must be converted for each iteration of the loop, but the COMP data item is used directly without a conversion.
Programs should be designed and developed in logical functional modules by establishing module types such as initialization modules, data-edit-validation modules, data manipulation/processing modules, input/output modules, etc.
The exact structure will be a matter of judgment and the only rigid standard will be inclusion of a main line module which is a series of perform statements that can be readily analyzed to determine the major logical sequence of events of the program. Primary purpose of the main line is to link all the processing modules together.
Once the main line module structure has been determined, it should be coded at the beginning of the Procedure Division. Other modules should follow the main line module in any manner that seems appropriate to the programmer. A brief comment description of the logic purpose for a module is added in front of each module structure for better program documentation.
The most important consideration to be given the processing modules is that they should be self indexing. A consecutive numbering scheme is extremely efficient for this purpose. A separate number for each paragraph is the preferred form. The paragraph names for the modules should be numbered according to their primary function following these established ranges:
000-099 Declarative 100 Logic Driver/Initialization/Housekeeping 200 Main Algorithm Processing Logic 300 Error/Exception Handling 400 END OF JOB Logic 500-899 Processing Functions 900 Input/Output
The paragraph names will reflect the sole function of the statements included in the paragraphs and as such make most programs self documenting in its purpose and scope.
The paragraph names should be brief, explicit, direct, and be defined only when necessary for PERFORM or GO TO statements. Double space or "eject" between paragraphs or sections.
Remember, a paragraph name can consist of up to 30 characters. The use of meaningful and self documenting names is always helpful for program maintenance. A sequential prefix will be given to each paragraph name and assigned in an ascending order with a minimum increment of 10.
EXAMPLE:
100-OPEN-FILES.
OPEN
.....
200-GET-TAX-TABLES.
.....
210-GET-MAST-DATA.
PERFORM-900-READ-MSTR
THRU 900-READ-MSTR-EXIT.
.....
240-CALC-GET-TAX.
.....
900-READ-MSTR.
READ .... INTO .... AT END ....
.....
950-WRT-NEW-MSTR.
.....
The general structure and format for paragraph names is:
999-VERB-ADJECTIVE-OBJECT.
.....
999-VERB-ADJECTIVE-OBJECT-EXIT.
In addition to data manipulation and processing modules, the READ and WRITE processing will also include PERFORM modules.
The program design should follow Structured Programming techniques. Structured programming involves a systematic "TOP-DOWN" approach for the design and development of a program. A program should follow a "TOP-DOWN" iterative construction.
The flow of control within a program (or paragraph) should be from top to bottom on a page. Here we are attempting to reduce the indiscriminate unconditional jumping from one part of a program to another. Ease of readability is the key here.
A structured program is subdivided into "modules" with each module consisting of one (1) paragraph. A module is designed to perform one specific task. This allows future changes to the program to be localized to a few modules and possibly reduce modification and enhancement design and development efforts.
Overlapping functions between modules should be kept of the barest minimum.
Within a program, the functional modules occupy a certain position in a hierarchy such that high level modules control the activities of subordinate modules. The following technique is used to control the flow of activity within the program.
A hierarchical relational system structure chart is built from a data flow diagram (DFD). The DFD is a graphical tool used to identify the necessary processes, functions, steps, and flow of a program solution.
The DFD is used to produce a hierarchical structured chart to further visualize how the separate modules (paragraphs) of the application solution will logically relate and fit together.
Each box in the hierarchical structure chart must be associated with one paragraph (module) in the program.
Each paragraph (module) must have only one point of entrance and one point of exit. This reduces the number of alternative paths in a program.
To minimize the effects of computer processing paging, any infrequently executed paragraph such as: initialization, termination, error detectors, and exception routine should be grouped together and separated from frequently executed paragraphs.
Data areas should be initialized in a separate reset area and processed just before they are needed to minimize the possibility of a S0C7 (numerical data exception).
Indent ELSE by aligning it with its associated IF. The ELSE must be the only text on that line. The statements associated with the ELSE must be indented at least four spaces under it.
EXAMPLE:
Instead of the following code:
MOVE SPACES TO FIELD-A FIELD-B.
Code the above as:
MOVE SPACES TO FIELD-A
FIELD-B.
Or else code it as:
MOVE SPACES TO FIELD-A.
MOVE SPACES TO FIELD-B.
READ NEXT-TRANS-RECD INTO HOLD-TRANS-FIELDS
AT END PERFORM 400-END-JOB-WRAP-UP
THRU 400-END-JOB-WRAP-UP-EXIT.
PERFORM 700-EDIT-TRANS-DATA
THRU 700-EDIT-TRANS-DATA-EXIT
VARYING INDXBY ONE
UNTIL BAD-DATA.
EXAMPLE:
SUBTRACT ALLOTTED FROM APPROPRIATED
GIVING ENCUMBRANCE.
The CALL subroutine name should be consistent using standard naming conventions. Do not use aliases. CALL arguments may be elementary or groups with any level number. The size of an argument in the USING clause may be greater than the size of the matching formal parameter, only when the argument or formal parameter is a group item. Arithmetic expressions and literals may be used as CALL arguments.
Use of CALL statements should be minimized and coded in paragraphs to be performed when needed to call shared global program processes
Use the DYNAM option when calling a subprogram.
Available standardized subroutine names and their descriptions that may be INCLUDED are found in Appendix B.
Only the main entry point name will be Called. Available standardized subroutine names and their descriptions that may be INCLUDED are found in Appendix B.
The parameter names should be aligned and begin on a consistent column
EXAMPLE:
CALL 'EXTRACTOR'
USING MAST-IN-DATA
SELECT-CRITERIA
ACCEPTED-DATA.
Comment lines may be written at any line, even before the IDENTIFICATION DIVISION header.
Comments will be used to point out or emphasize relationships and objectives of processes, comparisons, variables, complex formulas, derivations of formulas, or uses of tables or arrays
Each program routine and subroutine will have comments to summarize the source and function of the routine or subroutine, especially when its purpose is not immediately obvious by reading its COBOL statements. Comments are made by entering the asterisk (*) in column 7.
EXAMPLE: 500 VERIFY VALID DATA. * TRANSACTION DATE FIELD IS VERIFIED. MONTH-DAY-YEAR * FIELDS RANGES ARE EDITED. KEY FIELDS OF CUSTOMER-ID * AND ORDER NUMBERS ARE CHECKED AGAINST TABLES.
Enter an asterisk (*) in column 7 to comment a line. Do not use the "NOTE" statement."
The use of meaningful comment statements in program is strongly recommended. Briefly describe the task or function of the module to expand on the paragraph name.
A compound conditional statement contains multiple resultants for one elementary data item.
EXAMPLE-1: IF CHK-FIELD = 'A' OR = 'B' OR = 'C' ..... The above statement must be revised to be coded as: IF CHK-FIELD = 'A' OR CHK-FIELD = 'B' OR CHK-FIELD = 'C' EXAMPLE-2: IF (FLD-A IS NOT GREATER THAN FLD-B) OR (FLD-C IS EQUAL TO FLD-D),.... EXAMPLE-3: IF FLD-A IS NOT EQUAL TO NOT FLD-C IF NOT FLD-B IS NOT LESS THAN NOT-FLD-D IF NOT FLD-A IS NOT = FLD-B OR NOT FLD-C = FLD-D
The above conditional statements are examples of the type of logical comparisons to be avoided. As an alternative in the first negative example it would be simpler just to say that "field-a = field-c".
For arithmetic expressions, the use of the COMPUTE statement is encouraged. It is easy to check out and tends to be self documenting. However, sometimes it may be more intuitive to code
ADD 1 TO CNT-READ instead of coding: COMPUTE CNT-READ = CNT-READ + 1
Items referenced by arithmetic verbs should all be COMP or COMP 3. Items added or subtracted should have the same number of decimal places.
For items not in ideal formats of same attributes and same decimal lengths, move them to ideal data item formats in working storage before processing.
For computations involving several arithmetic operations, the COMPUTE verb is more efficient than a sequence of separate arithmetic verbs. However, the precision of the intermediate results cannot be controlled using COMPUTE, and may not generate the expected final report.
The relative speeds of the arithmetic operations are as follows:
ADD or + fast SUBTRACT or - fast MULTIPLY or * slow DIVIDE or / slower **(exponentiation) very slow
Avoid costly multiplication by 0 or 1 or division into 0 by careful arrangement of the logic or by coding an extra IF to bypass the calculation.
Eliminate unnecessary use of the rounded clause. Consider rounding directly in a calculation for values that always have the same sign, but be sure the formula is documented to eliminate misinterpretation in later maintenance.
The next example is the recommended syntax to control "rounding" for two decimal place accuracy after the computation.
EXAMPLE: COMPUTE PERCENT = RATE * TIME + 0.005.
The COMPUTE verb should always be used when multiple arithmetic operators are involved. Consider two sets of equivalent code:
Poor Code: MULTIPLY B BY B GIVING B SQUARED. MULTIPLY 4 BY A GIVING FOUR-A. MULTIPLY FOUR-A BY C GIVING FOUR-A-C. SUBTRACT FOUR-A-C FROM B-SQUARED GIVING RESULT-1. COMPUTE RESULT-2 = RESULT-1 ** .5. SUBTRACT B FROM RESULT-2 GIVING NUMERATOR. MULTIPLY 2 BY A GIVING DENOMINATOR. DIVIDE NUMERATOR BY DENOMINATOR GIVING X. Improved Code: COMPUTE X = ( B + ((B*B) (4 * A * C)) ** 0.5) / (2 * A).
Both 'poor-code' and 'improved-code' applies to the quadratic formula:
X = B + / (BB - 4AC)
2A
It is easier for the reader to determine what is happening from the single COMPUTE statement.
It is awkward and difficult to realize the cumulative effect of the 8 individual arithmetic statements. The interpretation and understanding of the unacceptable poor-code is further clouded by the mandatory syntax definition for temporary data names for the intermediate results, such as, RESULT-1, RESULT-2, etc.
Parentheses are often required in COMPUTE statements to control or alter the normal hierarchy of operations.
As an example, the parentheses are necessary around "2 * A" in the denominator. If the parentheses had been omitted, the numerator would have first been divided by "2" and then the quotient would have been multiplied by "A".
Sometimes parentheses are optional to the compiler, but should be coded to clarify things for the computer programmer. As an example, the set of parentheses around "4*A*C" do not alter the normal order of operations and hence are optional.
Meaningful condition names in the DATA DIVISION make excellent documentation and can be a great aid in revealing the program logic.
To minimize misunderstanding, the relational operators such as "&"
, ">", and "<"
should be coded "AND", "GREATER THAN" and "LESS THAN". It makes the program listing more self-documenting and more narrative and prose like
Do not use implied conditional subjects or operators.
Example: IF X = FIVE OR SIX OR Y OR TWO
The DISPLAY UPON CONSOLE is permitted only to designate the start of the batch program, or the result of the execution of the batch program.
Any other use requires prior approval from the Computer Operations Services Branch Chief. An important exception to this rule is a situation requiring operator action, such as, multiple uses of tapes for Read Only then Read/Write.
If the DISPLAY statement is used, a comment line should be noted in the FILE-CONTROL paragraph stating its use in the program.
DISPLAY messages should be identified by the PROGRAM-ID that issues it.
Example: DISPLAY "START PROGRAM - XLSA1A1L" DISPLAY "ABNORMAL END OF JOB - XLSA1A1L" DISPLAY "NORMAL END OF JOB - XLSA1A1L"
Do not use the DEPENDING ON format. Use separate nested "IF" statements instead.
Use of GO TO's will be kept to a bare minimum. The permissible GO TO's transfer control to a paragraph "EXIT".
The "GO TO" statement when employed should direct control of the program to a point subordinate to it within the same paragraph. Upward control movement is not allowed. The "GO TO" statement should not be used to transfer control to a point outside of the module in which it resides.
Example:
200-SAMPLE-GOTO.
READ TRAN-REC INTO WS-TRAN-REC
AT END MOVE HIGH-VALUES TO PREV-ID.
IF PREV-ID = HIGH-VALUES
GO TO 200-SAMPLE-GOTO-EXIT.
MOVE ID TO PREV-ID.
200-SAMPLE-GOTO-EXIT.
EXIT.
When it is necessary to loop back to the beginning of a module, use the "PERFORM ... VARYING ... UNTIL" or "PERFORM ... UNTIL" or "PERFORM ... TIMES" in lieu of the "GO TO" statement. By doing so, the condition(s) under which the looping is undertaken is well defined.
Nested IF statements are permitted. Nesting the "THEN" condition should be limited to no more than 3 levels. For longer nested IF statements, use the "END-IF" (scope terminator) for each IF statement. Consistent alignment of paired IF statements is required for ease of maintenance.
Example:
IF condition-1
IF condition-2
IF condition-3
statement-3-1
ELSE
statement-3-2
ELSE
IF condition-4
statement-4-1
ELSE
statement-4-2
ELSE
IF condition-5
statement-5-1
ELSE
statement-5-2.
Consistent indentation will show the subordination relationships.
Example:
IF GET-A-RECORD
PERFORM 210-GET-A-RECORD THRU
210-GET-A-RECORD-EXIT
ELSE
IF START-BROWSE
PERFORM 220-START-BROWSE THRU
220-START-BROWSE-EXIT
ELSE
IF GET-NEXT-RECORD
PERFORM 230-GET-NEXT-RECORD THRU
230-GET-NEXT-RECORD-EXIT
ELSE
IF GET-PREVIOUS-RECORD
PERFORM 240-GET-PREVIOUS-RECORD THRU
240-GET-PREVIOUS-RECORD-EXIT
ELSE
PERFORM 300-WRONG-GET-REQUEST THRU
300-WRONG-GET-REQUEST-EXIT.
The allowable exception to these relational indentations is for more than three (3) mutually exclusive case selection criteria.
Example:
IF GET-A-RECORD
PERFORM 210-GET-A-RECORD THRU
210-GET-A-RECORD-EXIT
ELSE
IF START-BROWSE
PERFORM 220-START-BROWSE THRU
220-START-BROWSE-EXIT
ELSE
IF GET-NEXT-RECORD
PERFORM 230-GET-NEXT-RECORD THRU
230-GET-NEXT-RECORD-EXIT
ELSE
IF GET-PREVIOUS-RECORD
PERFORM 240-GET-PREVIOUS-RECORD THRU
240-GET-PREVIOUS-RECORD-EXIT
ELSE
IF ....
In a sequence of mutually exclusive IF statements, try to order the statements from most likely to least likely, but do not sacrifice program readability or understandability.
Use the IF statement to isolate groups of code that do not require processing for every execution path.
Do not place any Input/Output statement within the conditional IF...ELSE.
The THEN is optional. It must be on a line by itself.
Example:
IF condition-1
THEN
IF condition-2
THEN
IF condition-3
THEN
statement-3-1
ELSE
statement-3-2
ELSE
IF condition-4
THEN
statement-4-1
ELSE
statement-4-2
ELSE
IF condition-5
THEN
statement-5-1
ELSE
statement-5-2
Use the negative IF condition only when the statement is more explicit, much clearer or eliminates the use of "THEN NEXT SENTENCE".
Example:
IF VARIABLE-NAME NOT NUMERIC
PERFORM 500-NOT-NUMERIC THRU
500-NOT-NUMERIC-EXIT.
For numeric compares, the items should both be COMP or COMP-3, be both signed or both unsigned, and have similar PICTUREs. Numeric data must be either COMP or COMP-3 for the machine compare instructions.
Comparing numeric items necessitates costly conversion and decimal point alignment steps, unless they have identical formats. COMP-3 is easier to trace in a dump, but COMP is calculated slightly faster than COMP-3.
The IF NUMERIC and IF ALPHABETIC class condition statements are quite essential but should be used with care. They are very costly, and use of class compares should generally be limited to validating raw input data.
Do not use MOVE CORRESPONDING. MOVE CORRESPONDING does not document well for readability, and can be difficult to maintain when exceptions occur at some later date.
When using "MOVE ... TO ..." for a group of MOVEs, the word "TO" should be aligned on the same column to improve readability.
Example: MOVE PAY-SSN TO PRT SSN. MOVE PAY-NAME TO PRT NAME. MOVE PAY-ADDRESS TO PRT ADDRESS.
Literals:
Before the required MOVE of data, fill out the literal field with the same number of characters as the receiving items.
If the sending/defining literal value is shorter than the receiving item, the statement actually results in an efficient move of the literal followed by an inefficient move of spaces to clear the remaining character positions.
Literal variables should be filled out (padded) unless that would entail a large number of trailing blanks (for example, 12 or more spaces).
Item Sizes
It is most efficient to define a constant data item of spaces in Working-Storage and move from this variable, rather than using the figurative constant SPACES.
The recommended technique to save CPU time and conserve memory is to define a figurative constants with a maximum size specification and let the compiler truncate it during the MOVE.
Example:
01 INIT-CONSTANTS.
03 ALL-SPACES PIC X(080) VALUE SPACES.
03 ALL-HIGH-VALUE PIC X(100) VALUE HIGH-VALUE.
03 ALL-LOW-VALUE PIC X(100) VALUE LOW-VALUE.
Consider group level moves rather than separate moves of elementary items when PICTURE and USAGE of sending and receiving items correspond.
The numeric move is always most efficient if both items are COMP or COMP-3, have the same number of decimal places (if any), and both (or neither) have S in PICTURE. However, if data items are initially not aligned, a planned move to the ideally formatted data items in Working-Storage will save repeated conversions.
Moves to an item which is the object of an OCCURS ... DEPENDING clause should be avoided except at WRITE time.
Eliminate unnecessary use of ON SIZE ERROR clause. Eliminate condition by using techniques such as checking for zero before dividing, etc.
Use a single OPEN statement rather than separate OPEN statements for files opened around the same time. Use of a single OPEN statement reduces routine loading time. System routines required for OPEN are referenced once for each OPEN statement regardless of the number of files specified in the statement.
Sometimes a programmer uses a file over and over to hold temporary data, repeating OPEN WRITE CLOSE and OPEN READ CLOSE sequences many times. These applications should be studied carefully to see whether a working storage table could be used instead. OPEN and CLOSE are very costly statements and are designed to be used only once or a couple of times by each program.
The OPEN/CLOSE statements should be executed only once per program. Files can be opened for INPUT, OUTPUT, or I-O.
Programmers must ensure that all files are properly opened and closed, especially for temporary datasets that are allocated in the step that executes the COBOL program.
The OPEN/CLOSE statements cannot be used in CICS programs.
To eliminate the possibility of logical "fall-thru", use the "PERFORM procedure-name-1" THRU "procedure-name-2" format. The "procedure-name-2" will be an exit for the "procedure-name-1" module.
EXAMPLE: PERFORM 510-READ-DATA THRU 510-READ-DATA-EXIT.
Perform paragraphs, do not perform sections.
The PERFORM UNTIL option is encouraged. Its use is usually obvious and is easy to check out. If possible, the program logic must check the parameters affecting the routine to assure it will not remain in a loop.
PERFORM VARYING format is permissible. Other forms are preferable.
When using the VARYING format, try to place numeric computations outside of the loop. When using the varied variable's value for computations that depend on the number of times the paragraph is performed, do the computations after the loop processing. The scope terminator (END-PERFORM) is required.
The VARYING or UNTIL clause should be indented on a line separate from the PERFORM verb.
EXAMPLE:
PERFORM 510-GET-VALID-TXN
THRU 510-GET-VALID-TXN-EXIT
UNTIL LAST-TXN-RECD.
Use multiple PERFORMS instead of NESTED PERFORMS.
Program switches should be kept at a minimum. However program initialization switches and end-of-job switches are encouraged since their use is usually apparent.
Switches that are set only once per program run are also obvious and should be set via an input control statement. Such as selecting only certain Counties to be processed; or selecting only certain reports to be generated. In any event, detailed annotation of switches is required.
The recommended switch practice is to set a switch as a result of a logical controlling condition. A preferable method is to test the condition again. If the condition is no longer present, anticipate the situation and route the program through a different series of modules.
In place of a separate switch to identify an EOF condition, the non numeric literal KEY field of the record may be set to high value. The KEY field can then be tested for the EOF condition. The high value in the KEY field simplifies the overall logic to complete processing of other input files. But a separate switch offers more flexibility.
If switches are used, use the level-88 feature and variable names that explain the condition.
Example:
05 EYES-COLOR PIC X(02) VALUE SPACES.
88 EYES-ARE-BLUE VALUE "BL".
88 EYES-ARE-BROWN VALUE "BR".
88 EYES-ARE-GREEN VALUE "GR".
IF EYES-ARE-BLUE
PERFORM 520-BLUE-EYES
THRU 520-BLUE-EYES-EXIT.
IF EYES-ARE-BROWN
PERFORM 540-BROWN-EYES
THRU 540-BROWN-EYES-EXIT.
IF EYES-ARE-GREEN
PERFORM 560-GREEN-EYES
THRU 560-GREEN-EYES-EXIT.
For traditional reports, before you start to build a line to be written out, move spaces to a redefined variable of the entire print line layout area.
Each program must have an audit control report. This report must include the following where it makes sense:
Data names should be used to express constant values instead of the actual literal constant. This promotes easier program maintenance and also provides for better readability and understanding.
Example: 05 VALUE-9 PIC 9(01) VALUE "9". 05 VALUE-X PIC X(01) VALUE "X". 05 ONE PIC S9(05) VALUE +1. 05 TWO PIC S9(05) VALUE +2.
3.4.21 Prohibited Or Restricted Verbs
The ALTER statement is never permitted.
ACCEPT FROM CONSOLE option is not permitted. Its use requires prior approval from the ICSD Production Services Branch (PSB) Chief. If used, it should be noted in the FILE CONTROL paragraph with a comment.
The EXAMINE verb is not permitted.
The ACCEPT, CURRENT DATE, DATE, DAY, DISPLAY, EXHIBIT, INSPECT, SIGN IS SEPARATE, STOP RUN, TIME, AND UNSTRING verbs are not allowed for CICS programs.
Data is to be read into a working storage defined area before any processing, and data is never read into the FD record description data fields for processing.
Use the READ...INTO...WORKING-STORAGE-INPUT-AREA format. This format provides a readable trace in memory dumps.
Use the "AT END" or "INVALID KEY" clauses for any "READ" statement.
Code only one READ statement for each file in a paragraph, that is PERFORMED whenever the data is needed.
Advantages of one functional READ or WRITE paragraph for each file are:
The input area should be filled with all high values at end of file unless the end of file condition forces an end of job condition. This particular approach is in the interest of uniformity for EOF logic rather than gaining any program advantage.
Whenever possible, avoid having more that one record per file in core at any one time. For example, when master record (with KEY=121) is in core, do not read another record (with KEY=122) in core until record (with KEY=121) has been completely processed. This avoids unnecessary complexity in a program.
Record Counts should be maintained for all input and output files. Definition of counter names should be meaningful and representative to the file.
Record counts serve as a good debugging tool and should be printed or displayed as part of the end of job routine whether the run is successful or not.
Record counts should be maintained when records are extracted, skipped, or found to contain severe errors.
Do not use the COBOL Report Writer Facility. The COBOL FOR MVS and VS COBOL II compilers do not support the REPORT WRITER FACILITIES.
Sequence checking should be performed whenever specific sequence is required of an input file. Any sequence error message generated should include previous and current keys as well as current record count.
The COBOL SORT verb should be avoided for these important reasons:
The SORT external utility is the recommended method for sorting.
The SORT feature, if it must be used, is for very short and very small files only. The record released to the SORT should be an exact image of the input record with a sort key tagged on to the left most position.
SORT CORE SIZE will default to a value specified at the time the SORT program was installed. This MAXSIZE should always be used. Give SORT as much information as possible. The USING file record size must be equal to the giving file record size otherwise the program will abend with CC=OC4.
Most SORTS will be accomplished through the external procedures using the utility SORT.
EXAMPLE: PROC=SORT PROC=SORTD PROC=REGSORT
Use simple key fields. Combine adjacent key fields to build super description keys.
The COBOL Optimizer will cause unpredictable results for the "USING/GIVING" clauses with the SORT feature.
STRING/UNSTRING should be used with care. A character by character MOVE loop is more efficient.
It is more efficient to REDEFINE the data as a table of one character items and to unstring the data with IF and MOVE statements.
The Indexed form is preferable but both forms are acceptable. The Indexed form is more efficient and generates good documentation.
A fixed length table or fixed length group items must not exceed 131,071 bytes in length.
The maximum storage size of varying tables is 32,767 bytes.
When defining a table, design it so that the rightmost index varies the most often, having the leftmost subscript vary the most is 7% slower.
When coding Table Entries, separate line entries should be made for each item in the table. Separate entries will aid in the correction of entries and provide for better readability.
Always verify that the subscript is valid and within the range. Do not use the SSRANGE option to catch the subscript range error.
Use indexes to address a table , do not use subscripts. The index already has the displacement from the start of the table. Subscripts are an occurrence number that must be converted to a displacement value at run-time. When using subscripts to address a table, use signed binary (COMP) data items with fewer than 8-digits, preferable is using 4-digits or less.
EXAMPLE: 05 MONTH LITERAL TABLE. 10 FILLER PIC X(18) VALUE "JANUARY FEBRUARY".
The above is not acceptable, whereas the following is:
05 MONTH LITERAL TABLE. 10 FILLER PIC X(09) VALUE "JANUARY". 10 FILLER PIC X(09) VALUE "FEBRUARY".
When working with TABLES, always use TABLE MAXIMUM checks to keep from exceeding the boundaries of the TABLE.
For efficiency, put frequently accessed items at the beginning of the TABLE for sequential searches.
Do not alter table entries in their table location. Move the entries to working storage areas and modify those area and then move the values back to the table locations.
Any table whose size or values may change during a program run must be designed to be loaded each time the program is executed.
Do not use the TRACE verb for any CICS program.
RESET TRACE Verb consumes time even if TRACE is never activated. Therefore, it is important to remove these statements when they are no longer needed for debugging.
The "WRITE FROM" format will be used.
Example:
WRITE PRINT-DETAIL FROM WORKING-OUTPUT-AREA.
The "AFTER ADVANCING" format is to be used instead of "AFTER POSITIONING".
WRITE statements will be kept to a minimum. One for TOP-OF-PAGE writing. And one other for all other writing to a file. The most CPU time consuming COBOL verbs are the I/O verbs. Put WRITE's in paragraphs to be PERFORMED.
Line counting is required for overflow testing.
REWRITE is a time-consuming verb. Often several successive transactions apply to the same record. Be sure your program waits to REWRITE a record until no further use can be made of it and all changes have been made to it.