Easytrieve Reusable Procedures Design Pattern

Copy-pasted IF blocks are the first sign an Easytrieve program outgrew its design. The reusable procedures pattern replaces repeated logic with PROC modules—labeled blocks ending in END-PROC—that callers invoke through PERFORM. One VALIDATE-DATE. PROC serves morning extracts and month-end reconciliation; one FORMAT-AMOUNT. PROC standardizes currency masks across detail and total lines. This pattern is how mature shops keep thousand-report portfolios maintainable: fix tax rounding once in a shared module instead of in forty-seven JOB activities. This page teaches module boundaries, parameter contracts via working storage, nesting without recursion, MACRO-based procedure libraries, and how reusable PROCs differ from automatic report hooks like BEFORE-LINE.

Progress0 of 0 lessons

Why Reusable PROC Modules Matter

Batch programs accrete logic over decades. A developer adds overtime calculation inline; another adds the same check with a one-cent difference; auditors find mismatched totals between two reports that should agree. PROC modules create a single authoritative implementation. PERFORM is the call mechanism: branch to the module, execute until END-PROC, resume on the next line after PERFORM. The pattern costs little syntactic overhead but demands discipline naming fields and documenting contracts so the next maintainer knows which variables a module reads and writes.

PROC Module Anatomy

text
1
2
3
4
5
6
7
8
9
10
11
VALIDATE-RECORD. PROC W-ERROR-FLAG = 'N' IF ACCT-NO EQ ZEROES W-ERROR-FLAG = 'Y' W-ERROR-TEXT = 'MISSING ACCOUNT' END-IF IF AMOUNT LT ZERO W-ERROR-FLAG = 'Y' W-ERROR-TEXT = 'NEGATIVE AMOUNT' END-IF END-PROC

VALIDATE-RECORD. PROC is the label plus PROC keyword. Body contains executable statements. END-PROC closes the module. Callers PERFORM VALIDATE-RECORD then test W-ERROR-FLAG. Output fields use consistent prefixes like W- for work fields shared across modules in the same program.

PERFORM as the Call Instruction

text
1
2
3
4
5
6
7
8
JOB INPUT TRANS-FILE PERFORM VALIDATE-RECORD IF W-ERROR-FLAG EQ 'N' PERFORM ACCUMULATE-TOTALS PRINT DETAIL-LINE ELSE PERFORM WRITE-EXCEPTION END-IF

JOB INPUT stays a high-level pipeline: validate, accumulate, print—or branch to exception handling. Each step is one PERFORM. Readers grasp flow without scrolling through hundreds of lines of inline IF tests. Conditional PERFORM inside IF branches selects different modules for order types, regions, or product lines without duplicating validation rules in each branch.

Parameter Contract Pattern

Easytrieve PERFORM does not accept a USING clause for internal PROCs. Reusable modules communicate through agreed field names—a informal API documented in header comments.

Standard parameter contract fields for reusable PROCs
Field roleDirectionExample
Input keyCaller sets before PERFORMWS-DATE-IN, IN-AMOUNT
Output resultCallee sets before END-PROCWS-DATE-OUT, OUT-MASKED-AMT
Status flagCallee sets; caller tests afterW-ERROR-FLAG, W-OK-FLAG
Message textCallee on failureW-ERROR-TEXT
Scratch workInternal to module onlyW-SCRATCH-1 not read by caller

Document at the top of each reusable module: Required inputs, outputs, side effects on file buffers, and fields that must not be modified. Violating the contract—reusing W-SCRATCH-1 as output in two nested PERFORMs—causes subtle overwrites.

Layered Procedure Architecture

Initialization layer

INIT-JOB-COUNTERS. PROC zeros W-RECORD-CNT, W-ERROR-CNT, and break accumulators. Called from START. PROC or first line of JOB after one-time setup. Keeps counter discipline consistent.

Validation layer

VALIDATE-* modules test field ranges, required codes, date formats, and cross-field rules. Return W-ERROR-FLAG without printing—callers decide whether to skip, exception, or fail job.

Transformation layer

DECODE-CODES, FORMAT-AMOUNT, COMPUTE-TAX modules transform data without I/O side effects when possible—easier to unit test in isolation with DISPLAY during development.

Persistence layer

WRITE-EXCEPTION, UPDATE-CONTROL-TOTAL, EMIT-TRAILER modules handle output files and counters shared with audit. Centralize so control totals always match exception counts.

Nesting PERFORM Safely

PROC A may PERFORM PROC B. B ends with END-PROC returning to A; A eventually END-PROC returns to JOB. Broadcom forbids recursion: B cannot PERFORM A directly or through a chain. Deep nesting beyond three levels compiles but hurts readability—flatten by merging tiny modules or inlining two-line helpers.

