跳至主要内容

使用 GitHub Copilot 现代化遗留代码

Copilot Chat 通过提供重构建议和创建测试来帮助现代化遗留代码,以捕获潜在问题。

注意

本文中显示的响应为示例。Copilot Chat 的响应是非确定性的,因此您可能会得到与此处显示不同的响应。

遗留代码是指旧的、已过时的或原开发人员不再支持的代码。由于它可能不遵循现代最佳实践(比如使用一致的命名约定或编写清晰的文档),维护和扩展起来可能很困难。

现代化遗留代码可以帮助您

  • 提升性能和可扩展性。
  • 使代码更易于维护和扩展。
  • 降低在修改时引入错误的风险。
  • 使代码更易于测试。

Copilot 可以通过以下方式帮助您现代化遗留代码:

  • 提供建议以重构代码,使其遵循现代最佳实践。
  • 生成文档,帮助您了解代码的工作方式。
  • 生成测试,帮助您验证更改未引入错误。

示例情景

在本示例中,我们将查看一个用 COBOL 编写的账户管理系统,并将其现代化为 Node.js。您可以在 modernize-legacy-cobol-app 仓库中找到 COBOL 代码。

该账户管理系统由三个关键文件组成

  • main.cob:主程序,读取用户输入并调用相应的子程序。
  • operations.cob:一个子程序,对账户数据执行操作,例如存款、取款和查看余额。
  • data.cob:一个子程序,管理账户余额的存储。

步骤 1:获取仓库的本地副本

在编译和运行程序之前,您需要在本地获取代码。如果尚未克隆仓库,请导航到想要存放项目的目录并运行以下命令。

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

步骤 2:编译并运行程序

您可以在首选的开发环境中安装 COBOL 编译器(例如开源的 GnuCOBOL 编译器),或在 GitHub Codespaces 中使用 Copilot Chat。

如果您使用 macOS,可以通过 Homebrew 安装 GnuCOBOL。

Shell
brew install gnu-cobol

如果您使用 Codespaces 或 Ubuntu Linux 系统,可以使用 apt 安装 GnuCOBOL。

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

要编译代码、链接文件并生成可执行文件,请在仓库根目录运行以下命令。

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

要运行程序,请使用以下命令。

Shell
./accountsystem

步骤 3:解释文件和代码

现代化代码的第一步是了解其工作原理。您可以让 Copilot Chat 解释每个文件中的代码。

在您的 IDE 中打开仓库,然后在 Copilot Chat 面板中输入以下提示。

示例提示 1

Copilot 提示
/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.

示例响应 1

以下是对上述提示的响应摘录

当然!以下是该 COBOL 应用程序的高级概述,以及对每个文件及其相互链接方式的详细解释。

高级概述

该 COBOL 应用程序模拟了一个账户管理系统。它允许用户查看当前余额、对账户进行存款、取款以及退出应用程序。应用程序分为三个主要的 COBOL 源文件:main.cob、operations.cob 和 data.cob ……

步骤 4:绘制文件之间的数据流图

下一步是了解文件之间是如何链接的。您可以使用 @workspace 为应用程序创建数据流图。

注意

VS Code 和 Visual Studio 中的 @workspace 聊天参与者为 Copilot 提供了工作区中所有代码的上下文。当您希望 Copilot 考虑项目结构及代码各部分的交互时,可以使用 @workspace。如果您使用 JetBrains IDE,请使用 @project 而不是 @workspace

示例提示 2

Copilot 提示
@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 会输出 Mermaid 标记语言,生成展示应用程序工作方式的完整时序图。您可以将此标记复制粘贴到 Mermaid 应用中生成图表。

步骤 5:生成测试计划

创建测试计划,以确保在进行更改后应用程序仍能按预期工作。您可以使用 @workspace 生成覆盖项目中所有文件的测试计划。

示例提示 3

Copilot 提示
@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 以 Markdown 格式输出测试计划,您可以使用它来验证应用程序。稍后在流程中使用此计划时,创建一个名为 TESTPLAN.md 的文件,并将建议的计划复制进去。这将使您在后续生成测试用例时能够参考该测试计划。

步骤 6:将文件从 COBOL 转换为 Node.js

下一步是将 COBOL 文件转换为 Node.js。请牢记以下提示实践要点。

  • 提供上下文
  • 给出明确指示
  • 明确您想要实现的结果

首先在项目中创建一个临时目录,用于保存即将创建的 JavaScript 文件。

Shell
mkdir temp-JS-project-directory

然后,逐步将 COBOL 文件转换为 Node.js。

示例提示 4

Copilot 提示
Convert the code in #file:main.cob to node.js

示例响应 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.

在使用之前,请彻底审查建议的代码。确认生成的代码满足需求后,按照以下步骤将其保存到本地并完成转换。

  1. 在之前创建的临时目录中,创建一个名为 main.js 的新文件。
  2. 从 Copilot Chat 面板复制生成的代码并粘贴到 main.js 中。
  3. 保存文件。
  4. 使用类似的提示将 operations.cobdata.cob 转换为 Node.js。
  5. 在同一临时目录中创建相应的 JavaScript 文件 operations.jsdata.js
  6. 将生成的代码复制粘贴到各文件中,然后保存。

