Рефакторинг

Поделись знанием:
Перейти к: навигация, поиск

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





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

Цель рефакторинга — сделать код программы более легким для понимания; без этого рефакторинг нельзя считать успешным.

Рефакторинг следует отличать от оптимизации производительности. Как и рефакторинг, оптимизация обычно не изменяет поведение программы, а только ускоряет её работу. Но оптимизация часто затрудняет понимание кода, что противоположно рефакторингу[3].

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

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

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

  1. необходимо добавить новую функцию, которая недостаточно укладывается в принятое архитектурное решение;
  2. необходимо исправить ошибку, причины возникновения которой сразу не ясны;
  3. преодоление трудностей в командной разработке, которые обусловлены сложной логикой программы.

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

Во многом при рефакторинге лучше полагаться на интуицию, основанную на опыте. Тем не менее имеются некоторые видимые проблемы в коде (англ. code smells), требующие рефакторинга:

  1. дублирование кода;
  2. длинный метод;
  3. большой класс;
  4. длинный список параметров;
  5. «жадные» функции — это метод, который чрезмерно обращается к данным другого объекта;
  6. избыточные временные переменные;
  7. классы данных;
  8. несгруппированные данные.

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

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

Иногда под рефакторингом неправильно подразумевают коррекцию кода с заранее оговоренными правилами отступа, перевода строк, внесения комментариев и прочими визуально значимыми изменениями, которые никак не отражаются на процессе компиляции, с целью обеспечения лучшей читаемости кода (см. code formatting).

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

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

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

Наиболее употребимые[4] методы рефакторинга:

Изменение сигнатуры метода (Change Method Signature)

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

Инкапсуляция поля (Encapsulate field)

В случае, если у класса имеется открытое поле, необходимо сделать его закрытым и обеспечить методы доступа. После «Инкапсуляции поля» часто применяется «Перемещение метода».

Выделение метода (Extract Method)

Выделение метода заключается в выделении из длинного и/или требующего комментариев кода отдельных фрагментов и преобразовании их в отдельные методы, с подстановкой подходящих вызовов в местах использования. В этом случае действует правило: если фрагмент кода требует комментария о том, что он делает, то он должен быть выделен в отдельный метод. Также правило: один метод не должен занимать более чем один экран (25-50 строк, в зависимости от условий редактирования), в противном случае некоторые его фрагменты имеют самостоятельную ценность и подлежат выделению. Из анализа связей выделяемого фрагмента с окружающим контекстом делается вывод о перечне параметров нового метода и его локальных переменных.

Перемещение метода (Move Method)

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

Замена условного оператора полиморфизмом (Replace Conditional with Polymorphism)

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

Основные принципы:

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

Проблемы, возникающие при проведении рефакторинга

  • проблемы, связанные с базами данных;
  • проблемы изменения интерфейсов;
  • трудности при изменении дизайна.

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

Технические критерии для инструментов рефакторинга:

  • базы данных программы;
  • деревья синтаксического разбора;
  • точность.

Практические критерии для инструментов рефакторинга:

  • скорость;
  • отмена модификаций;
  • интеграция с другими инструментами.

Напишите отзыв о статье "Рефакторинг"

Примечания

  1. М. Фаулер (2000), стр. 61-62
  2. Кериевски, 2008, Введение.
  3. 1 2 М. Фаулер (2000), стр. 62
  4. Кериевски, 2008.

См. также

Литература

  • Фаулер М., Бек К., Брант Д., Робертс Д., Апдайк У. Рефакторинг: улучшение существующего кода = Refactoring: Improving the Design of Existing Code (2000). — Спб: Символ-Плюс, 2009. — 432 с. — 3000 экз. — ISBN 5-93286-045-6.
  • Скотт В. Эмблер, Прамодкумар Дж. Садаладж. Рефакторинг баз данных: эволюционное проектирование = Refactoring Databases: Evolutionary Database Design (Addison-Wesley Signature Series). — М.: «Вильямс», 2007. — 368 с. — ISBN 0-321-29353-3.
  • Джошуа Кериевски. Рефакторинг с использованием шаблонов = Refactoring to Patterns. — Вильямс, 2008. — 400 с. — ISBN 5-93286-045-6.

