10 промтов для рефакторинга legacy кода: стратегии и примеры

Введение: Почему рефакторинг legacy кода — это не магия, а системная работа

Любой разработчик, проработавший в коммерческой разработке больше года, сталкивался с legacy-кодом. Это не просто «старый код» — это код, который работает, приносит деньги, но его поддержка превращается в ад: каждая правка рискует сломать «чёрный ящик», тестов нет, документация устарела настолько, что её проще выбросить. По данным исследования Stripe (2024), разработчики тратят в среднем 42% рабочего времени на чтение и понимание кода, а не на написание нового. В случае с legacy этот процент может достигать 70–80%.

Современные большие языковые модели (LLM), такие как GPT-4o, Claude 3.5 Sonnet и Gemini 2.5 Pro, способны кардинально изменить этот процесс. Но ключевой момент: нейросеть не сделает всю работу за вас. Она — мощный ассистент, который нужно правильно направить. Именно для этого нужны промты — структурированные инструкции, которые задают модели контекст, цель и формат ответа.

В этой статье я собрал 10 промтов для рефакторинга legacy кода, разделённых на три уровня: базовые (для ежедневных задач), продвинутые (для комплексного анализа) и экспертные (для архитектурной миграции). Каждый промт сопровождается примером результата и пояснением, почему он работает.

1. Базовые промты: быстрый анализ и понимание

Промт 1: Декомпозиция «чёрного ящика»

Задача: Понять, что делает большой неструктурированный метод (500+ строк).

Промт:

Ты — senior-разработчик с 15-летним стажем. Проанализируй следующий legacy-код на Python. Твоя задача:
1. Определи, какую бизнес-логику реализует функция.
2. Выдели все побочные эффекты (изменение глобальных переменных, запись в БД, вызовы API).
3. Предложи рефакторинг: разбей функцию на 3–5 логических блоков с комментариями.
4. Ответ дай в формате: "Бизнес-логика: ...\nПобочные эффекты: ...\nПредлагаемая структура: ..."

Код:
[вставьте ваш код]

Пример результата:

Бизнес-логика: Обработка заказа из корзины: валидация, расчёт скидки, обновление остатков на складе, отправка email-уведомления.
Побочные эффекты: 
- Изменение глобального списка active_orders
- Прямое обновление таблицы products через сырой SQL
- Вызов внешнего API отправки email (без обработки ошибок)
Предлагаемая структура:
1. validate_order(items) — проверка доступности товаров
2. calculate_total(items, user_tier) — расчёт суммы со скидкой
3. update_inventory(items) — атомарное обновление остатков
4. notify_user(user_email, order_details) — отправка уведомления

Промт 2: Генерация модульных тестов для legacy-функции

Задача: Создать тесты для функции, у которой нет тестов, но её нужно срочно изменить.

Промт:

Ты — QA-инженер с экспертизой в Python. Напиши модульные тесты (pytest) для следующей функции. Учти:
- Функция принимает строку ID заказа и возвращает словарь с деталями.
- В коде есть скрытые зависимости от глобальной конфигурации и БД.
- Нужно 3 теста: с валидным ID, с невалидным ID, с отсутствующим заказом.
- Используй mock для изоляции внешних зависимостей.
- Добавь комментарии к каждому тесту, поясняющие, что проверяется.

Код:
[вставьте код функции]

Пример результата:

import pytest
from unittest.mock import patch
from orders import get_order_details

@pytest.fixture
def mock_db():
    with patch('orders.database') as mock:
        yield mock

def test_valid_order_returns_details(mock_db):
    """Проверяет, что для существующего заказа возвращаются все поля"""
    mock_db.query.return_value = {'id': '123', 'status': 'paid'}
    result = get_order_details('123')
    assert result['status'] == 'paid'

def test_invalid_order_id_raises_error():
    """Проверяет, что невалидный ID вызывает ValueError"""
    with pytest.raises(ValueError):
        get_order_details('abc-def')  # неверный формат

def test_missing_order_returns_none(mock_db):
    """Проверяет, что отсутствующий заказ возвращает None"""
    mock_db.query.return_value = None
    result = get_order_details('999')
    assert result is None

