Apeiron
RU UA EN

IT технологии: Рефакторинг

26 мар. 2022 г., 17:38:22
Содержание статьи:

Что такое рефакторинг и для чего он нужен

рефакторинг это

Итак, что же такое рефакторинг? Грубо говоря, это переписывание программы для ее внутреннего улучшения.

Сам процесс существует довольно давно. Термин ввел Уильям Опдайк в одной из своих статей в 1993 году. В настоящее время многие IT-команды, включая нашу компанию, применяют рефакторинг и извлекают из этой технологии дополнительные выгоды.

Для начала рассмотрим простой пример. Лев Толстой переписывал «Войну и мир» восемь раз. Отдельные эпизоды – более двадцати шести раз. Конечно, этим занимались все писатели и до, и после него.

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

Рефакторинг – это процесс достижения прекрасного.

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

Взять того же Льва Толстого. Признанное достояние мировой культуры. При этом читать его откровенно трудно, у него очень сложный слог. А вот, например, Чехов или Булгаков читаются значительно проще, на одном дыхании. Речь просто льется с их страниц! Текст гораздо приятнее и красивее.

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

Таким образом, рефакторинг – это метод борьбы с бардаком, делающий проект и в целом мир прекраснее.

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

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

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

Масштаб проблемы

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

Крутые программисты и профессионалы в своей области переписывают свои программы, совершенствуют их как внутри, так и снаружи.

Признак хорошего тона считается, когда то, что творит программист, красиво и аккуратно - радует глаз. Если обнаружено, что где-то можно сделать лучше, возникает острое желание переписать этот кусок кода.

На рабочем столе может быть бардак, в голове может быть бардак. В коде всегда должно быть чисто и красиво! Всегда!

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

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

Как это вообще возможно? Есть различные методы и технологии для достижения этой цели. Сейчас не будем на них останавливаться.

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

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

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

У кого есть свой стандарт разработки? А кто всегда его придерживается? А кто знает, что они вообще существуют и в них более 200 страниц текста?

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

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

Вернемся к тому же Льву Толстому. Он без сомнения красавчик. Но кто прочитал полностью все четыре тома «Войны и мир»? Кто сделал это с первого раза? А кто при подготовке к экзамену прочитал ее же, но в кратком изложении? Разумеется, прочитать пару страниц сокращенного текста гораздо проще, чем четыре огромные книги.

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

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

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

Да, пока это отраслевой стандарт – большие запросы. По-другому пока не получается. Это прекрасная возможность придумать, как делать по-другому. Зачем? По фану. Из лени. И чтобы спасти пару-тройку жизней программистов.

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

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

программы без кода

Думаю, многие из вас знакомы с пакетами программ типа «Mathematica». Программа просто потрясающая. Пишешь уравнение или какую-либо математическую задачу на классическом математическом языке – и программа все сама понимает и решает. Как она это делает, пользователю, по сути, не важно. Мы сформулировали задачу и получили результат. При этом система может не только дать правильный ответ, но и подробное объяснение решения.

Еще один пример от тех же разработчиков, что и «Mathematica» – система «Wolfram|Alpha». Там вообще все гениально. В ней можно задать вопрос из 3 слов, какой цвет чаще всего используется во флагах стран мира, и система выдаст ответ. То есть программа фактически без кода делает то, что нам необходимо. Мы лишь формулируем задачу или вопрос и получаем результат.

Еще один великолепный пример на эту тему – когнитивная система «IBM Watson». Она в 2011 году выиграла у сильнейших игроков в американскую версию «Своей игры». Сейчас «IBM Watson» используется в медицине для лечения рака. Она диагностирует лучше врачей-экспертов и предлагает пациенту индивидуальное лечение.

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

Очень простой пример – что такое собачка?

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

Следующий пункт – отсутствие комментариев. В одном случае это один из основных критериев того, что код хороший. Но с другой стороны если код хромает, то лучше чтобы комментарии были.

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

Следующая очень важная задача – писать грамотно.

Другой важный момент – функции и отдельные их части не должны быть копипастом друг друга.

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

Если есть повторяющиеся действия, правильнее выносить их в отдельную функцию.

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

Идем дальше. Еще один признак хорошего кода – параметров в функциях и процедурах должно быть минимум.

Кто-то получает удовольствие, переписывая свой функционал, когда у библиотечной функции добавился новый обязательный параметр? А остальные? Не получали удовольствие, но все равно делали?

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

