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.
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.
1234567891011VALIDATE-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.
12345678JOB 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.
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.
| Field role | Direction | Example |
|---|---|---|
| Input key | Caller sets before PERFORM | WS-DATE-IN, IN-AMOUNT |
| Output result | Callee sets before END-PROC | WS-DATE-OUT, OUT-MASKED-AMT |
| Status flag | Callee sets; caller tests after | W-ERROR-FLAG, W-OK-FLAG |
| Message text | Callee on failure | W-ERROR-TEXT |
| Scratch work | Internal to module only | W-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.
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.
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.
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.
WRITE-EXCEPTION, UPDATE-CONTROL-TOTAL, EMIT-TRAILER modules handle output files and counters shared with audit. Centralize so control totals always match exception counts.
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.
12345678910111213PROCESS-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.
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.
| Aspect | User PROC + PERFORM | BEFORE-LINE / AFTER-BREAK |
|---|---|---|
| Invocation | PERFORM from JOB or PROC | Report writer on event |
| Purpose | Business logic reuse | Print-time formatting and breaks |
| Naming | Any valid label | Fixed special names with period |
| Reuse across programs | MACRO or copy pattern | Per-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 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.
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.
1. User-defined modules are invoked with:
2. A reusable procedure pattern requires each module to end with:
3. Recursion in PROC modules is:
4. Shared parameters between caller and callee typically use:
5. BEFORE-LINE. PROC is invoked by: