Case Study 2: MedClaim — Designing CLM-ADJUD Program Flow
Background
In early 2024, MedClaim made the decision to replace their 20-year-old claims adjudication program with a new implementation. The old program, CLM-ADJ-LEGACY, had grown to 12,000 lines over two decades and suffered from all the structural problems described in this chapter: poor naming, deep nesting, tight coupling, and a spaghetti-like flow that only James Okafor could fully navigate.
Rather than refactor the old program (as GlobalBank did with ACCT-MAINT), James proposed a greenfield rewrite: design the new program from scratch using modern structured programming principles, then migrate the business rules from the old program into the new structure.
"The old program works," James told the steering committee. "But it works the way a car with 200,000 miles works — it gets you there, but you are afraid to look under the hood. We need a new engine."
The Design Process
Step 1: Requirements Gathering (Week 1)
Sarah Kim, MedClaim's business analyst, documented the adjudication workflow as a sequential decision tree:
- Receive claim
- Validate member eligibility
- Check for duplicate claims
- Verify provider status and network
- Check service authorization requirements
- Price each line item against fee schedule
- Apply member benefits (deductible, copay, coinsurance)
- Apply plan maximums and accumulators
- Determine payment amount
- Generate explanation of benefits (EOB)
- Write adjudication decision
She also documented the exit conditions: at any step, the claim might be denied, pended, or flagged for manual review. Each exit condition had specific denial/pend reason codes that must be set.
Step 2: Paragraph Skeleton Design (Week 1)
James translated Sarah's workflow into a COBOL paragraph skeleton — paragraph names and hierarchy only, no business logic:
******************************************************************
* Program: CLM-ADJUD
* Purpose: Adjudicate medical claims
* Author: James Okafor, MedClaim Health Services
* Date: 2024-01-15
******************************************************************
1000-MAIN-PROCESS.
PERFORM 1100-INITIALIZE
PERFORM 1200-OPEN-FILES
PERFORM 1300-LOAD-REFERENCE-TABLES
PERFORM 1400-PROCESS-ALL-CLAIMS
PERFORM 1500-WRITE-BATCH-REPORT
PERFORM 1600-CLOSE-FILES
STOP RUN.
1100-INITIALIZE.
1200-OPEN-FILES.
1300-LOAD-REFERENCE-TABLES.
1310-LOAD-FEE-SCHEDULES.
1320-LOAD-BENEFIT-PLANS.
1330-LOAD-PROVIDER-NETWORK.
1340-LOAD-AUTH-REQUIREMENTS.
1400-PROCESS-ALL-CLAIMS.
1500-WRITE-BATCH-REPORT.
1600-CLOSE-FILES.
2000-ADJUDICATE-ONE-CLAIM.
2100-VALIDATE-MEMBER.
2200-CHECK-DUPLICATE.
2300-VERIFY-PROVIDER.
2310-CHECK-PROVIDER-STATUS.
2320-DETERMINE-NETWORK-STATUS.
2400-CHECK-AUTHORIZATION.
2500-PRICE-LINE-ITEMS.
2510-PRICE-ONE-LINE.
2520-LOOKUP-FEE-SCHEDULE.
2530-APPLY-FEE-SCHEDULE-RATE.
2600-APPLY-BENEFITS.
2610-APPLY-DEDUCTIBLE.
2620-APPLY-COPAY.
2630-APPLY-COINSURANCE.
2640-CHECK-PLAN-MAXIMUM.
2700-CALCULATE-PAYMENT.
2800-GENERATE-EOB.
2900-WRITE-DECISION.
2950-UPDATE-STATISTICS.
9100-LOG-ERROR.
9200-LOG-DENIAL.
9300-LOG-PEND.
9400-WRITE-AUDIT-TRAIL.
Step 3: Stakeholder Review (Week 2)
James presented the paragraph skeleton to three stakeholder groups:
Sarah Kim (Business): Verified that every business rule had a corresponding paragraph. She identified a missing step: "Where is the coordination of benefits (COB) check? If the member has a secondary insurer, we need to determine primary/secondary liability before calculating payment." James added:
2650-CHECK-COORDINATION-OF-BENEFITS.
2660-DETERMINE-PRIMARY-LIABILITY.
2670-APPLY-COB-REDUCTION.
Tomás Rivera (DBA): Reviewed the data access patterns implied by the paragraph structure. He noted that 1300-LOAD-REFERENCE-TABLES would require loading four large tables into WORKING-STORAGE. He suggested adding a paragraph for table size validation:
1350-VERIFY-TABLE-LOADS.
Quality Assurance Team: Reviewed the structure for testability. They requested that each validation step set a clear pass/fail condition name so that test harnesses could verify individual steps:
01 WS-ADJUDICATION-FLAGS.
05 WS-MEMBER-CHECK PIC X(01).
88 MEMBER-ELIGIBLE VALUE 'Y'.
88 MEMBER-INELIGIBLE VALUE 'N'.
05 WS-DUPLICATE-CHECK PIC X(01).
88 NOT-DUPLICATE VALUE 'N'.
88 IS-DUPLICATE VALUE 'Y'.
05 WS-PROVIDER-CHECK PIC X(01).
88 PROVIDER-OK VALUE 'Y'.
88 PROVIDER-INVALID VALUE 'N'.
05 WS-AUTH-CHECK PIC X(01).
88 AUTH-SATISFIED VALUE 'Y'.
88 AUTH-MISSING VALUE 'N'.
Step 4: Flow Logic Design (Week 2)
With the skeleton approved, James designed the flow logic for 2000-ADJUDICATE-ONE-CLAIM:
2000-ADJUDICATE-ONE-CLAIM.
SET CLAIM-PROCESSABLE TO TRUE
PERFORM 2100-VALIDATE-MEMBER
IF CLAIM-PROCESSABLE
PERFORM 2200-CHECK-DUPLICATE
END-IF
IF CLAIM-PROCESSABLE
PERFORM 2300-VERIFY-PROVIDER
END-IF
IF CLAIM-PROCESSABLE
PERFORM 2400-CHECK-AUTHORIZATION
END-IF
IF CLAIM-PROCESSABLE
PERFORM 2500-PRICE-LINE-ITEMS
END-IF
IF CLAIM-PROCESSABLE
PERFORM 2600-APPLY-BENEFITS
END-IF
IF CLAIM-PROCESSABLE
PERFORM 2650-CHECK-COORDINATION-OF-BENEFITS
END-IF
IF CLAIM-PROCESSABLE
PERFORM 2700-CALCULATE-PAYMENT
SET CLAIM-APPROVED TO TRUE
END-IF
PERFORM 2800-GENERATE-EOB
PERFORM 2900-WRITE-DECISION
PERFORM 2950-UPDATE-STATISTICS
.
Sarah reviewed this flow and approved it. She noted: "The EOB, decision write, and statistics update should always run — even for denied or pended claims. The member needs to know why their claim was denied, and we need the statistics regardless."
Step 5: Stub Development (Week 3)
James wrote stub implementations for every paragraph:
2100-VALIDATE-MEMBER.
* STUB - to be implemented
DISPLAY 'STUB: Validating member '
WS-MEMBER-ID
SET MEMBER-ELIGIBLE TO TRUE
.
He compiled and ran the stub program against test data to verify:
- The overall flow executed correctly
- The short-circuit logic worked (setting CLAIM-PROCESSABLE to false at any step skipped subsequent steps)
- The statistics updated correctly for all outcomes
- The batch report contained expected sections
Step 6: Business Logic Implementation (Weeks 3-6)
With the structure proven, James assigned individual paragraphs to team members: - James: 2100 (member validation), 2200 (duplicate check) - Developer 2: 2300 (provider), 2400 (authorization) - Developer 3: 2500 (pricing), 2600 (benefits) - Developer 4: 2700 (payment), 2800 (EOB)
Each developer implemented their paragraphs against the defined interfaces (the 88-level condition names). Because the coupling between paragraphs was minimal — each communicated through clearly named flags — the developers could work in parallel with minimal coordination.
Results
Development Metrics
| Metric | Old Program | New Program |
|---|---|---|
| Total lines | 12,000 | 8,400 |
| Number of paragraphs | 89 | 72 |
| Average paragraph size | 135 lines | 25 lines |
| Maximum paragraph size | 480 lines | 38 lines |
| 88-level condition names | 12 | 67 |
| GO TO statements | 156 | 0 |
| Development time | N/A (evolved over 20 years) | 6 weeks |
Quality Metrics (First 6 Months)
| Metric | Old Program | New Program |
|---|---|---|
| Adjudication accuracy | 99.2% | 99.7% |
| Production incidents (monthly avg) | 3.8 | 0.5 |
| New business rule implementation | 2-4 weeks | 2-4 days |
| Time for new developer to contribute | 3 months | 2 weeks |
The Stakeholder Verdict
Sarah Kim: "I can read the new program. I actually read it — I can follow 2000-ADJUDICATE-ONE-CLAIM and verify that it matches our business process document step by step. I could never do that with the old program."
Tomás Rivera: "The database access patterns are clean and predictable. I can tune the DB2 access paths because I can see exactly what data each paragraph needs."
QA Lead: "We wrote unit tests for each validation paragraph independently. Test coverage went from approximately 40% to 92%."
Lessons Learned
-
Design the structure before the logic. The skeleton-review-stub-implement sequence caught three structural issues (missing COB step, missing table verification, unclear flag contracts) before any business logic was written.
-
Stakeholder review of paragraph skeletons works. Sarah Kim found a missing business step by reading paragraph names — she did not need to read code.
-
88-level condition names are the contract between paragraphs. Defining them during design (not after implementation) ensured that all developers used the same interface.
-
Parallel development is possible with low coupling. Four developers implemented different sections simultaneously with zero integration bugs — because the inter-paragraph contracts were defined upfront.
-
The new program is shorter despite being better structured. 12,000 lines became 8,400 because good structure eliminates duplication. The old program had the same validation logic copied in multiple places; the new program has it once.
Discussion Questions
-
James chose a greenfield rewrite rather than refactoring the existing program. Under what circumstances is a rewrite the better choice? What are the risks of a rewrite that a refactoring avoids?
-
The
2000-ADJUDICATE-ONE-CLAIMparagraph uses repeatedIF CLAIM-PROCESSABLEchecks. Some would argue this is verbose. Could you use a different pattern (e.g., PERFORM THRU with guard clauses) to achieve the same short-circuit behavior? What are the tradeoffs? -
The stub development phase took a full week. Was this time well spent, or could it have been skipped? What risks would skipping it introduce?
-
Sarah Kim (a non-programmer) was able to review the paragraph skeleton and identify a missing business step. What does this tell us about the relationship between code structure and cross-functional collaboration?
-
The new program has zero GO TO statements. The team at GlobalBank kept 8. Is one approach objectively better, or does it depend on context? Defend your position.