2. Продвинутые промты: оптимизация и рефакторинг

Промт 3: Улучшение читаемости без изменения логики

Задача: Сделать код понятным для нового разработчика.

Промт:

Ты — code reviewer в крупной компании. Проведи рефакторинг следующего кода, следуя принципам Clean Code (Роберт Мартин):
1. Переименуй переменные и функции так, чтобы их назначение было ясно без комментариев.
2. Вынеси магические числа и строки в константы с понятными именами.
3. Упрости сложные условия: используй ранний возврат (early return) и тернарные операторы только если это улучшает читаемость.
4. Ответ верни в формате "diff" (как в Git): строки с '+' — новый код, строки с '-' — старый.

Код:
[вставьте код]

Пример результата:

- def chk(u, p):
-     if u == 'admin' and p == '12345':
-         return True
-     else:
-         return False
+ def validate_user_credentials(username: str, password: str) -> bool:
+     ADMIN_USERNAME = 'admin'
+     ADMIN_PASSWORD = '12345'  # TODO: перенести в переменные окружения
+     return username == ADMIN_USERNAME and password == ADMIN_PASSWORD

Промт 4: Выявление и устранение code smells

Задача: Найти проблемные паттерны в коде.

Промт:

Ты — статический анализатор кода на стероидах. Проанализируй следующий код и найди все code smells по классификации Мартина Фаулера. Для каждого найденного проблемы укажи:
- Тип (например, "Long Method", "Shotgun Surgery", "Primitive Obsession")
- Строку кода
- Почему это проблема (2-3 предложения)
- Конкретное предложение по рефакторингу

Код:
[вставьте код]

Пример результата:

Тип code smell Строка Почему проблема Предложение
Primitive Obsession 15 Использование строки для хранения статуса заказа ведёт к ошибкам при опечатках Создать Enum OrderStatus с константами PENDING, PAID, SHIPPED
Long Parameter List 42 Функция принимает 8 параметров, это усложняет тестирование Объединить связанные параметры в объект OrderContext

3. Экспертные промты: архитектурная миграция

Промт 5: Миграция с процедурного стиля на ООП

Задача: Переписать спагетти-код на классы с инкапсуляцией.

Промт:

Ты — архитектор ПО. Проведи рефакторинг следующего процедурного кода на объектно-ориентированный. Требования:
1. Выдели как минимум 3 класса, соблюдая принцип единственной ответственности (SRP).
2. Используй dependency injection для зависимостей (БД, API, логгер).
3. Добавь type hints для всех методов.
4. Напиши краткую документацию (docstring) для каждого класса.
5. Ответ дай в виде полного нового файла с комментариями, объясняющими архитектурные решения.

Код:
[вставьте процедурный код]

Промт 6: Стратегия инкрементального рефакторинга

Задача: Разработать план пошаговой замены legacy-модуля без остановки системы (strangler fig pattern).

Промт:

Ты — технический директор. Разработай стратегию инкрементального рефакторинга для системы, описанной ниже. Учти:
- Система на PHP (Legacy) и новая на Python (FastAPI).
- Обе версии должны работать параллельно 3 месяца.
- Критично: время простоя (downtime) не более 5 минут.
- В ответе укажи:
  1. Этапы миграции (минимум 4 этапа) с временными рамками.
  2. Как организовать роутинг трафика между версиями.
  3. Какие метрики отслеживать для подтверждения успешности.
  4. План отката (rollback) на каждом этапе.

Описание системы:
[опишите архитектуру текущей системы]

Пример результата (фрагмент):

Этап 1 (неделя 1-2): Feature Toggle
- Добавить в конфиг флаг USE_NEW_ORDER_SERVICE
- Создать пустой Python-сервис, который только логирует запросы
- Метрика: % запросов, ушедших в новый сервис (должен быть 0)
- Откат: отключить флаг, удалить Python-сервис

Этап 2 (неделя 3-4): Shadow Mode
- Настроить копирование 10% трафика в новый сервис без влияния на ответ
- Сравнивать результаты старого и нового сервиса по ключевым полям
- Метрика: процент расхождений (должен быть <1%)