在将所有文件转换为 Node.js 后,需要将它们链接在一起并建立一个可运行的 Node.js 项目。

  1. 在终端中进入临时目录。

  2. 运行以下命令以创建 package.json 文件

    Shell
    npm init -y
    
  3. 如果您的应用需要外部包,请运行以下命令安装它们

    Shell
    npm install
    
  4. 运行以下命令启动应用

    Shell
    npm start
    

此时,Node.js 应用可能尚未完全复制原始 COBOL 程序的功能。例如,余额可能未正确更新,或计算可能与 COBOL 逻辑不一致。

要改进该应用,您需要

  • 通过运行程序并与 COBOL 版本对比,识别不正确的行为。

  • 与 Copilot 迭代合作,调整逻辑直至 Node.js 程序表现如预期。

  • 使用有针对性的提示来调试和改进代码的特定部分,例如

    Copilot 提示
    @workspace - analyze main.js and ensure the account balance updates correctly when crediting an account.
    

重构遗留代码并非一次性完成的过程——在您细化新的 Node.js 实现时,Copilot 可以帮助调试和提升功能。

步骤 8:生成单元测试和集成测试

下一步是生成单元测试和集成测试,以确保应用程序按预期工作。您可以使用 @workspace 生成覆盖项目中所有文件的测试计划。

示例提示 5

Copilot 提示
@workspace I would like to create unit and integration tests cases from the test plan mentioned in #file:TESTPLAN.md file. The node.js code is in the node-accounting-app folder and I am looking to generate tests for #file:operations.js file. Use a popular testing framework and also provide all the dependencies required to run the tests.

示例响应 5

Copilot 生成了一系列基于 Jest(JavaScript 测试框架)的测试,并提供了完整的分步指南,说明如何实现和运行这些测试。

以下是对上述提示的响应摘录

“此测试计划覆盖了 COBOL 应用程序的主要功能,包括查看余额、存款、取款和退出应用程序。测试用例使用 Jest(Node.js 的流行测试框架)实现。请与业务相关方验证此测试计划,以确保其满足业务需求。验证通过后,您可以使用该计划为 Node.js 应用创建相应的单元测试和集成测试。”

步骤 9:运行测试并优化代码

生成测试计划并编写测试后,您需要运行它们并修复任何失败的测试。测试是一个迭代过程,您可能需要修改代码以解决问题,然后重新运行测试,直至全部通过。

如果测试失败,可使用 Copilot 帮助调试并完善实现。

示例提示 6

Copilot 提示
@workspace - analyze test failures in operations.test.js and suggest fixes to match the expected behavior.

即使所有测试均通过,程序仍可能存在问题。自动化测试并不总能捕获缺失的功能或逻辑错误,因此需要进行手动测试,以确保应用程序按预期运行。

步骤 10:将 JavaScript 项目移动到新位置

当应用按预期工作后,将新的 JavaScript 项目从 COBOL 目录中移出,以保持两者分离。

  1. 导航至 COBOL 项目的父目录。

  2. 将 JavaScript 项目移动到新位置

    Shell
    mv modernize-legacy-cobol-app new-js-project
    
  3. 进入新项目目录,确认所有内容正常运行

    Shell
    cd new-js-project
    npm start
    

现在,已重构的 Node.js 应用位于其独立的项目文件夹中,独立于原始的 COBOL 文件。

结论

在本示例中,我们查看了一个用 COBOL 编写的账户管理系统,并将其现代化为 Node.js。我们使用 Copilot Chat 解释代码、绘制数据流、生成测试计划,并将代码转换为 Node.js。遵循这些步骤,您即可现代化遗留代码,使其更易于维护和扩展。以下是现代化遗留代码的额外提示:

  • 提示最佳实践至关重要:提示的质量决定了 Copilot 建议的质量。提供清晰的上下文,将复杂任务拆分为更小的步骤,提供示例,并为 Copilot 设定具体目标。这将使工作流程更顺畅,结果更精准。
  • 在使用前审查代码:在将 Copilot 提供的代码用于您的应用之前,请确保您理解其内容。这有助于发现潜在问题,并确保代码符合您的要求。
  • 验证您的更改:在对代码进行更改后,务必验证应用仍能按预期工作。您可以使用 Copilot 生成的测试计划来创建单元测试和集成测试。

实战练习

通过 使用 GitHub Copilot 现代化您的遗留代码 技能练习 来实践现代化遗留代码。

在此练习中,你将学习如何

  • 使用 GitHub Copilot Chat 分析遗留 COBOL 代码,以了解业务逻辑。
  • 生成文档,例如 Mermaid 数据流图和测试计划。
  • 使用 Copilot 将 COBOL 代码库转换为 Node.js。
  • 根据生成的测试计划创建单元测试。

延伸阅读

© . This site is unofficial and not affiliated with GitHub, Inc.