Безопасный рефакторинг с ИИ
Перейти к разделу
Почему все боятся трогать легаси-код
Вы знаете это чувство: исправляешь что-то в одном месте — ломается в трёх других. Легаси-код хрупок, потому что не имеет тестов, чётких интерфейсов и часто содержит скрытые зависимости, проявляющиеся только в продакшене. Поэтому никто не хочет его менять. Поэтому технический долг растёт. И проблема усугубляется каждый месяц.
ИИ меняет эту динамику фундаментально. Не потому, что делает рефакторинг за вас (это опасная иллюзия), а потому что помогает создать страховочную сеть, позволяющую изменять код с уверенностью, что сломанные вещи всплывут до того, как попадут в продакшен.
Правило номер один: никогда не рефакторите без тестов. А если тесты не существуют, ваш первый шаг — попросить ИИ сгенерировать их, а не рефакторить.
Тесты-характеристики: фиксируем текущее поведение
Тесты-характеристики (иногда называемые «golden master» тестами) не проверяют, делает ли код то, что должен. Они проверяют, делает ли код то, что делает сейчас. Это принципиальное различие. С легаси-кодом вы часто не знаете, каким является «правильное» поведение. Но вы знаете, что код делает в данный момент — и именно это вы хотите зафиксировать перед любым изменением.
Промпт для ИИ: «Сгенерируй тесты-характеристики для этой функции. Для каждого теста используй реалистичные входные данные и захвати текущие выводы как ожидаемые значения. Включи граничные случаи, которые можно вывести из кода». ИИ читает код, определяет ветвления и граничные условия и генерирует тесты, фиксирующие текущее поведение.
Стратегия рефакторинга: маленькие шаги, частые проверки
Никогда не рефакторите большие куски кода за один раз. Разбивайте рефакторинг на маленькие шаги, где каждый шаг меняет одну вещь и после него проходят тесты. ИИ помогает проектировать эту последовательность: «Мне нужно отрефакторить класс OrderProcessor. Предложи последовательность маленьких, безопасных шагов, где каждый шаг независимо тестируем и обратим».
Типичная последовательность выглядит так: сначала переименуйте переменные и методы на понятные имена. Затем выделите повторяющиеся блоки в отдельные методы. Затем отделите побочные эффекты от чистой логики. Делайте коммит на каждом шаге. Если что-то сломается, вы откатываете ровно один коммит, а не целый день работы.
Попросите ИИ генерировать каждое изменение в виде диффа. Вы можете проверить, что именно изменится, прежде чем применять. Никогда не принимайте вслепую большие изменения, сгенерированные ИИ.
Точки швов: где вставлять границы тестирования
Майкл Физерс в книге «Эффективная работа с легаси-кодом» использует термин «швы» — места в коде, где можно изменить поведение, не меняя сам код. Например, интерфейсы, которые можно заменить mock-реализациями. ИИ может найти эти точки швов: «Найди места в этом коде, где можно вставить абстракцию или интерфейс, чтобы тестировать часть логики изолированно».
Важно: создание швов само по себе является рефакторингом — именно поэтому тесты-характеристики нужны ДО этого шага. Сначала тесты, фиксирующие поведение. Затем швы, открывающие лучшее тестирование. Затем больше тестов на более низком уровне. И только потом настоящий рефакторинг.
Когда рефакторинг с ИИ не работает
ИИ плохо справляется с рефакторингом, требующим глубокого понимания домена. Если бизнес-логика требует выполнения определённых операций в точном порядке по регуляторным причинам, ИИ не может этого знать из кода. Аналогично с критическими для производительности секциями, где существуют специфические оптимизации с веской причиной, даже если они выглядят как плохой код. Всегда спрашивайте: «Есть ли причина, по которой это выглядит именно так?»
Коммиты рефакторинга должны быть как можно меньше. Идеальный коммит меняет одну вещь: переименование, выделение метода, перемещение файла. Если что-то сломается, вы откатываете один коммит, а не целый день работы.
Выберите одну сложную функцию из вашего легаси-проекта. 1) Попросите ИИ сгенерировать тесты-характеристики (минимум 5). 2) Запустите тесты и убедитесь, что все проходят. 3) Попросите ИИ предложить последовательность из 3–5 шагов рефакторинга. 4) Выполните первый шаг и убедитесь, что тесты по-прежнему проходят. 5) Сделайте коммит и переходите к следующему шагу.
Подсказка
Если тесты падают после рефакторинга, откатите изменение и спросите ИИ, почему изменилось поведение. Вы часто обнаружите скрытый побочный эффект.
Выберите одну функцию в легаси-коде, требующую рефакторинга. Процесс: 1) Попросите ИИ написать тесты для текущего поведения, 2) Запустите тесты — все должны проходить, 3) Попросите ИИ предложить рефакторинг (с объяснением почему), 4) Реализуйте рефакторинг, 5) Запустите тесты снова — они должны по-прежнему проходить. Тесты служат страховочной сетью — если они падают, рефакторинг изменил поведение.
Подсказка
Документируйте процесс и результаты — они послужат справочником для похожих задач в будущем.
Выберите сложный класс из легаси-кода. Промпт для ИИ: «Найди точки швов в этом классе — места, где можно вставить интерфейс или абстракцию для изолированного тестирования. Для каждой точки шва укажи: 1) Где она находится, 2) Какой интерфейс ты предлагаешь, 3) Как это открывает лучшее тестирование, 4) Каковы риски этого изменения». Реализуйте одну точку шва и напишите тест, использующий её.
Подсказка
Типичные точки швов: вызовы базы данных (замените интерфейсом репозитория), HTTP-клиенты (замените абстракцией), системное время (замените интерфейсом часов).
- Никогда не рефакторьте без тестов — сначала попросите ИИ сгенерировать тесты-характеристики
- Разбивайте рефакторинг на маленькие шаги, каждый из которых независимо тестируем и обратим
- ИИ определяет точки швов, где можно вставить границы тестирования
- ИИ не понимает доменного контекста — всегда спрашивайте, нет ли причины, по которой код выглядит странно
В следующем уроке мы разбираем тесты, сгенерированные ИИ для непроверенного кода — техника, которая даст вам явное преимущество. Разблокируйте полный курс и продолжайте прямо сейчас.
2/6 завершено — продолжайте!