跳至主要内容

使用 GitHub Copilot 重构代码

利用 Copilot 人工智能帮助您快速且高效地重构代码。

简介

重构代码是对已有代码进行结构调整的过程,但不改变其行为。重构的好处包括提高代码可读性、降低复杂度、使代码更易维护,以及更方便地添加新功能。

本文为您提供了一些在 IDE 中使用 Copilot 重构代码的思路。

注意

本文中包含示例回复。GitHub Copilot 聊天可能会给出与此处示例不同的回复。

理解代码

在修改已有代码之前,您应确保了解其目的及当前的工作方式。Copilot 能帮助您完成这一步。

  1. 在 IDE 编辑器中选择相关代码。

  2. 打开行内聊天

    • 在 VS Code 中:Command+i(Mac)或 Ctrl+i(Windows/Linux)。
    • 在 Visual Studio 中:Alt+/
    • 在 JetBrains IDE 中:Control+Shift+i(Mac)或 Ctrl+Shift+g(Windows/Linux)。
  3. 在行内聊天的输入框中,输入斜杠(/)。

  4. 在下拉列表中,选择 /explain 并按 Enter

  5. 如果 Copilot 返回的解释超过几行,点击 在聊天中查看 以便更轻松阅读。

优化低效代码

Copilot 可以帮助您优化代码,例如,使代码运行更快。

示例代码

在下面的两个章节中,我们将使用以下示例 Bash 脚本来演示如何优化低效代码。

#!/bin/bash

# Find all .txt files and count lines in each
for file in $(find . -type f -name "*.txt"); do
    wc -l "$file"
done

使用 Copilot 聊天面板

Copilot 可以告诉您类似示例 Bash 脚本的代码是否可以优化。

  1. 选择 for 循环或整个文件的内容。

  2. 通过点击活动栏中的聊天图标或使用键盘快捷键打开 Copilot 聊天。

    • VS Code 和 Visual Studio: Control+Command+i(Mac)/ Ctrl+Alt+i(Windows/Linux)
    • JetBrains: Control+Shift+c
  3. 在聊天面板底部的输入框中键入:Can this script be improved?

    Copilot 会回复一个使代码更高效的建议。

  4. 要应用建议的更改

    • 在 VS Code 和 JetBrains 中: 将鼠标悬停在聊天面板的建议上,然后点击 Insert At Cursor 图标。

      Screenshot of the 'Insert at cursor' icon in the Copilot Chat panel.

    • 在 Visual Studio 中: 点击 Preview,然后在对比视图中点击 Accept

使用 Copilot 行内聊天

或者,如果您已经知道现有代码(如示例 Bash 脚本)效率低下

  1. 选择 for 循环或整个文件的内容。

  2. 打开行内聊天

    • 在 VS Code 中:Command+i(Mac)或 Ctrl+i(Windows/Linux)。
    • 在 Visual Studio 中:Alt+/
    • 在 JetBrains IDE 中:Control+Shift+i(Mac)或 Ctrl+Shift+g(Windows/Linux)。
  3. 键入 optimize 并按 Enter

    Copilot 提供改进后的代码。例如

    find . -type f -name "*.txt" -exec wc -l {} +
    

    这比本文前面展示的原始代码更高效,因为使用 -exec ... + 使 find 能一次性将多个文件传递给 wc,而不是对每个找到的 *.txt 文件都单独调用一次 wc

  4. 评估 Copilot 的建议,如果您同意该更改

    • 在 VS Code 和 Visual Studio 中: 点击 Accept
    • 在 JetBrains 中: 点击预览图标(双箭头),然后点击应用全部差异图标(双尖括号)。

和所有 Copilot 建议一样,您应始终检查改进后的代码是否能无错误运行并产生正确结果。

清理重复代码

避免重复会让代码更易于修改和调试。例如,如果同一计算在文件的不同位置多次执行,您可以将该计算抽取到函数中。

在下面这个非常简单的 JavaScript 示例中,同一计算(商品价格乘以售出数量)在两个位置出现。

let totalSales = 0;

let applePrice = 3;
let applesSold = 100;
totalSales += applePrice * applesSold;

let orangePrice = 5;
let orangesSold = 50;
totalSales += orangePrice * orangesSold;

console.log(`Total: ${totalSales}`);

