DEV Community

Alain Airom (Ayrom)
Alain Airom (Ayrom)

Posted on

Planning Modernizing Legacy Micro Focus COBOL to .Net? Listen to Bob Advices First

Modernization of legacy code needs a strong plan!

Introduction

In a recent discussion with a partner, we talked about a customer (running some application on Azure) case that wants to migrate legacy Micro Focus COBOL to .NET. Impressively, Bob came up with this plan:

  • Structural Analysis
  • Call Hierarchy
  • Data structures
  • Micro Focus specific extensions

The Big Picture

Migrating 60,000 lines of Micro Focus COBOL to .NET 8 / C# 12 is a strategically sound choice — particularly for organizations already operating in a Windows/Azure ecosystem or leveraging Microsoft’s enterprise toolchain.

The migration combines:

  • Static analysis tooling (Micro Focus Enterprise Analyzer, CAST Highlight, NDepend post-migration) for full-codebase intelligence
  • AI-assisted translation (Bob, per module) for business rule extraction, C# code generation, and xUnit test scaffolding
  • Incremental Strangler Fig pattern — replacing COBOL modules one at a time via an API gateway, with the legacy system as fallback
  • Automated parallel testing — running identical inputs through both COBOL and new C# code, comparing outputs record-by-record
  • Azure-native deployment using .NET 8 on Azure App Service, Azure Container Apps, or on-premises IIS/Windows Server

⚠️ A “big bang” full rewrite is the highest-risk path and is explicitly not recommended.

Why .NET over Java for Micro Focus COBOL?

Micro Focus COBOL has historically had deep integration with the Windows ecosystem and Microsoft tooling. Organizations already using Visual Studio, Azure DevOps, SQL Server, and Active Directory gain a natural convergence advantage by targeting .NET rather than the JVM stack.

Key Considerations

  • The 60k-Line Challenge: Why “Big Bang” rewrites fail and why Micro Focus COBOL extensions (SCREEN SECTION, COMP-3, proprietary APIs) require precise upfront intelligence.
  • Phase 1 Static Discovery: Using tools like Micro Focus Enterprise Analyzer alongside IBM Bob to build dependency maps, flag dead code, and trace PERFORM chains.
  • Domain Decomposition: Breaking the monolith into C# Bounded Contexts (e.g., Billing, Inventory, Customer, Reporting).
  • The Strangler Fig Architecture: How Yarp (Yet Another Reverse Proxy) or Azure API Management acts as the routing layer between legacy COBOL and new .NET services.

Recommended Strategy Overview

Key Architectural Diagram (.NET Strangler Pattern)

High-Level Migration Lifecycle (proposal timeline)


Phase 1 — Inventory & Deep Analysis

COBOL Program Anatomy — What to Inventory


Key Analysis Tasks

| Task                      | Tool                       | Output                                          |
| ------------------------- | -------------------------- | ----------------------------------------------- |
| Program inventory         | Enterprise Analyzer        | List of all active `.cbl` programs              |
| Copybook mapping          | Enterprise Analyzer / Bob  | Dependency tree — maps to C# shared models      |
| PERFORM/CALL graph        | Enterprise Analyzer / Bob  | Method call hierarchy for C# refactoring        |
| Dead code detection       | Enterprise Analyzer        | Programs/paragraphs to retire (expect 10–20%)   |
| Data structure extraction | Bob                        | C# record/class candidates from WORKING-STORAGE |
| Business rule extraction  | Bob                        | Plain-English + C# XML doc comment stubs        |
| VSAM file inventory       | Enterprise Analyzer        | Entity Framework Core schema candidates         |
| Complexity scoring        | CAST Highlight / SonarQube | Priority list for migration order               |
Enter fullscreen mode Exit fullscreen mode

Phase 2: Phase 2 — Modularization & Boundary Definition

Decomposing the Monolith into .NET Projects

Copybook → C# Model Mapping


### C# / .NET Specific Type Conversion Matrix

