Skip to main content

Copilot を使ってプロジェクトを別のプログラミング言語に移行する

GitHub Copilot Chat は、プロジェクトを別の言語に移行するのに役立ちます。 このガイドでは、移行プロセスに関連する内容について説明し、PHP から Python への移行例を示します。

はじめに

プロジェクトを新しいプログラミング言語に移行することは、困難で時間のかかる作業になる場合があります。 GitHub Copilot には、加える必要がある変更について説明し、新しい言語での置換コードを提案することで、このプロセスを支援する機能があります。

プロジェクトを新しい言語に移行するため場合の原則

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

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

    両方のプログラミング言語を十分に理解している必要があります。 Copilot を使ってコードを変換することはできますが、提案された選択肢を理解し、その提案を使うか、別の提案を求めるかを判断する必要があります。

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

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

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

    変換対象であるコードの特定の部分を理解できない場合は、ファイル全体、またはファイル内のコードの選択した部分に対して、Copilot の "説明" 機能を使います。 「IDE で GitHub Copilot に質問する」を参照してください。

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

    変換は複数ステージのプロセスです。 変換対象のプロジェクトが大きいほど、必要な手順数も多くなります。 プロセス全体を完了するために十分な時間を確保してください。

  • 繰り返し作業する

    プロジェクトの目立たない部分を個別に変換することを目指します。 プロジェクトの別の部分に進む前に、加えたすべての変更を必ず確認します。 新しいコンポーネントのそれぞれが期待どおりに機能することを確認できるように、進行に合わせて、プロジェクトの個々の部分についてテストを作成します。

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

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

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

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

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

既存のプロジェクトに既に慣れている場合、移行を始めるには、エディターでリポジトリのブランチを開いて、Copilot に支援を求めることをお勧めします。

  1. エディターで、Copilot Chat パネルを開きます。 「IDE で GitHub Copilot に質問する」を参照してください。

  2. プロジェクトを新しい言語に移行するために必要な手順の概要を Copilot に質問します。

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

    @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.

    Note

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

    通常、Copilot からは、プロジェクトを移行するために必要な手順の一覧が返されます。

  3. Copilot の回答をコピーし、これをプロセス全体で参照できる場所に保存します。

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

    Copilot からの個々の提案を慎重に検討します。 必ず提案されているコードを理解し、それがプロジェクトに適しているかどうかを評価してください。 よくわからない場合は、コードについて説明するように Copilot に依頼します。

    Copilot から提案された変更が何らかの点で正しくないと思われる場合は、別の提案を依頼します。

  5. コンポーネントを実行可能な状態に移行したらすぐに、想定どおりに機能することをチェックします。 エラーが発生した場合は、エラーを Copilot Chat ビューにコピーし、Copilot に修正を依頼します。

  6. 最初の変換が完了したら、Copilot を使って、新しい言語でコードをリファクターします。 詳しくは、「GitHub Copilot を使用したコードのリファクタリング」をご覧ください。

例: PHP プロジェクトを Python に移行する

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

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

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

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

単純な Web サイト プロジェクトを移行する

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

この例は、移行を完了するために Copilot Chat に入力できるプロンプトと、この移行の 1 つのインスタンスに対して Copilot から返される回答を示します。 Copilot Chat の回答は非決定的であるため、ここに示されているものとは多少異なる回答が返される可能性があります。

移行プロセス中に、先に進む前に修正が必要なエラーが発生する可能性があります。 Copilot は、次のことができるようにします: この例にはいくつかのエラーが含まれており、それらを修正するために Copilot の支援を受ける方法を示しています。

Copilot Chat から得られる回答はここに示されているものとは異なる可能性があるため、発生するエラーも異なることがあります。 そのため、Copilot から実際に得られるものではなく、ここに示されている回答を使って、この移行例の手順を実行するほうが簡単です。

この移行例を完了したら、同じ手法を自身のプロジェクトで使用できます。

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

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

    これを行うには、ターミナルでクローンされたリポジトリのルートに移動し、次のコマンドを実行します。

    Shell
     php -S localhost:8000
    

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

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

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

  5. 既存のプロジェクトの内容とアーキテクチャについてよく理解します。 Copilot は次の場合に役立ちます。

    1. Copilot Chat ビューを開きます。

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

      @workspace Describe this project in detail, explaining what the various components do and how they interact.

  6. 移行プロセスの概要について、Copilot に質問します。

    @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.
    
  7. Copilot の回答をコピーし、このプロセスの残りの部分で参照できるようにどこかに保存します。 Copilot の支援を受けながら、これらの各手順を実行します。

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

    @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 を使います。

  9. Copilot の概要に戻ると、最初の手順は Python 環境を設定し、必要なパッケージをインストールすることです。 その実行方法を確認するには、Copilot Chat で次のように入力します。

    @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
    
  10. Copilot の指示に従い、pip list を使って Flask がインストールされていることを確認します。

  11. Copilot の移行プロセスの概要に戻ると、次の手順は構成の変換です。 この点について Copilot に支援を依頼します。 次に例を示します。

    @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()
    
  12. includes/config.py ファイルを作成し、既存の includes/config.php ファイルを削除します。

  13. もう一度概要に戻り、PHP 関数の書き換えを Copilot に依頼します。

    @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()
    
  14. includes/functions.py ファイルを作成し、既存の includes/functions.php ファイルを削除します。

  15. 概要に続く次の手順は Flask アプリケーションの作成です。 この点について、Copilot に支援を依頼します。

    @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>
    
    
  16. 提案に従って、app.pytemplate/template.html の各ファイルを作成します。

  17. また、Copilot からは、これらのファイルを作成した後に、ターミナルでリポジトリのルートから python app.py を実行し、次に http://127.0.0.1:5000 を閲覧することが提案されることもあります。

    Note

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

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

  18. 最初の TemplateNotFound エラー メッセージを Copilot Chat ビューにコピーし、その修正方法を質問します。 次に例を示します。

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

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

    このエラー メッセージを Copilot Chat ビューにコピーして、支援を依頼します。

    @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 からは、Jinja2 テンプレート コンテキストでは get_config を使用できないためにエラーが発生すると回答されます。 次のコードを app.py ファイルの @app.route('/') 行の直前に追加するようにアドバイスされます。

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

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

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

  21. Copilot に次のように質問します。

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

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

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

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

    最初の移行を完了するには、必要に応じて支援を受けながら、Copilot から示された概要の手順に沿って作業を続けます。

移行を完了する

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

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