text
1
2
3
4
5
6
7
8
9
10
11
12
13
PROCESS-RECORD. PROC PERFORM VALIDATE-RECORD IF W-ERROR-FLAG EQ 'N' PERFORM DECODE-ALL-CODES PERFORM ACCUMULATE-TOTALS END-IF END-PROC JOB INPUT FILE-A PERFORM PROCESS-RECORD IF W-ERROR-FLAG EQ 'N' PRINT LINE-OUT END-IF

PROCESS-RECORD orchestrates submodules. JOB INPUT calls one orchestrator PERFORM keeping the top level readable. Testers focus on PROCESS-RECORD integration tests plus individual module edge cases.

MACRO Procedure Libraries

Enterprise shops store standard modules—VALIDATE-ZIP, FORMAT-SSN, STANDARD-EXCEPTION-WRITE—in MACRO source merged at compile. Benefits: one fix updates all including programs on next compile; naming standards enforced centrally. Risks: hidden coupling if MACRO assumes field names not present in every host program; version MACRO libraries and document required host fields in the MACRO header.

Alternative to MACRO: duplicate small PROC bodies in each program when logic differs slightly per report—avoid forced sharing that requires ten IF shop-id branches inside one MACRO.

Reusable PROC Versus Report Hooks

User PROCs versus special-name report PROCs
AspectUser PROC + PERFORMBEFORE-LINE / AFTER-BREAK
InvocationPERFORM from JOB or PROCReport writer on event
PurposeBusiness logic reusePrint-time formatting and breaks
NamingAny valid labelFixed special names with period
Reuse across programsMACRO or copy patternPer-report definition

User PROCs can be PERFORMed from report hooks when print-time logic needs shared calculation— for example BEFORE-LINE. PROC PERFORM FORMAT-AMOUNT before PRINT. Do not PERFORM BEFORE-LINE itself; the report engine owns that hook.

PERFORM Versus CALL

PERFORM stays inside Easytrieve source in the same activity. CALL links to external COBOL, Assembler, or C subprograms with USING parameters per language linkage rules. Reusable procedure pattern applies to PERFORM modules. Use CALL when math or date routines already exist in an approved subprogram library—not for ordinary report validation you can express in Easytrieve.

Common Anti-Patterns

  • Giant single PROC containing entire JOB logic—defeats modularity.
  • Undocumented shared fields—next developer overwrites W-TEMP used by two modules.
  • PERFORM inside tight loops without need—inline one-line logic instead.
  • Recursive PERFORM chains—compile may succeed; runtime is undefined.
  • Mixing validation and PRINT in one module—hard to test and reuse.
  • Duplicate PROC labels in same activity—compile error or wrong branch target.

Testing Reusable Modules

  1. Build small driver JOB that PERFORMs one module with boundary field values.
  2. Verify W-ERROR-FLAG and output fields for good, bad, and edge inputs.
  3. Regression: after changing shared MACRO, recompile all dependents and parallel-run sample jobs.
  4. Code review checklist: END-PROC present, no recursion, contract comment at module top.
  5. Compare totals before and after refactor from inline to PROC—must match penny for penny.

Explain It Like I'm Five

Reusable procedures are like recipe cards in a kitchen. Instead of writing make a sandwich from scratch on every order ticket, the cook grabs the sandwich card: get bread, add filling, cut in half. PERFORM is the cook saying I will follow the sandwich card now. END-PROC is putting the card back when the sandwich is done. If you fix the card once—more peanut butter—every cook makes the same better sandwich tomorrow.

Exercises

  1. Extract inline validation from a sample JOB into VALIDATE-RECORD. PROC with W-ERROR-FLAG contract.
  2. Add PROCESS-RECORD. PROC orchestrator performing validate, decode, accumulate modules.
  3. Document input and output fields in comments for one reusable module.
  4. Identify one report hook versus one user PROC in an existing program listing.
  5. Design a MACRO header listing host fields required by a shared FORMAT-AMOUNT module.

Frequently Asked Questions

Quiz

Test Your Knowledge

1. User-defined modules are invoked with:

  • PERFORM proc-name
  • CALL proc-name for internal modules
  • MACRO proc-name
  • JCL EXEC

2. A reusable procedure pattern requires each module to end with:

  • END-PROC
  • END-IF
  • STOP
  • CLOSE

3. Recursion in PROC modules is:

  • Forbidden by Broadcom
  • Unlimited
  • Required for loops
  • SCREEN only

4. Shared parameters between caller and callee typically use:

  • Common working-storage field names documented as a contract
  • JCL PARM only
  • REPORT TITLE
  • SQL cursors

5. BEFORE-LINE. PROC is invoked by:

  • Report writer automatically
  • PERFORM BEFORE-LINE
  • SORT statement
  • FILE TABLE
Published
Read time19 min
AuthorMainframeMaster
Reviewed by MainframeMaster teamVerified: Broadcom Easytrieve Report Generator 11.6 PROC and PERFORM processingSources: Broadcom Easytrieve 11.6 Procedures, PERFORM statement, MACRO expansionApplies to: Easytrieve reusable procedure design pattern for batch modularization