Skip to main content

GitHub Copilot を使用してprojectを別のプログラミング言語に移行する

ギットハブ コパイロット チャット は、プロジェクトを別の言語に移動するのに役立ちます。 このガイドでは、移行プロセスに関連する内容について説明し、PHP から Python への移行例を示します。

はじめに

projectを新しいプログラミング言語に移行することは、困難で時間のかかる作業になる場合があります。 GitHub Copilot は、行う必要がある変更を説明し、新しい言語で置換コードを提案することで、このプロセスに役立ちます。

projectを新しい言語に移行する原則

移行プロセスを開始する前に、次の点を考慮してください。

  • コーディングに関する知識

    両方のプログラミング言語を十分に理解している必要があります。 Copilotはコードを翻訳できますが、提案する選択肢を理解し、その提案を使用するか、代替提案を求めるかを決定する必要があります。

  • 移行するシステムに関する知識

    ユーザーに提供される機能に加えて、現在のシステムのアーキテクチャとロジックを理解する必要があります。 変換後のコードで、元のコードと同じ操作をすべて実行し、同じ結果が生成されることをチェックできる必要があります。

  • AI を使って支援を受ける

    翻訳しようとしているコードの特定の部分が理解できない場合は、ファイル全体またはファイル内のコードの選択された部分で、 Copilotの "説明" 機能を使用します。 「GitHub CopilotにIDEで質問を行う を参照してください。

  • 移行を完了する時間をスケジュールする

    変換は複数ステージのプロセスです。 変換するprojectが大きいほど、実行する必要があるステップの数が多くなります。 プロセス全体を完了するために十分な時間を確保してください。

  • 繰り返し作業する

    あなたのプロジェクトの個別の部分を別々に変換することを目指してください。 projectの別の部分に進む前に、行ったすべての変更を確認してください。 新しい各コンポーネントが期待どおりに動作することを確認できるように、projectの個々の部分に対してテストを記述します。

  • プロセスが複雑にならないようにする

    最初に目指すべきは、同等な変換を行うことです。 これは、project内のすべてのコードでは実行できません。 ただし、移行タスクが複雑にならないように、コードの変換や新しいフレームワークと適切な依存関係の使用だけでなく、新たに加える変更の数を制限するように努めることをお勧めします。

  • 変換されたコードのベンチマークとリファクター

    最初の変換が完了し、システムが機能するようになったら、ベンチマークを実行して新旧のシステムを比較できます。 これで、コードを新しい言語でリファクターできるようになりました。 これは、コードを最適化し、技術的負債を削減できるチャンスです。

Copilotを使用してプロジェクトを新しい言語に移行する

既存のプロジェクトについて既に理解していると仮定すると、移行を開始するには、エディターでリポジトリのブランチを開き、 Copilot にヘルプを依頼することをお勧めします。

  1. エディターで、 コパイロットチャット パネルを開きます。 「GitHub CopilotにIDEで質問を行う を参照してください。

  2. Copilotに、プロジェクトを新しい言語に移行するために必要な手順の概要を説明するように依頼します。

    たとえば、PHP から Python への移行の場合、次のように質問することができます。

    Copilot prompt
    @workspace I want to migrate this project from PHP to Python. Give me a high-level overview of the steps I need to take. Don't go into detail at this stage.
    

    メモ

    @workspace チャット参加者は、現在のワークスペース内のファイルを、あなたが聞く質問のコンテキストとして設定します。

Copilot 通常は、プロジェクトの移行に必要な手順の一覧が表示されます。

  1. Copilotの応答をコピーし、プロセス全体を通して参照する場所に保存します。

  2. プロセスの各手順を実行し、必要に応じて Copilot からの詳細なヘルプを求めます。

Copilotからの各提案を慎重に検討してください。 提案しているコードを理解し、projectに適しているかどうかを評価してください。 不明な場合は、 Copilot にコードを説明するよう依頼してください。

Copilotによって提案された変更が何らかの方法で正しくないと思われる場合は、別の提案を依頼してください。

  1. コンポーネントを実行可能な状態に移行したらすぐに、想定どおりに機能することをチェックします。 エラーが発生した場合は、 コパイロットチャット ビューにエラーをコピーし、修正に役立つ Copilot を依頼します。
  2. 最初の変換が完了したら、 Copilot を使用して、新しい言語でコードをリファクタリングします。 詳細については、「GitHub Copilot を使用したコードのリファクタリング」を参照してください。

