Введение
Миграция кода — это не просто техническая задача, а стратегический вызов, с которым сталкиваются многие команды. Переход с Python 2 на Python 3, с JavaScript на TypeScript или с REST на GraphQL требует не только ручного рефакторинга, но и автоматизации. Согласно отчету JetBrains Developer Ecosystem Survey 2023, более 40% проектов на JavaScript уже используют TypeScript, а доля Python 3 среди пользователей Python превышает 95% (источник: Python Software Foundation, январь 2023). Однако ручная миграция тысяч строк кода — это дорого и чревато ошибками. В этой статье я собрал 12 проверенных промтов (инструкций для AI-ассистентов), которые помогут вам ускорить миграцию. Каждый промт сопровождается реальным примером и кодом.
1. Базовый: Преобразование print-выражений Python 2 в Python 3
Задача: Автоматически заменить print-выражения (например, print "Hello") на функцию print(). Это первый шаг миграции, описанный в официальном руководстве Python.
Промт: «Замени все print-выражения Python 2 в следующем коде на вызовы функции print() в Python 3. Учти, что в Python 2 print мог быть с пробелами или без скобок. Пример: print "Hello" → print("Hello")».
Пример результата:
# Исходный код Python 2:
print "Hello, world!"
print "Value:", 42
# Результат после применения промта:
print("Hello, world!")
print("Value:", 42)
2. Базовый: Замена xrange() на range() в Python 3
Задача: В Python 3 xrange() удален, а range() ведет себя как xrange() в Python 2 (ленивая итерация). Этот промт автоматизирует замену.
Промт: «Найди все вхождения xrange() в коде и замени их на range(). Убедись, что аргументы остаются без изменений. Пример: for i in xrange(10) → for i in range(10)».
Пример результата:
# Исходный код Python 2:
for i in xrange(10):
print i
# Результат после применения промта:
for i in range(10):
print(i)
3. Продвинутый: Обработка Unicode в Python 2→3
Задача: В Python 2 строки — это байты по умолчанию, а в Python 3 — Unicode. Промт помогает преобразовать строковые литералы и методы.
Промт: «Замени все префиксы u перед строковыми литералами (например, u"текст") на обычные строки без префикса. Если в коде есть вызовы unicode(), замени их на str(). Пример: u"привет" → "привет"».
Пример результата:
# Исходный код Python 2:
name = u"Иван"
print unicode(name)
# Результат после применения промта:
name = "Иван"
print(str(name))
4. Продвинутый: Преобразование классов Python 2 (object) в Python 3
Задача: В Python 2 классы по умолчанию не наследуются от object, что делает их старыми (old-style). В Python 3 все классы — new-style. Промт добавляет явное наследование.
Промт: «Добавь (object) ко всем определениям классов, которые не имеют явного родителя. Пример: class MyClass: → class MyClass(object):».
Пример результата:
# Исходный код Python 2:
class MyClass:
def __init__(self):
pass
# Результат после применения промта:
class MyClass(object):
def __init__(self):
pass
5. Экспертный: Миграция декораторов Python 2 с @staticmethod
Задача: В Python 2 декораторы @staticmethod и @classmethod работают так же, но в Python 3 изменилось поведение при наследовании. Промт оптимизирует код.
Промт: «Проанализируй код на наличие @staticmethod и @classmethod. Если метод не использует первый аргумент (cls), замени @classmethod на @staticmethod. Удали лишние обертки».
Пример результата:
# Исходный код Python 2:
class MyClass:
@classmethod
def create(cls, name):
return cls()
# Результат после применения промта (если cls не используется):
class MyClass(object):
@staticmethod
def create(name):
return MyClass()
6. Базовый: Добавление типов в JavaScript (JS→TS)
Задача: Преобразовать простой JavaScript-файл в TypeScript с аннотациями типов. Это первый шаг миграции.
Промт: «Добавь аннотации типов к параметрам функций и возвращаемым значениям в следующем JavaScript-коде. Используй базовые типы: string, number, boolean, any. Пример: function add(a, b) → function add(a: number, b: number): number».
Пример результата:
// Исходный код JavaScript:
function greet(name) {
return "Hello " + name;
}
// Результат после применения промта:
function greet(name: string): string {
return "Hello " + name;
}
7. Продвинутый: Создание интерфейсов для объектов JS→TS
Задача: В JavaScript объекты часто не имеют строгой структуры. Промт генерирует интерфейсы TypeScript на основе использования объекта.
Промт: «Создай интерфейс TypeScript для объекта, который используется в функции. Проанализируй все поля объекта и их типы. Пример: function processUser(user) → interface User { name: string; age: number }».
Пример результата:
// Исходный код JavaScript:
function processUser(user) {
console.log(user.name, user.age);
}
// Результат после применения промта:
interface User {
name: string;
age: number;
}
function processUser(user: User): void {
console.log(user.name, user.age);
}
8. Экспертный: Преобразование колбэков в async/await (JS→TS)
Задача: Многие старые JavaScript-проекты используют колбэки. Промт помогает преобразовать их в async/await с типизацией.
Промт: «Замени цепочки колбэков на async/await с обработкой ошибок через try/catch. Добавь типы Promise. Пример: fs.readFile(path, callback) → async function readFile(path: string): Promise<string>».
Пример результата:
// Исходный код JavaScript:
fs.readFile('file.txt', function(err, data) {
if (err) throw err;
console.log(data);
});
// Результат после применения промта:
import { promises as fs } from 'fs';
async function readFile(path: string): Promise<void> {
try {
const data = await fs.readFile(path, 'utf-8');
console.log(data);
} catch (err) {
console.error(err);
}
}
readFile('file.txt');
9. Базовый: Преобразование REST-запроса в GraphQL (REST→GraphQL)
Задача: Заменить простой REST-запрос на GraphQL-запрос с теми же данными.
Промт: «Преобразуй следующий REST-запрос (GET /api/users/1) в GraphQL-запрос. Предположи, что сервер поддерживает схему с типом User. Пример: GET → query { user(id: 1) { name email } }».
Пример результата:
# REST запрос: GET /api/users/1
# Ответ: { "name": "Alice", "email": "alice@example.com" }
# GraphQL запрос:
query {
user(id: 1) {
name
email
}
}
10. Продвинутый: Создание GraphQL-мутации из REST POST
Задача: REST POST-запросы создают ресурсы. Промт преобразует их в GraphQL-мутации.
Промт: «Преобразуй REST POST-запрос (POST /api/users с телом { name: "Bob" }) в GraphQL-мутацию. Используй input-тип. Пример: mutation { createUser(input: { name: "Bob" }) { id name } }».
Пример результата:
# REST запрос: POST /api/users
# Тело: { "name": "Bob" }
# Ответ: { "id": 2, "name": "Bob" }
# GraphQL мутация:
mutation {
createUser(input: { name: "Bob" }) {
id
name
}
}
11. Экспертный: Оптимизация N+1 запросов в GraphQL
Задача: При миграции REST→GraphQL часто возникает проблема N+1 запросов. Промт помогает написать DataLoader-логику.
Промт: «Проанализируй REST-эндпоинты, которые возвращают списки связанных данных. Создай GraphQL-резолвер с использованием DataLoader для батчинга запросов. Пример: GET /api/users и GET /api/users/:id/posts → DataLoader для загрузки постов пачкой».
Пример результата:
// REST: GET /api/users (возвращает список пользователей)
// Затем для каждого пользователя: GET /api/users/:id/posts
// GraphQL резолвер с DataLoader:
import DataLoader from 'dataloader';
const postLoader = new DataLoader(async (userIds: number[]) => {
const posts = await db.query('SELECT * FROM posts WHERE userId IN ($1)', [userIds.join(',')]);
return userIds.map(id => posts.filter(post => post.userId === id));
});
const resolvers = {
User: {
posts: (parent) => postLoader.load(parent.id)
}
};
12. Экспертный: Преобразование REST-авторизации в GraphQL-директивы
Задача: В REST авторизация часто реализуется через middleware. В GraphQL лучше использовать директивы. Промт генерирует кастомную директиву.
Промт: «Создай GraphQL-директиву @auth, которая проверяет роль пользователя на основе JWT-токена. Пример: @auth(requires: ADMIN) → резолвер проверяет роль в контексте».
Пример результата:
# Схема:
directive @auth(requires: Role = USER) on FIELD_DEFINITION
enum Role {
USER
ADMIN
}
type Query {
users: [User] @auth(requires: ADMIN)
}
Заключение
Миграция кода — это процесс, который требует внимания к деталям, но правильные промты могут сэкономить часы работы. Начните с базовых преобразований, таких как замена print или добавление типов, а затем переходите к сложным задачам, например, оптимизации N+1 запросов. Помните, что AI-инструменты — это помощники, а не замена ручного тестирования. Перед развертыванием всегда проверяйте результат. Если вы хотите углубиться в тему, рекомендую изучить официальные руководства: Python 2→3 Migration Guide (python.org), TypeScript Handbook (typescriptlang.org) и GraphQL Best Practices (graphql.org). Удачной миграции!
Комментарии