/
Вопросы и ответы
/
Промт-инжиниринг
/

LLM для рефакторинга легаси-кода

LLM для рефакторинга легаси-кода

9 часов назад

Никита Вихров

Ответы

0

LLM для рефакторинга легаси-кода

Легаси — код без тестов, без документации, с неочевидной логикой и магическими числами. Трогать страшно. ИИ помогает разобраться и рефакторить безопаснее — не заменяет понимание, но ускоряет его.


Шаг 1: понять что делает код

Прежде чем рефакторить — разберись. ИИ читает плохой код быстрее человека:

from anthropic import Anthropic

client = Anthropic()

legacy_code = """
def proc(d, t=None, f=False):
    r = []
    for i in d:
        if t and i['tp'] != t:
            continue
        if f and i['st'] != 1:
            continue
        x = i['amt'] * 0.87 if i['cur'] == 'USD' else i['amt']
        r.append({'id': i['id'], 'v': x, 'tp': i['tp']})
    return sorted(r, key=lambda x: x['v'], reverse=True)
"""


def explain_code(code: str) -> str:
    response = client.messages.create(
        model="claude-opus-4-5",
        max_tokens=1024,
        messages=[{
            "role": "user",
            "content": f"""Объясни что делает этот код.
Для каждой переменной и параметра угадай настоящее название по контексту.
Опиши логику пошагово.

```python
{code}
```"""
        }]
    )
    return response.content[0].text


print(explain_code(legacy_code))
# → Функция фильтрует список транзакций/платежей.
#   d — данные (список объектов), t — тип фильтра, f — флаг активных записей
#   Конвертирует USD в другую валюту (курс 0.87), сортирует по сумме...

Шаг 2: переименовать переменные

После понимания — сначала переименование, без изменения логики:

def rename_variables(code: str, context: str = "") -> str:
    response = client.messages.create(
        model="claude-opus-4-5",
        max_tokens=1024,
        system="""Переименовываешь переменные в коде.
Правила:
- Только переименование, логику не трогаешь
- Имена — говорящие, в snake_case
- Параметры функций тоже переименовываешь
- Добавляешь type hints если очевидны
- Возвращаешь только код без объяснений""",
        messages=[{
            "role": "user",
            "content": f"Контекст: {context}\n\nКод:\n```python\n{code}\n```"
        }]
    )
    return response.content[0].text


renamed = rename_variables(
    legacy_code,
    context="Финтех-приложение, обработка платёжных транзакций"
)
print(renamed)
# → def filter_transactions(transactions, transaction_type=None, only_active=False):
#       result = []
#       for transaction in transactions:
#           if transaction_type and transaction['type'] != transaction_type: ...

Шаг 3: написать тесты на легаси до рефакторинга

Критически важно: сначала тесты на текущее поведение, потом рефакторинг:

def generate_characterization_tests(code: str, function_name: str) -> str:
    """
    Characterization tests — тесты на текущее поведение кода.
    Не проверяют правильность, фиксируют что есть.
    """
    response = client.messages.create(
        model="claude-opus-4-5",
        max_tokens=2048,
        system="""Пишешь characterization tests (тесты-фиксации).
Цель: зафиксировать текущее поведение кода перед рефакторингом.
Придумай разные входные данные и запиши ожидаемые выходы.
Тесты должны пройти на текущем коде и сломаться если логика изменится.""",
        messages=[{
            "role": "user",
            "content": f"Функция:\n```python\n{code}\n```\n\nНапиши characterization tests для {function_name}"
        }]
    )
    return response.content[0].text

Шаг 4: рефакторинг по принципам

После тестов — рефакторинг с явными требованиями:

def refactor_with_principles(code: str, principles: list[str]) -> str:
    principles_text = "\n".join(f"- {p}" for p in principles)

    response = client.messages.create(
        model="claude-opus-4-5",
        max_tokens=2048,
        system=f"""Рефакторишь код по этим принципам:
{principles_text}

Правила:
- Сохраняй поведение — только рефакторинг, не новый функционал
- Каждое изменение должно быть обосновано принципом выше
- Добавляй docstring
- Возвращай только код""",
        messages=[{
            "role": "user",
            "content": f"```python\n{code}\n```"
        }]
    )
    return response.content[0].text


refactored = refactor_with_principles(legacy_code, [
    "Говорящие имена переменных",
    "Единственная ответственность функции",
    "Магические числа в константы",
    "Type hints для всех параметров",
    "Разбить на маленькие функции если больше 20 строк",
])

Пайплайн целиком

def safe_refactor(code: str, function_name: str, context: str = "") -> dict:
    print("1. Анализирую код...")
    explanation = explain_code(code)

    print("2. Генерирую тесты-фиксации...")
    tests = generate_characterization_tests(code, function_name)

    print("3. Рефакторю...")
    refactored = refactor_with_principles(code, [
        "Говорящие имена",
        "Type hints",
        "Константы вместо магических чисел",
        "Разбивка на маленькие функции",
    ])

    return {
        "explanation": explanation,
        "characterization_tests": tests,
        "refactored_code": refactored,
        "next_steps": "1. Запусти тесты на оригинальном коде. 2. Примени рефакторинг. 3. Убедись что тесты всё ещё проходят."
    }

На курсе «ИИ для разработчиков» на Хекслете разбирают как использовать ИИ-агентов для работы с реальным кодом: рефакторинг, дебаг, ревью на живом проекте.

9 часов назад

Никита Вихров

+7 800 100 22 47

бесплатно по РФ

+7 495 085 21 62

бесплатно по Москве

108813 г. Москва, вн.тер.г. поселение Московский,
г. Московский, ул. Солнечная, д. 3А, стр. 1, помещ. 20Б/3
ОГРН 1217300010476
ИНН 7325174845