Введение
Перенос проекта на новый язык программирования может быть сложной задачей. GitHub Copilot поможет вам в этом процессе, объяснив изменения, которые необходимо внести и предложить код замены на новом языке.
Принципы переноса проекта на новый язык
Прежде чем начать процесс миграции, рассмотрите следующие моменты:
-
Знания по написанию кода
Убедитесь, что у вас есть хорошее представление о обоих языках программирования. Хотя Copilot может переводить код для вас, необходимо понять варианты, которые он предлагает, и решить, следует ли использовать его предложения или попросить альтернативное предложение.
-
Знание системы, перенесенной
Убедитесь, что вы понимаете архитектуру и логику текущей системы, помимо функциональных возможностей и функций, предоставляемых пользователям. Необходимо убедиться, что переведенный код выполняет все те же операции, что и исходный код, и создает одинаковые результаты.
-
Использование ИИ для помощи вам
Если вы не понимаете определенную часть кода, которую вы хотите перевести, используйте функцию Copilot", либо в целом файле, либо выбранную часть кода в файле. См . раздел AUTOTITLE.
-
Расписание завершения миграции
Преобразование — это многоэтапный процесс. Чем больше проект преобразуется, тем большее количество шагов, которые потребуется выполнить. Убедитесь, что вы разрешаете много времени для завершения всего процесса.
-
Работа итеративно
Стремитесь преобразовать отдельные части проекта в дискретные части. Убедитесь, что вы проверили все внесенные изменения, прежде чем перейти к другой части проекта. Напишите тесты для отдельных частей проекта, чтобы убедиться, что каждый из новых компонентов работает должным образом.
-
Избегайте внедрения сложности процесса
Изначально необходимо выполнить подобное преобразование. Это не может быть возможным для всего кода в проекте. Однако, чтобы избежать добавления сложности в задачу миграции, следует попытаться ограничить количество новых изменений, которые вы вводите, кроме преобразования кода и использования новой платформы и соответствующих зависимостей.
-
Тест и рефакторинг преобразованного кода
Завершив начальное преобразование, и у вас есть рабочая система, вы можете выполнить тестирование для сравнения старых и новых систем. Теперь можно рефакторинг кода на новом языке. Это возможность оптимизировать код и сократить технический долг.
Использование Copilot для переноса проекта на новый язык
Если вы уже ознакомились с существующим проектом, хорошим способом начать миграцию является открытие ветви репозитория в редакторе и запрос Copilot для справки.
-
В редакторе откройте панель Copilot Chat. См . раздел AUTOTITLE.
-
Попросите 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 обычно возвращается со списком шагов, которые необходимо выполнить для переноса проекта.
-
Скопируйте ответ Copilotи сохраните его где-то, чтобы ссылаться на весь процесс.
-
Проработайте каждый этап процесса, запрашивая подробную справку от Copilot по мере необходимости.
Тщательно рассмотрите каждое предложение от Copilot . Убедитесь, что вы понимаете код, который он предлагает и оценивает, подходит ли он для вашего проекта. Если вы не уверены, попросите Copilot объяснить вам код.
Если вы считаете, что изменение, предлагаемое Copilot, не правильно, попросите альтернативное предложение.
-
Как только вы перенесли компонент в состояние, которое можно запустить, убедитесь, что он работает должным образом. Если ошибка возникает, скопируйте ошибку в представление Copilot Chat и попросите Copilot, чтобы устранить эту ошибку.
-
После завершения первоначального преобразования используйте Copilot для рефакторинга кода на новом языке. Дополнительные сведения см. в разделе Рефакторинг кода с помощью GitHub Copilot.
Пример. Перенос проекта PHP на Python
В следующем примере описывается миграция простого веб-приложения из PHP в Python. Даже если они не являются языками программирования, которые вы используете для миграции, может потребоваться выполнить следующие действия, описанные здесь, чтобы ознакомиться с миграцией проекта. Шаги будут аналогичны для переноса других небольших проектов с одного языка на другой.
В коде из этого примера предполагается следующее:
- Вы работаете в 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
В этом примере приводятся запросы, которые можно ввести в Copilot Chat для завершения миграции, а ответы Copilot возвращены для одного экземпляра этой миграции. Модель GPT 4o по умолчанию использовалась для создания этих ответов. Ответы Copilot Chat являются недетерминированными, поэтому вы, вероятно, будете получать немного разные ответы на указанные здесь ответы.
Во время процесса миграции, скорее всего, возникают ошибки, которые необходимо исправить перед переходом вперед. Copilot может помочь вам в этом. В примере содержатся некоторые ошибки и показано, как получить Copilot для их устранения.
Так как ответы, полученные от Copilot Chat, скорее всего, отличаются от указанных здесь, могут возникнуть различные ошибки. Таким образом, вы можете легко выполнить этот пример миграции с помощью ответов, показанных здесь, а не тех, которые вы получаете от Copilot самостоятельно.
После завершения этого примера миграции можно использовать ту же методологию для собственного проекта.
-
Начните с клонирования копии репозитория на локальный компьютер.
-
Запустите приложение, чтобы проверить его работу.
Для этого в терминале перейдите в корень клонированного репозитория и выполните следующую команду:
Shell php -S localhost:8000
php -S localhost:8000
Затем в браузере перейдите к: http://localhost:8000
-
Щелкните по веб-сайту, чтобы узнать его, чтобы убедиться, что миграция выполнена успешно.
-
Создайте рабочую ветвь в репозитории и откройте ее как новую рабочую область в Visual Studio Code.
-
Ознакомьтесь с содержимым и архитектурой существующего проекта. Copilot поможет вам с этим:
-
Откройте представление Copilot Chat.
-
Введите запрос, например:
@workspace Describe this project in detail, explaining what the various components do and how they interact.
-
-
Попросите 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.
-
Скопируйте ответ Copilotи сохраните его где-то, чтобы ссылаться на оставшуюся часть этого процесса. Вы будете работать с каждым из этих шагов, запрашивая Copilot для получения справки по мере продолжения.
-
Если вы еще не решили, какую платформу 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.
-
Возвращаясь к высокоуровневой обзору 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
-
Следуйте инструкциям Copilotи используйте для
pip list
проверки установки Flask. -
Возвращаясь к обзору 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()
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()
-
includes/config.py
Создайте файл и удалите существующийincludes/config.php
файл. -
Вернитесь к обзору еще раз, попросите Copilot помочь перезаписать функции PHP.
@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()
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()
-
includes/functions.py
Создайте файл и удалите существующийincludes/functions.php
файл. -
Продолжая обзор, следующим шагом является создание приложения 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)
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>©{{ get_config('version') }} {{ get_config('name') }}.<br>{{ get_config('version') }}</small> </footer> </div> </body> </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>©{{ get_config('version') }} {{ get_config('name') }}.<br>{{ get_config('version') }}</small> </footer> </div> </body> </html>
-
app.py
Создайте иtemplate/template.html
файлы, как показано ниже. -
Copilot также может предложить, что, создав эти файлы, теперь вы запускаете
python app.py
в терминале, из корневого каталога репозитория и перейдите к нейhttp://127.0.0.1:5000[](http://127.0.0.1:5000).Note
В зависимости от того, как Python установлен на компьютере, может потребоваться использовать команду
python3 app.py
вместоpython app.py
того, чтобы убедиться, что используется правильная версия Python.При этом в браузере будут отображаться сообщения об ошибках.
-
Скопируйте исходное
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
файл, изменив назначениеapp = Flask(__name__)
, чтобы включитьtemplate_folder
параметр:Python app = Flask(__name__, template_folder='template')
app = Flask(__name__, template_folder='template')
-
Если сервер разработки 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 отвечает на то, что ошибка возникает из-за
get_config
недоступности в контексте шаблона Jinja2. Он советует добавить следующий код вapp.py
файл непосредственно перед строкой@app.route('/')
:Python app.jinja_env.globals.update(get_config=get_config)
app.jinja_env.globals.update(get_config=get_config)
-
Обновите браузер и теперь увидите веб-сайт.
Однако ни один из стилей CSS не применяется. Далее мы исправим эту проблему.
-
Спросите Copilot:
@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') }}">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
При обновлении браузера веб-сайт должен правильно отображаться.
Чтобы завершить начальную миграцию, продолжайте работать с инструкциями в высокоуровневом обзоре, который Copilot предоставил вам, запросив помощь по мере необходимости.
Завершение миграции
Дальнейшие действия по успешному выполнению процесса миграции будут включать:
- Тщательно проверьте начальную миграцию.
- Исправление ошибок. Например, в приведенном здесь примере ссылки на страницы работают только в том случае, если задано
pretty_uri
True
значение вconfig
разделеapp.py
файла. Если вы хотите использовать параметры строки запроса в URL-адресах страницы или удалить этот параметр из кода, можно попросить Copilot помочь вам сделать это. - Написание тестов для перенесенного проекта.
- Очистка проекта путем удаления всех файлов, которые больше не нужны.
- Рефакторинг кода на новом языке. Процесс миграции привел к проекту Python, архитектура которого основана на архитектуре исходного проекта PHP. Выполнив начальную миграцию, теперь можно рефакторинг кода, чтобы лучше всего использовать функции языка Python и платформы Flask.
- Обновление документации. Теперь
readme.md
файл устарел и должен быть перезаписан.