Основы программирования

Рефакторинг: улучшение кода без изменения поведения

Код читается в 10 раз чаще, чем пишется. Если через 6 месяцев ты не понимаешь свой код - это провал. Рефакторинг - это уважение к своему будущему «я» и к коллегам.

  • Google: любой код проходит code review - читаемость критична
  • Legacy-системы: без рефакторинга банковский код 1990-х становится нечитаемым за 30 лет
  • Open Source: понятный код получает больше контрибьюторов
  • Техдолг: каждый «быстрый фикс» без рефакторинга делает следующее изменение дороже

Предварительные знания

  • Уметь читать чужой код: разобрать функцию, понять зависимости между файлами
  • Базовое понимание ООП и SOLID: для рефакторинга больших классов
  • Опыт работы с системой контроля версий (git): рефакторинг идёт малыми коммитами
  • Functions
  • Design Patterns: Singleton, Factory, Observer

От диссертации Опдайка до IntelliJ и второго издания Фаулера

Слово refactoring как технический термин впервые появилось в диссертации Уильяма Опдайка Refactoring Object-Oriented Frameworks, Университет Иллинойса, 1992 год. Опдайк работал под руководством Ральфа Джонсона (одного из четверых GoF) и описал автоматизированные преобразования над Smalltalk-кодом, сохраняющие поведение. В 1995 Джон Робертс и Дон Брант на той же кафедре собрали Smalltalk Refactoring Browser, первый IDE-инструмент, который умел выполнять Extract Method, Rename, Move Method одним нажатием. В 1999 Мартин Фаулер выпустил книгу Refactoring: Improving the Design of Existing Code: 70+ каталогизированных рефакторингов на Java с пошаговыми инструкциями и code smells. В том же году Кент Бек выпустил Extreme Programming Explained, где рефакторинг стал одной из 12 практик XP вместе с TDD и парным программированием. В 2001 Максим Моссиенко в команде JetBrains добавил в IntelliJ IDEA первое в Java-мире меню Refactor с десятками автоматизированных операций; через несколько лет это меню скопировали Eclipse, NetBeans и Visual Studio. В 2018 Фаулер выпустил второе издание Refactoring, переписав все примеры с Java на JavaScript: язык изменился, но каталог за 20 лет почти не устарел.

Extract Function: разбивай длинные функции

**Самый частый рефакторинг:** если функция стала слишком длинной или её часть имеет смысл как самостоятельная операция - выделяй в новую функцию. Правило: функция должна делать одно дело и делать это хорошо.

Когда функцию нужно разбить на несколько?

Переименование: код должен читаться как текст

**Плохие имена - корень всех зол.** Переименование - простейший, но самый высокорычажный рефакторинг. Хорошее имя снимает потребность в комментарии.

Какое имя лучше для переменной, хранящей флаг «пользователь авторизован»?

Replace Conditional with Polymorphism

Длинные цепочки if/elif/else по одному полю - признак того, что нужен полиморфизм или словарь диспатч. Паттерн «стратегия» делает код расширяемым.

Длинная цепочка if/elif - это плохой стиль. Её надо немедленно заменить полиморфизмом или Strategy, потому что так предписывает Фаулер.

Replace Conditional with Polymorphism оправдан, когда веток 3+ И они меняются вместе И различаются поведением, а не данными. Для 2 веток или для switch по enum-у класс-иерархия добавляет больше сложности, чем убирает.

Рефакторинг как ритуал («увидел if - замени») путает форму с целью. Фаулер сам подчёркивает: рефакторинг применяется по запаху, а не по шаблону. Полиморфизм оправдан, когда добавление нового case без полиморфизма требует менять N мест - тогда классы дают расширяемость. На 2 ветках или однократном switch иерархия классов утяжеляет понимание, а не упрощает.

Какой «запах кода» (code smell) указывает на необходимость паттерна Стратегия?

Ключевые идеи

  • Extract Function: одна функция = одна ответственность
  • Переименование: лучшее имя = лучший комментарий
  • Replace Conditional with Polymorphism: убирает if-switch цепочки
  • Рефакторинг НЕ меняет поведение - сначала тест, потом рефактор
  • «Сначала сделай зелёными тесты, потом рефакторинг»

Связанные темы

Рефакторинг невозможен без тестов:

  • Паттерны проектирования — Рефакторинг часто ведёт к паттернам
  • Тестирование — Тесты - защитная сетка при рефакторинге

Вопросы для размышления

  • Почему рефакторинг нужно делать малыми шагами? Что происходит при «мегарефакторинге» одним коммитом?
  • Как отличить рефакторинг от реструктуризации (изменения логики)?
  • Найдите в своём коде одну функцию, которую можно улучшить через Extract Function.

Связанные уроки

  • prog-13-patterns — Рефакторинг часто ведёт к паттернам как более чистому решению
  • prog-15-testing — Без тестов рефакторинг опасен: тесты страхуют изменения
  • plt-01-paradigms — Paradigm shift - крайний случай рефакторинга
  • db-11-query-optimization — Query optimization - рефакторинг SQL: то же поведение, чище план
  • alg-01-big-o
Рефакторинг: улучшение кода без изменения поведения

0

1

Войти