Legacy-код — это не приговор, а поле для стратегической работы. Когда перед тобой 1000 строк спагетти-функции, которая «работает и не трогай», ИИ-ассистент может стать твоим скальпелем. Но чтобы он не навредил, нужны точные промты. Я собрал 10 проверенных шаблонов — от поиска дублирования до профилирования узких мест. Каждый промт снабжён примером и пояснением, как он применяется в реальном проекте.
1. Охота на дублирование: найди повторяющиеся блоки
Промт: Проанализируй файл [имя_файла.py]. Найди фрагменты кода, которые повторяются более двух раз с минимальными отличиями (переменные, литералы). Для каждого дубля предложи функцию, которая его заменит, с сигнатурой и примером вызова. Укажи, какие импорты и зависимости понадобятся.
Как работает: Модель сканирует синтаксис и AST, выявляя паттерны. Это не просто поиск по Ctrl+C/Ctrl+V, а семантическое сопоставление.
Пример:
# Было: три блока обработки ошибок в разных местах
try:
result = parse_data(data)
except ValueError:
log_error("Parsing failed", data)
raise
# Стало:
def safe_parse(data):
try:
return parse_data(data)
except ValueError:
log_error("Parsing failed", data)
raise
Когда применять: На этапе анализа кодовой базы перед крупным рефакторингом.
2. Разделяй и властвуй: разбивка монолитных функций
Промт: Функция [имя_функции] в файле [имя_файла.py] слишком длинная (N строк) и выполняет несколько задач. Разбей её на несколько меньших функций, каждая из которых отвечает за одну операцию. Сохрани общий интерфейс, чтобы внешние вызовы не изменились. Покажи получившийся код и объясни, как улучшилась читаемость.
Пример:
def process_order(order):
# 50 строк: валидация, расчёт, сохранение
...
# Результат:
def validate_order(order): ...
def calculate_total(order): ...
def save_order(order): ...
Почему это важно: Монолитные функции — корень большинства багов. Разбиение улучшает тестируемость.
3. Магические числа и строки: наведи порядок в константах
Промт: В файле [имя_файла.py] найди все «магические числа» и строки (литералы, используемые в логике). Предложи именованные константы или Enum для их замены. Приведи примеры до/после и объясни, как это повысит поддерживаемость.
Пример:
# Было:
if status == 1: ...
# Стало:
class OrderStatus(IntEnum):
PENDING = 1
PAID = 2
SHIPPED = 3
if status == OrderStatus.PAID: ...
4. Убить спагетти-условия: рефакторинг вложенных if
Промт: Функция [имя_функции] содержит сложную логику с множеством вложенных if-else. Перепиши её с использованием ранних выходов (guard clauses) и, если возможно, паттерна Strategy. Покажи код до/после и проанализируй, как изменилась сложность (цикломатическая).
Пример:
# Было:
def process(data):
if data:
if data.type == 'A':
# 20 строк
else:
# 10 строк
else:
raise ValueError()
# Стало:
def process(data):
if not data:
raise ValueError()
if data.type == 'A':
handle_A(data)
else:
handle_B(data)
5. Типизируй это: добавь аннотации в старый код
Промт: Добавь аннотации типов к функциям в файле [имя_файла.py] в соответствии с PEP 484. Используй typing.Optional, Union, List, Dict и т.д. Не меняй логику, только типы. После этого проверь код с помощью mypy (команда: mypy [файл]). Покажи, какие ошибки выдаст mypy и как их исправить.
Почему это работает: Аннотации типов — это документация, которую проверяет машина. Они снижают количество ошибок на этапе разработки.
6. Долой глобальные переменные: инкапсуляция состояния
Промт: В проекте [имя_проекта] глобальные переменные используются в [список файлов]. Предложи рефакторинг, который инкапсулирует их в классы или передаёт как параметры. Оцени риски: какие модули зависят от этих глобальных переменных? Приведи план миграции.
Пример:
# Было:
config = {"debug": True}
def log(message):
if config["debug"]: print(message)
# Стало:
class Logger:
def __init__(self, debug: bool):
self.debug = debug
def log(self, message):
if self.debug: print(message)
7. Профилируй и оптимизируй: найди узкие места
Промт: Проанализируй производительность функции [имя_функции] в файле [имя_файла.py]. Предположи, какие операции могут быть медленными (циклы, обращение к БД, регулярные выражения). Предложи оптимизации: использование генераторов, кэширование с lru_cache, векторизация с NumPy и т.д. Приведи бенчмарк до/после (используй timeit).
Пример:
from functools import lru_cache
@lru_cache(maxsize=128)
def compute_heavy(x): ...
8. Избавляемся от dead code: безопасное удаление мусора
Промт: Найди в проекте мёртвый код: функции, классы, импорты, которые нигде не используются. Используй инструменты статического анализа (например, vulture или pyflakes). Составь список удаляемых элементов и предупреди о возможных последствиях (вдруг код используется динамически). Покажи, как проверить, что код действительно не вызывается.
Важно: Не удаляй вслепую — используй grep или IDE для поиска упоминаний.
9. Документируй правильно: добавь docstring и комментарии
Промт: Добавь docstring в стиле Google или NumPy для всех публичных функций и классов в файле [имя_файла.py]. Опиши параметры, возвращаемые значения, исключения. Также добавь комментарии в сложных местах, объясняя «почему», а не «что». Не переусердствуй: комментируй только неочевидные решения.
Пример:
def calculate_discount(price: float, customer_type: str) -> float:
"""Рассчитать скидку.
Args:
price: Исходная цена.
customer_type: Тип клиента ('regular', 'vip').
Returns:
Цена со скидкой.
Raises:
ValueError: Если type не поддерживается.
"""
10. Тестируемость: рефакторинг для юнит-тестов
Промт: Функция [имя_функции] трудно тестируема из-за внешних зависимостей (сеть, БД, глобальное состояние). Предложи рефакторинг с использованием внедрения зависимостей: передавай зависимости как параметры с значениями по умолчанию. Покажи, как написать юнит-тест с mock для этой функции (используй pytest и unittest.mock).
Пример:
# Было:
def fetch_data():
import requests
return requests.get("https://api.example.com").json()
# Стало:
def fetch_data(session=None):
if session is None:
import requests
session = requests
return session.get("https://api.example.com").json()
11. Снижаем связанность: выделение модулей
Промт: Модуль [имя_модуля] выполняет слишком много обязанностей: работа с БД, бизнес-логика, форматирование. Разбей его на несколько модулей по принципу единственной ответственности. Составь план: какие классы/функции переедут, какие импорты изменятся. Покажи структуру каталога после рефакторинга.
12. Переходим на современный синтаксис: f-строки, dataclasses, pathlib
Промт: Обнови код в [имя_файла.py] до современных стандартов Python 3.10+: замени форматирование % и .format() на f-строки, замени классы-структуры на dataclasses, замени os.path на pathlib. Убедись, что код остался совместимым с Python 3.8+ (если это требование проекта). Покажи примеры до/после.
Пример:
# Было:
import os
path = os.path.join("dir", "file.txt")
# Стало:
from pathlib import Path
path = Path("dir") / "file.txt"
13. Оптимизация алгоритмов: замена квадратичной сложности
Промт: Проанализируй алгоритмическую сложность функции [имя_функции]. Если она содержит вложенные циклы, которые можно заменить на хэш-таблицы или сортировку, предложи оптимизацию. Приведи оценку сложности до и после (O(n^2) → O(n log n)). Покажи код.
14. Безопасность исключений: обработка ошибок
Промт: В файле [имя_файла.py] есть «голые» except: или except Exception, которые проглатывают ошибки. Замени их на конкретные типы исключений, добавь логирование с traceback. Предложи иерархию собственных исключений для модуля. Покажи пример до/после.
15. Убираем запах кода: выявление антипаттернов
Промт: Проверь код в [имя_файла.py] на наличие антипаттернов: God Object, Feature Envy, Shotgun Surgery, Primitive Obsession, Long Parameter List. Для каждого найденного паттерна предложи конкретный рефакторинг (например, замена параметров на объект). Опиши, как это улучшит дизайн.
16. Чистые функции: убираем побочные эффекты
Промт: Функция [имя_функции] изменяет глобальное состояние или входные данные. Перепиши её как чистую функцию: она должна возвращать новое значение, не изменяя аргументы. Если это невозможно, обоснуй, почему, и предложи альтернативу. Покажи пример использования до/после.
17. Модульное тестирование после рефакторинга
Промт: После рефакторинга функции [имя_функции] напиши набор юнит-тестов с использованием pytest. Покрой основные сценарии: нормальное поведение, граничные случаи, обработку ошибок. Используй параметризацию для сокращения дублирования. Покажи код тестов и объясни, какие случаи ты выбрал.
18. Миграция на асинхронность: когда это оправдано
Промт: Проанализируй функцию [имя_функции], которая выполняет блокирующие I/O операции (сеть, диски). Оцени, стоит ли перевести её на asyncio для улучшения пропускной способности. Если да, предложи реализацию с async/await и покажи, как изменить вызывающий код. Если нет, объясни почему (например, из-за сложности или отсутствия выгоды).
Важно помнить: промты — это не серебряная пуля. Всегда проверяй предложения модели, особенно в legacy-коде, где логика может быть хрупкой. Начни с малого: выбери функцию, примени промт, прогони тесты. Постепенно ты превратишь болото в структурированный парк.
А какие приёмы используешь ты? Поделись в комментариях!
Комментарии