Delphi.int.ru — Портал программистов

Вход Регистрация | Забыли пароль?

События

Сегодня:
Вопросы0    Ответы0    Мини-форумы0


Последние:
Вопрос26.08, 21:10 / #6673
Ответ02.08, 00:42 / #6619
Новости30 апреля 2012


Сейчас онлайн:
На сайте — 20
На IRC-канале — 3

Ссылки

Рефакторинг

Автор: Вадим К

Сложность программы растет до тех пор, пока не превысит способности программиста... (из законов Мерфи)

Вступление

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

И действительно, такая технология существует и называется Рефакторинг. На английском пишется "Refactoring" и мне кажется, что лучше переводить как "повторная движущая сила". Вполне оправданное название.

Но технология была бы лишь только технологией, если бы популярные среды разработки не добавили в свои возможности и рефакторинг. Среда Delphi, начиная с версии 2005, также эту технологию поддерживает.

Так что же такое рефакторинг? Wikipedia даёт длинный ответ: "Рефакторинг или Реорганизация — процесс полного или частичного преобразования внутренней структуры программы при сохранении её внешнего поведения. В его основе лежит последовательность небольших эквивалентных (т.е., сохраняющих поведение) преобразований. Поскольку каждое преобразование маленькое, программисту легче проследить за его правильностью, и в то же время, вся последовательность может привести к существенной перестройке программы и улучшению её согласованности и четкости. Рефакторинг позволяет разрабатывать архитектуру программы постепенно, откладывая проектные решения до тех пор, пока не станет более ясной их необходимость».

Более простыми словами, рефакторинг – это технология улучшения читабельности вашей программы без изменения функциональности. Но иногда в процессе рефакторинга находятся ошибки – тут уже функциональность изменяется, но для конечного пользователя, который надеется, что в программе нет ошибок, функциональность не меняется :-)

Переименование

Как часто, написав большой участок кода, понимаешь, что имя для переменной крайне неудачное (хороша мысль обычно приходит поздно)... И хорошо, если этот код только что написан, а если нет? Сидеть разбирать, искать все переменные, изменять имена? Или воспользоваться методом "найти-заменить"? Как по мне, то в втором случае ошибок точно больше будет. И здесь нам поможет один из методов рефакторинга под названием "переименование".

Итак, начнём. Загрузите в Delphi какой-нибудь проект, желательно побольше, не забыв перед этим сделать его резервную копию, а то мало ли что понаделаете...

Выбираем подопытную функцию, в которой находим переменную для переименования. Оставляем просто на ней текстовый курсор и идём в меню Refactor » Rename (или комбинацию клавиш Ctrl+Shift+E). Появится окошко:

Окно "Rename variable"

В поле "New name" вводим новое имя. Галочку "View reference before refactoring" (показать, что изменится перед самим изменением) на первое время рекомендую оставлять – будете видеть, что меняется; потом её обычно снимают. Жмём ОК и видим, как в нижней части редактора появилось небольшое окно:

Окно со списком изменений при переименовании переменной (Rename variable)

Все изменения видны как на ладони. Теперь достаточно нажать кнопку, где изображен кубик. Понаблюдайте за результатом.

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

Попробуйте выделить в редакторе кода имя кнопки или формы и попробовать его переименовать. В окошке Refactoring в самом низу можно будет увидеть фразу VCL Designer Update – компонент будет переименован не только в коде, но и на форме. По-моему, очень удобно.

Аналогичным методом переименовываются и типы, имена классов, имена процедур. Просто пробуйте и будете приятно удивлены.

Для того, чтобы сделать всё это, Delphi делает лексический/синтаксический анализ кода. Что-то вроде компиляции на лету. Наверное, вы уже заметили, что неверные участки кода подчёркиваются волнистой линией (хотя иногда и неверно).

Извлечение методов

А теперь представим такую ситуацию. Есть очень большая процедура. Надо из неё выделить кусочек кода в отдельную процедуру ("разделяй и властвуй"). Маленькие куски кода проще поддаются анализу. Существует негласное правило, что процедуры больше 30 строк – это очень плохо. Процедура извлечения в меню называется Extract Method.

Выделите у себя в коде небольшой участок кода и нажмите Ctrl+Shift+M (или выберите в меню Refactor » Extract Method). Появится следующее окно:

Окно "Extract Method"

Теперь достаточно ввести имя процедуры и нажать "ОК". При этом анализируются переменные, переносятся в новую подпрограмму, организовывается список параметров.

Правда, у этого метода есть пара недостатков. Delphi не может извлечь метод, если в нём есть команда Exit или оператор Continue/Break и мы находимся внутри цикла, которому они принадлежат. Но и мы не всегда сходу можем выделить в таком коде процедуру.

