Подготовка (1 час перед днем рефакторинга). Успех на 90% зависит от подготовки.
- Выберите цель. Рефакторинг ради рефакторинга — путь в никуда. Сформулируйте конкретную, измеримую цель:
- «Подготовить код к добавлению новой фичи X, которая сейчас требует изменений в 10 файлах».
- Обеспечьте безопасную среду. Убедитесь, что система контроля версий (Git) в порядке. Создайте новую ветку от актуального main/master. Убедитесь, что есть полное покрытие CI/CD (сборка, линтеры, все тесты). Это ваш «спасательный круг».
- Соберите метрики. Запустите статический анализ: сложность когнитивной нагрузки (cognitive complexity), количество строк в функциях, глубина вложенности, дублирование. Используйте инструменты: SonarQube, CodeClimate, cloc, встроенные анализаторы в IDE. Зафиксируйте «до». Это будет ваша карта сокровищ и способ доказать успех.
Утро (3 часа): Низко висящие фрукты и санитарная обработка.
- 09:00 - 10:00: Устранение явного дублирования. Используйте инструменты поиска дубликатов (например, `jscpd` для JS, `PMD Copy/Paste Detector` для Java). Найдите 2-3 самых больших блока повторяющегося кода (более 10 строк) и выделите их в функции, методы или общие модули. Это даст быстрый результат и уменьшит энтропию.
- 10:00 - 11:00: Упрощение условий и циклов. Пройдитесь по файлам с самой высокой цикломатической сложностью. Упростите гигантские условия `if-else-if` с помощью `switch`, `guard clauses` (досрочный возврат) или стратегии/состояния. Прервите глубоко вложенные циклы, выделив внутреннюю логику в отдельную функцию.
- 11:00 - 12:00: Чистые функции и устранение побочных эффектов. Найдите функции, которые делают слишком много: читают глобальные переменные, меняют внешнее состояние, печатают в лог и вычисляют значение. Разделите их на чистые (вычисление) и процедуры (изменение состояния). Это сделает код предсказуемее.
День (4 часа): Стратегические изменения.
- 13:00 - 14:30: Работа с зависимостями. Проанализируйте граф импортов/зависимостей. Разорвите циклические зависимости, даже если для этого потребуется создать новый интерфейс или модуль-прослойку. Выделите «стабильные» модули (те, что редко меняются) от «нестабильных» (часто меняются). Это улучшит пересборку и тестирование.
- 14:30 - 16:00: Улучшение именования. Плохие имена — главный враг понимания. Составьте список самых непонятных аббревиатур, однобуквенных переменных (кроме `i` в цикле) и функций с названиями `processData()`, `handle()`. Переименуйте их, чтобы они точно отражали суть. Современные IDE делают это безопасно (rename refactoring). Не трогайте публичный API, если нет 100% уверенности в обратной совместимости.
- 16:00 - 17:00: Применение принципов SOLID (точечно). Не надо переделывать всю архитектуру. Выберите один самый «толстый» класс (God Object) и попробуйте:
- **L/I/D**: На этом этапе, скорее всего, не понадобятся. Сфокусируйтесь на Single Responsibility.
Вечер (2 часа): Интеграция и проверка.
- 17:00 - 18:00: Запуск тестов. После каждого значимого изменения (после каждого часового блока) вы запускали модульные тесты. Теперь запустите ВСЕ тесты: модульные, интеграционные, end-to-end. Убедитесь, что ничего не сломалось. Если что-то упало — отладка и исправление. Это приоритет №1.
- 18:00 - 18:30: Сбор метрик «после». Запустите те же инструменты статического анализа, что и утром. Сравните результаты. Увидьте прогресс: уменьшение дублирования, снижение сложности.
- 18:30 - 19:00: Фиксация результатов и создание Pull/Merge Request. Напишите исчерпывающее описание к PR: какую цель ставили, что сделали, какие метрики улучшились, как это проверить (пройтись по ключевым изменениям). Приложите скриншоты или отчеты анализаторов. Это не только для ревью, но и для истории проекта.
- Не добавляйте новую функциональность. Рефакторинг и фичи — разные процессы.
- Делайте маленькие коммиты. Каждый коммит — одно логическое изменение. «Переименовал функцию X», «Выделил дублирующийся код в метод Y».
- Постоянно запускайте тесты. Локально, на каждый коммит. Не копите проблемы.
- Имейте план отката. Если к 16:00 всё пошло не так, вы всегда можете отбросить ветку и вернуться к исходному состоянию. Не надо геройствовать.
Было (сложная, запутанная функция):
```
function checkOrder(order) {
let result = {
Комментарии (9)