| Micro Focus COBOL Construct | .NET 8 / C# Target                      | Risk / Mitigation                                            |
| --------------------------- | --------------------------------------- | ------------------------------------------------------------ |
| `PIC 9(n)V9(m) COMP-3`      | `decimal`                               | 🔴 **High** — Never use `float` or `double` for financial data. |
| `PIC X(n)`                  | `string` (fixed-length aware)           | 🟡 **Medium** — Use String padding helper functions where necessary. |
| `COMP-1` / `COMP-2`         | `float` / `double`                      | 🟡 **Medium** — Validate precision tolerance across mathematical operations. |
| `SCREEN SECTION`            | **ASP.NET Core Controllers / Blazor**   | 🟢 **Low** — Decouple UI logic completely into REST endpoints. |
| `VSAM / Sequential Files`   | **SQL Server / PostgreSQL via EF Core** | 🟡 **Medium** — Map key-indexed records to relational schema or Document DB. |
Enter fullscreen mode Exit fullscreen mode

Phase 3 — Target .NET Architecture Design

Recommended .NET Solution Structure

COBOL Batch → .NET Worker Service Pattern

VSAM → SQL Server / Azure SQL Migration


Phase 4 — AI-Assisted Translation to C

Bob’s Role in the C# Translation Pipeline

COBOL → C# Pattern Translation Reference

Per-Module Translation Workflow

Context Window Strategy


Phase 5 — Testing & Validation

Azure Deployment Architecture

Canary Deployment Strategy

Decommissioning Checklist


End-to-End Workflow with Bob


Micro Focus COBOL → C# Specifics

Extension Handling Map


### COBOL Data Type → C# Type Mapping

| COBOL Type             | Micro Focus Behavior      | C# Target                                          | Risk           |
| ---------------------- | ------------------------- | -------------------------------------------------- | -------------- |
| `PIC 9(n)`             | Unsigned integer          | `int` / `long`                                     | 🟢 Low          |
| `PIC S9(n)`            | Signed integer            | `int` / `long`                                     | 🟢 Low          |
| `PIC 9(n)V9(m) COMP-3` | Packed decimal            | `decimal` (native base-10)                         | 🔴 **Critical** |
| `PIC X(n)`             | Fixed-length alphanumeric | `string` (padded-aware)                            | 🟡 Medium       |
| `PIC A(n)`             | Alphabetic                | `string`                                           | 🟢 Low          |
| `COMP` / `COMP-4`      | Binary integer            | `int` / `long`                                     | 🟢 Low          |
| `COMP-1`               | Single float              | `float` (**never for financials**)                 | 🔴 **Critical** |
| `COMP-2`               | Double float              | `double` (**never for financials**)                | 🔴 **Critical** |
| `COMP-5`               | Native binary             | `int` / `long`                                     | 🟢 Low          |
| `88-level condition`   | Boolean flag              | `bool` property or `enum`                          | 🟢 Low          |
| `REDEFINES`            | Memory overlay            | C# `[StructLayout]` union or `discriminated union` | 🟡 Medium       |
| Group item (01 level)  | Struct/record             | `record` or `struct` in C#                         | 🟢 Low          |

### 

Enter fullscreen mode Exit fullscreen mode

COBOL 88-Level Conditions → C# Enum


Toolchain Summary


Risk Register

| Risk                                                     | Probability | Impact     | .NET-Specific Mitigation                                     |
| -------------------------------------------------------- | ----------- | ---------- | ------------------------------------------------------------ |
| Loss of undocumented business rules                      | 🔴 High      | 🔴 Critical | Bob extracts rules as C# XML doc comments before any translation; SME sign-off required |
| COMP-3 precision → `double` instead of `decimal`         | 🟡 Medium    | 🔴 Critical | SonarQube rule: ban `double`/`float` for financial fields; enforce `decimal` in code review |
| Micro Focus SCREEN SECTION has no direct .NET equivalent | 🟡 Medium    | 🟡 High     | Plan dedicated UI redesign sprint; Blazor or React/Carbon as replacement |
| OO-COBOL CLASS/METHOD structures complex to map          | 🟡 Medium    | 🟡 Medium   | Bob maps to C# interface + class pattern; manual review for inheritance hierarchies |
| VSAM data integrity loss during migration                | 🟢 Low       | 🔴 Critical | Full data export validation; EF Core migration scripts + record-level reconciliation |
| AI hallucination in complex procedural logic             | 🟡 Medium    | 🟡 High     | Always generate xUnit tests *before* C# translation; parallel COBOL validation required |
| Azure latency vs on-premises COBOL batch throughput      | 🟡 Medium    | 🟡 Medium   | Baseline COBOL SLAs; BenchmarkDotNet + Azure Load Testing before cutover |
| Key COBOL SME leaves during project                      | 🟡 Medium    | 🔴 Critical | Document all tribal knowledge in Phase 1; Bob assists reverse-engineering from code |
| Scope creep — feature requests during migration          | 🔴 High      | 🟡 Medium   | Freeze scope; new features only after full migration; use separate feature branch |
| NuGet supply-chain vulnerability                         | 🟢 Low       | 🟡 Medium   | Azure DevOps Dependabot + SonarQube SAST on all dependencies |

