Как провести рефакторинг кода зомби

Если вы какое-то время занимались разработкой программного обеспечения, вы, вероятно, встречали хотя бы один пример этого: страшный код, которого никто не хочет трогать.

Почему я должен убить этого дракона?

Существует очень простая причина, по которой некоторый код нуждается в рефакторинге.

Слишком больно поддерживать "как есть". Никто не знает, что делает код. Если вы попытаетесь переписать код с нуля, вы можете пропустить несколько важных (но неясных) крайних случаев, о которых все забыли.

В двух словах о рефакторинге

Весь процесс рефакторинга выглядит так:

  1. Сделайте одно простое изменение.
  2. Убедитесь, что вы ничего не сломали.
  3. Повторить.

Давайте углубимся в каждый из этих шагов.

1. Сделайте одно простое изменение

Поскольку вы работаете с ужасающей кодовой базой, вам нужно найти способы ограничить риски, на которые вы идете.

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

Некоторые примеры простых изменений:

  • Переименование переменной.
  • Перемещение функции из одного класса в другой.
  • Вставить пару строк кода в собственную функцию.
  • Удаление зависимости (при условии, что вы уже удалили все вызовы этого кода).
  • Создание нового пустого пакета или двоичного файла.

2. Убедитесь, что вы ничего не сломали

В зависимости от кодовой базы, над которой вы работаете, это может оказаться нетривиальной задачей.

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

Если вам не повезло, вы работаете с кодом, который либо очень сложно, либо невозможно протестировать автоматически. С сожалением вынужден сообщить, что вам придется проверить свои изменения вручную.

Если это достаточно болезненно, вы можете придумать несколько творческих способов выбраться из этого затруднительного положения. Есть ли обходные пути? Нетрадиционные подходы к тестированию вашего кода?

3. Повторить

В идеале после каждого шага рефакторинга вы должны фиксироваться в своем локальном филиале. На практике вы, скорее всего, объедините несколько изменений вместе.

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

Проверка кода, содержащая более 50 файлов, может раздражать товарищей по команде. Если все, что вы сделали, это переименовать функцию, и, таким образом, все 50+ файлов были изменены точно так же, тогда проверка кода станет очень простой и быстрой.

Если вы работаете с пугающей кодовой базой, вы хотите избежать ненужных рисков. Большие, запутанные изменения кода - плохая идея. Убедитесь, что вашим товарищам по команде очень легко понять все внесенные вами изменения.

Остерегайтесь следующего развертывания: избегайте накопления гигантской горы изменений между развертываниями и производством. Чем больше изменений будет внесено в производство одновременно, тем выше риск.

Почему рефакторинг - это удовольствие, а не уловка

Одна из основных причин, по которой мне так нравится рефакторинг, - его непредсказуемость.

Вы откроете для себя тайные отношения и скрытые сокровища. Некоторые части кода заставят вас смеяться. Другой код заставит вас плакать внутри. Вы можете учиться на ошибках других людей и составлять в уме список того, «чего не следует делать».

Есть много творческих путей, которые вы можете выбрать в своем пути рефакторинга. По мере того, как вы набираетесь опыта, вы лучше понимаете, какой путь приведет вас к цели быстрее всего.

Застрять в лабиринте

Я не всегда знаю, с чего мне начать. Итак, я просто выбираю место и пробую кое-что.

Если я чувствую себя слишком застрявшим, я начинаю с простого обновления кода, чтобы он соответствовал стандартам кодирования моей команды (правилам, которые описывают, как «чистый код» выглядит в вашей команде). По мере того, как я делаю уборку, я узнаю еще кое-что, что хочу изменить.

Иногда я понимаю, что пошел не в том направлении. Но даже когда это произойдет, я узнаю некоторые важные вещи о кодовой базе, над которой работаю. Это не потраченные впустую усилия.

Если кто-то пытается сказать вам, что следующий шаг всегда очевиден, он либо неопытен, либо каким-то образом знает то, чего не знает никто другой, либо он лжет вам.

Вы приручили монстра

Поздравляю! Наслаждайтесь этим, пока оно длится.