您可以请求 Copilot 将重复的计算移入函数中。

  1. 选择文件的全部内容。

  2. 打开行内聊天

    • 在 VS Code 中:Command+i(Mac)或 Ctrl+i(Windows/Linux)。
    • 在 Visual Studio 中:Alt+/
    • 在 JetBrains IDE 中:Control+Shift+i(Mac)或 Ctrl+Shift+g(Windows/Linux)。
  3. 键入:move repeated calculations into functions 并按 Enter

    Copilot 提供改进后的代码。例如

    function calculateSales(price, quantity) {
      return price * quantity;
    }
    
    let totalSales = 0;
    
    let applePrice = 3;
    let applesSold = 100;
    totalSales += calculateSales(applePrice, applesSold);
    
    let orangePrice = 5;
    let orangesSold = 50;
    totalSales += calculateSales(orangePrice, orangesSold);
    
    console.log(`Total: ${totalSales}`);
    
  4. 评估 Copilot 的建议,如果您同意该更改

    • 在 VS Code 和 Visual Studio 中: 点击 Accept
    • 在 JetBrains 中: 点击预览图标(双箭头),然后点击应用全部差异图标(双尖括号)。

和所有 Copilot 建议一样,您应始终检查改进后的代码是否能无错误运行并产生正确结果。

让代码更简洁

如果代码冗长,阅读和维护会变得困难。Copilot 可以为所选代码提供更简洁的版本建议。

在下面的示例中,这段 Python 代码输出矩形和圆的面积,但可以写得更简洁。

def calculate_area_of_rectangle(length, width):
    area = length * width
    return area

def calculate_area_of_circle(radius):
    import math
    area = math.pi * (radius ** 2)
    return area

length_of_rectangle = 10
width_of_rectangle = 5
area_of_rectangle = calculate_area_of_rectangle(length_of_rectangle, width_of_rectangle)
print(f"Area of rectangle: {area_of_rectangle}")

radius_of_circle = 7
area_of_circle = calculate_area_of_circle(radius_of_circle)
print(f"Area of circle: {area_of_circle}")
  1. 选择文件的全部内容。

  2. 打开行内聊天

    • 在 VS Code 中:Command+i(Mac)或 Ctrl+i(Windows/Linux)。
    • 在 Visual Studio 中:Alt+/
    • 在 JetBrains IDE 中:Control+Shift+i(Mac)或 Ctrl+Shift+g(Windows/Linux)。
  3. 键入:make this more concise 并按 Enter

    Copilot 提供改进后的代码。例如

    import math
    
    def calculate_area_of_rectangle(length, width):
      return length * width
    
    def calculate_area_of_circle(radius):
      return math.pi * (radius ** 2)
    
    print(f"Area of rectangle: {calculate_area_of_rectangle(10, 5)}")
    print(f"Area of circle: {calculate_area_of_circle(7)}")
    
  4. 评估 Copilot 的建议,如果您同意该更改

    • 在 VS Code 和 Visual Studio 中: 点击 Accept
    • 在 JetBrains 中: 点击预览图标(双箭头),然后点击应用全部差异图标(双尖括号)。

和所有 Copilot 建议一样,您应始终检查改进后的代码是否能无错误运行并产生正确结果。

拆分复杂代码单元

执行多项操作的大方法或函数通常比专注于单一操作的更小、更简洁的函数提供更少的复用机会,而且也更难理解和调试。

Copilot 可以帮助您将复杂代码块拆分为更适合复用的更小单元。

下面的 Python 代码是一个非常简单的示例,但它展示了将单个函数拆分为两个执行特定操作的函数的原理。

import pandas as pd
from pandas.io.formats.style import Styler

def process_data(item, price):
    # Cleanse data
    item = item.strip()  # Strip whitespace from item
    price = price.strip()  # Strip whitespace from price
    price = float(price) # Convert price to a float
    # More cleansing operations here

    # Create and print a DataFrame
    data = {'Item': [item], 'Price': [price]}
    df = pd.DataFrame(data)
    print(df.to_string(index=False))

# Example usage
item = "   Apple "
price = " 1.25"
process_data(item, price)

拆分 process_data 函数

  1. 将光标置于函数名称处。

  2. 打开行内聊天

    • 在 VS Code 中:Command+i(Mac)或 Ctrl+i(Windows/Linux)。
    • 在 Visual Studio 中:Alt+/
    • 在 JetBrains IDE 中:Control+Shift+i(Mac)或 Ctrl+Shift+g(Windows/Linux)。
  3. 键入:split into 2 separate functions: one for cleansing data, the other for printing 并按 Enter

    Copilot 提供改进后的代码。例如

    def cleanse_data(item, price):
      # Cleanse data
      item = item.strip()  # Strip whitespace from item
      price = price.strip()  # Strip whitespace from price
      price = float(price)  # Convert price to a float
      return item, price
    
    def print_data(item, price):
      # Create and print a DataFrame
      data = {'Item': [item], 'Price': [price]}
      df = pd.DataFrame(data)
      print(df.to_string(index=False))
    
    def process_data(item, price):
      item, price = cleanse_data(item, price)
      print_data(item, price)
    

    注意

    上面示例的建议将原有函数替换为三个函数。第三个函数仅调用另外两个函数,从而兼容已有调用 process_data 函数的代码。

  4. 评估 Copilot 的建议,如果您同意该更改

    • 在 VS Code 和 Visual Studio 中: 点击 Accept
    • 在 JetBrains 中: 点击预览图标(双箭头),然后点击应用全部差异图标(双尖括号)。

