Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Курсовая работа. Рефакторинг ПО

.pdf
Скачиваний:
139
Добавлен:
05.06.2015
Размер:
817.87 Кб
Скачать

Московский Государственный Университет Экономики, Статистики и

Информатики

ИНСТИТУТ КОМПЬЮТЕРНЫХ ТЕХНОЛОГИЙ

Кафедра комплексного обеспечения информационной безопасности автоматизированных систем

Дисциплина: «Технологии и методы программирования»

Курсовая работа

На тему: «Рефакторинг программного обеспечения»

Выполнил студент группы ДКБ-301

Горбачев Александр

Руководитель

Осенина Е.А.

Москва 2013 г.

Оглавление

 

Введение ......................................................................................................................................................

4

Цели рефакторинга .....................................................................................................................................

4

Причины применения рефакторинга ........................................................................................................

4

Признаки плохого кода...............................................................................................................................

5

Дублирование кода.................................................................................................................................

5

Длинный метод .......................................................................................................................................

6

Большой класс .........................................................................................................................................

6

Длинный список параметров .................................................................................................................

7

Расходящиеся модификации .................................................................................................................

7

Стрельба дробью.....................................................................................................................................

8

Завистливые функции .............................................................................................................................

8

Группы данных.........................................................................................................................................

9

Одержимость элементарными типами.................................................................................................

9

Операторы типа switch............................................................................................................................

9

Параллельные иерархии наследования .............................................................................................

10

Ленивый класс .......................................................................................................................................

10

Теоретическая общность ......................................................................................................................

10

Временное поле ....................................................................................................................................

11

Цепочка вызовов ...................................................................................................................................

11

Посредник..............................................................................................................................................

11

Неуместная близость ............................................................................................................................

12

Альтернативные классы с разными интерфейсами ...........................................................................

12

Неполнота библиотечного класса........................................................................................................

12

Классы данных.......................................................................................................................................

13

Отказ от наследства...............................................................................................................................

13

Комментарии .........................................................................................................................................

13

Рефакторинг кода ......................................................................................................................................

14

Методы рефакторинга ..............................................................................................................................

15

Изменение сигнатуры метода..............................................................................................................

15

Инкапсуляция поля................................................................................................................................

15

Выделение метода ................................................................................................................................

16

Перемещение метода...........................................................................................................................

16

Замена условного оператора полиморфизмом .................................................................................

16

Проблемы при проведении рефакторинга .............................................................................................

17

Базы данных...........................................................................................................................................

17

 

2

Изменение интерфейсов ......................................................................................................................

18

Изменения проектных решений ..........................................................................................................

19

Когда в рефакторинге нет необходимости .............................................................................................

19

Рефакторинг баз данных...........................................................................................................................

20

Категории рефакторинга баз данных ..................................................................................................

20

Когда проводить рефакторинг .............................................................................................................

21

Переходный период..............................................................................................................................

22

Пример рефакторинга базы данных....................................................................................................

22

Средства автоматизации рефакторинга..................................................................................................

23

Рефакторинг в Visual Studio ......................................................................................................................

23

Visual Assist X..........................................................................................................................................

23

Refactor!..................................................................................................................................................

25

JustCode!.................................................................................................................................................

26

ReSharper................................................................................................................................................

27

CodeIt.Once.............................................................................................................................................

28

Список используемой литературы...........................................................................................................

29

Книги.......................................................................................................................................................

29

Интернет-ресурсы..................................................................................................................................

29

3

Введение

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

Цели рефакторинга

Цель рефакторинга — сделать код программы легче для понимания; без этого рефакторинг нельзя считать успешным. Рефакторинг следует отличать от оптимизации производительности. Как и рефакторинг, оптимизация обычно не изменяет поведение программы, а только ускоряет её работу. Но оптимизация часто затрудняет понимание кода, что противоположно рефакторингу. С другой стороны, нужно отличать рефакторинг от реинжиниринга, который осуществляется для расширения функциональности программного обеспечения. Как правило, крупные рефакторинги предваряют реинжиниринг.

