logo search
Методичка Java

Рефакторинг

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

Приведём три наиболее часто встречающихся примера рефакторинга.

В сложных проектах, конечно, возникают и другие варианты рефакторинга (например, выделение части кода в отдельный метод – “Extract method”), но с упомянутыми приходится встречаться постоянно. Поэтому рассмотрим эти три случая подробнее.

Первый случай - переименование элементов программы.

Для того, чтобы в среде NetBeans переименовать элемент, следует щёлкнуть по его имени правой кнопкой мыши. Это можно сделать в исходном коде программы, а можно и в окне Projects или Navigator. В появившемся всплывающем меню следует выбрать Refactor/Rename… После чего ввести новое имя и нажать кнопку “Next>”.

Переименование класса. Шаг 1

Переименование класса. Шаг 2

Если галочка “Preview All Changes” (“Предварительный просмотр всех изменений”) не снята, в самом нижнем окне, Output (“Вывод”), появится дерево со списком мест, где будут проведены исправления. В случае необходимости галочки можно снять, и в этих местах переименование проводиться не будет. При нажатии на кнопку “Do Refactoring” (“Провести рефакторинг”) проводится операция переименования в выбранных местах программы. В отличие от обычных текстовых процессоров переименование происходит с учётом синтаксиса программы, так что элементы, не имеющие отношения к переименовываемому, но имеющие такие же имена, не затрагиваются. Что в выгодную сторону отличает NetBeans от многих других сред разработки, не говоря уж об обычных текстовых редакторах.

Переименование класса. Шаг 3

Требуется быть внимательными: довольно часто начинающие программисты не замечают появления в окне Output списка изменений и кнопки “Do Refactoring”. Особенно если высота этого окна сделана очень малой. Если в диалоге переименования (шаг 2) флажок “Preview all Changes” снят, при нажатии на кнопку “Next>” сразу происходит рефакторинг.

Следует также отметить, что после проведения рефакторинга возможен возврат к первоначальному состоянию (“откат”, операция undo). Обычно такая операция осуществляется с помощью главного меню проекта (кнопка Undo или пункт меню Edit/Undo), но в случае рефакторинга требуется правой клавишей мыши вызвать всплывающее окно и выбрать пункт Refactor/Undo. Откат может быть на несколько шагов назад путём повторения данного действия. Пре необходимости отказа от отката в меню рефакторинга следует выбрать пункт Redo.

Второй случай - перемещение элементов программы с одного места на другое.

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

Если при перемещении возникают проблемы, о них выдаётся сообщение. Как правило, проблемы бывают связаны с неправильными уровнями видимости. Например, если указан пакетный уровень видимости метода, он доступен другим классам этого пакета. А при переносе класса в другой пакет в месте исходного кода, где осуществляется такой доступ, в новом варианте кода возникает ошибка доступа. Перенос класса в отдельный пакет, отличающийся от пакета приложения – хороший способ проверить правильности выбранных уровней доступа для членов класса.

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

Третий случай - инкапсуляция полей данных.

Напрямую давать доступ к полю данных – дурной тон программирования. Поэтому рекомендуется давать полям уровень видимости private, а доступ к ним по чтению и записи осуществлять с помощью методов getИмяПоля и setИмяПоля - получить и установить значение этого поля. Такие методы в Java называют геттерами (getters) и сеттерами (setters).

Но при введении в класс новых полей на первом этапе часто бывает удобнее задать поля с модификатором public и обеспечивать чтение значения полей напрямую, а изменение значения – путём присваивания полям новых значений. А затем можно исправить данный недостаток программы с помощью инкапсуляции полей данных. Это делается просто: в дереве элементов программы окна Projects в разделе Fields (“поля”) щёлкнем правой кнопкой мыши по имени поля и выберем в появившемся всплывающем меню Refactor/Encapsulate Fields… (“Провести рефакторинг”/ “Инкапсулировать поля…”).В появившемся диалоге нажмём на кнопку “Next>” и проведём рефакторинг. При этом каждое поле приобретёт модификатор видимости private, а во всех местах программы, где напрямую шёл доступ к этому полю, в коде будет проведена замена на вызовы геттеров и сеттеров.

Более подробную информацию по идеологии и методах рефакторинга проектов, написанных на языке Java, можно найти в монографии [7]. Правда, эта книга уже несколько устарела – среда NetBeans позволяет делать в автоматическом режиме многие из описанных в [7] действий.