Прибыль:
- Возможность настроить систему безопасности тестирования, которая фиксирует текущее поведение перед рефакторингом.
- Возможность запрашивать у ИИ небольшие одношаговые преобразования, сохраняющие поведение, и проверять каждый шаг.
- Способность выявлять и расставлять приоритеты технического долга в контексте бизнеса.
Рефакторинг — это улучшение внутренней структуры кода без изменения его внешнего поведения: он становится более читабельным, простым и удобным в сопровождении. Технический долг, с другой стороны, — это компромисс в дизайне, сделанный ради быстрого решения и окупаемый «с лихвой» с течением времени — каждый угол, который вы срезаете сегодня, завтра обернется замедлением или ошибкой. Искусственный интеллект — мощный помощник, ускоряющий повторяющиеся и механические задачи рефакторинга; Но есть одно золотое правило рефакторинга, и сам по себе ИИ не может его гарантировать: поведение не должно меняться.
В этом модуле мы узнаем, как проводить безопасный рефакторинг с помощью ИИ: небольшие и обратимые шаги, защиту с помощью тестов, обнаружение запахов кода и определение приоритетов технического долга. Критический момент заключается в следующем: именно прохождение тестов, а не слово ИИ, доказывает, что поведение сохраняется.
Золотое правило рефакторинга: поведение остается постоянным
Что делает рефакторинг опасным, так это неосознанное изменение поведения, когда вы говорите: «Я улучшаюсь». Отказ от краевого случая при упрощении условия, нарушение порядка при преобразовании цикла, пропуск побочного эффекта при разделении функции — все это приводит к созданию «чистого на вид», но неработающего кода.
Вот почему тестирование является обязательным условием рефакторинга: перед изменением у вас должны быть тесты, фиксирующие существующее поведение. Эти тесты являются «сеткой безопасности»; Если вы случайно что-то сломаете во время рефакторинга, они сломаются и предупредят вас. Если у вас нет тестов, сначала напишите тесты, которые исправят существующее поведение (как мы узнали в модуле 5) — именно здесь ИИ получает быстрый старт.
Внимание: рефакторинг с помощью ИИ без тестовой сети — один из самых коварных источников ошибок. Легко сказать: «Я сохранил поведение»; Доказательством является то, что одни и те же тесты проходят до и после изменения.
Шаг за шагом: безопасный процесс рефакторинга
- Установите защитную сетку. Пусть будут тесты, фиксирующие текущее поведение кода, который вы будете рефакторить; Если нет, сначала запишите их (и посмотрите, как они будут выполнены).
- Назовите запах. Что вы улучшаете и почему? «Эта функция делает 3 вещи», «одна и та же логика повторяется в 4 местах», «имена вводят в заблуждение».
- Попросите о маленьких, одношаговых шагах. Попросите ИИ выполнить одно преобразование (например, просто «разделить эту функцию пополам»), а не перезаписывать весь файл.
- Запустите тесты. После каждого шага. Если зеленый — продолжай, если красный — забери обратно.
- Прочтите Дифф. Подтвердите построчно, что изменение действительно сохраняет поведение; Когда говорят, что ИИ — это «просто структура», может возникнуть логическая ошибка.
- Соедините на небольшие кусочки. Крупные разовые заявки на рефакторинг являются рискованными и непересматриваемыми.
Три мини-кейса
Случай 1 — 220-строчная функция безопасно разделена. У одной команды была функция обработки заказов на 220 строк. Были написаны первые 14 тестов (с помощью ИИ), которые фиксировали текущее поведение, все они прошли. Затем функция была разделена на 5 меньших функций шаг за шагом с помощью ИИ; Тесты проводились после каждого шага. Два теста были сломаны за один шаг — ИИ пропустил возврат в крайнем случае. Тесты сразу это заметили и исправили. Без сети ошибка могла бы дойти до рабочей среды.
Случай 2 — Катастрофа без тестовой сети. Другой разработчик «подчистил» модуль расчета даты, у которого не было тестов с ИИ. Код выглядел лучше, но високосный год рассчитывался неправильно; Ошибка обнаружилась через две недели после жалобы клиента. Потери намного перевесили время, сэкономленное на рефакторинге. Урок: рефакторинг без тестирования — это авантюра.
Случай 3 — Приоритизация технического долга. Одна команда дала ИИ резерв в 30 или около того «улучшаемых» баллов, и каждый из них оценивался по оси «частота изменений × риск × усилия». В полученной таблице уродливый модуль, который редко трогали, на самом деле имел низкий приоритет, а модуль средней сложности, который часто менялся, имел высокий приоритет. Команда направила свою энергию в нужное место.
Четыре копируемых шаблона
Обнаружение запаха кода и определение приоритетов:
Перечислите кандидата на рефакторинг, который «пахнет» в этом коде: длинная функция, повтор (DRYViolation), вводящее в заблуждение имя, глубоко вложенное условие, скрытый побочный эффект, магическое число. Для каждого: местоположение, причина проблемы, предлагаемый небольшой шаг, предполагаемый риск (низкий/средний/высокий). НЕ МЕНЯЙТЕ код, просто планируйте.{{code}}
Одношаговая трансформация, сохраняющая поведение:
ПРОСТО сделайте это: {{одиночное преобразование, например Разделите эту функцию на 3 меньшие именованные функции}}. ИЗМЕНИТЕ видимое поведение, подпись и возвращаемые значения. Напишите в одном предложении, почему все, что вы изменили, сохраняет поведение.{{code}}
Сеть безопасности перед рефакторингом (тестирование характеристик):
Напишите тесты, которые фиксируют ТЕКУЩЕЕ поведение этой функции (правильное или нет); цель состоит в том, чтобы уловить изменение поведения во время рефакторинга. Включите типичные + пограничные записи. Запишите ожидания на основе текущего результата функции.{{function}}
Формирование записи технического долга (незавершенной работы):
Внесите следующий список запахов в таблицу приоритетов: вещество, область воздействия, частота изменения (насколько мне известно: {{...}}), риск, предполагаемые усилия, рекомендуемый приоритет. Поместите высокоэффективные + легкие усилия вверху. {{smell_list}}
Слабая подсказка / Сильная подсказка
Слабое: «Очистите этот код и сделайте его лучше».
Сильный: «Разделите эту 90-строчную функцию на 3 меньшие функции с одной ответственностью, не меняя ее внешнего поведения и сигнатуры. Оставьте побочные эффекты (запись в БД) в текущем порядке. У меня есть тесты, поведение должно остаться прежним. Дайте разницу и объясните в одном предложении, почему каждое разделение сохраняет поведение. [код]»
Мощная версия; Он требует единственного конкретного преобразования, явно накладывает ограничения на поведение и сигнатуры и требует обоснования. Расплывчатые требования, такие как «сделать лучше», приводят к неконтролируемым и рискованным изменениям.
Тип рефакторинга
надежность ИИ
Предварительное условие
переименовывать
высокий
Объем правильный?
Разделение функций
средне-высокий
Тестнет обязателен
Делимся повторением
средний
Разница в поведении может быть скрыта
Изменение алгоритма/структуры
низкий
Обширное тестирование + проверка на людях
Архитектурная перепланировка
низкий
Под руководством человека, при поддержке ИИ
Управление техническим долгом, а не его погашение
Технический долг не так уж и плох; Иногда осознанное заимствование (для удовлетворения поставок) является правильным решением. Цель состоит не в том, чтобы ликвидировать долг, а в том, чтобы сделать его видимым и управляемым. ИИ быстро обнаруживает и определяет приоритетность долгов, но решение «какой долг следует выплатить, а от какого следует отказаться» требует бизнес-контекста: как часто этот модуль меняется, скольких людей он затрагивает, каков риск? Это решение принимает команда, которая знает кодовую базу и продукт; ИИ просто уточняет варианты.
Совет: Держите PR по рефакторингу отдельно от PR, связанных с изменением поведения. Возможность сказать: «Этот PR — всего лишь рефакторинг, поведение такое же» упрощает расследование и позволяет быстро сузить причину возникновения проблемы.
Распространенные ошибки
- Рефакторинг без тестнета. Вам нечего доказать, что поведение сохранилось.
- Это означает «очистить весь файл». Большие неконтролируемые изменения скрывают ошибку и не могут быть проверены.
- Принятие Diff без его чтения. Возможно, ИИ упустил некоторую логику, когда сказал «просто структура».
- Путаница рефакторинга с изменением поведения. Выполнение того и другого в одном и том же PR делает невозможным отслеживание первопричин.
- Пытаюсь исправить каждый запах. Уродливый код, который редко меняется, часто имеет низкий приоритет; Направьте энергию на то место, которое часто меняется.
В заключение
Единственное правило рефакторинга — поведение остается постоянным, и доказательством этого являются тесты. ИИ обладает мощными возможностями в обнаружении запахов кода, одноэтапных преобразованиях и определении приоритетов технического долга; но вам нужно настроить систему безопасности, запустить тесты и прочитать разницу после каждого шага. Делайте небольшие обратимые шаги; отличать рефакторинг от изменения поведения; и позвольте команде, которая знает бизнес-контекст, решить, какой долг выплатить.
Задача приложения
Выберите функцию из своей базы кода, которая кажется вам длинной или сложной. Сначала напечатайте тесты, фиксирующие его текущее поведение с помощью шаблона «сети безопасности», и посмотрите, все ли они пройдены. Затем выполните рефакторинг функции одним способом (например, разделение пополам) с использованием шаблона «одношаговое преобразование, сохраняющее поведение», и снова запустите тесты. Если тест дает сбой, выясните, почему; Если ничего не сломалось, прочитайте разницу построчно, чтобы убедиться, что поведение действительно сохранилось.
контрольный список
- [ ] Я знаю, что рефакторинг не должен менять поведение, и есть тесты, подтверждающие это.
- [ ] Я настраиваю систему безопасности, которая фиксирует текущее поведение перед рефакторингом.
- [ ] Я хочу небольших одноэтапных преобразований с помощью ИИ, а не больших разовых преобразований.
- [ ] После каждого шага я запускаю тесты и читаю различия.
- [ ] Я продолжаю заниматься рефакторингом PR отдельно от PR, связанного с изменением поведения.
- [ ] Я отдаю предпочтение техническому долгу в контексте бизнеса, а не пытаюсь слепо его обнулить.