4 простых способа рефакторинга кода
Здравствуйте, в этой статье мы постараемся ответить на вопрос: «4 простых способа рефакторинга кода». Если у Вас нет времени на чтение или статья не полностью решает Вашу проблему, можете получить онлайн консультацию квалифицированного юриста в форме ниже.
Есть гласное правило для всех программистов – код должен быть лаконичным, хорошо структурированным и понятным для разработчиков, работающих с ним. Проблема в том, что написать такой код с первого раза – очень сложная задача. Каким бы опытным ни был программист, начальство заставит его спешить, заказчики будут менять требования по ходу разработки, а иногда код будет становиться непонятным из-за банального недосыпа. Более того, сами языки программирования регулярно совершенствуются и обретают новые возможности, позволяя заметно сократить количество кода. Поэтому и нужен рефакторинг.
Зачем нужен рефакторинг и нужен ли
Refactoring можно сравнить с приведением рабочего места в порядок. Стол разработчика с течением времени засоряется бумагами, записками, справочной литературой по языкам программирования и прочими лишними предметами. Если периодически убирать мусор и расставлять предметы по своим местам, суть работы кардинально не изменится, но делать ее будет куда приятнее и проще.
Рефакторинг не ускоряет работу программы, не добавляет и не убирает из нее функционал – для этих задач используется оптимизация. Метод устраняет повторы, слишком «раздутые» участки и другие типичные проблемы, из-за которых код становится сложным для понимания, занимает неоправданно много места, а его доработка занимает гораздо больше времени, чем могла бы.
Можно обойтись и без рефакторинга, но чем дальше идет разработка без него, тем сложнее будет работать с приложением. Особенно ярко это проявляется у крупных продуктов, над созданием которых трудятся большие команды разработчиков.
Простые программы можно не рефакторить с меньшими последствиями, но лучше выработать привычку исправлять код во всех своих проектах.
В каких случаях нужен рефакторинг?
Есть ряд ситуаций, которые «кричат» о необходимости рефакторинга:
-
Попытка внести любое улучшение или добавление новой функции в приложение превращается в проблему для разработчиков, а сроки выполнения, на первый взгляд, несложных операций затягиваются на неадекватный срок из-за того, что база кода напоминает дебри.
-
Сроки добавления новых функций в приложение на постоянной основе становятся размытыми, потому что разработчикам приходится закладывать время на анализ кода.
-
Приходится выполнять идентичные процедуры в разных участках кода (объектах, классах) вместо того, чтобы внести изменение в одном классе, и оно возымело бы эффект в других участках ПО.
-
Код не соответствует общепризнанным в компании практикам оформления, из-за чего не может использоваться для дальнейшей разработки с учетом ранее установленных требований.
Зачем нужен рефакторинг
Когда программисты пишут код, они решают определенную задачу. Иногда происходит так, что решить ее нужно в очень сжатые сроки. От спешки страдает не только программист, но и код: он становится сложным, хаотичным и неструктурированным.
Неструктурированный код можно сравнить с неструктурированным текстом — без заголовков и абзацев. Чтобы структурировать такой код и сделать его понятнее, разработчики используют рефакторинг.
Американский программист и автор множества книг по разработке ПО Мартин Фаулер определяет рефакторинг как «изменение внутренней структуры ПО без изменения его наблюдаемого поведения, призванное облегчить его понимание и удешевить модификацию». Разработчики переписывают какие-то части кода, чтобы они стали понятнее, лаконичнее, а еще — чтобы было проще добавлять новую функциональность.
Представим такую ситуацию: мы открыли кафе, построили там классную кухню и наняли шеф-повара. Когда кафе только запускалось, в меню были самые простые блюда, которые можно было разогреть в микроволновке. Вы купили микроволновку и поставили на кухне. Рядом разместили стеллаж для всего нужного.
Через два месяца дела пошли лучше, и мы решили добавить в меню выпечку. Купили духовой шкаф, протянули провода, добавили рядом стойку с подносами. Место на кухне уменьшилось, повар всё время перешагивает через провода и обходит стойку, но работать можно.
Ещё через месяц поставили фритюрницу и миксер для теста. К ним тоже протянули провода, добавили рядом шкафы для утвари и наняли второго повара. В итоге на кухне полный бардак, всё друг другу мешает, а блюда готовить неудобно. Если мы захотим добавить новую плиту, то это будет уже сложно: места нет, хотя по площади можно поставить хоть две таких плиты.
В этот момент приходит кухонный проектировщик и рисует всё заново: где что должно стоять.
Через неделю на кухне всё по-другому: оборудование стоит так, чтобы не мешать поварам, провода спрятаны в короба, а стойки с оборудованием не загораживают выход. При этом меню в кафе не изменилось: посетители даже не знают, что у нас что-то происходило на кухне, потому что мы оптимизировали процессы, а не меню. Это и есть рефакторинг — когда мы меняем что-то внутри так, что снаружи это незаметно, но работать дальше становится проще.
При проведении рефакторинга важным предварительным условием является наличие надежных тестов.
Правила разработки тестов
- Делайте все тесты полностью автоматическими, так чтобы они проверяли собственные результаты.
- Комплект тестов служит мощным детектором ошибок, резко сокращающим время их поиска.
- Чаще запускайте тесты. Запускайте тесты при каждой компиляции — каждый тест хотя бы раз в день.
- Получив сообщение об ошибке, начните с создания теста модуля, показывающего эту ошибку.
- Лучше написать и выполнить неполные тесты, чем не выполнить полные тесты.
- Подумайте о граничных условиях, которые могут быть неправильно обработаны, и сосредоточьте на них свои тесты.
- Не забывайте проверять, чтобы в случае возникновения проблем генерировались исключительные ситуации.
- Опасение по поводу того, что тестирование не выявит все ошибки, не должно помешать написанию тестов, которые выявят большинство ошибок.
Проблемы рефакторинга
Изначально понятие рефакторинга (refactoring) сформировалось применительно к Smalltalk, а потом уже концепция постепенно распространилась среди сторонников других языков программирования. Собственно, рефакторинг — это уже неотъемлемый элемент процесса разработки структуры приложений (framework development). Речь идет именно о рефакторинге, когда структурщики работают над иерархией классов и сокращением кодов.
Грамотные специалисты понимают, что слёту хорошую структуру не создать, она совершенствуется в ходе работы, как говорится «на опыте». И еще они знают, что чаще речь идет об улучшении читаемости и модификации старого кода (а не о создании нового). Вот тут и вступает в силу рефакторинг, применимый и для всего ПО, и отдельно для структур (frameworks).
Связаны ли с рефакторингом какие-либо риски? Да, они есть. Дело в том, что анализу и рефакторингу подвергается чистый, уже работающий код, и по ходу дела в нем могут появиться ошибки, на поиск которых потом придется потратить целые дни, а то и недели. Еще хуже, когда рефакторинг проводится бессистемно и без соблюдения формальностей.
Оценка эффективности рефакторинга
Анализ и рефакторинг сделан успешно, если в результате вы имеете чистый, простой и понятный код.
К примеру, если количество покупателей в программе обозначено буквой Z, то лучше вместо неё поставить customerCount. Так код будет выглядеть яснее, и выполняемые в нём операции – тоже.
Если какая-то часть кода повторяется два раза и более, то есть смысл задать её в виде функции или метода. Тогда эти повторяющиеся фрагменты не нужно будет выискивать по всему коду, понадобится сделать замену лишь в одном месте.
Размеры функций, методов и классов тоже имеют значения. Если функция не влезает целиком в экран, то её нужно разбить на две части, тогда код будет легче читаться.
Еще один способ упростить код – все функции собрать в самостоятельный файл, а потом уже ввести его в программу.
Когда не стоит заниматься рефакторингом кода
Несмотря на всю пользу рефакторинга, применять его стоит не всегда. К примеру, если вы разрабатываете маленький и несложный продукт, развитие которого идет очень медленно. В таком случае править код может и не понадобиться. Хотя, конечно, лучше соблюдать порядок в любых проектах.
Также от рефакторингов можно отказаться при приближении дедлайна. Эффективность этой процедуры чувствуется лишь со временем, поэтому, если вы начнете рефакторить код перед самой сдачей проекта, заметного роста производительности не произойдет, а значит, вы впустую потратите время. Польза рефакторинга именно в том, что после него становится легче работать с существующим продуктом. Если делать этого больше не нужно — не нужен и рефакторинг.
Еще один пример — ситуация, когда проще переписать код с нуля, чем разбираться в нем. Рефакторинг — не панацея. Иногда распутывать безнадежный клубок из программных строк слишком долго и затратно. Быстрее и эффективнее написать все заново.
Когда нужен рефакторинг в программировании
Существует два вида рефакторинга: плановый и при необходимости.
Рефакторинг, который изначально закладывается программистами в цикл разработки, называется плановым. Например, его могут планировать на каждые 6 месяцев или каждые 4 сплита.
В крупных компаниях, где обычно много legacy-кода, вообще формируются отдельные команды, занимающиеся исключительно рефакторингом старья. Благодаря этому остальные команды легче и быстрее понимают, что происходит в этом коде и как его использовать.
Второй вариант – рефакторинг при необходимости. К нему прибегают, когда возникают сложности с добавлением новых возможностей к старому коду. Тогда мы приостанавливаем процесс и выделяем какое-то время на переустройство того, что было.
Использование метрик позволяет вам расставить приоритеты для основных действий по исправлению, которые вам действительно нужно внести в свой код. Это не дает вам делать все сразу и заставляет фокусироваться в первую очередь на самых важных задачах.
Кроме того, вам нужны метрики, чтобы оценить эффективность рефакторинга исходного кода — речь идет не только об изменении неэффективного кода, но и об изменении неэффективного кода для добавления ценности. Чтобы понять реальную ценность, вам нужны тесты, как модульные (например, количество неудачных модульных тестов), так и функциональные. Другие показатели могут включать меньшее количество ошибок и снижение цикломатической сложности — рефакторинг должен быть направлен на снижение сложности. Методы или функции с высокой сложностью (например, более 350 строк) являются хорошими целями для рефакторинга.
Также стоит подумать о том, как рефакторинг соотносится с более широкими целями или этапами команды в отношении рабочего процесса и задач. В метрики нужно включать меньший размер кода и более понятный код.
Вам нужны специальные инструменты для рефакторинга? Мартин Фаулер говорит, что автоматизированные инструменты полезны, но не важны. Он отмечает:
Многие языки имеют IDE, которые автоматизируют стандартный рефакторинг. Это действительно ценная часть моего набора инструментов, позволяющая мне быстрее выполнять рефакторинг. Но такие инструменты не являются необходимыми — я часто работаю с языками программирования без поддержки инструментов, и в этом случае я полагаюсь на небольшие шаги и частое тестирование для обнаружения ошибок.
Многие среды разработки автоматизируют механические аспекты рефакторинга. Инструменты рефакторинга ключевого кода:
- Visual studio intellicode
- Eclipse IDE
- Spring Tool Suite 4
- Rider
- IntelliJ IDEA
- SonarQube
Каковы преимущества рефакторинга?
Рефакторинг исходного кода дает множество преимуществ. Он превращает беспорядочный, неправильный и/или повторяющийся код в чистый код. Он решает проблемы стандартизации, которые могут возникнуть, когда несколько разработчиков пишут свой собственный код. Рефакторинг обеспечивает лучшую читаемость и улучшает поддерживаемость исходного кода, а также его общую структуру и функциональность. Рефакторинг может упростить расширение кода и добавить новые функции. Удаление ненужных частей, таких как дубли, также может привести к тому, что код будет использовать меньше памяти и работать быстрее.
Например, в 2014 году инженеры Kickstarter столкнулись с проблемой экспоненциального роста числа пользователей, что привело к снижению производительности запросов. В ответ они перенесли запросы MySQL на Redis и сократили типичное время загрузки более чем на 100 мс, что привело к уменьшению дисперсии времени загрузки и в целом более быстрой работе сайта.
Зачем нужен рефакторинг
Стройный, хорошо структурированный код легко читается и быстро дорабатывается. Но редко удаётся сразу сделать его таким. Разработчики спешат, в процессе могут меняться требования к задаче, тестировщики находят баги, которые нужно быстро исправить, или возникают срочные доработки, и их приходится делать второпях.
В результате даже изначально хорошо структурированный исходник становится беспорядочным и непонятным. Программисты знают, как легко завязнуть в этом хаосе. Причём неважно, чужой это код или собственный.
Чтобы решить все эти проблемы, делается рефакторинг программы. В новом проекте он нужен, чтобы:
Но любое приложение со временем устаревает: язык программирования совершенствуется, появляются новые функции, библиотеки, операторы, делающие код проще и понятнее. То, что год назад требовало пятидесяти строк, сегодня может решаться всего одной.
Поэтому даже идеальная когда-то программа со временем требует нового рефакторинга, обновляющего устаревшие участки кода.
Программный код предназначен не только для компьютера, но и для человека, который будет его дорабатывать. Плохо, если ему придётся неделю разбираться в исходниках, чтобы изменить в программе несколько строк. И не исключено, что этим человеком окажетесь вы сами.
Что такое рефакторинг
Начиная с последнего десятилетия прошлого века получили широкое распространение эволюционные методологии разработки программного обеспечения, часто называемые адаптивными, такие как экстремальное программирование (Extreme Programming — ХР), метод Scrum, унифицированный процесс компании Rational (Rational Unified Process — RUP), адаптивный унифицированный процесс (Agile Unified Process — AUP) и др. [38]. Часть этих методологий рассмотрена в третьей главе книги, где рассматривалась сущность их методов, которые по своему характеру являются и итеративными, и инкрементными, а адаптивный подход является эволюционным и вместе с тем характеризуется высокой степенью взаимодействия участников разработки проектов.
В организациях, применяющих подобные технологии, внедряются такие адаптивные методики, как рефакторинг, программирование в паре, разработка на основе тестирования (Test-Driven Development — TDD) и адаптивное проектирование на основе модели (Agile Model Driven Development — AMDD). Концепция рефакторинга (refactoring) возникла в кругах, связанных со Smalltalk, но вскоре нашла себе дорогу и в лагеря приверженцев других языков программирования [3]. Несколько позже М. Фаулер в своей фундаментальной монографии, выдержавшей в нашей стране несколько изданий [33], дал определение рефакторинга как небольшого изменения в исходном коде, которое способствует улучшению проекта кода без изменения его семантики.