Рефакторинг ( англ. refactoring ) - преобразование кода, изменение внутренней структуры программы для облегчения понимания кода и легкого внесения дальнейших изменений без изменения внешнего поведения самой системы. Слово «рефакторинг» произошло от термина «факторинг» в структурном программировании, означавший декомпозицию программы на максимально автономны и элементарные части.
Причины рефакторинга
Существует миф о том, что правильно организованный процесс разработки продукта методично придерживается поставленных требований, определяет однозначный, стабильный список обязанностей программы, и при этом программный код может быть написан почти линейно - от начала до окончания, каждый участок - один раз написана, тестированы и забыта. Согласно этому мифу, единственный случай, когда существующий код может меняться - это в процессе поддержки и администрирования программы, когда начальная версия продукта уже сдана заказчику.
Однако реальность несколько иной. На самом деле код эволюционирует в процессе разработки продукта. Как правило, кодирования, отладки и модульное тестирование занимают в среднем 30-65% усилий от общего времени существования проекта (в зависимости от величины проекта). Даже на хорошо организованных проектах требования меняются в среднем на 1-4% за месяц, что неминуемо влечет модифицировать - как мелкие, так и достаточно серьезные.
Также, в отличие от более старых методик разработки программных продуктов, где основной акцент ставился на минимизации изменений в код, современная методика видит большой потенциал во внесении изменений. Она является более сфокусированной на коде (code-centered) и при разработке можно ожидать, что код будет совершенствоваться больше обычного.
Основания для проведения рефакторинга
- Код дублируется.
- Это нередко приводит к необходимости вносить параллельные изменения в ряд скопированных участков кода одновременно (что не соответствует принципам «DRY» (Don't Repeat Yourself) и «Copy And Paste is a Design Error»).
- Подпрограмма слишком длинная.
- Хотя вопрос, какую максимальную длину может иметь подпрограмма, является достаточно противоречивым, однако общепринятым неофициальным стандартом является написание подпрограмм длиной не более, чем один экран кода.
- Цикл слишком длинный, или уровень вложенности тела цикла слишком большой.
- Класс имеет много обязанностей, слабо связанных между собой.
- В таком случае лучше разделить класс на несколько атомарных классов.
- Интерфейс класса не обеспечивает достаточный уровень абстракции.
- Функция имеет слишком много параметров.
- Нужно одновременно менять несколько параллельных иерархий классов.
- Для решения этой проблемы можно, например, воспользоваться шаблоном «Мост».
- Родственные данные, используемые вместе, не организованные в класс.
- Класс не выполняет никакую работу самостоятельно, а только перепоручает обязанности другим классам.
- Название класса или метода имеет имя, недостаточно точно соответствует содержанию.
- Класс имеет слишком много открытых (public) членов.
- Нестатические класс состоит только из данных или только из методов.
- В цепочке вызовов методов передается много лишних данных.
- Слишком распространено использование глобальных переменных.
Приемы рефакторинга
- Приемы, позволяющие разбить код на мелкие, понятные части.
- Обособление метода (Extract Method).
- Отделения базового класса (Extract Superclass).
- Приемы, позволяющие обеспечить дополнительную абстракцию.
- Инкапсуляция поля (Encapsulate Field) - заменяет прямой доступ к полю на доступ через методы-аксесоры (или свойства в C #).
- Обобщения типа (Generalize Type) - замена типов, с которыми работает класс, на более обобщенные.
- Замена блоков проверки типов на шаблоны «Состояние» (State) или «Стратегия» (Strategy).
- Замена условных операторов полиморфизмом.
- Создание поля или локальной переменной (Introduce Field / Introduce Local Variable).
- Приемы, меняют названия членов и их расположение.
- Перемещение метода / поля (Move Method / Field) в другие классы или файлы кода.
- Переименование члена (Rename) - изменение имени, с автоматической заменой всех ссылок на старое имя в коде.
- Перемещение члену к базовому / дочернего класса (Pull Up / Push Down).
Автоматизированный рефакторинг
На сегодняшний день многие интегрированных сред разработки содержат встроенные механизмы рефакторинга кода. Кроме интегрированной функциональности, существует также много продуктов сторонних производителей, которые, как правило, реализованы в виде дополнений (plugins) в соответствующий IDE. Примеры таких пакетов:
Пакет |
Язык |
Среда |
Microsoft Visual Studio |
C# |
Microsoft Visual Studio (встроенный) |
Java Development Tooklit |
Java |
Eclipse (встроенный) |
IntelliJ IDEA |
Java |
IntelliJ IDEA (встроенный) |
NetBeans |
Java |
NetBeans (встроенный) |
Visual Assist |
C#, C+ +, VB, VB.NET |
Microsoft Visual Studio |
Photran |
Fortran |
Eclipse |