Причины применения рефакторинга

Рефакторинг нужно применять постоянно при разработке кода. Основными стимулами его проведения являются следующие задачи:

Необходимо добавить новую функцию, которая недостаточно укладывается в принятое архитектурное решение;

Необходимо исправить ошибку, причины возникновения которой сразу не ясны;

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

4

Признаки плохого кода

Код с запашком (код с душком, дурно пахнущий код англ. Code smell) - термин, обозначающий код с признаками (запахами) проблем в системе. Был введен Кентом Беком и использован Мартином Фаулером в его книге «Рефакторинг». Улучшение существующего кода с тех пор активно используется разработчиками программного обеспечения.

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

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

Среди признаков плохого кода можно выделить основные:

Дублирование кода

Дублирование кода - это использования одинаковых структур кода в нескольких местах. Объединение этих структур позволит улучшить программный код.

Примеры дублирования и методы их устранения:

Одно и то же выражение присутствует в двух методах одного и того же класса: необходимо применить «Выделение метода» (Extract Method) и вызывать код созданного метода из обеих точек;

Одно и то же выражение есть в двух подклассах, находящихся на одном уровне: необходимо применить «Выделение метода» (Extract Method) для обоих классов с последующим «Подъемом поля» (Pull up Field) или «Формированием шаблона метода» (Form Template Method),

5

если код похож, но не совпадает полностью. Если оба метода делают одно и то же с помощью разных алгоритмов, можно выбрать более четкий из этих алгоритмов и применить «Замещение алгоритма»

(Substitute Algorithm);

Дублирующийся код находится в двух разных классах: необходимо применить «Выделение класса» (Extract Class) в одном классе, а затем использовать новый компонент в другом.

Длинный метод

Среди объектных программ, дольше всего живут программы с короткими методами. Чем длиннее процедура, тем труднее ее понять. Если у метода хорошее название, то не нужно смотреть его тело.

Следует придерживаться эвристического правила: если ощущается необходимость что-то прокомментировать, нужно написать метод. Даже одну строку имеет смысл выделить в метод, если она нуждается в разъяснениях.

Для сокращения метода достаточно применить «Выделение метода»

(Extract Method);

Если локальные переменные и параметры препятствуют выделению метода, можно применить «Замену временной переменной вызовом метода» (Replace Temp with Query), «Введение граничного объекта»

(Introduce Parameter Object) и «Сохранение всего объекта» (Preserve Whole Object);

Условные операторы и циклы свидетельствуют о возможности выделения в отдельный метод. Для работы с условными выражениями подходит «Декомпозиция условных операторов» (Decompose Conditional). Для работы с циклом — «Выделение метода» (Extract Method).

Большой класс

Когда класс реализует слишком обширный функционал, стоит подумать о вынесении некоторой части кода в подкласс. Это избавит разработчиков от чрезмерного количества имеющихся у класса атрибутов и дублирования кода.

6

Для уменьшения класса используется «Выделение класса» (Extract Class) или «Выделение подкласса» (Extract Subclass). При этом следует обращать внимание на общность в названии атрибутов и на то, использует ли класс их все одновременно;

Если большой класс является классом GUI, может потребоваться переместить его данные и поведение в отдельный объект предметной области. При этом может оказаться необходимым хранить копии некоторых данных в двух местах и обеспечить их согласованность. «Дублирование видимых данных» (Duplicate Observed Data) предлагает путь, которым можно это осуществить.

Длинный список параметров

В длинных списках параметров трудно разбираться, они становятся противоречивыми и сложными в использовании. Использование объектов позволяет, в случае изменения передаваемых данных, модифицировать только сам объект. Работая с объектами, следует передавать ровно столько, чтобы метод мог получить необходимые ему данные.

