{"meta":{"title":"コードの読みやすさと保守容易性を改良する","intro":"コパイロットチャット は、コードの理解と保守を容易にする方法を提案できます。","product":"GitHub Copilot","breadcrumbs":[{"href":"/ja/copilot","title":"GitHub Copilot"},{"href":"/ja/copilot/tutorials","title":"チュートリアル"},{"href":"/ja/copilot/tutorials/copilot-chat-cookbook","title":"GitHub Copilot チャットクックブック"},{"href":"/ja/copilot/tutorials/copilot-chat-cookbook/refactor-code","title":"コードのリファクタリング"},{"href":"/ja/copilot/tutorials/copilot-chat-cookbook/refactor-code/improve-code-readability","title":"コードの読みやすさを改良する"}],"documentType":"article"},"body":"# コードの読みやすさと保守容易性を改良する\n\nコパイロットチャット は、コードの理解と保守を容易にする方法を提案できます。\n\n読みづらいコードは、他の開発者にとって保守や拡張が困難です。 コパイロットチャット はさまざまな方法で役に立ちます。 たとえば、次のものによって:\n\n* [変数名の改善を提案する](#improving-variable-names)\n* [連続した条件チェックを回避する](#avoiding-sequential-conditional-checks)\n* [入れ子になったロジックを減らす](#reducing-nested-logic)\n* [大規模なメソッドを小さくて読みやすいメソッドに分割する](#splitting-up-large-methods)\n\nコードの保守性を改良するもう 1 つの方法は、コードの文書化です。 コパイロットチャット を使ってコードに役立つコメントを追加する方法については、「[コードの文書化](/ja/copilot/copilot-chat-cookbook/documenting-code)」のプロンプト例を参照してください。\n\n> \\[!NOTE] この記事に示されている応答は例です。 コパイロットチャット の応答は決定論的ではないため、ここで示したものとは異なる応答を受け取る可能性があります。\n\n## 変数名を改善する\n\nわかりやすい変数名とパラメーター名を使うと、その目的を理解しやすくなります。\n\n### サンプル シナリオ\n\nこの JavaScript コードを使うと、人の年齢に関するメッセージをコンソールにログできます。 抽象的なパラメーター名を使うと、コードの目的を理解することが難しくなります。\n\n```javascript id=log-persons-age\nfunction logPersonsAge(a, b, c) {\n  if (c) {\n    console.log(a + \" is \" + b + \" years old.\");\n  } else {\n    console.log(a + \" does not want to reveal their age.\");\n  }\n}\n```\n\n### プロンプトの例\n\nエディターで変更する関数を選んでから、コパイロットチャット に尋ねます。\n\n```copilot copy prompt ref=log-persons-age\nImprove the variable names in this function\n```\n\n### 応答の例\n\nCopilot からは、わかりやすい変数名が提案されます。\n\n```javascript\nfunction logPersonAge(name, age, revealAge) {\n  if (revealAge) {\n    console.log(name + \" is \" + age + \" years old.\");\n  } else {\n    console.log(name + \" does not want to reveal their age.\");\n  }\n}\n```\n\n## 連続した条件チェックを回避する\n\n```\n          `if...else` チェーンは、特に長くなると読みづらくなります。\n```\n\n### サンプル シナリオ\n\nこの Python コードにより、さまざまな動物の鳴き声 (定義されている場合)、または \"Unknown animal\" (動物の種類が認識されない場合) が出力されます。 ただし、`if...else` ステートメントのチェーンがあるので、コードは非効率的で煩雑です。\n\n```python id=animal-sound\nclass Animal:\n    def speak(self):\n        pass\n\nclass Dog(Animal):\n    def speak(self):\n        return \"Woof!\"\n\nclass Cat(Animal):\n    def speak(self):\n        return \"Meow!\"\n\nclass Bird(Animal):\n    def speak(self):\n        return \"Tweet!\"\n\ndef animal_sound(animal_type):\n    if animal_type == \"dog\":\n        return Dog().speak()\n    elif animal_type == \"cat\":\n        return Cat().speak()\n    elif animal_type == \"bird\":\n        return Bird().speak()\n    else:\n        return \"Unknown animal\"\n\nprint(animal_sound(\"dog\"))\nprint(animal_sound(\"cat\"))\nprint(animal_sound(\"bird\"))\nprint(animal_sound(\"fish\"))\n```\n\n### プロンプトの例\n\n```copilot copy prompt ref=animal-sound\nSimplify this code. Avoid using if/else chains but retain all function return values.\n```\n\n### 応答の例\n\nCopilot からは、ディクショナリを使って動物の種類をそれに対応するクラスにマップすることが提案されます。\n\n```python\nclass Animal:\n    def speak(self):\n        pass\n\nclass Dog(Animal):\n    def speak(self):\n        return \"Woof!\"\n\nclass Cat(Animal):\n    def speak(self):\n        return \"Meow!\"\n\nclass Bird(Animal):\n    def speak(self):\n        return \"Tweet!\"\n\ndef animal_sound(animal_type):\n    animals = {\n        \"dog\": Dog,\n        \"cat\": Cat,\n        \"bird\": Bird\n    }\n    animal_class = animals.get(animal_type, Animal)\n    return animal_class().speak() if animal_class != Animal else \"Unknown animal\"\n\nprint(animal_sound(\"dog\"))\nprint(animal_sound(\"cat\"))\nprint(animal_sound(\"bird\"))\nprint(animal_sound(\"fish\"))\n```\n\n## 入れ子になったロジックを減らす\n\n構造が深く入れ子になっていると、コードがわかりづらくなり、将来的にコードのロジックを変更したり拡張したりすることが困難になる可能性があります。\n\n### サンプル シナリオ\n\nこの Ruby コードにより、3 つのパラメーターに基づいてユーザー アカウントに関する情報が出力されます。 入れ子になった `if...else` ステートメントを使うと、コードが不必要に複雑になります。\n\n```ruby id=determine-access\ndef determine_access(user_role, has_permission, is_active)\n  if user_role == \"admin\"\n    if has_permission\n      if is_active\n        \"Active admin account with full access.\"\n      else\n        \"Inactive admin account.\"\n      end\n    else\n      \"Admin account lacks necessary permissions.\"\n    end\n  else\n    \"Access denied.\"\n  end\nend\n\nputs determine_access(\"admin\", true, true)\nputs determine_access(\"admin\", true, false)\nputs determine_access(\"admin\", false, true)\nputs determine_access(\"user\", true, true)\n```\n\n### プロンプトの例\n\n```copilot copy prompt ref=determine-access\nRewrite this code to avoid the nested if/else statements\n```\n\n### 応答の例\n\nCopilot からは、guard 句を使って条件を早期に処理し、適切なメッセージを返すことが提案されます。\n\n```ruby\ndef determine_access(user_role, has_permission, is_active)\n  return \"Access denied.\" unless user_role == \"admin\"\n  return \"Admin account lacks necessary permissions.\" unless has_permission\n  return \"Inactive admin account.\" unless is_active\n\n  \"Active admin account with full access.\"\nend\n\nputs determine_access(\"admin\", true, true)\nputs determine_access(\"admin\", true, false)\nputs determine_access(\"admin\", false, true)\nputs determine_access(\"user\", true, true)\n```\n\n## 大規模なメソッドを分割する\n\nメソッドや関数が長すぎると、その実行内容を正確に把握することが難しくなり、保守が困難になります。 複数のタスクを実行するメソッドまたは関数は、他のコンテキストでは再利用できない場合があります。 また、各タスクを分離してテストすることも難しい場合があります。\n\n### サンプル シナリオ\n\nこの Java メソッドは、顧客の注文を処理し、メッセージを出力するものです。 1 つのメソッドで複数のタスクが実行されます。\n\n```java id=process-order\npublic void processOrder(Order order) {\n  if (order == null || order.getItems().isEmpty()) {\n    throw new IllegalArgumentException(\"Order is invalid.\");\n  }\n\n  double totalPrice = 0.0;\n  for (Item item : order.getItems()) {\n    totalPrice += item.getPrice() * item.getQuantity();\n  }\n  order.setTotalPrice(totalPrice);\n\n  if (totalPrice > 0) {\n    order.setStatus(\"Processed\");\n  } else {\n    order.setStatus(\"Pending\");\n  }\n\n  System.out.println(\"Order for customer \" + order.getCustomerName() + \" has been processed. Total price: \" + totalPrice);\n}\n```\n\n### プロンプトの例\n\n```copilot copy prompt ref=process-order\nHow could the processOrder method be refactored to be more useful and easier to maintain\n```\n\n### 応答の例\n\nCopilot からは、このメソッドをより小さく、より焦点を絞ったメソッドに分割することが提案されます。\n\n```java\npublic void processOrder(Order order) {\n    validateOrder(order);\n    double totalPrice = calculateTotalPrice(order);\n    updateOrderStatus(order, totalPrice);\n    printOrderSummary(order, totalPrice);\n}\n\nprivate void validateOrder(Order order) {\n    if (order == null || order.getItems().isEmpty()) {\n        throw new IllegalArgumentException(\"Order is invalid.\");\n    }\n}\n\nprivate double calculateTotalPrice(Order order) {\n    double totalPrice = 0.0;\n    for (Item item : order.getItems()) {\n        totalPrice += item.getPrice() * item.getQuantity();\n    }\n    order.setTotalPrice(totalPrice);\n    return totalPrice;\n}\n\nprivate void updateOrderStatus(Order order, double totalPrice) {\n    if (totalPrice > 0) {\n        order.setStatus(\"Processed\");\n    } else {\n        order.setStatus(\"Pending\");\n    }\n}\n\nprivate void printOrderSummary(Order order, double totalPrice) {\n    System.out.println(\"Order for customer \" + order.getCustomerName() + \" has been processed. Total price: \" + totalPrice);\n}\n```\n\n## 参考資料\n\n* [GitHub Copilot Chat のプロンプト エンジニアリング](/ja/copilot/using-github-copilot/prompt-engineering-for-github-copilot)\n* [GitHub Copilot の使用に関するベスト プラクティス](/ja/copilot/using-github-copilot/best-practices-for-using-github-copilot)"}