Единица 8 / 12

Рефакторинг и управление техническим долгом

Прибыль:

  • Возможность настроить систему безопасности тестирования, которая фиксирует текущее поведение перед рефакторингом.
  • Возможность запрашивать у ИИ небольшие одношаговые преобразования, сохраняющие поведение, и проверять каждый шаг.
  • Способность выявлять и расставлять приоритеты технического долга в контексте бизнеса.

Рефакторинг — это улучшение внутренней структуры кода без изменения его внешнего поведения: он становится более читабельным, простым и удобным в сопровождении. Технический долг, с другой стороны, — это компромисс в дизайне, сделанный ради быстрого решения и окупаемый «с лихвой» с течением времени — каждый угол, который вы срезаете сегодня, завтра обернется замедлением или ошибкой. Искусственный интеллект — мощный помощник, ускоряющий повторяющиеся и механические задачи рефакторинга; Но есть одно золотое правило рефакторинга, и сам по себе ИИ не может его гарантировать: поведение не должно меняться.

В этом модуле мы узнаем, как проводить безопасный рефакторинг с помощью ИИ: небольшие и обратимые шаги, защиту с помощью тестов, обнаружение запахов кода и определение приоритетов технического долга. Критический момент заключается в следующем: именно прохождение тестов, а не слово ИИ, доказывает, что поведение сохраняется.

Золотое правило рефакторинга: поведение остается постоянным

Что делает рефакторинг опасным, так это неосознанное изменение поведения, когда вы говорите: «Я улучшаюсь». Отказ от краевого случая при упрощении условия, нарушение порядка при преобразовании цикла, пропуск побочного эффекта при разделении функции — все это приводит к созданию «чистого на вид», но неработающего кода.

Вот почему тестирование является обязательным условием рефакторинга: перед изменением у вас должны быть тесты, фиксирующие существующее поведение. Эти тесты являются «сеткой безопасности»; Если вы случайно что-то сломаете во время рефакторинга, они сломаются и предупредят вас. Если у вас нет тестов, сначала напишите тесты, которые исправят существующее поведение (как мы узнали в модуле 5) — именно здесь ИИ получает быстрый старт.

Внимание: рефакторинг с помощью ИИ без тестовой сети — один из самых коварных источников ошибок. Легко сказать: «Я сохранил поведение»; Доказательством является то, что одни и те же тесты проходят до и после изменения.

Шаг за шагом: безопасный процесс рефакторинга

  1. Установите защитную сетку. Пусть будут тесты, фиксирующие текущее поведение кода, который вы будете рефакторить; Если нет, сначала запишите их (и посмотрите, как они будут выполнены).
  2. Назовите запах. Что вы улучшаете и почему? «Эта функция делает 3 вещи», «одна и та же логика повторяется в 4 местах», «имена вводят в заблуждение».
  3. Попросите о маленьких, одношаговых шагах. Попросите ИИ выполнить одно преобразование (например, просто «разделить эту функцию пополам»), а не перезаписывать весь файл.
  4. Запустите тесты. После каждого шага. Если зеленый — продолжай, если красный — забери обратно.
  5. Прочтите Дифф. Подтвердите построчно, что изменение действительно сохраняет поведение; Когда говорят, что ИИ — это «просто структура», может возникнуть логическая ошибка.
  6. Соедините на небольшие кусочки. Крупные разовые заявки на рефакторинг являются рискованными и непересматриваемыми.

Три мини-кейса

Случай 1 — 220-строчная функция безопасно разделена. У одной команды была функция обработки заказов на 220 строк. Были написаны первые 14 тестов (с помощью ИИ), которые фиксировали текущее поведение, все они прошли. Затем функция была разделена на 5 меньших функций шаг за шагом с помощью ИИ; Тесты проводились после каждого шага. Два теста были сломаны за один шаг — ИИ пропустил возврат в крайнем случае. Тесты сразу это заметили и исправили. Без сети ошибка могла бы дойти до рабочей среды.

Случай 2 — Катастрофа без тестовой сети. Другой разработчик «подчистил» модуль расчета даты, у которого не было тестов с ИИ. Код выглядел лучше, но високосный год рассчитывался неправильно; Ошибка обнаружилась через две недели после жалобы клиента. Потери намного перевесили время, сэкономленное на рефакторинге. Урок: рефакторинг без тестирования — это авантюра.

Случай 3 — Приоритизация технического долга. Одна команда дала ИИ резерв в 30 или около того «улучшаемых» баллов, и каждый из них оценивался по оси «частота изменений × риск × усилия». В полученной таблице уродливый модуль, который редко трогали, на самом деле имел низкий приоритет, а модуль средней сложности, который часто менялся, имел высокий приоритет. Команда направила свою энергию в нужное место.

Четыре копируемых шаблона

Обнаружение запаха кода и определение приоритетов:

Перечислите кандидата на рефакторинг, который «пахнет» в этом коде: длинная функция, повтор (DRYViolation), вводящее в заблуждение имя, глубоко вложенное условие, скрытый побочный эффект, магическое число. Для каждого: местоположение, причина проблемы, предлагаемый небольшой шаг, предполагаемый риск (низкий/средний/высокий). НЕ МЕНЯЙТЕ код, просто планируйте.{{code}}

Одношаговая трансформация, сохраняющая поведение:

ПРОСТО сделайте это: {{одиночное преобразование, например Разделите эту функцию на 3 меньшие именованные функции}}. ИЗМЕНИТЕ видимое поведение, подпись и возвращаемые значения. Напишите в одном предложении, почему все, что вы изменили, сохраняет поведение.{{code}}

Сеть безопасности перед рефакторингом (тестирование характеристик):

Напишите тесты, которые фиксируют ТЕКУЩЕЕ поведение этой функции (правильное или нет); цель состоит в том, чтобы уловить изменение поведения во время рефакторинга. Включите типичные + пограничные записи. Запишите ожидания на основе текущего результата функции.{{function}}

Формирование записи технического долга (незавершенной работы):

Внесите следующий список запахов в таблицу приоритетов: вещество, область воздействия, частота изменения (насколько мне известно: {{...}}), риск, предполагаемые усилия, рекомендуемый приоритет. Поместите высокоэффективные + легкие усилия вверху. {{smell_list}}

Слабая подсказка / Сильная подсказка

Слабое: «Очистите этот код и сделайте его лучше».
Сильный: «Разделите эту 90-строчную функцию на 3 меньшие функции с одной ответственностью, не меняя ее внешнего поведения и сигнатуры. Оставьте побочные эффекты (запись в БД) в текущем порядке. У меня есть тесты, поведение должно остаться прежним. Дайте разницу и объясните в одном предложении, почему каждое разделение сохраняет поведение. [код]»

Мощная версия; Он требует единственного конкретного преобразования, явно накладывает ограничения на поведение и сигнатуры и требует обоснования. Расплывчатые требования, такие как «сделать лучше», приводят к неконтролируемым и рискованным изменениям.

Тип рефакторинга

надежность ИИ

Предварительное условие

переименовывать

высокий

Объем правильный?

Разделение функций

средне-высокий

Тестнет обязателен

Делимся повторением

средний

Разница в поведении может быть скрыта

Изменение алгоритма/структуры

низкий

Обширное тестирование + проверка на людях

Архитектурная перепланировка

низкий

Под руководством человека, при поддержке ИИ

Управление техническим долгом, а не его погашение

Технический долг не так уж и плох; Иногда осознанное заимствование (для удовлетворения поставок) является правильным решением. Цель состоит не в том, чтобы ликвидировать долг, а в том, чтобы сделать его видимым и управляемым. ИИ быстро обнаруживает и определяет приоритетность долгов, но решение «какой долг следует выплатить, а от какого следует отказаться» требует бизнес-контекста: как часто этот модуль меняется, скольких людей он затрагивает, каков риск? Это решение принимает команда, которая знает кодовую базу и продукт; ИИ просто уточняет варианты.

Совет: Держите PR по рефакторингу отдельно от PR, связанных с изменением поведения. Возможность сказать: «Этот PR — всего лишь рефакторинг, поведение такое же» упрощает расследование и позволяет быстро сузить причину возникновения проблемы.

Распространенные ошибки

  • Рефакторинг без тестнета. Вам нечего доказать, что поведение сохранилось.
  • Это означает «очистить весь файл». Большие неконтролируемые изменения скрывают ошибку и не могут быть проверены.
  • Принятие Diff без его чтения. Возможно, ИИ упустил некоторую логику, когда сказал «просто структура».
  • Путаница рефакторинга с изменением поведения. Выполнение того и другого в одном и том же PR делает невозможным отслеживание первопричин.
  • Пытаюсь исправить каждый запах. Уродливый код, который редко меняется, часто имеет низкий приоритет; Направьте энергию на то место, которое часто меняется.

В заключение

Единственное правило рефакторинга — поведение остается постоянным, и доказательством этого являются тесты. ИИ обладает мощными возможностями в обнаружении запахов кода, одноэтапных преобразованиях и определении приоритетов технического долга; но вам нужно настроить систему безопасности, запустить тесты и прочитать разницу после каждого шага. Делайте небольшие обратимые шаги; отличать рефакторинг от изменения поведения; и позвольте команде, которая знает бизнес-контекст, решить, какой долг выплатить.

Задача приложения

Выберите функцию из своей базы кода, которая кажется вам длинной или сложной. Сначала напечатайте тесты, фиксирующие его текущее поведение с помощью шаблона «сети безопасности», и посмотрите, все ли они пройдены. Затем выполните рефакторинг функции одним способом (например, разделение пополам) с использованием шаблона «одношаговое преобразование, сохраняющее поведение», и снова запустите тесты. Если тест дает сбой, выясните, почему; Если ничего не сломалось, прочитайте разницу построчно, чтобы убедиться, что поведение действительно сохранилось.

контрольный список

  • [ ] Я знаю, что рефакторинг не должен менять поведение, и есть тесты, подтверждающие это.
  • [ ] Я настраиваю систему безопасности, которая фиксирует текущее поведение перед рефакторингом.
  • [ ] Я хочу небольших одноэтапных преобразований с помощью ИИ, а не больших разовых преобразований.
  • [ ] После каждого шага я запускаю тесты и читаю различия.
  • [ ] Я продолжаю заниматься рефакторингом PR отдельно от PR, связанного с изменением поведения.
  • [ ] Я отдаю предпочтение техническому долгу в контексте бизнеса, а не пытаюсь слепо его обнулить.