«Замена параметра вызовом метода» (Replace Parameter With Method) применяется, когда можно получить данные путем вызова метода объекта. Этот объект может быть полем или другим параметром.

«Сохранение всего объекта» (Preserve Whole Object) позволяет взять группу данных, полученных от объекта, и заменить их самим объектом.

«Введение граничного объекта» (Introduce Parameter Object) применяется, если есть несколько элементов данных без логического объекта.

Расходящиеся модификации

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

Если набор методов необходимо изменять каждый раз при внесении определенных модификаций в код, то применяется «Выделение класса» (Extract Class) (Например, три метода меняются каждый раз

7

когда подключается новая база данных, а четыре — при добавлении финансового инструмента).

Стрельба дробью

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

Вынести все изменения в один класс позволят «Перемещение метода»

(Move Method) и «Перемещение поля» (Move Field);

Если нет подходящего класса, то следует создать новый класс;

Если это необходимо, следует воспользоваться «Встраиванием класса»

(Inline Class).

Завистливые функции

Метод обращается к данным другого объекта чаще, чем к собственным данным.

«Перемещение метода» (Move Method) применяется, если метод явно следует перевести в другое место;

«Выделение метода» (Extract Method) применяется к части метода, если только эта часть обращается к данным другого объекта;

Метод использует функции нескольких классов: определяется, в каком классе находится больше всего данных, и метод помещается в класс вместе с этими данными, или с помощью «Выделения метода» (Extract Method) метод разбивается на несколько частей и они помещаются в разные места.

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

8

Группы данных

Группы данных, встречающихся совместно, нужно превращать в самостоятельный класс.

«Выделение метода» (Extract Method) используется для полей;

«Введение граничного объекта» (Introduce Parameter Object) или «Сохранение всего объекта» (Preserve Whole Object) для параметров методов.

Хорошая проверка: удалить одно из значений данных и проверить, сохранят ли смысл остальные. Если нет, это верный признак того, что данные напрашиваются на объединение их в объект.

Одержимость элементарными типами

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

«Замена значения данных объектом» (Replace Data Value with Object);

«Замена массива объектом» (Replace Array with Object);

Если это код типа, то используйте «Замену кода типа классом» (Replace Type Code with Class), «Замену кода типа подклассами» (Replace Type Code with Subclass) или «Замену кода типа состоянием/стратегией»

(Replace Type Code with State/Strategy).

Операторы типа switch

Одним из очевидных признаков объектно-ориентированного кода служит сравнительно редкое использование операторов типа switch (или case). Часто один и тот же блок switch оказывается разбросанным по разным местам программы. При добавлении в переключатель нового варианта приходится искать все эти блоки switch и модифицировать их. Как правило, заметив блок switch, следует подумать о полиморфизме.

Если switch переключается по коду типа, то следует использовать

«Замену кода типа подклассами» (Replace Type Code with Subclasses)

9

или «Замену кода типа состоянием/стратегией» (Replace Type Code with State/Strategy);

Может понадобиться «Выделение метода» (Extract Method) и «Перемещение метода» (Move Method) чтобы изолировать switch и поместить его в нужный класс;

После настройки структуры наследования следует использовать «Замену условного оператора полиморфизмом» (Replace Conditional with Polymorphism).

Параллельные иерархии наследования

В коде с таким запашком всякий раз при порождении подкласса одного из классов приходится создавать подкласс другого класса.

Общая стратегия устранения дублирования состоит в том, чтобы заставить экземпляры одной иерархии ссылаться на экземпляры другой иерархии, а затем убрать иерархию в ссылающемся классе c помощью «Перемещения метода» (Move Method) и «Перемещения поля» (Move Field).

Ленивый класс

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

При наличии подклассов с недостаточными функциями попробуйте «Свертывание иерархии» (Collapse Hierarchy);

Почти бесполезные компоненты должны быть подвергнуты «Встраиванию класса» (Inline Class).

Теоретическая общность

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

10