Enter fullscreen mode Exit fullscreen mode

Effort & Budget Allocation

Recommended Effort Distribution

⚠️ Testing and validation require 30–35% of total effort. Under-allocating here is the leading cause of COBOL migration project failure. For financial systems, allocate toward the higher end.

### Recommended Team Composition

| Role                         | FTE  | Responsibility                                            |
| ---------------------------- | ---- | --------------------------------------------------------- |
| COBOL SME / Business Analyst | 1–2  | Business rule validation, domain expertise, UAT sign-off  |
| C# / .NET Developer (Senior) | 2–3  | Translation review, architecture, EF Core, deployment     |
| C# / .NET Developer (Mid)    | 2    | Test writing, module translation, CI/CD pipeline          |
| QA / Test Engineer           | 2    | xUnit suites, parallel validation harness, UAT            |
| DevOps / Azure Engineer      | 1    | Azure infrastructure, CI/CD, Application Insights         |
| Data Engineer                | 1    | VSAM → SQL migration, EF Core schema design               |
| Project Manager              | 1    | Coordination, risk management, stakeholder communication  |
| **Bob (AI)**                 | —    | Analysis, documentation, C# translation, xUnit generation |

---

## 
Enter fullscreen mode Exit fullscreen mode
## Recommendations

### ✅ Do

1. **Provide one module at a time** — 500–2,000 lines per Bob session, with relevant copybooks included
2. **Ask for documentation first**, then xUnit tests, then C# translation — this ordering produces the most reliable results
3. **Use TDD**: ask Bob to generate `[Fact]` / `[Theory]` xUnit tests *before* writing the implementation
4. **Specify the exact target stack**: `"C# 12 / .NET 8 / ASP.NET Core / Entity Framework Core 8 / SQL Server"`
5. **Ask Bob to flag Micro Focus extensions** explicitly — it will identify what needs manual attention
6. **Ask for C# `record` types for COBOL copybooks** — these are the cleanest, most idiomatic mapping
7. **Always validate with a parallel COBOL run** — never trust AI-generated C# without output equivalence testing
8. **Ask Bob to produce XML doc comments** (`/// <summary>`) — these become living documentation

### ❌ Don't

1. **Don't paste the full 60K codebase** in one session — context overload causes hallucination
2. **Don't use `double` or `float` for any financial field** — always `decimal` with explicit rounding
3. **Don't skip the parallel validation phase** — even if all xUnit tests pass
4. **Don't decommission COBOL until 30+ days of parallel validation** with zero discrepancies
5. **Don't allow AI-translated code to go to production without a senior C# review**
6. **Don't hard-code connection strings, API keys, or credentials** — use Azure Key Vault via `IConfiguration`

Enter fullscreen mode Exit fullscreen mode

Platform Comparison Matrix: .NET 8 Target Ecosystem

