Здравствуйте, в этой статье мы постараемся ответить на вопрос: «Что такое рефакторинг кода? Основные принципы и правила рефакторинга». Если у Вас нет времени на чтение или статья не полностью решает Вашу проблему, можете получить онлайн консультацию квалифицированного юриста в форме ниже.
Есть гласное правило для всех программистов – код должен быть лаконичным, хорошо структурированным и понятным для разработчиков, работающих с ним. Проблема в том, что написать такой код с первого раза – очень сложная задача. Каким бы опытным ни был программист, начальство заставит его спешить, заказчики будут менять требования по ходу разработки, а иногда код будет становиться непонятным из-за банального недосыпа. Более того, сами языки программирования регулярно совершенствуются и обретают новые возможности, позволяя заметно сократить количество кода. Поэтому и нужен рефакторинг.
Зачем нужен рефакторинг?
Ожидаемые преимущества рефакторинга:
-
Улучшение объективной читаемости кода за счет его сокращения или реструктуризации.
-
Провоцирование разработчиков на более вдумчивое написание ПО с соблюдением заданной стилистики и критериев.
-
Подготовка плацдарма для создания переиспользуемых кусков кода.
-
Упрощение поиска ошибок в большом объеме кода.
Методики рефакторинга
Разработчики и специалисты в области рефакторинга часто называют десятки различных тактик переработки кода, но почти все они четко привязаны к изменяемому компоненту (объекту, функции и т.п.), поэтому нет смысла их все перечислять. Обобщая, есть три основных способа выполнить рефакторинг:
-
Red-Green-Refactor. Это некий аналог «На старт, внимание, марш!». Находим кусок кода для переработки, пишем юнит-тест, переходим к переписыванию.
-
Абстракция. Эта стратегия используется, когда нужно почистить дубликаты. Разработчиками придумываются абстрактные классы или другие классы высокого уровня, чтобы вынести туда повторяющиеся методы.
-
Фрагментация. Стратегия изменения кода с целью увеличить количество компонентов, но сделать сами компоненты меньше. Что-то в духе методик планирования задач, часто применяемых для повышения личной эффективности.
Рефакторинг и проектирование
Рефакторинг — дорогой для бизнеса процесс. Программисты получают зарплату, но не добавляют новых функций и не ускоряют код. Вместо этого они переписывают уже существующий. Данный процесс зачастую необходим и может сохранить много времени и денег в будущем, но возможно ли убрать полностью или сократить время, которое тратится на рефакторинг? Ответ: да, можно.
Еще до написания нужно подумать об архитектуре будущего кода. Часто перед тем, как начать писать программу, программисты проектируют ее структуру. Это сильно помогает в создании качественного кода и позволяет тратить меньше времени на его рефакторинг в дальнейшем.
Кроме того, проще думать над структурой программы, когда она находится в разработке, чем в тот момент, когда она уже работает и участвует в бизнес-процессах.
Как договориться с коллегами?
Может оказаться, что менеджеру не понравится, что вы ковыряетесь в старом коде вместо того, чтобы делать новый. А может быть, и коллегам не понравится, что вы трогаете старый код с риском сломать его — особенно если это их код.
Что ж, самое простое тут — это менеджер. Рефакторинг — способ двигаться быстрее, так что можно попробовать зайти с экономической стороны вопроса. Но, в целом, можете просто ничего про рефакторинг не рассказывать, не его это дело. Фича готова? Готова. А как именно — это уже детали реализации. Самое главное — помнить, что вы профессионал и вам лучше видно, как делать свою работу.
Если против вас ополчилась команда и договориться не удалось никак, то тут все плохо. Обычно такие глубокие разногласия приводят к разводам — кто-то уходит, а кто-то остается. Вопрос лишь в том, кто у руля.
На этом мы, пожалуй, и закончим знакомство с НАСТОЯЩИМ рефакторингом.
И теперь у вас уже достаточно инструментов, чтобы безопасно и качественно приводить свою кодовую базу в порядок.
Проблемы рефакторинга
Изначально понятие рефакторинга (refactoring) сформировалось применительно к Smalltalk, а потом уже концепция постепенно распространилась среди сторонников других языков программирования. Собственно, рефакторинг — это уже неотъемлемый элемент процесса разработки структуры приложений (framework development). Речь идет именно о рефакторинге, когда структурщики работают над иерархией классов и сокращением кодов.
Грамотные специалисты понимают, что слёту хорошую структуру не создать, она совершенствуется в ходе работы, как говорится «на опыте». И еще они знают, что чаще речь идет об улучшении читаемости и модификации старого кода (а не о создании нового). Вот тут и вступает в силу рефакторинг, применимый и для всего ПО, и отдельно для структур (frameworks).
Связаны ли с рефакторингом какие-либо риски? Да, они есть. Дело в том, что анализу и рефакторингу подвергается чистый, уже работающий код, и по ходу дела в нем могут появиться ошибки, на поиск которых потом придется потратить целые дни, а то и недели. Еще хуже, когда рефакторинг проводится бессистемно и без соблюдения формальностей.
- Обнаружив, что в программу необходимо добавить новую функциональность, но код программы не структурирован удобным для добавления этой функциональности образом, сначала произведите рефакторинг программы, чтобы упростить внесение необходимых изменений, а только потом добавьте функцию.
- Перед началом рефакторинга убедитесь, что располагаете надежным комплектом тестов. Эти тесты должны быть самопроверяющимися.
- При применении рефакторинга программа модифицируется небольшими шагами. Ошибку нетрудно обнаружить.
- Написать код, понятный компьютеру, может каждый, но только хорошие программисты пишут код, понятный людям.
Самый важный урок, который должен преподать данный пример, это ритм рефакторинга: тестирование, малые изменения, тестирование, малые изменения, тестирование, малые изменения. Именно такой ритм делает рефакторинг быстрым и надежным.
Для чего нужен рефакторинг?
Существует несколько причин. Например, погоня за простотой и лаконичностью кода. Сторонники этой теории считают, что код должен быть максимально кратким, даже если для его понимания нужно несколько десятков строк комментарий. Другие разработчики уверены, что код должен подвергаться рефакторингу настолько, чтобы он был понятен с минимальным количеством комментариев. Каждая команда выбирает свою позицию, но нужно помнить, что рефакторинг — это не сокращение. Его главная цель — улучшить структуру кода. В эту глобальную цель можно включить несколько задач:
- Рефакторинг улучшает понимание кода, который написан другим разработчиком;
- Помогает искать и устранять ошибки;
- Позволяет повысить скорость разработки ПО;
- В целом улучшает композицию программного обеспечения.
Демонстрация результатов рефакторинга
Несмотря на то, что рефакторинг ведется на уровне кода (под капотом), как и для любой другой пользовательской истории, команды должны иметь возможность продемонстрировать результаты.
Если брать пример выше, то команды могли бы это сделать так:
- Уменьшено время обработки на нескольких веб-страницах по сравнению с предыдущим эталонным тестом.
- Понятна зависимость времени обработки от размера пакета, который теперь можно прочитать из файла.
- Есть сниппет кода кода для возможности асинхронной обработки.
- Есть файл логирования, в котором фиксируются все операции.
- Количество запросов к словарям из расчета на один пакет (по статистике из лога).
Когда нужен рефакторинг в программировании
Существует два вида рефакторинга: плановый и при необходимости.
Рефакторинг, который изначально закладывается программистами в цикл разработки, называется плановым. Например, его могут планировать на каждые 6 месяцев или каждые 4 сплита.
В крупных компаниях, где обычно много legacy-кода, вообще формируются отдельные команды, занимающиеся исключительно рефакторингом старья. Благодаря этому остальные команды легче и быстрее понимают, что происходит в этом коде и как его использовать.
Второй вариант – рефакторинг при необходимости. К нему прибегают, когда возникают сложности с добавлением новых возможностей к старому коду. Тогда мы приостанавливаем процесс и выделяем какое-то время на переустройство того, что было.
Как понять, что проекту нужен рефакторинг
Заказчику стоит задуматься о рефакторинге, если:
- проект работает, но медленнее обычного, часто случаются сбои;
- даже небольшие правки затягиваются по времени;
- разработчики не могут оценить объем задач, поскольку говорят о том, что сначала нужно разобраться;
- при выгрузке изменений в релиз часто встречают баги.
Для разработчика «красные флаги», сигнализирующие о необходимости чистки кода будут такими:
- дублирование кода;
- длинные или ресурсоемкие методы;
- большие классы;
- несгруппированные данные;
- длинные списки параметров;
- избыточные переменные;
- если понимание кода занимает много времени. Иногда код может быть написан с соблюдением принципов DRY и KISS, но работа кода всё-равно остается непонятной разработчикам. Здесь стоит задуматься о смене паттернов проектирования и проектировании другой модели абстракции. Часто помогает и переименование переменных по рекомендациям Мартина Фаулера.
В рамках рефакторинга проводятся, на первый взгляд, элементарные работы:
- перемещение поля из одного класса в другой;
- вынесение фрагмента кода из метода в самостоятельный метод;
- перемещение кода по иерархии классов.
Рефакторинг в твоей команде
- Фиксируйте «временные решения» и составляйте к каждому из них проработанное TO-BE решение;
- Обозначьте сроки, когда вы вернетесь к вопросу перехода на целевое решение и внесите обсуждение этих вопросов в план спринта;
- Обозначьте риски в случае неперехода на целевое решение (как правило, долгосрочные риски);
- Информируйте смежные команды и прочих стейкхолдеров о том, что планируется реализация временного решения и сообщайте, когда планируется переход на целевой вариант;
- Выделяйте время в спринте на работу с техническим долгом;
- Проводите оценку временной функциональности и пересматривайте при необходимости целевые варианты. Зачастую временные решения оказываются вполне рабочими;
- Не занимайтесь рефакторингом в ущерб проектной работе: не допускайте смещения сроков проекта или вреда работающим системам и сервисам.
Если вы следуете этим рекомендациям и не копите технический долг, вы можете заметить следующие положительные моменты в своем рабочем процессе, которые говорят об успешности проведенного рефакторинга:
- При реализации новой функциональности вы не сталкиваетесь с необходимостью изобретать сложные логические конструкции;
- Обмен данными в системе проходит быстро и без ненужных преобразований;
- У вас не встает вопросов о полной замене какого-либо компонента или системы в виду их неуправляемости;
- В команде не тратится слишком много времени на технические груминги и проработку дизайна;
- Вхождение в проект новых сотрудников (аналитиков, разработчиков, тестировщиков) проходит легко благодаря понятному коду и качественной документации;
- Ваш проект идет «в ногу со временем»: в него относительно безболезненно внедряются новые современные технологии;
- Вы никогда не слышали о legacy-системах и сейчас пошли гуглить этот термин😊
Итак, рефакторинг – не такое уж ресурсоемкое занятие, если проводить его с умом и не доводить системы до неуправляемого состояния. Придерживаясь вышеперечисленных рекомендаций, вы сможете достигнуть баланса между проектными и техническими задачами и повысить эффективность систем в целом.
Определение Мартина Фаулера
Вопрос «Что такое рефакторинг?» часто возникает у программистов-новичков, а иногда и у более опытных разработчиков. Поэтому он регулярно всплывает на форумах в духе StackOverflow.
Там в качестве ответа на вопрос приводят цитату из книги «Refactoring: Improving the Design of Existing Code» за авторством Мартина Фаулера:
Рефакторинг – это контролируемая техника совершенствования структуры существующего кода. Суть рефакторинга заключается во внесении серии мелких изменения (с сохранением функциональности приложения), каждое из которых «слишком мелкое, чтобы тратить на него время». Тем не менее эффект от внесения всех этих изменений достаточно ощутимый.
Также в этой книге рекомендуется выполнять рефакторинг пошагово, чтобы исключить появление ошибок. А пользователи StackOverflow советуют каждое изменение сопровождать применением юнит-тестов. И хотя многие отрицают столь тесную связь этих двух операций, большинство опытных кодеров все же не упускают возможности задействовать тесты на любом из этапов разработки или модификации ПО.
В каких случаях нужен рефакторинг?
Есть ряд ситуаций, которые «кричат» о необходимости рефакторинга:
Попытка внести любое улучшение или добавление новой функции в приложение превращается в проблему для разработчиков, а сроки выполнения, на первый взгляд, несложных операций затягиваются на неадекватный срок из-за того, что база кода напоминает дебри.
Сроки добавления новых функций в приложение на постоянной основе становятся размытыми, потому что разработчикам приходится закладывать время на анализ кода.
Приходится выполнять идентичные процедуры в разных участках кода (объектах, классах) вместо того, чтобы внести изменение в одном классе, и оно возымело бы эффект в других участках ПО.
Код не соответствует общепризнанным в компании практикам оформления, из-за чего не может использоваться для дальнейшей разработки с учетом ранее установленных требований.
Впрочем, есть и другие, более индивидуальные факторы, подвигающие команду программистов на рефакторинг кода. Это зависит и от особенностей работы в конкретной компании, где серьезным поводом для рефакторинга может считаться даже неправильное количество пробелов в начале строки.
Принципы рефакторинга
Примечание: представленный здесь список ни в коем случае не является исчерпывающим, а принципы не оригинальны (хотя я представляю их своим собственным голосом и в соответствии со своим пониманием). На мой взгляд, наибольшая ценность этого поста – в реальных примерах, которые сопровождают принципы.
Пять принципов, представленных здесь:
- Скрыть «как» с «что»
- Стремление к последовательности
- Избегайте глубокого вложения
- Отдельные проблемы (= принцип единой ответственности)
- Избегайте дублирования с умом (= Не повторяйте себя)