Skip to content
PYD ENTERPRISES

COBOL anti-pattern

REDEFINES memory overlay

REDEFINES gives the same bytes two or more layouts, usually chosen by a type code elsewhere in the record, so one field name can hold a card token in one row and a packed amount in the next.

FAMILY
COBOL
CUTOVER RISK
Critical
Changes runtime behavior in ways a line-by-line reading misses. Resolve before any cutover plan.
MODERN MAPPING
Discriminated union (oneOf with a tag)
GENERATED ARTIFACT
PaymentRecord.schema.json

Before and after

legacy source → modern mapping

Legacy: exhibits the pattern

PAYREC.cpyCOBOL
1 01 PAYMENT-REC.
2 05 PAY-ID PIC X(12).
3 05 PAY-METHOD PIC X(01).
4 88 PAY-IS-CARD VALUE 'C'.
5 88 PAY-IS-ACH VALUE 'A'.
6 05 PAY-DETAIL PIC X(30).
7 05 PAY-CARD REDEFINES PAY-DETAIL.
8 10 CARD-TOKEN PIC X(19).
9 10 CARD-EXP-YYMM PIC 9(04).
10 10 FILLER PIC X(07).
11 05 PAY-ACH REDEFINES PAY-DETAIL.
12 10 ACH-ROUTING PIC 9(09).
13 10 ACH-ACCOUNT PIC X(17).
14 10 ACH-LIMIT PIC S9(5)V99 COMP-3.

Modern: Discriminated union (oneOf with a tag)

PaymentMethod.javaJava
1public sealed interface PaymentDetail
2 permits CardDetail, AchDetail { }
3
4// PAY-METHOD = 'C' (88 PAY-IS-CARD)
5public record CardDetail(
6 String token, // offset 13, 19 bytes
7 YearMonth expiry // offset 32, 4 bytes
8) implements PaymentDetail { }
9
10// PAY-METHOD = 'A' (88 PAY-IS-ACH)
11public record AchDetail(
12 String routing, // offset 13, 9 bytes
13 String account, // offset 22, 17 bytes
14 BigDecimal limit // offset 39, 4 bytes
15) implements PaymentDetail { } // COMP-3 S9(5)V99

Why it is dangerous in modernization

A REDEFINES overlay is a union type without a tag the compiler knows about. The discriminator is a convention: a one-byte type code, a record length, or a flag set by an earlier program. Nothing stops a program from writing through one view and reading through another, and some programs do it on purpose, for example redefining a numeric field as alphanumeric to test it for spaces. When teams map copybooks to relational tables or JSON by flattening every field, they create columns that are meaningless for half the rows, and they convert bytes with the wrong type. Packed decimal read through a character view produces garbage; character data read through a COMP-3 view raises a data exception (S0C7) on the mainframe and silent corruption in a converter that does not check.

How PYD ENTERPRISES detects it

The COBOL front end computes a byte-accurate storage layout for every 01 level after copybook expansion, so each field resolves to an offset, a length and a usage. For each REDEFINES group the engine searches the procedure division for the condition that guards access to each variant: IF and EVALUATE tests on 88-levels and type codes that dominate reads of the variant's fields in the control-flow graph. When every access to a variant is dominated by the same test, the test becomes the discriminator. Accesses with no dominating test, and writes through one view followed by reads through another, are flagged.

Maps to: Discriminated union (oneOf with a tag)

Each overlay becomes a tagged variant: a sealed interface with records in Java, a discriminated union in TypeScript, and a JSON Schema oneOf whose branches are selected by the tag field. In a relational target, the usual choice is one table per variant or a typed JSON column, never a single wide table with nullable columns from every view.

Generated specification fragment

PaymentRecord.schema.jsonJSON
1{
2 "$schema": "https://json-schema.org/draft/2020-12/schema",
3 "title": "PaymentRecord",
4 "type": "object",
5 "required": ["id", "method", "detail"],
6 "properties": {
7 "id": { "type": "string", "maxLength": 12 },
8 "method": { "enum": ["C", "A"] }
9 },
10 "oneOf": [
11 {
12 "properties": {
13 "method": { "const": "C" },
14 "detail": { "$ref": "#/$defs/CardDetail" }
15 }
16 },
17 {
18 "properties": {
19 "method": { "const": "A" },
20 "detail": { "$ref": "#/$defs/AchDetail" }
21 }
22 }
23 ]
24}

Every generated element links back to the source file and line range shown in the legacy pane. Review and sign off before building against it.

The layout, byte by byte

PAYMENT-REC is 43 bytes. PAY-ID occupies offsets 0 to 11, PAY-METHOD offset 12, and PAY-DETAIL offsets 13 to 42. The card view uses 19 bytes of token, 4 bytes of expiry and 7 bytes of filler. The ACH view uses 9 bytes of routing number, 17 bytes of account number and a 4-byte packed field: S9(5)V99 COMP-3 holds 7 digits plus a sign nibble, which is 8 nibbles, so (7 + 1) / 2 = 4 bytes. Both views are exactly 30 bytes, matching PAY-DETAIL.

Getting these numbers right is not optional. Every downstream conversion, whether a file transfer to a data lake or a CDC feed into PostgreSQL, depends on offsets and usages. PYD ENTERPRISES exports the resolved layout with each extracted schema, so the team writing the converter does not recompute it by hand from the copybook.

Discriminators that are not in the record

The example has a clean discriminator: PAY-METHOD with two 88-levels. Many production copybooks do not. Common alternatives are a record length in a variable-length file, a record type in a header record read earlier, or a program-level switch set by the JCL parameter that started the job. When the guard is outside the record, the engine reports the variant together with the dataflow path that feeds the discriminator, so the schema reviewer can decide whether the tag belongs in the new contract or should be derived by the producer.

Deliberate type punning

Some programs redefine a numeric field as PIC X only to test IF WS-AMT-X = SPACES before arithmetic, because an all-spaces zoned field would fail a numeric operation. That is not a business variant; it is input validation. The engine classifies single-field alphanumeric redefinitions used only in such tests as plumbing, and maps them to a nullable numeric property with a validation rule rather than a second variant.

Find every REDEFINES memory overlay in your codebase.

Run PYD ENTERPRISES in your private VPC and get each occurrence with file, line range, modern mapping and equivalence fixtures, ready for your architects to review.