| Architectural Layer                 | Microsoft Azure Target                                     | IBM Cloud Target                                             | Trade-offs & Recommendations                                 |
| ----------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| **Serverless / Container Compute**  | **Azure Container Apps (ACA)** *(Powered by KEDA & Envoy)* | **IBM Cloud Code Engine** *(Serverless container runtime)*   | **ACA** offers native .NET integration, microservice scaling, and simple Dapr support. **Code Engine** provides zero-management serverless execution with standard Docker images. |
| **Enterprise Kubernetes Platform**  | **Azure Kubernetes Service (AKS)**                         | **Red Hat OpenShift on IBM Cloud **                    | **AKS** is ideal for pure cloud-native .NET workloads. **ROKS** is better for hybrid cloud scenarios where legacy mainframe and cloud workloads co-exist. |
| **API Gateway & Strangler Routing** | **Azure API Management (APIM)**                            | **IBM API Connect**                                          | Both easily implement the Strangler Fig pattern with path-based routing (`/api/v1/billing` → .NET, `/api/v1/legacy/*` → Legacy/Mainframe). |
| **Database & Persistence**          | **Azure SQL Database / Azure Cosmos DB**                   | **IBM Db2 on Cloud / PostgreSQL**                            | **Azure SQL** provides easy migration for enterprise relational schema. **Db2 on Cloud** preserves schema compatibility if migrating from IBM z/OS Db2. |
| **CI/CD & Developer Tooling**       | **GitHub Actions / Azure DevOps**                          | **IBM Bob / Tekton Pipelines / Red Hat OpenShift Pipelines** | **Azure DevOps** has native .NET SDK building blocks. **IBM Bob** integrates with Tekton and IBM SDLC pipelines. |

Enter fullscreen mode Exit fullscreen mode

Option A: Microsoft Azure Target Architecture

Azure provides a native developer experience for .NET 8 applications. In this setup, Azure API Management handles the Strangler Fig routing between legacy COBOL endpoints and modernized .NET microservices running on Azure Container Apps.
https://miro.medium.com/v2/resize:fit:1400/format:webp/1*GW_z30CGZIcmbkj2FnvCeQ.png

Advantage of the Azure Path

  • Native .NET Support: Zero-friction CI/CD setup with GitHub Actions, native Visual Studio tooling, and telemetry through Azure Application Insights.

Option B: IBM Cloud Target Architecture

IBM Cloud is structured for enterprises operating in hybrid or multi-cloud environments. IBM API Connect directs traffic, while IBM Cloud Code Engine (running on ROKS) runs containerized .NET 8 microservices, maintaining tight integration with mainframe systems via IBM z/OS Connect or dedicated direct links.

Key Advantages of the IBM Cloud Path

  • Db2 Schema Continuity: If legacy COBOL relied on Db2 data structures, IBM Db2 on Cloud preserves column definitions and SQL statements with minimal refactoring required.
  • OpenShift Flexibility: Running on Red Hat OpenShift on IBM Cloud prevents cloud lock-in, allowing the containerized .NET services to run on-premises or across other cloud providers.

Which Path to Choose?

  • Choose Azure if your primary goal is maximizing developer productivity within a pure Microsoft ecosystem and simplifying .NET operational management.
  • Choose IBM Cloud if you require close hybrid integration with existing IBM infrastructure (z/OS, IBM MQ, Db2), or if your organization standardizes on Red Hat OpenShift for multi-cloud deployments.

Appendix — Sample Bob Prompts for COBOL → C# Migration

// ─── Prompt 1: Structural Analysis ─────────────────────────────────────────
"Analyze this Micro Focus COBOL program. Map all paragraphs to candidate C#
methods, extract all WORKING-STORAGE variables as C# field/property candidates,
identify all COPY statements and map copybooks to C# record types, and flag
any Micro Focus-specific extensions. Generate a Mermaid flowchart of the
PERFORM call chain."

// ─── Prompt 2: Copybook → C# Record ────────────────────────────────────────
"Convert this COBOL copybook to a C# record type for .NET 8. Use:
- 'decimal' for all PIC 9...COMP-3 fields
- 'string' for PIC X fields (note original fixed length in XML doc comment)
- 'int' or 'long' for PIC 9 COMP fields
- 'bool' properties for 88-level condition names
- C# XML doc comments (///) documenting each field's COBOL origin"

// ─── Prompt 3: Business Rule Extraction ─────────────────────────────────────
"Extract all business rules from the PROCEDURE DIVISION of this COBOL module.
For each rule, document: rule name, trigger/condition, action taken, edge
cases, and error handling. Format as C# XML doc comments ready to be placed
on the equivalent C# service class methods."

// ─── Prompt 4: xUnit Test Generation (TDD — before translation) ─────────────
"Based on the documented business rules, generate an xUnit 2 test class for
the C# equivalent of this COBOL module. Use [Fact] for single-scenario tests,
[Theory] with [InlineData] for parameterized cases. Structure each test with
Arrange / Act / Assert comments. Include boundary conditions and error paths.
Do NOT write the implementation — only the tests."