例: PHP projectを Python に移行する

次の例は、単純な Web アプリケーションを PHP から Python に移行する方法を示しています。 移行に使用しているプログラミング言語ではない場合でも、ここで説明する手順に従って、project移行について理解しておくと役立つ場合があります。 他の小規模なプロジェクトをある言語から別の言語に移行する場合も手順は同様です。

PHP から Python に移行する前の 'Simple PHP Website' のスクリーンショット。

この例では、次のことを前提条件としています。

  • Visual Studio Codeで作業しています。
  • PHP と Python バージョン 3.12 以降の両方の言語がインストールされています。

単純なウェブサイトプロジェクトの移行

このパブリック リポジトリのコードは、GitHub: docs/simple-php-website に移行します。

このリポジトリは以下のファイルで構成されています。

.gitignore
.htaccess
LICENSE
content
├── 404.phtml
├── about-us.phtml
├── contact.phtml
├── home.phtml
└── products.phtml
includes
├── config.php
└── functions.php
index.php
readme.md
template
├── style.css
└── template.php

この例では、移行を完了するために コパイロットチャット 入力できるプロンプトと、この移行の 1 つのインスタンスに対して返される応答 Copilot 示します。 GPT-4.1 モデルは、これらの応答を生成するために使用されました。 コパイロットチャット 応答は非決定論的であるため、ここに示されている応答に対して少し異なる応答が返される可能性があります。

移行プロセス中に、先に進む前に修正が必要なエラーが発生する可能性があります。 Copilot は、これについてお手伝いできます。 この例にはいくつかのエラーが含まれており、修正に役立つ Copilot を取得する方法を示しています。

コパイロットチャットから取得する応答は、ここに示されているものと異なる可能性があるため、異なるエラーが発生する可能性があります。 そのため、自分で Copilot から取得した応答ではなく、ここで示す応答を使って、この移行例を順を追って進める方が簡単かもしれません。

この移行例を完了したら、独自のprojectで同じ手法を使用できます。

  1. まず、リポジトリのコピーをローカル コンピューターにクローンします。

  2. アプリケーションを実行して動作をチェックします。

    ターミナルを開き、複製したリポジトリのルートディレクトリに移動して、次のコマンドを実行します。

    Shell
     php -S localhost:8000
    

    次に、ブラウザーで http://localhost:8000 に移動します。

  3. Web サイトのあちこちをクリックして詳細を調べ、移行が成功したことを確認できます。

  4. リポジトリに作業ブランチを作成し、 Visual Studio Codeで新しいワークスペースとして開きます。

  5. 既存のprojectの内容とアーキテクチャについて理解します。 Copilot は、次の操作に役立ちます。

    1. コパイロットチャット ビューを開きます。

    2. 次のようなプロンプトを入力します。

      Copilot prompt
      @workspace Describe this project in detail, explaining what the various components do and how they interact.
      
  6. 移行プロセスの概要については、 Copilot にお問い合わせください。

    Copilot prompt
    @workspace I want to migrate this project from PHP to Python. Give me a high-level overview of the steps I need to take. Don't go into detail at this stage.
    

Copilot は、次のような手順で応答します。

To migrate this project from PHP to Python, follow these high-level steps:

1. Set Up Python Environment:
   - Install Python and set up a virtual environment.
   - Install necessary packages (e.g., Flask for web framework).

2. Convert Configuration:
   - Translate the configuration settings from config.php to a Python configuration file.

3. Rewrite Functions:
   - Convert PHP functions in functions.php to Python functions.

4. Create Flask Application:
   - Set up a Flask application to handle routing and views.
   - Map the routes to corresponding views.

5. Convert Templates:
   - Translate template.php to a Jinja2 template.
   - Update the CSS file path in the template.

6. Convert Content Pages:
   - Convert .phtml content files to HTML or Jinja2 templates.

7. Update .htaccess Rules:
   - Translate .htaccess rewrite rules to Flask route handling.

8. Run and Test:
   - Run the Flask application and test all routes and functionalities.
   - Ensure the site works as expected and fix any issues.