Следующий пункт – вложенность операторов и конструкций. Большой вложенности лучше избегать. Одного-двух уровней достаточно, чтобы не перегружать код.

Когда стоит заниматься рефакторингом

Давайте теперь разберемся, когда вообще стоит, а когда не стоит заниматься рефакторингом.

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

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

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

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

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

Следующий пункт. Можно написать код, а потом заниматься рефакторингом. А можно сразу писать хорошо. Естественно, делать хорошо сразу – правильнее, быстрее и дешевле.

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

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

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

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

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

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

Как избежать проблем рефакторинга

Экстремальное программирование

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

На текущий момент рефакторинг – это одна из методологий экстремального программирования. В него входят разные «вкусняшки». Далее мы поговорим о них, и как они взаимосвязаны.

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

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

Следующий важный момент. Представьте, вы написали какой-то код и вернулись к нему спустя год или пять. Смотрите на него и думаете: «Кто это сделал? Оторвать бы автору руки!»

У всех такое было?

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

Двигаемся дальше. Рефакторинг очень полезен как способ повышения квалификации.

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

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

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

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

В некоторых командах принято, что все новое попадет в релиз только после защиты кода. Защитили – принимаем. В противном случае переделываем и снова защищаем.

Другая методология экстремального программирования – парное программирование. Это почти та же самая защита кода, но в реальном времени.

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

Выгоды

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

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

Метрики

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

Кроме того, вам нужны метрики, чтобы оценить эффективность рефакторинга исходного кода — речь идет не только об изменении неэффективного кода, но и об изменении неэффективного кода для добавления ценности. Чтобы понять реальную ценность, вам нужны тесты, как модульные (например, количество неудачных модульных тестов), так и функциональные. Другие показатели могут включать меньшее количество ошибок и снижение цикломатической сложности — рефакторинг должен быть направлен на снижение сложности. Методы или функции с высокой сложностью (например, более 350 строк) являются хорошими целями для рефакторинга.

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

Инструменты кода

Вам нужны специальные инструменты для рефакторинга? Мартин Фаулер говорит, что автоматизированные инструменты полезны, но не важны. Он отмечает:

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

Многие среды разработки автоматизируют механические аспекты рефакторинга. Инструменты рефакторинга ключевого кода:

  • Visual studio intellicode
  • Eclipse IDE
  • Spring Tool Suite 4
  • Rider
  • IntelliJ IDEA
  • SonarQube

Чем отличается от оптимизации

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

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

После рефакторинга программа может начать работать быстрее, но главное — её код становится проще и понятнее.

Примеры

Давайте на конкретных примерах разберем где недостатки, а где дефекты.

Пример 1. Форма подписки

форма подписки 1


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

Над полем текстовая метка — подсказывает что надо ввести. Не логин, телефон или еще что-то, а email. Она также косвенно убирает недостаток интерфейса.

Недостатком на картинке является активная кнопка “Подписать”. Если пользователь нажмет на неё, не введя адрес, то он получит дефект — сообщение об ошибке. Как минимум, ее стоит сделать неактивной. Идеально — убрать вообще, чтобы даже неактивная кнопка не была индикатором тупикового действия и не смущала пользователя.

форма подписки 2


Если же по шагам посмотреть как пользователь вводит адрес, то можно сделать подсказки, что ожидается символ ввода @, а затем точка.

Смените раскладку


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

А если делать рефакторинг не отдельной формы, а всего сайта, то единожды введенный email на сайте (при регистрации, в форме обратного звонка, при оформлении доставки, при подписке) — автоматически должен подставиться во всех местах сайта, где предполагается ввод электронной почты пользователя. Один раз ввели — используем везде.

Пример 2. Сообщение в Word

Сообщение в Word


Сообщение в Word при закрытии несохраненного файла

Что мешает, например, сохранять файл в Word автоматически? При закрытии останется выбор между двумя кнопками — “Не сохранять” / “Отмена”. Тем более, что он уже где-то сохранен, раз будет “временно доступен”. Кнопка “Сохранить” нужна только для того, чтоб задать корректный путь к папке, где будет храниться файл.

Кнопка “Отмена” фактически означает действие “Продолжить редактирование”. Чем “Отмена” отличается от “Не сохранять” из сообщения об ошибке не очевидно. Это недостаток первого типа.

Вместо выводов

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