Best Practices, Coding Standards & Pitfalls
43.1 Coding standards
Structure: one main paragraph that reads like a table of contents; numbered paragraphs (1000-, 2000-…); one function per paragraph; no fall-through between paragraphs.
Scope terminators everywhere (END-IF, END-READ, END-EVALUATE, END-PERFORM, END-COMPUTE); one period per paragraph.
No GO TO (except, if your standard allows, to an -EXIT paragraph or abend routine); no ALTER, no NEXT SENTENCE.
Naming: meaningful names with consistent prefixes (WS-, LS-, LK-, file-record prefixes); 88-level condition names for every flag and code; avoid abbreviations nobody knows.
Data: signed fields for amounts; COMP-3 for arithmetic, COMP/COMP-5 for counters and subscripts; size fields generously; one copybook per shared layout.
Robustness: FILE STATUS on every file and check it after every I/O; ON SIZE ERROR on calculations that can overflow; validate input with class tests (NUMERIC) before arithmetic; check SQLCODE and CICS RESP after every call.
Return codes: set RETURN-CODE consistently (0/4/8/12/16) so JCL and schedulers can react.
Comments: explain *why* (business rules, regulatory references), not *what*; keep a change log in the header or in Git history.
Layout: indent nested logic by 4 spaces; align PIC clauses; keep every line within column 72.
Tools: compile with all warnings; use static analysis (SonarQube COBOL, IBM ADDI, Broadcom tools) and peer review.
43.2 Common pitfalls
Stray period inside IF Statements after the period always execute
Use scope terminators; one period per paragraph Code past column 72 Statements silently truncated
Configure the editor ruler; enable compiler warnings Unsigned field receives a negative value Sign lost (−5 becomes 5) Use S in the PICTURE Receiving field too small High-order digits silently truncated Size fields; ON SIZE ERROR Missing ROUNDED Cents lost on every calculation ROUNDED on final results Uninitialized numeric field S0C7 data exception
VALUE clauses, INITIALIZE, INITCHECK Subscript out of range
Overwritten storage, S0C4, wrong results SSRANGE/-debug in test, bounds checks
Loop counter too small (PIC 9 counting to 10) Size counters with headroom; use COMP SEARCH without SET idx TO 1 Search starts mid-table, misses entries Always set the index first SEARCH ALL on unsorted data Wrong "not found" results Guarantee sort order; validate on load STRING without clearing target Leftover characters from earlier values MOVE SPACES first Ignoring FILE STATUS Silent data loss or loops on error
Check after every I/O; 88-levels for statuses Group MOVE over packed/binary fields Corrupt numeric data
Move elementary items, or use matching layouts Parameter layout mismatch between caller and callee Garbage data, S0C4 Shared copybooks for LINKAGE Fall-through into the next paragraph Code runs twice or unexpectedly GOBACK/STOP RUN at end of mainline Date fields with 2-digit years 4-digit years; FROM DATE YYYYMMDD EBCDIC/ASCII assumptions Different sort order after migration
Explicit collating sequences; test with real data