9. Documentation:
   - Update the readme.md with new instructions for running the Python project.
  1. Copilotの応答をコピーし、このプロセスの残りの部分で参照するためにこれをどこかに保存します。 これらの各手順を実行し、続行するときに Copilot にヘルプを求めます。

  2. 使用するPythonフレームワークをまだ決定していない場合は、Copilotにアドバイスを求めることができます。

    Copilot prompt
    @workspace What Python frameworks can I use for this project once it is migrated to Python? Give me a selection of options, with a brief summary of the pros and cons of each in relation to this website project. Which framework would you recommend?
    

Copilot は、さまざまなフレームワークに関する情報を含む応答を返し、次のように終了します。

For a project like yours - which is a simple, content-driven website - Flask is highly recommended. Its simplicity, flexibility, and ease of use (especially with its templating system that can easily replace your current PHP template structure) make it a great fit.

Copilotのアドバイスを受け、Flask を使用します。

  1. Copilotの概要に戻り、最初にPython環境を設定し、必要なパッケージをインストールします。 これを行う方法を確認するには、 コパイロットチャットに次のように入力します。

    Copilot prompt
    @workspace I want to use Flask. Tell me how to set up a virtual environment and install the necessary packages.
    

Copilot は、次のような手順で応答します。

1. Create a virtual environment:
   - Open a terminal and navigate to your project directory.
   - Run the following command to create a virtual environment:
     python3 -m venv venv

2. Activate the virtual environment:
   - On macOS and Linux:
     source venv/bin/activate

   - On Windows:
     venv\Scripts\activate

3. Install Flask and necessary packages:
   - With the virtual environment activated, run the following command
     to install Flask and other necessary packages:
     pip install Flask

4. Verify the installation:
   - You can verify that Flask is installed by running:
     pip list
  1. Copilotの指示に従い、pip listを使用して Flask がインストールされていることを確認します。

  2. 移行プロセスの Copilotの概要に戻り、次の手順では構成を変換します。 これに関するヘルプについては、 Copilot にお問い合わせください。 次に例を示します。

    Copilot prompt
    @workspace As the first step in migrating this project from PHP to Python, create a Python configuration file by converting the functions in functions.php to Python functions. Tell me where to locate the Python config file in the project.
    

Copilot は、次のコードを含む config.py という名前のファイルを includes ディレクトリに作成することを提案します。

Python
config = {
   'name': 'Simple Python Website',
   'site_url': '',
   'pretty_uri': False,
   'nav_menu': {
      '': 'Home',
      'about-us': 'About Us',
      'products': 'Products',
      'contact': 'Contact',
   },
  'template_path': 'template',
  'content_path': 'content',
  'version': 'v3.1',
}

def get_config(key=''):
   return config.get(key, None)

def site_name():
   return get_config('name')

def site_url():
   return get_config('site_url')

def site_version():
   return get_config('version')

def nav_menu(sep=' | '):
   nav_menu = ''
   nav_items = get_config('nav_menu')

   for uri, name in nav_items.items():
      query_string = request.args.get('page', '')
      class_active = ' active' if query_string == uri else ''
      url = f"{get_config('site_url')}/{'' if get_config('pretty_uri') or uri == '' else '?page='}{uri}"

      nav_menu += f'<a href="{url}" title="{name}" class="item{class_active}">{name}</a>{sep}'

   return nav_menu.strip(sep)

def page_title():
   page = request.args.get('page', 'Home')
   return ' '.join(word.capitalize() for word in page.split('-'))

def page_content():
   page = request.args.get('page', 'home')
   path = os.path.join(os.getcwd(), get_config('content_path'), f'{page}.phtml')

   if not os.path.exists(path):
      path = os.path.join(os.getcwd(), get_config('content_path'), '404.phtml')

   with open(path, 'r') as file:
      return file.read()

def init():
   template_path = os.path.join(get_config('template_path'), 'template.html')
   with open(template_path, 'r') as file:
      return file.read()
  1. includes/config.py ファイルを作成し、既存の includes/config.php ファイルを削除します。

  2. 概要に戻り、PHP 関数の書き換えに役立つ Copilot を依頼してください。

    Copilot prompt
    @workspace Continuing the migration of this project from PHP to Python, create Python functions to replace the existing PHP functions. Tell me where to locate the Python functions in the project.
    