Также замечен один баг – если в функции после извлечения не остаётся своих локальных переменных, то список их очищается (что ожидалось), но слово var не удаляется. Что ж поделаешь...

Объявление переменных

Как иногда не хочется перемещаться в блок объявления переменных и вписывать туда новую переменную... Хорошо, если это процедура и всё просто. А если это новый метод класса?

Всё предельно просто. Пишем код, но переменную не объявляем. Потом, оставив курсор на ней, выбираем в меню Refactor » Declare variable (Ctrl+Shif+V).

Окно "Declare Variable"

К сожалению, Delphi иногда не может "угадать" тип переменной, и подставляет TObject, но курсор сразу оказывается в поле Type, следовательно, можно сразу ввести имя типа и нажать Enter. Отметив галочку Set Value (установить начальное значение), будет добавлен код инициализации нашей новой переменной.

Аналогичным способом можно объявлять новые поля для классов. А для объявления ручками иногда приходится скроллить сотни строк...

Уточнение имени типа

Иногда помнишь имя типа, но немного забыл. Или обявляешь переменную какого-то типа, а оно не хочет с ней компилироваться, ругается (причина проста – есть ещё один класс/тип с таким же именем). Как найти эти типы? Очень просто. Для этого вызываем в меню пункт Refactor » Find Unit (Ctrl+Shift+A).

Окно "Find Unit"

Как видно, я написал часть имени и были найдены все типы и функции, которые содержат это слово. Вот только мне непонятно, почему выделенное не вставляется по нажатию Ок. А то было бы очень удобно. Но этот диалог употребляется в другом месте – там он отрабатывает по полной программе.

Изменение параметров функции/метода

Иногда нужно добавить в функцию новый параметр или удалить старый. В этом случае Delphi тоже предоставляет инструмент. Для этого нужно, чтобы текстовый курсор был на имени процедуры в её объявлении (в той строке должно быть слово procedure или function). А потом в меню выбираем Refactor » Change Params... Дальнейшее изучение этого метода оставляю как домашнее задание.

А что делать с младшими версиями Delphi?

Здесь на помощь придут такие инструменты как Castalia (http://www.twodesk.com/castalia/index.html). У них на сайте можно посмотреть демонстрацию возможностей. Как по мне, то некоторые вещи реализованы очень хорошо. Но автодополнения кода иногда вызывает неконтролируемую агрессию с моей стороны – я его просто отключаю. Но есть один существенный недостаток – продукт платный.

Также на помощь может прийти MMX (http://www.modelmakertools.com/code-explorer/index.html). Вначале он вызывает непонятные чувства, но потом помогает находить спорные участки кода, сортировать процедуры, управлять комментариями к процедурам.

Вывод

Используя рефакторинг, вы можете дать своему продукту вторую жизнь. Но также он очень помогает ускорить процесс написания кода, ведь вначале можно написать, потом улучшить. Конечно, откровенно неверный код рефакторинг не улучшит, но работающий код в руках опытного программиста может превратиться в красивый и легкосопровождаемый. Если вас заинтересовала эта тема и вы хотите узнать о рефакторинге больше – поищите книги/статьи Мартина Фаулера.

Автор: Вадим К

Статья добавлена: 9 апреля 2008

Следующая статья: Читаем цитаты с bash.org.ru своей программой »

Рейтинг статьи: 5.00 Голосов: 4 Ваша оценка:

Зарегистрируйтесь/авторизируйтесь,
чтобы оценивать статьи.


Статьи, похожие по тематике

 

Для вставки ссылки на данную статью на другом сайте используйте следующий HTML-код:

Ссылка для форумов (BBCode):

Быстрая вставка ссылки на статью в сообщениях на сайте:
{{a:46}} (буква a — латинская) — только адрес статьи (URL);
{{статья:46}} — полноценная HTML-ссылка на статью (текст ссылки — название статьи).

Поделитесь ссылкой в социальных сетях:


Комментарии читателей к данной статье

Amidamaru
Репутация: +35

Amidamaru (6 сентября 2011, 00:37):

Отличная статья! У самого делфи 2006 но на подобное както не натыкался, а зря. Отлично вижу, что теперь писать будет ещё быстрее.

ps C объявлением переменных пока не экспериментировал, но думаю, что вносить изменения в объявление класса буду традиционным способом.
Да и скроллить вовсе не надо, ведь есть магическая кнопка Ctrl, держа которую все идентификаторы под курсором мышки становятся какбы гиперссылками, и простым щелчком можно перейти на объявление или наоборот описание того, что нужно. Ну и конечно же есть "браузерные" стрелки, с помощью которых можно быстро вернуться назад.

Оставлять комментарии к статьям могут только зарегистрированные пользователи.