Введение
Каждый разработчик хотя бы раз сталкивался с legacy-кодом — тем самым, который писали «ещё до тебя», без тестов, с магическими числами и функциями на 500 строк. Рефакторинг такого кода — не просто прихоть, а необходимость: по данным отчёта Stripe (2018), разработчики тратят около 42% времени на технический долг. Однако вручную разбирать монолит страшно и долго. Современные AI-инструменты, такие как Claude 3.5 Sonnet, GPT-4o или Copilot, могут взять на себя черновую работу, если правильно составить промт. В этой статье — 7 проверенных промтов, которые я использую для рефакторинга legacy-кода. Каждый снабжён реальным примером и пояснением.
1. Декомпозиция монолитной функции
Проблема: Функция на 200+ строк с вложенными циклами и условиями. Нужно разбить на мелкие, тестируемые части.
Промт:
Разбей следующую функцию на несколько маленьких функций. Каждая новая функция должна иметь единственную ответственность и понятное имя. Добавь JSDoc-комментарии с описанием параметров и возвращаемого значения. Исходный код: [вставьте код].
Пример применения:
Была функция processOrder(data), которая валидировала, рассчитывала скидку, обновляла склад и отправляла email. После промта AI предложил 4 отдельные функции: validateOrder, calculateDiscount, updateInventory, sendConfirmation. Каждая — не более 20 строк.
Результат: Код стал читаемым, покрываемым юнит-тестами (можно тестировать каждую функцию отдельно), а баги локализуются быстрее.
2. Замена магических чисел на константы
Проблема: В коде разбросаны числа вроде 86400, 0.15, 1000 — без контекста.
Промт:
Найди в этом коде все магические числа и строки. Замени их на именованные константы с понятными названиями. Константы вынеси в начало модуля или в отдельный файл. Сгруппируй по смыслу (таймауты, лимиты, ставки). Код: [вставьте код].
Пример применения:
В обработчике платежей были числа 0.15 (налог), 2.9 (комиссия шлюза), 30 (дней для возврата). После промта появились const TAX_RATE = 0.15, const GATEWAY_FEE = 2.9, const REFUND_PERIOD_DAYS = 30. Изменение ставки налога теперь требует правки в одном месте.
3. Упрощение цепочек if-else через полиморфизм или стратегию
Проблема: Лестница из 10+ вложенных if-else для обработки разных типов событий.
Промт:
Перепиши эту цепочку if-else, используя шаблон проектирования Strategy. Для каждого условия создай отдельный класс с методом handle(). Верни код с примерами вызова. Исходный код: [вставьте код].
Пример применения:
Код обрабатывал уведомления: email, SMS, push. Вместо if (type === 'email') {...} else if (type === 'sms') {...} появились классы EmailNotifier, SmsNotifier, PushNotifier, реализующие общий интерфейс NotifierStrategy. Новый тип уведомления добавляется без изменения существующего кода (принцип Open-Closed).
4. Извлечение условий в функции-предикаты
Проблема: Условия вида if (order.status === 'shipped' && Date.now() - order.createdAt > 7 * 24 * 60 * 60 * 1000).
Промт:
Вынеси каждое сложное условие из if-ов в отдельную функцию-предикат с говорящим названием. Например, isOrderReturnable(order). Используй camelCase. Код: [вставьте код].
Пример применения:
После промта условие превратилось в if (isOrderShippedRecently(order) && hasExceededReturnWindow(order)). Функции-предикаты переиспользуются в других местах, а логика становится самодокументируемой.
5. Замена callback-ов на async/await
Проблема: Legacy-код с callback-ами, ведущий к Callback Hell.
Промт:
Перепиши этот код с колбэками на async/await с обработкой ошибок через try-catch. Если колбэки используют Node.js style (err, result), оберни их в promisify. Добавь комментарии к ключевым шагам. Код: [вставьте код].
Пример применения:
Код загрузки файла с тремя вложенными callback-ами превратился в три последовательных await с единым блоком catch. Читаемость повысилась, отладка упростилась (стек-трейс стал плоским).
6. Удаление мёртвого кода
Проблема: В коде есть функции, переменные и комментарии, которые не используются, но смущают.
Промт:
Проанализируй этот модуль и удали неиспользуемые функции, переменные, импорты и закомментированные блоки. Если функция не вызывается нигде в проекте — удали. Если импорт не используется — удали. Верни очищенный код. Исходный код: [вставьте код].
Пример применения:
В модуле обработки заказов была функция calculateLegacyTax(), которая не вызывалась с 2019 года. AI удалил её, а также 3 неиспользуемых импорта. Размер файла сократился на 30%, линтер перестал выдавать предупреждения.
7. Приведение к единому стилю и типизация
Проблема: В коде смешаны разные стили (camelCase, snake_case, kebab-case), нет типов.
Промт:
Приведи этот код к единому стилю: используй camelCase для переменных и функций, PascalCase для классов. Добавй TypeScript-типизацию для всех параметров и возвращаемых значений. Если тип сложный — создай интерфейс. Код: [вставьте код].
Пример применения:
Код на JavaScript без типов, переменные user_name, getOrderTotal. После промта — userName, getOrderTotal(): number, интерфейс IOrder. Это снизило количество ошибок на проде на 20% (по опыту команды).
Заключение
Рефакторинг legacy-кода — это не разовая акция, а постоянный процесс. Промты выше помогают автоматизировать рутину: декомпозицию, замену магических чисел, упрощение условий, переход на современный синтаксис. Однако помните: AI не понимает бизнес-логику. Всегда проверяйте результат тестами и код-ревью. Начните с малого — возьмите одну функцию, примените промт, и вы увидите, как код становится чище. Используйте эти промты как стартовую точку и адаптируйте под свой проект.
Источники:
- Отчёт Stripe о техническом долге (2018): stripe.com/reports/developer-experience-2018
- Martin Fowler, «Refactoring: Improving the Design of Existing Code» (2nd edition, 2018)
- Документация OpenAI по промпт-инжинирингу: platform.openai.com/docs/guides/prompt-engineering
Комментарии