Любой разработчик программного обеспечения знает о необходимости добавления новых функций или исправления ошибок в устаревший код. Часто код, который мы стремимся изменить, был написан кем-то другим, слишком сложен и чаще, чем хотелось бы, не имеет адекватного тестового покрытия. Вот почему рефакторинг - незаменимый инструмент для любого разработчика. В этой статье основное внимание будет уделено передовым методам рефакторинга, основанным на моем опыте, в основном, как Front-end разработчика, а также на книге Мартина Фаулера «Рефакторинг - улучшение дизайна существующего кода» (которую я настоятельно рекомендую вам прочитать!).

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

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

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

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

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

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

Зачем нам проводить рефакторинг?

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

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

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

Когда следует провести рефакторинг?

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

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

Почему тесты так важны при рефакторинге?

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

Как написать хорошие тесты?

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

Посмотрите на следующий пример (песочница кода):

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

Теперь давайте посмотрим на простой тест для этого компонента (Test A) с использованием Enzyme:

Как видите, он вызывает непосредственно метод onClick, что означает, что если мы проведем рефакторинг и изменим имя, например, на «УвеличитьСчетчик», нам нужно будет обновить тест, несмотря на то, что для пользователя ничего не изменится. Это не очень хорошая практика, и мы видим это часто!

В этом случае лучшим подходом было бы использовать метод «моделирования» из Enzyme API, поскольку он больше соответствует поведению пользователя.

Теперь, если мы переименуем метод «onClick», нам не нужно будет обновлять тест, и мы сразу же получим обратную связь, если наше изменение работает правильно.

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

Заключение

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

Педро Коста - фронтенд-инженер в AddCode.io

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

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