Copilotでは、次のコードを含む functions.py ディレクトリに includes という名前のファイルを作成することを提案します。

Python
import os
from flask import request
from .config import get_config

def site_name():
   return get_config('name')

def site_url():
   return get_config('site_url')

def site_version():
   return get_config('version')

def nav_menu(sep=' | '):
   nav_menu = ''
   nav_items = get_config('nav_menu')

   for uri, name in nav_items.items():
      query_string = request.args.get('page', '')
      class_active = ' active' if query_string == uri else ''
      url = f"{get_config('site_url')}/{'' if get_config('pretty_uri') or uri == '' else '?page='}{uri}"

      nav_menu += f'<a href="{url}" title="{name}" class="item{class_active}">{name}</a>{sep}'

   return nav_menu.strip(sep)

def page_title():
   page = request.args.get('page', 'Home')
   return ' '.join(word.capitalize() for word in page.split('-'))

def page_content():
   page = request.args.get('page', 'home')
   path = os.path.join(os.getcwd(), get_config('content_path'), f'{page}.phtml')

   if not os.path.exists(path):
      path = os.path.join(os.getcwd(), get_config('content_path'), '404.phtml')

   with open(path, 'r') as file:
      return file.read()

def init():
   template_path = os.path.join(get_config('template_path'), 'template.html')
   with open(template_path, 'r') as file:
      return file.read()
  1. includes/functions.py ファイルを作成し、既存の includes/functions.php ファイルを削除します。

  2. 概要に続く次の手順は Flask アプリケーションの作成です。 Copilotにこの問題を解決するよう依頼します。

    Copilot prompt
    @workspace Set up a Flask application to handle routing and views, and map the routes to corresponding views. Tell me the location of any files that need to be created or changed.
    

Copilot は、次のコードを含む、プロジェクトのルートに app.py という名前のファイルを作成することを提案します。

Python
from flask import Flask, render_template, request
import os

app = Flask(__name__)

config = {
   'name': 'Simple Python Website',
   'site_url': '',
   'pretty_uri': False,
   'nav_menu': {
      '': 'Home',
      'about-us': 'About Us',
      'products': 'Products',
      'contact': 'Contact',
   },
   'template_path': 'template',
   'content_path': 'content',
   'version': 'v3.1',
}

def get_config(key=''):
   return config.get(key, None)

@app.route('/')
@app.route('/<page>')
def index(page='home'):
   page_content = get_page_content(page)
   page_title = get_page_title(page)
   nav_menu = get_nav_menu()
   return render_template('template.html', page_title=page_title, page_content=page_content, nav_menu=nav_menu)

def get_page_title(page):
   return ' '.join(word.capitalize() for word in page.split('-'))

def get_page_content(page):
   path = os.path.join(os.getcwd(), get_config('content_path'), f'{page}.phtml')
   if not os.path.exists(path):
      path = os.path.join(os.getcwd(), get_config('content_path'), '404.phtml')
   with open(path, 'r') as file:
      return file.read()

def get_nav_menu(sep=' | '):
   nav_menu = ''
   nav_items = get_config('nav_menu')
   for uri, name in nav_items.items():
      query_string = request.args.get('page', '')
      class_active = ' active' if query_string == uri else ''
      url = f"{get_config('site_url')}/{'' if get_config('pretty_uri') or uri == '' else '?page='}{uri}"
      nav_menu += f'<a href="{url}" title="{name}" class="item{class_active}">{name}</a>{sep}'
   return nav_menu.strip(sep)

if __name__ == '__main__':
   app.run(debug=True)

Copilot また、 template/template.php の名前を変更して template/template.html し、Jinja2 テンプレート構文を使用するようにファイルを更新することも提案します。

HTML

<!DOCTYPE html>
<html>
<head>
   <meta charset="utf-8" />
   <meta http-equiv="x-ua-compatible" content="ie=edge"/>
   <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
   <title>{{ page_title }} | {{ get_config('name') }}</title>
   <link href="{{ get_config('site_url') }}/template/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="wrap">

   <header>
      <h1>{{ get_config('name') }}</h1>
      <nav class="menu">
         {{ nav_menu|safe }}
      </nav>
   </header>

   <article>
      <h2>{{ page_title }}</h2>
      {{ page_content|safe }}
   </article>

   <footer>
      <small>&copy;{{ get_config('version') }} {{ get_config('name') }}.<br>{{ get_config('version') }}</small>
   </footer>