Ссылки

  • [c2.com/cgi/wiki?WhatIsRefactoring Что такое рефакторинг?] (англ.)
  • [www.refactoring.com/ Домашняя страница Мартина Фаулера о рефакторинге] (англ.)
  • Ксензов Михаил. [citforum.ru/SE/project/refactor/ Рефакторинг архитектуры программного обеспечения: выделение слоев]. — Рассматривается один из основных методов рефакторинга архитектуры ПО – выделение слоев, а также его место в контексте рефакторинга архитектуры как многошагового итеративного процесса. Проверено 30 ноября 2007. [www.webcitation.org/61C8PRY2e Архивировано из первоисточника 25 августа 2011].
  • [www.softkey.info/reviews/review5449.php Обзор программ для автоматического рефакторинга]
  • [blog.symprise.net/2009/04/revisiting-fowlers-video-store-refactoring-code-reengineering-abstractions/ Revisiting Fowler’s Video Store: Refactoring Code, Refining Abstractions]

Отрывок, характеризующий Рефакторинг

На зарево первого занявшегося 2 го сентября пожара с разных дорог с разными чувствами смотрели убегавшие и уезжавшие жители и отступавшие войска.
Поезд Ростовых в эту ночь стоял в Мытищах, в двадцати верстах от Москвы. 1 го сентября они выехали так поздно, дорога так была загромождена повозками и войсками, столько вещей было забыто, за которыми были посылаемы люди, что в эту ночь было решено ночевать в пяти верстах за Москвою. На другое утро тронулись поздно, и опять было столько остановок, что доехали только до Больших Мытищ. В десять часов господа Ростовы и раненые, ехавшие с ними, все разместились по дворам и избам большого села. Люди, кучера Ростовых и денщики раненых, убрав господ, поужинали, задали корму лошадям и вышли на крыльцо.
В соседней избе лежал раненый адъютант Раевского, с разбитой кистью руки, и страшная боль, которую он чувствовал, заставляла его жалобно, не переставая, стонать, и стоны эти страшно звучали в осенней темноте ночи. В первую ночь адъютант этот ночевал на том же дворе, на котором стояли Ростовы. Графиня говорила, что она не могла сомкнуть глаз от этого стона, и в Мытищах перешла в худшую избу только для того, чтобы быть подальше от этого раненого.
Один из людей в темноте ночи, из за высокого кузова стоявшей у подъезда кареты, заметил другое небольшое зарево пожара. Одно зарево давно уже видно было, и все знали, что это горели Малые Мытищи, зажженные мамоновскими казаками.
– А ведь это, братцы, другой пожар, – сказал денщик.
Все обратили внимание на зарево.
– Да ведь, сказывали, Малые Мытищи мамоновские казаки зажгли.
– Они! Нет, это не Мытищи, это дале.
– Глянь ка, точно в Москве.
Двое из людей сошли с крыльца, зашли за карету и присели на подножку.
– Это левей! Как же, Мытищи вон где, а это вовсе в другой стороне.
Несколько людей присоединились к первым.
– Вишь, полыхает, – сказал один, – это, господа, в Москве пожар: либо в Сущевской, либо в Рогожской.
Никто не ответил на это замечание. И довольно долго все эти люди молча смотрели на далекое разгоравшееся пламя нового пожара.
Старик, графский камердинер (как его называли), Данило Терентьич подошел к толпе и крикнул Мишку.
– Ты чего не видал, шалава… Граф спросит, а никого нет; иди платье собери.
– Да я только за водой бежал, – сказал Мишка.
– А вы как думаете, Данило Терентьич, ведь это будто в Москве зарево? – сказал один из лакеев.
Данило Терентьич ничего не отвечал, и долго опять все молчали. Зарево расходилось и колыхалось дальше и дальше.
– Помилуй бог!.. ветер да сушь… – опять сказал голос.
– Глянь ко, как пошло. О господи! аж галки видно. Господи, помилуй нас грешных!
– Потушат небось.
– Кому тушить то? – послышался голос Данилы Терентьича, молчавшего до сих пор. Голос его был спокоен и медлителен. – Москва и есть, братцы, – сказал он, – она матушка белока… – Голос его оборвался, и он вдруг старчески всхлипнул. И как будто только этого ждали все, чтобы понять то значение, которое имело для них это видневшееся зарево. Послышались вздохи, слова молитвы и всхлипывание старого графского камердинера.


