COBOL anti-pattern
GO TO DEPENDING ON
A computed jump table that transfers control to the Nth paragraph in a list, and silently falls through to the next statement when the index is out of range.
- FAMILY
- COBOL
- CUTOVER RISK
- High
- Hides business logic or coupling that a rewrite will drop unless it is extracted explicitly.
- MODERN MAPPING
- Dispatch table with explicit default
- GENERATED ARTIFACT
- TXNROUTE.routing.dmn.json
Before and after
legacy source → modern mapping
Legacy: exhibits the pattern
1 01 WS-TXN-INDEX PIC 9(02) COMP.2 ...3 1000-ROUTE-TRANSACTION.4 EVALUATE TXN-CODE5 WHEN 'DEP' MOVE 1 TO WS-TXN-INDEX6 WHEN 'WDL' MOVE 2 TO WS-TXN-INDEX7 WHEN 'XFR' MOVE 3 TO WS-TXN-INDEX8 WHEN 'FEE' MOVE 4 TO WS-TXN-INDEX9 WHEN OTHER MOVE 0 TO WS-TXN-INDEX10 END-EVALUATE11 GO TO 2100-DEPOSIT12 2200-WITHDRAWAL13 2300-TRANSFER14 2400-FEE-ASSESS15 DEPENDING ON WS-TXN-INDEX.16 * INDEX 0: FALLS THROUGH TO SUSPENSE POSTING17 PERFORM 2900-SUSPENSE-POST18 GO TO 1999-EXIT.
Modern: Dispatch table with explicit default
1type TxnCode = "DEP" | "WDL" | "XFR" | "FEE";23const handlers: Record<TxnCode, (t: Txn) => Result> = {4 DEP: postDeposit, // 2100-DEPOSIT5 WDL: postWithdrawal, // 2200-WITHDRAWAL6 XFR: postTransfer, // 2300-TRANSFER7 FEE: assessFee, // 2400-FEE-ASSESS8};910export function routeTransaction(t: Txn): Result {11 const handler = handlers[t.code as TxnCode];12 if (handler === undefined) {13 // Legacy behavior: out-of-range index fell through14 // to 2900-SUSPENSE-POST, it did not abend.15 return postToSuspense(t);16 }17 return handler(t);18}
Why it is dangerous in modernization
GO TO DEPENDING ON packs a routing decision into one line: the value of an integer selects one of several paragraph names. The business meaning of each index value usually lives somewhere else, in a transaction code table, a copybook comment, or nowhere. The worst behavior is the out-of-range case. When the identifier is zero, negative, or larger than the number of procedure names, COBOL ignores the GO TO entirely and continues with the next statement. Many programs rely on that as an implicit default branch without saying so. A rewrite that turns the table into a switch with an exception on the default case changes the behavior for exactly the records that nobody tested.
How PYD ENTERPRISES detects it
The parser emits a multi-way branch node with one edge per listed procedure name, labelled with its 1-based position, plus an explicit fall-through edge for the out-of-range case. Value-range analysis on the selector variable then works backwards through MOVE, COMPUTE, SEARCH and 88-level SET statements to determine which index values can actually reach the jump. Unreachable entries and a reachable fall-through edge are both reported as findings, and the selector's upstream definitions are traced to the input field or table that feeds it.
Maps to: Dispatch table with explicit default
Map the jump table to an enum keyed dispatch (a switch expression in Java or C#, a map of handlers in TypeScript or Go) and make the default branch explicit. When the selector is derived from a business code such as a transaction type, the routing itself is a decision and belongs in a DMN table with a FIRST or UNIQUE hit policy, so analysts can review which codes reach which handler.
Generated specification fragment
1{2 "decision": "Route transaction",3 "hitPolicy": "UNIQUE",4 "inputs": ["txnCode"],5 "outputs": ["handler"],6 "rules": [7 { "id": "R1", "txnCode": "\"DEP\"", "handler": "deposit", "source": "TXNROUTE.cbl:5" },8 { "id": "R2", "txnCode": "\"WDL\"", "handler": "withdrawal", "source": "TXNROUTE.cbl:6" },9 { "id": "R3", "txnCode": "\"XFR\"", "handler": "transfer", "source": "TXNROUTE.cbl:7" },10 { "id": "R4", "txnCode": "\"FEE\"", "handler": "feeAssess", "source": "TXNROUTE.cbl:8" },11 { "id": "R5", "txnCode": "-", "handler": "suspense", "source": "TXNROUTE.cbl:9, 17",12 "note": "implicit fall-through when index is out of range" }13 ]14}
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 fall-through rule, precisely
The COBOL standard and IBM Enterprise COBOL define the semantics the same way: if the value of the DEPENDING ON identifier is 1, control goes to the first procedure name; if it is 2, to the second; and so on. If the value is outside the range 1 to n, where n is the number of procedure names, the GO TO is not executed and control passes to the next statement in sequence. There is no runtime error and no condition raised.
In the example above the author used that rule on purpose: the WHEN OTHER branch sets the index to zero so that unknown codes fall through to suspense posting. In older code the zero case is often an accident, for instance a selector loaded from a packed field that can arrive as zero when an upstream file has a blank record. Both cases look identical in the source, which is why the engine reports the fall-through edge as reachable and asks a reviewer to classify it.
When the table is also a business rule
A jump table keyed by transaction type, product code or claim category is routing logic that the business owns. Leaving it as a switch statement inside a service hides it again. PYD ENTERPRISES exports the selector derivation and the jump targets together as one decision table, so the analyst who signs off fee assessment can also see that a new code value, added in the channel layer but not in the mainframe table, would land in suspense posting rather than fail.
Testing the conversion
Generate one equivalence fixture per index value, one for zero, and one for n plus 1. The last two are the cases most often lost. If value-range analysis proves the selector can never exceed n, the engine marks the n plus 1 fixture as unreachable instead of emitting it, and records the proof steps so the reviewer can check them.
Related patterns
Usually found in the same codebase.
Find every GO TO DEPENDING ON 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.