</div>
</body>
</html>

  1. 提案に従って、app.pytemplate/template.html の各ファイルを作成します。

  2. Copilot また、これらのファイルを作成したら、リポジトリのルートからターミナルで python app.py を実行し、 http://127.0.0.1:5000を参照することもできます。

    メモ

    コンピューターに Python をインストールした方法によっては、必要に応じて python3 app.py ではなくコマンド python app.py を使って、正しいバージョンの Python が使われていることを確認します。

    これを実行すると、ブラウザーにエラー メッセージが表示されます。

  3. 最初の TemplateNotFound エラー メッセージを コパイロットチャット ビューにコピーし、これを修正する方法を確認します。 次に例を示します。

    Copilot prompt
    @workspace When I run `python3 app.py`, I get the following error in the browser: `jinja2.exceptions.TemplateNotFound: template.html`. How can I fix this?
    

Copilot は、Flask が template.html ファイルを見つけることができないことを示すエラーを返します。

既定では、Flask はprojectのルート ディレクトリで templates という名前のフォルダー内のテンプレートを検索することを示します。 ただし、template.html ファイルは template ディレクトリ内にあります。 これを修正するには、Flask アプリの作成時に正しいテンプレート フォルダーを指定する必要があります。 app.py ファイルを更新し、app = Flask(__name__) パラメーターを含むように割り当て template_folder を変更することがアドバイスされます。

Python
app = Flask(__name__, template_folder='template')
  1. Flask 開発サーバーがまだ実行中であると想定すると、http://127.0.0.1:5000/ のブラウザー ページを更新したときに get_config 関数に関連する新しいエラーが表示されます。

    このエラー メッセージを コパイロットチャット ビューにコピーし、ヘルプを求めます。

    Copilot prompt
    @workspace When I run `python3 app.py`, I get the following error in the browser: `jinja2.exceptions.UndefinedError: 'get_config' is undefined.` How can I fix this?
    

Copilot は、 get_config が Jinja2 テンプレート コンテキストで使用できないためにエラーが発生したことを返します。 次のコードを app.py ファイルの @app.route('/') 行の直前に追加するようにアドバイスされます。

Python
app.jinja_env.globals.update(get_config=get_config)
  1. ブラウザーを更新すると、Web サイトが表示されます。

    CSS スタイルを適用していない 'Simple Python Website' のスクリーンショット。

    ただし、CSS スタイルは何も適用されていません。 次にこれを修正します。

  2. Copilotに質問する:

    Copilot prompt
    @workspace The deployed website does not use the CSS styles. How can I fix this?
    

Copilot は、Flask が CSS ファイルを static というディレクトリに含める必要があることを示します。 既存の style.css ファイルを template ディレクトリから新しい static ディレクトリに移動し、style.css ファイルの head 部分にある template.html ファイルのパスを更新することが提案されます。 これを次のように変更します。

HTML

<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">

ブラウザーを更新すると、Web サイトは正しく表示されるようになります。

最初の移行を完了するには、 Copilot が提供した概要の手順に進み、必要に応じてサポートを求めます。

移行を完了する

移行プロセスを正常に完了するには、さらに以下の作業が必要です。

  • 最初の移行を徹底的にチェックします。
  • バグ修正。 たとえば、ここで説明した例では、現時点で、pretty_uri ファイルの True セクションにある configapp.py に設定した場合にのみページ リンクが機能します。 ページ URL でクエリ文字列パラメーターを使用するオプションが必要な場合、またはコードからこのオプションを削除する場合は、 Copilot にこれを行うように依頼できます。
  • 移行されたプロジェクトのテストを書くこと。
  • Cleaning upプロジェクトから不要なファイルを削除します。
  • コードを新しい言語でリファクターします。 移行プロセスにより、元の PHP projectのアーキテクチャに基づく Python projectが作成されました。 最初の移行を完了したら、コードをリファクターして、Python 言語と Flask フレームワークの機能を最大限に活用できるようになります。
  • ドキュメントを更新しますreadme.md ファイルは古くなっているため、書き直す必要があります。