Skip to main content

コードの読みやすさと保守容易性を改良する

Copilot Chat から、コードを理解し、保守しやすくする方法の提案を受けることができます。

読みづらいコードは、他の開発者にとって保守や拡張が困難です。 Copilot Chat はさまざまな方法で役立ちます。 例:

コードの保守性を改良するもう 1 つの方法は、コードの文書化です。 コードに役立つコメントを追加するために Copilot Chat を使う方法については、「コードの文書化」のプロンプト例を参照してください。

Note

この記事に示されている応答は例です。 Copilot Chat の応答は非決定的であるため、ここに示されているものとは異なる応答が返される可能性があります。

変数名を改善する

わかりやすい変数名とパラメーター名を使うと、その目的を理解しやすくなります。

サンプル シナリオ

この JavaScript コードを使うと、人の年齢に関するメッセージをコンソールにログできます。 抽象的なパラメーター名を使うと、コードの目的を理解することが難しくなります。

function logPersonsAge(a, b, c) {
  if (c) {
    console.log(a + " is " + b + " years old.");
  } else {
    console.log(a + " does not want to reveal their age.");
  }
}

プロンプトの例

エディターで、変更する関数を選んでから、Copilot Chat に尋ねます。

Improve the variable names in this function

応答の例

Copilot からは、わかりやすい変数名が提案されます。

function logPersonAge(name, age, revealAge) {
  if (revealAge) {
    console.log(name + " is " + age + " years old.");
  } else {
    console.log(name + " does not want to reveal their age.");
  }
}

連続した条件チェックを回避する

if...else チェーンは、特に長くなると読みづらくなります。

サンプル シナリオ

この Python コードにより、さまざまな動物の鳴き声 (定義されている場合)、または "Unknown animal" (動物の種類が認識されない場合) が出力されます。 ただし、if...else ステートメントのチェーンがあるので、コードは非効率的で煩雑です。

class Animal:
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "Woof!"

class Cat(Animal):
    def speak(self):
        return "Meow!"

class Bird(Animal):
    def speak(self):
        return "Tweet!"

def animal_sound(animal_type):
    if animal_type == "dog":
        return Dog().speak()
    elif animal_type == "cat":
        return Cat().speak()
    elif animal_type == "bird":
        return Bird().speak()
    else:
        return "Unknown animal"

print(animal_sound("dog"))
print(animal_sound("cat"))
print(animal_sound("bird"))
print(animal_sound("fish"))

プロンプトの例

Simplify this code. Avoid using if/else chains but retain all function return values.

応答の例

Copilot からは、ディクショナリを使って動物の種類をそれに対応するクラスにマップすることが提案されます。

class Animal:
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return "Woof!"

class Cat(Animal):
    def speak(self):
        return "Meow!"

class Bird(Animal):
    def speak(self):
        return "Tweet!"

def animal_sound(animal_type):
    animals = {
        "dog": Dog,
        "cat": Cat,
        "bird": Bird
    }
    animal_class = animals.get(animal_type, Animal)
    return animal_class().speak() if animal_class != Animal else "Unknown animal"

print(animal_sound("dog"))
print(animal_sound("cat"))
print(animal_sound("bird"))
print(animal_sound("fish"))

入れ子になったロジックを減らす

構造が深く入れ子になっていると、コードがわかりづらくなり、将来的にコードのロジックを変更したり拡張したりすることが困難になる可能性があります。

サンプル シナリオ

この Ruby コードにより、3 つのパラメーターに基づいてユーザー アカウントに関する情報が出力されます。 入れ子になった if...else ステートメントを使うと、コードが不必要に複雑になります。

def determine_access(user_role, has_permission, is_active)
  if user_role == "admin"
    if has_permission
      if is_active
        "Active admin account with full access."
      else
        "Inactive admin account."
      end
    else
      "Admin account lacks necessary permissions."
    end
  else
    "Access denied."
  end
end

puts determine_access("admin", true, true)
puts determine_access("admin", true, false)
puts determine_access("admin", false, true)
puts determine_access("user", true, true)

プロンプトの例

Rewrite this code to avoid the nested if/else statements

応答の例

Copilot からは、guard 句を使って条件を早期に処理し、適切なメッセージを返すことが提案されます。

def determine_access(user_role, has_permission, is_active)
  return "Access denied." unless user_role == "admin"
  return "Admin account lacks necessary permissions." unless has_permission
  return "Inactive admin account." unless is_active

  "Active admin account with full access."
end

puts determine_access("admin", true, true)
puts determine_access("admin", true, false)
puts determine_access("admin", false, true)
puts determine_access("user", true, true)

大規模なメソッドを分割する

メソッドや関数が長すぎると、その実行内容を正確に把握することが難しくなり、保守が困難になります。 複数のタスクを実行するメソッドまたは関数は、他のコンテキストでは再利用できない場合があります。 また、各タスクを分離してテストすることも難しい場合があります。

サンプル シナリオ

この Java メソッドは、顧客の注文を処理し、メッセージを出力するものです。 1 つのメソッドで複数のタスクが実行されます。

public void processOrder(Order order) {
  if (order == null || order.getItems().isEmpty()) {
    throw new IllegalArgumentException("Order is invalid.");
  }

  double totalPrice = 0.0;
  for (Item item : order.getItems()) {
    totalPrice += item.getPrice() * item.getQuantity();
  }
  order.setTotalPrice(totalPrice);

  if (totalPrice > 0) {
    order.setStatus("Processed");
  } else {
    order.setStatus("Pending");
  }

  System.out.println("Order for customer " + order.getCustomerName() + " has been processed. Total price: " + totalPrice);
}

プロンプトの例

How could the processOrder method be refactored to be more useful and easier to maintain

応答の例

Copilot からは、このメソッドをより小さく、より焦点を絞ったメソッドに分割することが提案されます。

public void processOrder(Order order) {
    validateOrder(order);
    double totalPrice = calculateTotalPrice(order);
    updateOrderStatus(order, totalPrice);
    printOrderSummary(order, totalPrice);
}

private void validateOrder(Order order) {
    if (order == null || order.getItems().isEmpty()) {
        throw new IllegalArgumentException("Order is invalid.");
    }
}

private double calculateTotalPrice(Order order) {
    double totalPrice = 0.0;
    for (Item item : order.getItems()) {
        totalPrice += item.getPrice() * item.getQuantity();
    }
    order.setTotalPrice(totalPrice);
    return totalPrice;
}

private void updateOrderStatus(Order order, double totalPrice) {
    if (totalPrice > 0) {
        order.setStatus("Processed");
    } else {
        order.setStatus("Pending");
    }
}

private void printOrderSummary(Order order, double totalPrice) {
    System.out.println("Order for customer " + order.getCustomerName() + " has been processed. Total price: " + totalPrice);
}

参考資料