Камердинер, вернувшись, доложил графу, что горит Москва. Граф надел халат и вышел посмотреть. С ним вместе вышла и не раздевавшаяся еще Соня, и madame Schoss. Наташа и графиня одни оставались в комнате. (Пети не было больше с семейством; он пошел вперед с своим полком, шедшим к Троице.)
Графиня заплакала, услыхавши весть о пожаре Москвы. Наташа, бледная, с остановившимися глазами, сидевшая под образами на лавке (на том самом месте, на которое она села приехавши), не обратила никакого внимания на слова отца. Она прислушивалась к неумолкаемому стону адъютанта, слышному через три дома.
– Ах, какой ужас! – сказала, со двора возвративись, иззябшая и испуганная Соня. – Я думаю, вся Москва сгорит, ужасное зарево! Наташа, посмотри теперь, отсюда из окошка видно, – сказала она сестре, видимо, желая чем нибудь развлечь ее. Но Наташа посмотрела на нее, как бы не понимая того, что у ней спрашивали, и опять уставилась глазами в угол печи. Наташа находилась в этом состоянии столбняка с нынешнего утра, с того самого времени, как Соня, к удивлению и досаде графини, непонятно для чего, нашла нужным объявить Наташе о ране князя Андрея и о его присутствии с ними в поезде. Графиня рассердилась на Соню, как она редко сердилась. Соня плакала и просила прощенья и теперь, как бы стараясь загладить свою вину, не переставая ухаживала за сестрой.
– Посмотри, Наташа, как ужасно горит, – сказала Соня.
– Что горит? – спросила Наташа. – Ах, да, Москва.
И как бы для того, чтобы не обидеть Сони отказом и отделаться от нее, она подвинула голову к окну, поглядела так, что, очевидно, не могла ничего видеть, и опять села в свое прежнее положение.
– Да ты не видела?
– Нет, право, я видела, – умоляющим о спокойствии голосом сказала она.
И графине и Соне понятно было, что Москва, пожар Москвы, что бы то ни было, конечно, не могло иметь значения для Наташи.
Граф опять пошел за перегородку и лег. Графиня подошла к Наташе, дотронулась перевернутой рукой до ее головы, как это она делала, когда дочь ее бывала больна, потом дотронулась до ее лба губами, как бы для того, чтобы узнать, есть ли жар, и поцеловала ее.
– Ты озябла. Ты вся дрожишь. Ты бы ложилась, – сказала она.
– Ложиться? Да, хорошо, я лягу. Я сейчас лягу, – сказала Наташа.
С тех пор как Наташе в нынешнее утро сказали о том, что князь Андрей тяжело ранен и едет с ними, она только в первую минуту много спрашивала о том, куда? как? опасно ли он ранен? и можно ли ей видеть его? Но после того как ей сказали, что видеть его ей нельзя, что он ранен тяжело, но что жизнь его не в опасности, она, очевидно, не поверив тому, что ей говорили, но убедившись, что сколько бы она ни говорила, ей будут отвечать одно и то же, перестала спрашивать и говорить. Всю дорогу с большими глазами, которые так знала и которых выражения так боялась графиня, Наташа сидела неподвижно в углу кареты и так же сидела теперь на лавке, на которую села. Что то она задумывала, что то она решала или уже решила в своем уме теперь, – это знала графиня, но что это такое было, она не знала, и это то страшило и мучило ее.
– Наташа, разденься, голубушка, ложись на мою постель. (Только графине одной была постелена постель на кровати; m me Schoss и обе барышни должны были спать на полу на сене.)
– Нет, мама, я лягу тут, на полу, – сердито сказала Наташа, подошла к окну и отворила его. Стон адъютанта из открытого окна послышался явственнее. Она высунула голову в сырой воздух ночи, и графиня видела, как тонкие плечи ее тряслись от рыданий и бились о раму. Наташа знала, что стонал не князь Андрей. Она знала, что князь Андрей лежал в той же связи, где они были, в другой избе через сени; но этот страшный неумолкавший стон заставил зарыдать ее. Графиня переглянулась с Соней.
– Ложись, голубушка, ложись, мой дружок, – сказала графиня, слегка дотрогиваясь рукой до плеча Наташи. – Ну, ложись же.
– Ах, да… Я сейчас, сейчас лягу, – сказала Наташа, поспешно раздеваясь и обрывая завязки юбок. Скинув платье и надев кофту, она, подвернув ноги, села на приготовленную на полу постель и, перекинув через плечо наперед свою недлинную тонкую косу, стала переплетать ее. Тонкие длинные привычные пальцы быстро, ловко разбирали, плели, завязывали косу. Голова Наташи привычным жестом поворачивалась то в одну, то в другую сторону, но глаза, лихорадочно открытые, неподвижно смотрели прямо. Когда ночной костюм был окончен, Наташа тихо опустилась на простыню, постланную на сено с края от двери.
– Наташа, ты в середину ляг, – сказала Соня.
– Нет, я тут, – проговорила Наташа. – Да ложитесь же, – прибавила она с досадой. И она зарылась лицом в подушку.
Графиня, m me Schoss и Соня поспешно разделись и легли. Одна лампадка осталась в комнате. Но на дворе светлело от пожара Малых Мытищ за две версты, и гудели пьяные крики народа в кабаке, который разбили мамоновские казаки, на перекоске, на улице, и все слышался неумолкаемый стон адъютанта.
Долго прислушивалась Наташа к внутренним и внешним звукам, доносившимся до нее, и не шевелилась. Она слышала сначала молитву и вздохи матери, трещание под ней ее кровати, знакомый с свистом храп m me Schoss, тихое дыханье Сони. Потом графиня окликнула Наташу. Наташа не отвечала ей.
– Кажется, спит, мама, – тихо отвечала Соня. Графиня, помолчав немного, окликнула еще раз, но уже никто ей не откликнулся.
Скоро после этого Наташа услышала ровное дыхание матери. Наташа не шевелилась, несмотря на то, что ее маленькая босая нога, выбившись из под одеяла, зябла на голом полу.
Как бы празднуя победу над всеми, в щели закричал сверчок. Пропел петух далеко, откликнулись близкие. В кабаке затихли крики, только слышался тот же стой адъютанта. Наташа приподнялась.
– Соня? ты спишь? Мама? – прошептала она. Никто не ответил. Наташа медленно и осторожно встала, перекрестилась и ступила осторожно узкой и гибкой босой ступней на грязный холодный пол. Скрипнула половица. Она, быстро перебирая ногами, пробежала, как котенок, несколько шагов и взялась за холодную скобку двери.
Ей казалось, что то тяжелое, равномерно ударяя, стучит во все стены избы: это билось ее замиравшее от страха, от ужаса и любви разрывающееся сердце.
Она отворила дверь, перешагнула порог и ступила на сырую, холодную землю сеней. Обхвативший холод освежил ее. Она ощупала босой ногой спящего человека, перешагнула через него и отворила дверь в избу, где лежал князь Андрей. В избе этой было темно. В заднем углу у кровати, на которой лежало что то, на лавке стояла нагоревшая большим грибом сальная свечка.