# 使用 GitHub Copilot 重构代码

利用 Copilot 人工智能帮助你快速有效地重构代码。

## 简介

重构代码是重新构建现有代码的过程，而不更改其外部行为的过程。 重构的好处包括提高代码可读性、降低复杂性、使代码更易于维护，并可以更轻松地添加新功能。

本文提供了使用 Copilot 在 IDE 中重构代码的一些想法。

> \[!NOTE] 本文中包含示例响应。 GitHub Copilot 聊天功能 可能会为你提供与此处所示不同的响应。

## 了解代码

在修改现有代码之前，应确保了解其用途及其当前工作原理。 Copilot 可以帮助达到此目的。

1. 在 IDE 的编辑器中选择相关代码。
2. 打开内联聊天：

   * **在 VS Code 中：** 按“命令”<kbd></kbd>+<kbd>i</kbd> (Mac) 或 <kbd>Ctrl</kbd>+<kbd>i</kbd> (Windows/Linux)。
   * **在 Visual Studio 中：** 按 <kbd>Alt</kbd>+<kbd>/</kbd>。
   * **在 JetBrains IDEs 中：** 按 <kbd>Control</kbd>+<kbd>Shift</kbd>+<kbd>i</kbd> (Mac) 或 <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>g</kbd> (Windows/Linux)。
3. 在内联聊天的输入框中，键入正斜杠 (`/`)。
4. 在下拉列表中，选择“/explain”\*\*\*\*，然后按“Enter”<kbd></kbd>。
5. 如果 Copilot 返回的解释多于几行，请单击“聊天中的视图”\*\*\*\*，以便更轻松地阅读说明。

## 优化低效代码

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

### 示例代码

在下面的两个部分中，我们将使用以下示例 bash 脚本来演示如何优化低效代码：

```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 可以告诉你是否可以优化代码（如示例 bash 脚本）。

1. 选择 `for` 循环或文件的全部内容。

2. 单击活动栏中的聊天图标或使用键盘快捷方式打开 副驾驶聊天：

   * **VS Code 和 Visual Studio：**<kbd>Control</kbd>+<kbd>Command</kbd>+<kbd>i</kbd> (Mac) / <kbd>Ctrl</kbd>+<kbd>Alt</kbd>+<kbd>i</kbd> (Windows/Linux)
   * **JetBrains**：<kbd>Control</kbd>+<kbd>Shift</kbd>+<kbd>c</kbd>

3. 在聊天面板底部的输入框中，键入：`Can this script be improved?`

   Copilot 回复一项将提高代码效率的建议。

4. 若要应用建议的更改，请执行以下操作：

   * **在 VS Code 和 JetBrains 中：** 将鼠标悬停在聊天面板中的建议上方，然后单击“在光标处插入”\*\*\*\* 图标。

     ![副驾驶聊天 面板中“在光标处插入”图标的屏幕截图。](/assets/images/help/copilot/insert-at-cursor.png)

   * **在 Visual Studio 中：** 单击“预览”****，然后在比较视图中单击“接受”****。

### 使用 Copilot 内联聊天

或者，如果已经知道现有代码（如示例 bash 脚本）效率低下：

1. 选择 `for` 循环或文件的全部内容。

2. 打开内联聊天：

   * **在 VS Code 中：** 按“命令”<kbd></kbd>+<kbd>i</kbd> (Mac) 或 <kbd>Ctrl</kbd>+<kbd>i</kbd> (Windows/Linux)。
   * **在 Visual Studio 中：** 按 <kbd>Alt</kbd>+<kbd>/</kbd>。
   * **在 JetBrains IDEs 中：** 按 <kbd>Control</kbd>+<kbd>Shift</kbd>+<kbd>i</kbd> (Mac) 或 <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>g</kbd> (Windows/Linux)。

3. 键入 `optimize`，然后按“Enter”<kbd></kbd>。

   Copilot 建议修订代码。 例如：

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

   这比本文前面所示的原始代码更有效，因为使用 `-exec ... +` 允许 `find` 一次性将多个文件传递到 `wc`，而不是为找到的每个 `wc` 文件分别调用 `*.txt`。

4. 如果你同意更改，评估 Copilot 的建议：

   * **在 VS Code 和 Visual Studio 中：** 单击“接受”\*\*\*\*。
   * **在 JetBrains 中**：单击“预览”图标（双箭头），然后单击“应用所有差异”图标（双尖括号）。

与所有 Copilot 建议一样，应始终检查修改后的代码运行时是否没有错误，并产生正确的结果。

## 清理重复的代码

避免重复将使代码更易于修改和调试。 例如，如果同一计算在文件不同位置重复出现，可以将其封装为函数。

在以下非常简单的 JavaScript 示例中，在两个位置执行相同的计算（商品价格乘以销售的商品数）。

```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 中：** 按“命令”<kbd></kbd>+<kbd>i</kbd> (Mac) 或 <kbd>Ctrl</kbd>+<kbd>i</kbd> (Windows/Linux)。
   * **在 Visual Studio 中：** 按 <kbd>Alt</kbd>+<kbd>/</kbd>。
   * **在 JetBrains IDEs 中：** 按 <kbd>Control</kbd>+<kbd>Shift</kbd>+<kbd>i</kbd> (Mac) 或 <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>g</kbd> (Windows/Linux)。

