Что такое рефакторинг кода и зачем он нужен

Здравствуйте, в этой статье мы постараемся ответить на вопрос: «Что такое рефакторинг кода и зачем он нужен». Если у Вас нет времени на чтение или статья не полностью решает Вашу проблему, можете получить онлайн консультацию квалифицированного юриста в форме ниже.


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

Определение Мартина Фаулера

Вопрос «Что такое рефакторинг?» часто возникает у программистов-новичков, а иногда и у более опытных разработчиков. Поэтому он регулярно всплывает на форумах в духе StackOverflow.

Там в качестве ответа на вопрос приводят цитату из книги «Refactoring: Improving the Design of Existing Code» за авторством Мартина Фаулера:

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

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

В каких случаях нужен рефакторинг?

Есть ряд ситуаций, которые «кричат» о необходимости рефакторинга:

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

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

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

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

Зачем нужен рефакторинг

Когда программисты пишут код, они решают определенную задачу. Иногда происходит так, что решить ее нужно в очень сжатые сроки. От спешки страдает не только программист, но и код: он становится сложным, хаотичным и неструктурированным.

Неструктурированный код можно сравнить с неструктурированным текстом — без заголовков и абзацев. Чтобы структурировать такой код и сделать его понятнее, разработчики используют рефакторинг.

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

Что такое рефакторинг?

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

Читайте также:  Что такое супружеская доля в наследстве?

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

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

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

Рефакторинг и производительность

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

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

С производительностью связано то интересное обстоятельство, что при анализе большинства программ обнаруживается, что большая часть времени расходуется небольшой частью кода. Если в равной мере оптимизировать весь код, то окажется, что 90% оптимизации произведено впустую, потому что оптимизировался код, который выполняется не слишком часто. Время, ушедшее на ускорение программы, и время, потерянное из-за ее непонятности — все это израсходовано напрасно.

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

races = ["Terran", "Protoss", "Zerg"]
for i in range(len(races)):
print(i+1, races[i])# 1 Terran
# 2 Protoss
# 3 Zerg

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

Целесообразность применения рефакторинга

Рефакторинг бывает двух вариантов: запланированный либо проводящийся по мере надобности.

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

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

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

Как встроить рефакторинг в свой рабочий процесс?

Обычно самый первый вопрос — как правильно выделить время под рефакторинг. Заводить ли для этого отдельные таски и когда рефакторить, если фичи в приоритете?

Ответ такой: рефакторинг должен проводиться непрерывно на всем этапе разработки.

Обычно это выглядит так:

— Вы взяли задачу и начали читать код. На этом моменте обычно вам уже придется что-то подрефакторить.

— Потом вы приступили к разработке. Буквально через 5-10 минут, максимум полчаса-час, у вас должен быть рабочий кусок кода, покрытый тестом. Тут же надо его рефакторить.

— Снова разработка, снова покрытый тестами кусок кода через непродолжительный отрезок времени.

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

Если вы делаете это в парадигме TDD, то этот подход будет называться Red-Green-Refactor. То есть сначала пишете красный тест на какой-то фрагмент функционала, потом пишете код, который делает ваш тест зеленым, потом рефакторите.

Когда нужен рефакторинг в программировании

Существует два вида рефакторинга: плановый и при необходимости.

Рефакторинг, который изначально закладывается программистами в цикл разработки, называется плановым. Например, его могут планировать на каждые 6 месяцев или каждые 4 сплита.

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

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

Когда делать рефакторинг

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

  • Правило 3 ударов


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

  • Делайте рефакторинг, когда добавляете новую функцию
  • Делайте рефакторинг, если требуется исправить ошибку
  • Делайте рефакторинг при разборе кода

Ресурсы для дополнительного погружения в рефакторинг

Самая известная книга о рефакторинге — это “Рефакторинг. Улучшение проекта существующего кода” Мартина Фаулера. Также есть интересное издание о рефакторинге, написанное на основе предыдущей книги — “Рефакторинг с использованием шаблонов” Джошуа Кириевски. Кстати о шаблонах. При рефакторинге всегда очень полезно знать основные паттерны проектирования приложений. В этом помогут эти отличные книги:

  1. “Паттерны проектирования” — авторства Эрика Фримена, Элизабет Фримен, Кэтти Сьерра, Берта Бейтса из серии Head First;
  2. “Читаемый код, или программирование как искусство” — Дастин Босуэлл, Тревор Фаучер.
  3. “Совершенный код” Стива Макконнелла, в которой изложены принципы красивого и элегантного кода.
Читайте также:  Сроки сдачи отчётности в 2023 году

Каковы преимущества рефакторинга?

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

Например, в 2014 году инженеры Kickstarter столкнулись с проблемой экспоненциального роста числа пользователей, что привело к снижению производительности запросов. В ответ они перенесли запросы MySQL на Redis и сократили типичное время загрузки более чем на 100 мс, что привело к уменьшению дисперсии времени загрузки и в целом более быстрой работе сайта.

Что такое рефакторинг и каким он бывает?

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

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

В целом, разница этих видов – в области применения:

  • Рефакторинг на системном уровне подразумевает изменения в логике работы приложения: переход на другие алгоритмы обработки информации и источники данных, изменение структуры данных в базе, изменения механизмов сохранения, получения и передачи данных внутри одной системы;
  • Архитектурный рефакторинг охватывает взаимодействие нескольких систем: он может включать в себя изменение механизмов интеграции, замену некоторых системных компонентов, изменение работы сервисов без изменения их контрактов, переход на новую архитектуру.
  • Рефакторинг технической документации означает периодическую вычитку технических заданий и спецификаций, улучшение структуры документов (перенос и группировка разделов, работа над логическими переходами), удаление дублирующей информации, работа над формулировками. Цель такая же, как в рефакторинге кода – повышение ясности и читаемости текста. Описание должно быть логичным и последовательным, при прочтении документа не должна возникать необходимость постоянно «перескакивать» в другие разделы за дополнительной информацией.

Как избежать рефакторинга?

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

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


Похожие записи:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *