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

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

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

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

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

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

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

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

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

Кстати, этот доклад – тоже результат рефакторинга. Изначально он был больше 3 часов. Мы его переработали, чтобы вам было вкуснее слушать.

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

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

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

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

В классическом понимании рефакторинг – это улучшение кода без изменения функциональности продукта. Лично я считаю чуть по-другому.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Существует программный продукт «Автоматизированная проверка конфигураций». Наша компания разрабатывает его для фирмы «1С». Он предназначен для выполнения проверки конфигураций на соответствие стандартам. В том числе в него встроена проверка орфографии.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Все ведь писали программу «вчера»? Отлично вас понимаю, я и писал, и стоял «над душой».

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

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

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

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

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

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

Например, у нас в компании мы сразу учим стажеров рефакторингу. И не допускаем к каким-то реальным задачам до тех пор, пока ученик допускает нарушение стандартов.

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

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

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

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

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

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

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

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

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

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

У всех такое было? Я очень вас понимаю, я сам себя часто по рукам бил.

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

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

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

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

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

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

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

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

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

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

Выгоды

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

Метрики

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

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

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

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

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

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

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

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

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

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

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

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

Примеры

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

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


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

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

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


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


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

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

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



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

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

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

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

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

Источники
  • https://infostart.ru/1c/articles/933332/
  • https://apptractor.ru/info/articles/rukovodstvo-dlya-inzhenerov-po-refaktoringu-koda.html
  • https://skillbox.ru/media/code/chto_takoe_refaktoring_koda_i_zachem_on_nuzhen/
  • https://medium.com/lessplusmore/uxrefactoring-ebbb7e911f9d
  • http://gs-studio.com/news-about-it/32280-2018-01-29-22-03-11

tett
Зарплатто.ру - сайт о зарплатах и доходах, деньгах и финансах