3. 键入 `move repeated calculations into functions`，然后按“Enter”<kbd></kbd>。

   Copilot 建议修订代码。 例如：

   ```javascript
   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 中：** 单击“接受”\*\*\*\*。
   * **在 JetBrains 中**：单击“预览”图标（双箭头），然后单击“应用所有差异”图标（双尖括号）。

与所有 Copilot 建议一样，应始终检查修改后的代码运行时是否没有错误，并产生正确的结果。

## 使代码更加简洁

如果代码没必要太冗长，则很难读取和维护。 Copilot 可以建议选定代码的更简洁版本。

在以下示例中，此 Python 代码输出矩形和圆的区域，但可以更简洁地编写：

```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 中：** 按“命令”<kbd></kbd>+<kbd>i</kbd> (Mac) 或 <kbd>Ctrl</kbd>+<kbd>i</kbd> (Windows/Linux)。
   * **在 Visual Studio 中：** 按 <kbd>Alt</kbd>+<kbd>/</kbd>。
   * **在 JetBrains IDEs 中：** 按 <kbd>Control</kbd>+<kbd>Shift</kbd>+<kbd>i</kbd> (Mac) 或 <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>g</kbd> (Windows/Linux)。

3. 键入 `make this more concise`，然后按“Enter”<kbd></kbd>。

   Copilot 建议修订代码。 例如：

   ```python
   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 中：** 单击“接受”\*\*\*\*。
   * **在 JetBrains 中**：单击“预览”图标（双箭头），然后单击“应用所有差异”图标（双尖括号）。

与所有 Copilot 建议一样，应始终检查修改后的代码运行时是否没有错误，并产生正确的结果。

## 拆分复杂的代码单元

执行多个操作的大型方法或函数可能比专注于执行特定操作的较小、更简单的函数提供的重用机会更少。 它们还可能更难理解和调试。

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

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

```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 中：** 按“命令”<kbd></kbd>+<kbd>i</kbd> (Mac) 或 <kbd>Ctrl</kbd>+<kbd>i</kbd> (Windows/Linux)。
   * **在 Visual Studio 中：** 按 <kbd>Alt</kbd>+<kbd>/</kbd>。
   * **在 JetBrains IDEs 中：** 按 <kbd>Control</kbd>+<kbd>Shift</kbd>+<kbd>i</kbd> (Mac) 或 <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>g</kbd> (Windows/Linux)。

3. 键入 `split into 2 separate functions: one for cleansing data, the other for printing`，然后按“Enter”<kbd></kbd>。

   Copilot 建议修订代码。 例如：

   ```python
   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)
   ```

   > \[!NOTE] 上面显示的示例建议将现有函数替换为三个函数。 第三个函数只调用其他两个函数，并允许调用 `process_data` 函数的现有代码。

4. 如果你同意更改，评估 Copilot 的建议：

   * **在 VS Code 和 Visual Studio 中：** 单击“接受”\*\*\*\*。
   * **在 JetBrains 中**：单击“预览”图标（双箭头），然后单击“应用所有差异”图标（双尖括号）。

与所有 Copilot 建议一样，应始终检查修改后的代码运行时是否没有错误，并产生正确的结果。

## 重写条件代码以提高可读性

根据不同的条件，通常有几种方法可以编写执行或不执行的代码。 特定用例中某些条件结构更具优势，选择合适的条件结构有时可以让代码更易理解。

此 Java 方法使用一系列 `if` 和 `else if` 语句来确定要执行的操作：

```java
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 中：** 按“命令”<kbd></kbd>+<kbd>i</kbd> (Mac) 或 <kbd>Ctrl</kbd>+<kbd>i</kbd> (Windows/Linux)。
   * **在 Visual Studio 中：** 按 <kbd>Alt</kbd>+<kbd>/</kbd>。
   * **在 JetBrains IDEs 中：** 按 <kbd>Control</kbd>+<kbd>Shift</kbd>+<kbd>i</kbd> (Mac) 或 <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>g</kbd> (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. 按 <kbd>Enter</kbd>。

   Copilot 建议修订代码。 例如：

   ```java
   /**
    * 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 中：** 单击“接受”\*\*\*\*。
   * **在 JetBrains 中**：单击“预览”图标（双箭头），然后单击“应用所有差异”图标（双尖括号）。

与所有 Copilot 建议一样，应始终检查修改后的代码运行时是否没有错误，并产生正确的结果。

## 重新格式化代码以使用其他结构

假设你在 JavaScript 中具有此函数：

```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 中：** 按“命令”<kbd></kbd>+<kbd>i</kbd> (Mac) 或 <kbd>Ctrl</kbd>+<kbd>i</kbd> (Windows/Linux)。
   * **在 Visual Studio 中：** 按 <kbd>Alt</kbd>+<kbd>/</kbd>。
   * **在 JetBrains IDEs 中：** 按 <kbd>Control</kbd>+<kbd>Shift</kbd>+<kbd>i</kbd> (Mac) 或 <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>g</kbd> (Windows/Linux)。
3. 键入 `use arrow notation and better parameter names`，然后按“Enter”<kbd></kbd>。

   Copilot 建议修订代码。 例如：

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

## 改进符号的名称

> \[!NOTE]
>
> * 仅限 VS Code 和 Visual Studio。
> * 对此功能的支持取决于在 IDE 中为所使用的语言安装适当的语言扩展。 并非所有语言扩展都支持此功能。

精心选择的名称有助于使代码更易于维护。 利用 Copilot 和 VS Code 中的 Visual Studio，可以建议变量或函数等符号的替代名称。

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

2. 按“F2”<kbd></kbd>。

3. ```
          **仅 Visual Studio：** 按 <kbd>Ctrl</kbd>+<kbd>Space</kbd>。
   ```

   Copilot 建议使用可选名称。

   ![VS Code 中提供符号名称的替代项的下拉列表的屏幕截图。](/assets/images/help/copilot/rename-symbol.png)

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

   整个项目的名称都被更改。