Skip to main content

Modernizing legacy code with GitHub Copilot

Copilot Chat helps modernize legacy code by suggesting refactors and creating tests to catch potential issues.

Note

The responses shown in this article are examples. Copilot Chat responses are non-deterministic, so you may get different responses from the ones shown here.

Legacy code is code that is old, outdated, or no longer supported by the original developers. It can be difficult to maintain and extend because it may not follow modern best practices, such as using consistent naming conventions or writing clear documentation.

Modernizing legacy code can help you:

  • Improve performance and scalability.
  • Make the code easier to maintain and extend.
  • Reduce the risk of introducing bugs when making changes.
  • Make the code easier to test.

Copilot can help you modernize your legacy code by:

  • Providing suggestions for refactoring the code to follow modern best practices.
  • Generating documentation to help you understand how the code works.
  • Generating tests to help you verify that your changes haven't introduced bugs.

Example scenario

In this example, we’ll be looking at an account management system written in COBOL and modernizing it into Node.js. You can find the COBOL code in the modernize-legacy-cobol-app repository.

The account management system consists of three key files:

  • main.cob: The main program that reads input from the user and calls the appropriate subprogram.
  • operations.cob: A subprogram that performs operations on the account data, such as credit, debit, and view balance.
  • data.cob: A subprogram that manages the storage of the account balance.

Step 1: Get a local copy of the repository

Before you compile and run the program, you need to have the code locally. If you haven't already cloned the repository, navigate to the directory where you want to store the project and run the following command:

Shell
git clone https://github.com/continuous-copilot/modernize-legacy-cobol-app.git

Step 2: Compile and run the program

You can either install a COBOL compiler in your preferred development environment (for example, the open source GnuCOBOL compiler), or use Copilot Chat in GitHub Codespaces.

If you use MacOS, you can install GnuCOBOL using Homebrew:

Shell
brew install gnu-cobol

If you use Codespaces or an Ubuntu Linux system, you can install GnuCOBOL using apt:

Shell
sudo apt-get update && \
sudo apt-get install gnucobol

To compile the code, link the files, and create an executable, run the following command from the root of the repository:

Shell
cobc -x main.cob operations.cob data.cob -o accountsystem

To run the program, use the following command:

Shell
./accountsystem

Step 3: Explain the files and code

The first step in modernizing the code is to understand how it works. You can ask Copilot Chat to explain the code in each file.

Open the repository in your IDE then, in the Copilot Chat panel, enter the following prompt.

Example prompt 1

Copilot Chat prompt
/explain #file:main.cob #file:operations.cob #file:data.cob. Create a high level overview of the app. Explain each file in detail and how they are linked.

Example response 1

This is an excerpt from the response to the prompt above:

Sure! Here's a high-level overview of the COBOL application, along with detailed explanations of each file and how they are linked together.

High-Level Overview

This COBOL application simulates an account management system. It allows users to view the current balance, credit the account, debit the account, and exit the application. The application is divided into three main COBOL source files: main.cob, operations.cob, and data.cob. ...

Step 4: Chart out the data flow between the files

The next step is to understand how the files are linked together. You can use @workspace to create a data flow diagram for the application.

Note

The @workspace chat participant in VS Code and Visual Studio provides Copilot with context about all of the code in your workspace. You can use @workspace when you want Copilot to consider the structure of your project and how different parts of your code interact. If you're using a JetBrains IDE, use @project rather than @workspace.

Example prompt 2

Copilot Chat prompt
@workspace Create a sequence diagram of the app showing the data flow of the app. Create this in mermaid format so that I can render this in a markdown file.

Copilot outputs the Mermaid markup for a full sequence diagram that shows how the application works. You can copy and paste this markup into a Mermaid application to generate the diagram.

Step 5: Generate a test plan

Create a test plan to ensure that the application works as expected after you make changes. You can use @workspace to generate a test plan that covers all of the files in the project.

Example prompt 3

Copilot Chat prompt
@workspace The current COBOL app has no tests. Create a test plan of current business logic that I can use to validate with business stakeholders about the current implementation.

Later I would like to use this test plan to create unit and integration tests in a node.js app. I am in the middle of transforming the current COBOL app to a node.js app.

The test plan should include the following:

1. Test Case ID
2. Test Case Description
3. Pre-conditions
4. Test Steps
5. Expected Result
6. Actual Result
7. Status (Pass/Fail)
8. Comments

Create the test plan in a markdown table format. The test plan should cover all the business logic in the current COBOL app.

Convert this to markdown syntax to insert as a new file

Copilot outputs a test plan in Markdown format that you can use to validate the application. To use this plan later in the process, create a file called TESTPLAN.md and copy the suggested plan into it. This will allow you to reference the test plan when generating test cases in the next steps.

Step 6: Convert the files from COBOL to Node.js

The next step is to convert the COBOL files to Node.js. It's important to keep the following prompt practices in mind:

  • Provide context
  • Give clear directions
  • Be specific about the outcome you want to achieve

Start by creating a temporary directory within your project, in which to save the JavaScript files you're going to create.

Shell
mkdir temp-JS-project-directory

Then, iteratively convert the COBOL files to Node.js.

Example prompt 4

Copilot Chat prompt
Convert the code in #file:main.cob to node.js

Example response 4

Sure! Here is the equivalent Node.js code for the main.cob file. This code will simulate the same account management system functionality.

### COBOL Code:

main.cob

```COBOL
IDENTIFICATION DIVISION.
       PROGRAM-ID. MainProgram.

       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  CONTINUE-FLAG      PIC X VALUE 'Y'.
       01  USER-CHOICE        PIC 9.
       01  FINAL-BALANCE      PIC 9(6)V99 VALUE 1000.00.

       PROCEDURE DIVISION.
           PERFORM UNTIL CONTINUE-FLAG = 'N'
               DISPLAY "1. View Balance"
               DISPLAY "2. Credit Account"
               DISPLAY "3. Debit Account"
               DISPLAY "4. Exit"
               ACCEPT USER-CHOICE

               EVALUATE USER-CHOICE
                   WHEN 1
                       CALL 'Operations' USING 'TOTAL'
                   WHEN 2
                       CALL 'Operations' USING 'CREDIT'
                   WHEN 3
                       CALL 'Operations' USING 'DEBIT'
                   WHEN 4
                       MOVE 'N' TO CONTINUE-FLAG
                       DISPLAY "Exiting the program. Goodbye!"
                   WHEN OTHER
                       DISPLAY "Invalid choice. Please try again."
               END-EVALUATE
           END-PERFORM
           STOP RUN.

### Node.js Code: `main.js`
```javascript
const readline = require('readline');

let continueFlag = 'Y';
let finalBalance = 1000.00;

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

function displayMenu() {
    console.log("1. View Balance");
    console.log("2. Credit Account");
    console.log("3. Debit Account");
    console.log("4. Exit");
}

function handleUserChoice(choice) {
    switch (choice) {
        case '1':
            viewBalance();
            break;
        case '2':
            creditAccount();
            break;
        case '3':
            debitAccount();
            break;
        case '4':
            continueFlag = 'N';
            console.log("Exiting the program. Goodbye!");
            rl.close();
            break;
        default:
            console.log("Invalid choice. Please try again.");
            promptUser();
            break;
    }
}

function viewBalance() {
    console.log(`Current balance: ${finalBalance.toFixed(2)}`);
    promptUser();
}

function creditAccount() {
    rl.question("Enter credit amount: ", (amount) => {
        amount = parseFloat(amount);
        if (!isNaN(amount) && amount > 0) {
            finalBalance += amount;
            console.log(`Amount credited. New balance: ${finalBalance.toFixed(2)}`);
        } else {
            console.log("Invalid amount. Please try again.");
        }
        promptUser();
    });
}

function debitAccount() {
    rl.question("Enter debit amount: ", (amount) => {
        amount = parseFloat(amount);
        if (!isNaN(amount) && amount > 0) {
            if (finalBalance >= amount) {
                finalBalance -= amount;
                console.log(`Amount debited. New balance: ${finalBalance.toFixed(2)}`);
            } else {
                console.log("Insufficient funds for this debit.");
            }
        } else {
            console.log("Invalid amount. Please try again.");
        }
        promptUser();
    });
}

function promptUser() {
    if (continueFlag === 'Y') {
        displayMenu();
        rl.question("Select an option: ", handleUserChoice);
    }
}

promptUser();

This Node.js code replicates the functionality of the COBOL main.cob file, providing a simple command-line interface for viewing the balance, crediting the account, debiting the account, and exiting the application.

You should review the suggested code thoroughly before using it. Once you're satisf