// ─── Prompt 5: C# Translation ───────────────────────────────────────────────
"Translate this COBOL module to C# targeting .NET 8 / ASP.NET Core 8.
Rules:
- Use 'decimal' (never double/float) for all numeric COMP-3 fields
- Map EVALUATE to C# switch expressions or switch statements
- Map PERFORM VARYING to for/foreach loops
- Map PERFORM paragraph-name to private methods
- Map CALL 'SUBPROG' to injected service interface calls
- Use async/await for all I/O operations
- Follow C# 12 idioms: records, pattern matching, primary constructors
- Add XML doc comments on all public members
- Avoid JOBOL — write idiomatic modern C#, not COBOL-shaped C#"

// ─── Prompt 6: EF Core Entity Design ────────────────────────────────────────
"Based on this COBOL FILE SECTION and the VSAM KSDS structure described,
generate an Entity Framework Core 8 entity class and DbContext configuration
targeting SQL Server. Include:
- Primary key mapping (from VSAM record key)
- Decimal column precision annotations for financial fields
- Fixed-length string column annotations for PIC X fields
- A migration-ready DbContext with HasColumnType annotations"

// ─── Prompt 7: Micro Focus Extension Audit ──────────────────────────────────
"Review this COBOL code and identify all Micro Focus-specific features:
SCREEN SECTION definitions, OO-COBOL constructs (CLASS/METHOD/INVOKE),
CBL_* API calls, proprietary COPY libraries, and CICS commands. For each,
provide the recommended C# / .NET 8 / Azure equivalent or flag for
mandatory manual review with an explanation of the complexity involved."
Enter fullscreen mode Exit fullscreen mode

Conclusion-COBOL to .NET Migration Strategy

The successful migration of 60,000 lines of legacy Micro Focus COBOL to a modern .NET 8 / C# 12 architecture is a viable and strategic imperative for organizations looking to modernize their core systems. By targeting the Microsoft ecosystem, organizations already leveraging Visual Studio, Azure, and SQL Server can realize a natural technological convergence and gain access to a powerful, modern platform for future growth.

  • Avoid “Big Bang” Rewrites: The document explicitly warns against a full, single-step rewrite due to its high risk. The recommended approach is an incremental strategy using the Strangler Fig pattern, where COBOL modules are progressively replaced by .NET services through an API gateway. This approach allows the legacy system to remain active as a fallback, significantly de-risking the process.
  • Discipline in Testing is Paramount: The document places an overwhelming emphasis on testing, suggesting it should consume 30–35% of the total effort. This is not an area for cost-cutting. A multi-layered testing strategy is essential:
  • Unit Tests: Generated by Bob using xUnit, covering every service method.
  • Integration Tests: Using TestContainers for service-to-service validation.
  • Automated Parallel Validation: This is a critical step where both the legacy COBOL and new C# systems run identical inputs, and their outputs are compared field-by-field. The migration should not be considered successful until zero discrepancies are found over a set period (e.g., 30 days).
  • Absolute Numeric Precision: In financial and core business systems, numeric precision is non-negotiable. The document stresses that COMP-3 packed decimal fields must be mapped to C# decimal types. The use of floating-point types (double or float) for financial fields is explicitly forbidden due to potential for rounding errors and precision loss.
  • AI-Assisted, Not AI-Automated: While Bob (IBM AI SDLC Partner) is central to this proposition, its role is clearly defined as an accelerator and guide, not a fully autonomous migration engine. Developers must review, validate, and sign off on all AI-generated code, documentation, and tests. Bob’s power is maximized when used incrementally (e.g., translating one 500–2,000 line module at a time with relevant copybooks) and with a structured TDD workflow: ask for documentation first, then tests, then implementation.
  • Targeted Platform Benefits: The migration to .NET 8 / C# 12 offers immediate access to modern architectural patterns like ASP.NET Core Web APIs for services, Worker Services for batch job replacements, and a robust ORM with Entity Framework Core 8. The deployment strategy leverages IBM and/or Azure services for cloud-native scalability and managed infrastructure.

In summary, this migration proposition outlines a disciplined, tooled, and incremental path to modernization. By adhering to these key emphasis areas, organizations can transform their legacy COBOL assets into a maintainable, resilient, and performant .NET foundation.

Thanks for reading

Top comments (0)