Промт 7: Автоматическая генерация документации по коду

Задача: Создать документацию для модуля, где её нет.

Промт:

Ты — технический писатель. Создай документацию для следующего legacy-модуля. Формат:
1. Краткое описание модуля (1-2 абзаца).
2. Список всех публичных функций с сигнатурами и описанием параметров.
3. Примеры использования (2-3 примера с разными сценариями).
4. Секция "Known Issues" — что может пойти не так (на основе анализа кода).
5. Секция "Dependencies" — от каких внешних систем/библиотек зависит модуль.

Код:
[вставьте код модуля]

4. Специализированные промты

Промт 8: Рефакторинг SQL-запросов

Задача: Оптимизировать медленные запросы в legacy-коде.

Промт:

Ты — DBA (Database Administrator) с 10-летним опытом. Проанализируй следующий SQL-запрос из legacy-системы:
1. Объясни план выполнения (EXPLAIN).
2. Найди узкие места (отсутствие индексов, full table scan, N+1).
3. Предложи оптимизированную версию запроса.
4. Если возможно, предложи альтернативу с использованием оконных функций (агрегация без GROUP BY).

SQL:
[вставьте запрос]

Промт 9: Безопасность в legacy-коде

Задача: Найти и исправить уязвимости.

Промт:

Ты — white-hat хакер и специалист по AppSec. Проведи аудит безопасности следующего legacy-кода. Ищи:
- SQL-инъекции (конкатенация строк в запросах)
- XSS (неэкранированный вывод пользовательских данных)
- Использование устаревших криптографических функций (MD5, SHA1)
- Хранение секретов в коде (пароли, API-ключи)
- Отсутствие валидации входных данных

Для каждой уязвимости укажи:
- CWE ID (например, CWE-89 для SQL-инъекции)
- Строку кода
- Exploit: как злоумышленник может это использовать
- Fix: исправленный код

Код:
[вставьте код]

Промт 10: Рефакторинг с сохранением обратной совместимости

Задача: Изменить API, но не сломать старых клиентов.

Промт:

Ты — backend-разработчик. Нужно провести рефакторинг REST API эндпоинта /api/v1/orders так, чтобы:
1. Изменить формат ответа (добавить поле 'total' вместо 'sum').
2. Старый формат должен поддерживаться ещё 6 месяцев (версионирование).
3. Написать код, который проверяет заголовок Accept-Version и возвращает соответствующий формат.
4. Добавить логирование, какой процент клиентов использует старую версию.
5. Ответ дай в виде функции-обработчика на Python (FastAPI) с комментариями.

Текущий формат ответа:
{"sum": 1000, "items": [{"name": "...", "price": 500}]}
Новый формат:
{"total": 1000, "items": [{"name": "...", "price": 500}], "currency": "USD"}

Заключение: Рефакторинг — это процесс, а не событие

Рефакторинг legacy кода — это не разовая акция, а постоянный процесс. Промты, которые я привёл выше — это не магическая таблетка, а инструменты, которые помогают систематизировать работу. Самое главное, что нужно помнить:

  1. Всегда имейте тесты. Без тестов рефакторинг — это гадание. Используйте промт 2 для их генерации, если их нет.
  2. Рефакторинг не добавляет функциональности. Не пытайтесь заодно «добавить фичу» — это ведёт к хаосу.
  3. Используйте промты как чек-лист. Каждый раз, когда берётесь за legacy-код, прогоните его через 3-4 промта из этой статьи — и вы увидите проблемы, которые раньше упускали.

Если вы хотите глубже изучить, как применять промты в реальных проектах, обратите внимание на специализированные курсы. Например, ASI Biont поддерживает подключение к различным AI-моделям через API и предлагает практические задания по рефакторингу — подробнее на asibiont.com/courses. Там же можно найти шаблоны промтов для типовых задач, которые мы разобрали.

Помните: лучший код — это код, который можно прочитать, понять и безопасно изменить через полгода. И промты — ваш помощник на этом пути.

← Все статьи

Комментарии

Читайте также