和所有 Copilot 建议一样,您应始终检查改进后的代码是否能无错误运行并产生正确结果。

重写条件代码以提升可读性

针对不同条件,代码的执行与否通常有多种写法。某些条件结构比其他结构更适合特定场景,选择替代的条件结构有时可以使代码更易阅读。

此 Java 方法使用一系列 ifelse if 语句来决定执行哪个操作

public String getSound(String animal) {
  if (animal == null) {
      System.out.println("Oops! A null animal?");
  } else if (animal.equalsIgnoreCase("Dog")) {
      return "Bark";
  } else if ( animal.equalsIgnoreCase("Cat")) {
      return "Meow";
  } else if ( animal.equalsIgnoreCase("Bird")) {
      return "Tweet";
  }
  return "Unknown";
}

使用 switch 语句可能是更好的实现方式。

  1. 将光标置于方法名称处。

  2. 打开行内聊天

    • 在 VS Code 中:Command+i(Mac)或 Ctrl+i(Windows/Linux)。
    • 在 Visual Studio 中:Alt+/
    • 在 JetBrains IDE 中:Control+Shift+i(Mac)或 Ctrl+Shift+g(Windows/Linux)。
  3. 键入:rewrite the condition to use a switch and use Java 21 syntax with null case, but also add documentation and provide a better function name

    这演示了如何使用单个提示请求 Copilot 进行多项更改。

  4. Enter

    Copilot 提供改进后的代码。例如

    /**
     * Retrieves the sound made by a given animal.
     *
     * @param animal The name of the animal.
     * @return The sound made by the animal, or "Unknown" if the animal is not recognized.
     */
    public String getAnimalSound(String animal) {
        return switch (animal) {
            case null -> {
                System.out.println("Oops! A null animal?");
                yield "Unknown";
            }
            case String a when a.equalsIgnoreCase("Dog") -> "Bark";
            case String a when a.equalsIgnoreCase("Cat") -> "Meow";
            case String a when a.equalsIgnoreCase("Bird") -> "Tweet";
            default -> "Unknown";
        };
    }
    
  5. 评估 Copilot 的建议,如果您同意该更改

    • 在 VS Code 和 Visual Studio 中: 点击 Accept
    • 在 JetBrains 中: 点击预览图标(双箭头),然后点击应用全部差异图标(双尖括号)。

和所有 Copilot 建议一样,您应始终检查改进后的代码是否能无错误运行并产生正确结果。

重新格式化代码以使用不同的结构

假设您有以下 JavaScript 函数

function listRepos(o, p) {
 return fetch(`https://api.github.com/orgs/${o}/repos?per_page=${parseInt(p)}`)
   .then((response) => response.json())
   .then( (data) => data);
}

如果您的编码规范要求使用箭头函数表示法,并为参数使用描述性名称,您可以使用 Copilot 来帮助完成这些更改。

  1. 将光标置于函数名称处。

  2. 打开行内聊天

    • 在 VS Code 中:Command+i(Mac)或 Ctrl+i(Windows/Linux)。
    • 在 Visual Studio 中:Alt+/
    • 在 JetBrains IDE 中:Control+Shift+i(Mac)或 Ctrl+Shift+g(Windows/Linux)。
  3. 键入:use arrow notation and better parameter names 并按 Enter

    Copilot 提供改进后的代码。例如

    const listRepos = (org, perPage) => {
      return fetch(`https://api.github.com/orgs/${org}/repos?per_page=${parseInt(perPage)}`)
        .then(response => response.json())
        .then(data => data);
    };
    

改进符号的名称

注意

  • 仅适用于 VS Code 和 Visual Studio。
  • 此功能的支持取决于您在 IDE 中为所使用语言安装了相应的语言扩展,并非所有语言扩展都支持该功能。

恰当的命名有助于提升代码的可维护性。VS Code 和 Visual Studio 中的 Copilot 可为变量或函数等符号提供替代名称建议。

  1. 将光标置于符号名称处。

  2. F2

  3. 仅 Visual Studio:Ctrl+Space

    Copilot 提供替代名称建议。

    Screenshot of a dropdown list in VS Code giving alternatives for a symbol name.

  4. 在下拉列表中,选择一个建议的名称。

    名称将在整个项目中同步更改。

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