О вреде рефакторинга и сокращении его необходимости (PAI)

В прошлых публикациях (техвремя, техразвитие и техдолг) мы подробно поговорили о том, что не все задачи одинаково полезны для того, чтобы тратить на них ограниченные ресурсы технического времени. Одна из самых коварных — рефакторинг. Он выглядит как инвестиция в будущее, но часто превращается в бездонную яму для ресурсов. Или скорее в казино. Разберёмся, почему так происходит и как этого избежать.

Рефакторинг (или переработка кода) – это процесс изменения внутренней структуры программы, не затрагивающий её внешнего поведения и имеющий целью облегчить понимание её работы.

Что мы узнаем из этого определения?

Рефакторинг – не переписывание

Во-первых, рефакторинг – это перепроектирование кода, а не переписывание. В чем разница? В объекте изменения. Перепроектирование означает изменение дизайна, структуры, реализации алгоритмов – без смены функциональности.

Таким образом, из определения рефакторинга, им не являются следующие мероприятия: 1. Переписывание имеющегося кода с Obj-C на Swift или c Java на Kotlin; 2. Переписывание дизайн-системы с UIKit на SwiftUI (или аналогичные изменения для андроид); 3. Радикальное изменение интерфейсов компонентов и т.д. Во всех этих случаях не меняется ни дизайн, ни структура кода, ни алгоритмы.

Сфера применения рефакторинга очень узкая — и её можно ещё дополнительно сократить.

Во-вторых, рефакторинг имеет конкретную цель — сделать код программы более легким для понимания.

Эта деталь сильно сокращает сферу применимости рефакторинга. Какой код должен быть лёгким для понимания? Тот, который часто читается, а значит и меняется. Чаще всего меняется продуктовый код. Инфраструктурный и обслуживающий код меняется редко – значит, и причин для его рефакторинга мало. Внезапно!

Отсюда вытекает не всем известное, но очень важное следствие: специальными инструментами и мероприятиями можно сократить объем кода, к которому необходимо применять рефакторинг.

Такими мероприятиями могут быть: 1. инкапсуляция и изоляция; 2. модуляризация (обсудим в одном из будущих постов); 3. Single Responsibility; 4. Open/Closed.

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

Необходимое условие для рефакторинга: достаточное покрытие тестами всех уровней

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

Чем это можно гарантировать? Я знаю только один достаточно дешевый способ – наличие достаточного покрытия кодовой базы, подвергающейся рефакторингу, тестами различных уровней пирамиды тестирования. Это – необходимое условие начала рефакторинга.

Например, Мод Лемер, СТО Slack, в своей книге «Масштабируемый рефакторинг. Возвращаем контроль над кодом» пишет об этом так: «Поэтому бессмысленно прилагать какие-либо усилия к началу рефакторинга, пока не достигнут достаточный тестовый охват».

Вывод:

Перед тем как запланировать рефакторинг, задайте себе следующие вопросы: 1. Этот код меняется чаще раза в месяц? 2. Его сложно понять новому разработчику или джуниору? 3. У нас есть тесты, покрывающие 50+% логики? 4. Нельзя ли инкапсулировать или изолировать этот код, чтобы снизить частоту его изменений?

Рефакторинг оправдан только тогда, когда вы ответили «да» на 3 вопроса из четырех. В остальных случаях – ищите альтернативы.

И еще раз: не пытайтесь прикрывать рефакторингом обыкновенное бесполезное «переписывание» ради эстетики и красоты.

А у вас были случаи, когда рефакторинг оказался полным провалом? Пишите мне в личку или в комментарии – мне будет очень интересно!

В следующем посте я покажу вам лучшие практики по экономии усилий и повышению эффективности при миграции с одного языка разработки на другой. В частности с Objective С на Swift.

C u!