Разное

Что такое рефакторинг кода: Что такое рефакторинг кода? Основные принципы и правила рефакторинга

Содержание

Цена рефакторинга / Хабр

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

Вдохновители

Писать начал после очередного просмотра пулл-реквеста на 150+ файлов, где было люто замешана новая функциональность и рефакторинг существующей. Рефакторинг был не только косметическим, но и логическим, который вызывал наибольшую боль. Например, в Ruby amount == 0 смело заменялся на amount.zero? без учёта того, что для случая nil в amount эти конструкции не эквивалентны. Объяснялось же всё это примерно так: «но по код стандарту так положено!» На логичный вопрос «какая цель следования код стандарту и вообще, какая цель у тебя как разработчика?» человек замыкался в себе и немного виновато повторял «но по код-стандарту же вот так писать надо…» и выглядел как блондинка в магазине одежды, которая не в силах совладать с желанием отрефакторитькупить всё.

Определение

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

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

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

Ценность продукта

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

Прямые ценности продукта

Тут всё просто. Продуктом пользуются, поэтому прямые ценности это то, что явно щупает/видит/чувствует пользователь. А именно:

  1. всевозможная функциональность продукта;
  2. удобство использования (UI/UX, быстродействие, отказоустойчивость и тд).

Второй пункт может вызвать некоторую дискуссию. Ведь многие считают, что это не главное. Так как если функциональность хороша, то не важно во что она завёрнута. Хорошие примеры функциональности без вменяемого UI/UX: Redmine и SAP. Однако я с таким взглядом не согласен и ближе по взглядам к товарищу Алану Куперу и его «Психбольнице в руках пациентов».

Косвенные ценности продукта

Это те ценности, которые сами по себе на пользователя не влияют. Но могут «выстрелить» или «накопиться» и оказать влияние (разной степени тяжести) на продукт или его функциональность.

  1. Баги. Пограничный случай ценностей. Вторичны они потому, что сами ценности не несут, а забирают её у соседних фичей.
  2. Чистота. Это про читабельность, модульность, минимизацию входящих компонентов, стандартизацию и унификацию интерфейсов и тд.
  3. Документированность. Это про код и пояснения для разработчиков, не про бизнес описание или пользовательские юзкейсы. Хорошо иллюстрируется фразой весёлого мужика с одного из собеседований: «Логика в БД написана как книга».
  4. Масштабируемость/защищённость/безопасность. Пользователь их не видит, пока не случится что-нибудь нехорошее.

Ценности для разработчика

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

  1. Код по стандарту.
  2. Отступы по фен-шую.
  3. Иные сделки с совестью. Ведь код писал, значит результат за день есть, а значит и польза есть.
  4. Согласие кода с внутренним миром.

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

Взгляд со стороны бизнеса

Для полноты картины надо бы посмотреть на всё это со стороны бизнеса, а не программного продукта. В этом случае, разделение на прямые и косвенные ценности становится довольно банальным: прямые — явно приносят деньги и можно дать однозначную количественную оценку; косвенные — денег не приносят и/или количественную оценку дать очень сложно; ценности для разработчика денег не приносят ни в каком виде (возможно, даже отнимают их).

Например.

  • Новая фича с прикручиванием OAuth увеличила количество регистраций на 10% и мы получили +1к$.
  • Разделили модуль биллинга на несколько независимых частей, основываясь на паттерне single-responsibility. Вроде как поддерживать проще стало, но измерить никак не получилось.
  • Мы привели кодовую базу к соответствию с код-стандартом и… «ничего» не получили.

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

Справедливости ради, тут нужно вспомнить понятие enabler’а, который «открывает дорогу» к реализации желаемой фичи, но явного профита пользователю не несёт. Но это уже другая история.

Причём тут рефакторинг?

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

Так же, важно помнить про энтропию. Рефакторинг всегда неуменьшает её. Для уменьшения энтропии, в идеале, нужна команда архитекторов, минимизирующих энтропию на этапе проектирования. Процитирую кусочек из Мифического человекомесяца:

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

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

Какие цели могут быть у рефакторинга?

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

За энтропию!

Такое самому провернуть сложно. А протащить через ревью так и вообще нереально. Цель конечно благая: расчистить плацдарм для новых свершений, а так же вычистить шлаки и токсины, накопленные за время поддержки продукта. Но перелопатить с нуля пару модулей не потеряв ничего по пути — это не самая простая задача. Её надо бы решать совместно с бизнес-аналитиками и архитекторами, если таковые есть. Так что таким мало кто рискует заниматься на добровольных началах.

За документацию!

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

За быстродействие!

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

В эту категорию входит всё: от безобидного исправления N+1 до серьёзного ускорения за счёт изменения алгоритмов работы. Вся проблема в том, что на скорости всегда сидит «чётность» багов. Вот, к случаю, пример из жизни: внутри одной транзакции пушатся данные в БД и в этой же транзакции ставится задача в Sidekiq; очередь Sidekiq’а в Redis’е и транзакция на него не распространяется; при увеличении скорости работы очереди таска иногда берётся на выполнение раньше, чем закоммитятся данные; последствия и процесс дебага можете представить сами.

За рефакторинг!

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

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

Смирение и принятие

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

  1. Я увеличиваю количество багов в проекте и могу за это получить в бубен.
  2. Я становлюсь владельцем отрефакторенного кода и все вопросы по нему, в первую очередь, будут направлены ко мне.
  3. Своими действиями я не произвожу ничего ценного для конечного пользователя.

Немного пояснений.

  1. Любое изменение кода имеет ненулевой шанс породить баг. А раз это действие не связано с конечной функциональностью, то вы просто плодите баги без генерации основных ценностей. Хорошо это осознавать и не прикидываться шлангами, когда к вам придут с вопросами.
  2. Отмазки вида «anotate previous» и подобные очень убоги, ибо в том же гитхабе/гитлабе нет такой фичи. Плюс, предыдущий автор подтвердил, что именно в его конфигурации всё работает, а за ваши изменения он ответственности не несёт и теряет часть картины происходящего. Точнее, вы её забираете у него вместе с ответственностью.
  3. Пользователю реально пофиг на рефакторинг, его интересует стабильность и функциональность, а рефакторинг не об этом.

И ещё раз: если не согласны с хотя бы одним из пунктов — не начинайте рефакторинг. Лучше почитайте хабр, лурк, чаю выпейте или, на худой конец, запилите следующую фичу с дашборда.

Конец

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

Рефакторить или не рефакторить? / Блог компании Enterra / Хабр

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

Если вы хоть немного разделяете мои ощущения, то нам есть о чём поговорить. Дело в том, что со временем что-то внутри меня начало подсказывать, что рефакторить всё подряд, везде и всё время — не самая лучшая идея. Поймите меня правильно, код должен быть хорошим (а лучше бы ему быть идеальным), но в условиях суровой реальности не всегда разумно постоянно заниматься улучшением кода. Я вывел для себя несколько правил о своевременности рефакторинга. Если у меня начинают чесаться руки что-нибудь улучшить, то я оглядываюсь на эти правила и начинаю думать: «А действительно ли сейчас тот момент, когда нужно нарефакторить?». Давайте порассуждаем о том, в каких же случаях рефакторинг уместен, а в каких — не очень.

Дисклеймер. Скорее всего, многим захочется после прочтения поста сразу сказать: «Да это уже 600 раз обсуждалось!» или «Это же настолько очевидно, зачем же об этом писать?». Возможно, вы и правы, но только вот какой момент: в окружающем мире по-прежнему творится хаос. Вроде бы всем всё понятно, но на деле получается, что не так уж и понятно. Поэтому я думаю, что не будет слишком вредно ещё разок взглянуть на эту тему. Но если конкретно у вас проблем с рефакторингом нет, то можете просто пропустить этот пост, у вас уже всё хорошо.

Слишком ранний рефакторинг

Можете ли вы припомнить, когда у вас последний раз было постоянное ТЗ, которое месяцами не менялось? У меня вот такое вспомнить не очень получается. Мы живём в реальном мире, требования всё время меняются. Причём это не обязательно внешние требования — это могут быть ваши собственные требования к проекту. Поясню мысль на примере: допустим, вы взяли задачку среднего размера на один-два дня. Первые несколько классов уже написаны, но запустить пока нечего — идёт процесс написания суровой архитектурной части. И тут вы замечаете, что одна из частей проекта написана не особо универсально: «А вот если через полгода понадобится сделать X, то все будут страдать». Вполне разумно, что вам не хочется отправлять в репозиторий хреновый код, чтобы другие разработчики потом вспоминали вас плохим словом. И вы начинаете рефакторить ещё не готовую фичу. Иногда это оправдано, но на подобном пути следовало бы повесить табличку «ОПАСНОСТЬ». Вот поправите вы одну штуку, потом другую, потом третью. Неделя прошла, фича всё ещё не запускается, а вы говорите: «Как-то всё неправильно сделано. Но теперь я точно понял, как надо делать. Сейчас быстренько всё перепишу с нуля». Основная проблема заключается в том, что фидбека по фиче ещё не получено, а вы уже начали работать над улучшением кодовой базы. Подобный подход редко приводит к успеху. Не знаю, как у вас, а у меня часто бывает, что после реализации фичи я начинаю понимать, что работать всё должно несколько иначе. И это не из-за того, что я такой глупый, заранее не смог нормально продумать. Просто некоторую функциональность нужно «пощупать», чтобы понять как всё должно быть в релизе. Иногда нужен небольшой прототипчик (пусть даже с говнокодом и багами), чтобы обсудить фичу с коллегами. Иногда нужно что-то показать заказчику, чтобы он мог сказать: «Не, ну я не так хотел, всё должно быть наоборот». Порой пользователями не нравятся нововведения, они хотят всё как было. Проблема новых фич в том, что сложно предсказать их судьбу. Нередко случается так, что все наработки отправляются в помойку, т. к. после обсуждения первой версии коллектив принял решение делать всё иначе. Общий вывод: не стоит рефакторить код слишком рано, особенно если вы не уверены, что этот код 100 % останется в проекте.

Нецелевой рефакторинг

Скорее всего, у вас есть план разработки на ближайшее время. Вполне вероятно, что у вас есть сроки (даже если вы их поставили сами). Релизы нужно делать вовремя, затягивать разработку не стоит. Нужно контролировать себя, нужно заниматься теми вещами, которые входят в ваши непосредственные цели. Допустим, у вас есть кусок кода, который выглядит как полное… Ну, в общем, плохо выглядит. Но, продолжим наше допущение, вы с ним сейчас не работаете. Этот плохой кусок кода стабильно работает, успешно справляется со своими задачами и никак не связан с вашей текущей задачей. Ну так и не трогайте его! Да, вас может крайне печалить то обстоятельство, что на другом конце проекта всё очень плохо. Но заметьте, что прямо сейчас вам это никак не мешает. У вас есть текущие задачи, занимайтесь ими. Конечно, бывают задачи по улучшению кодовой базы, но нечасто — зачастую важнее добавлять новый функционал или фиксить баги. Концентрируйтесь на текущих задачах и не бросайте их из-за того, что где-то там что-то как-то не так.

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

Ок, вы пришли к выводу, что нужно обязательно отрефакторить часть проекта. Хорошо, давайте отрефакторим. Вроде бы запланированные улучшения выполнены, но тут возникает мысль: «А что я могу ещё улучшить? Ага, вон ту штуку». А после вон той штуки появится вот эта штука, а потом ещё одна, а потом ещё и т. д. Нужно понимать, что есть плохой код, есть хороший код, есть идеальный код. Последнего в большом проекте у вас никогда не будет. Это не значит, что не нужно к нему стремиться, но нужно понимать его недостижимость. Обычно задача стоит в написании хорошего кода, а не идеального. Допустим, после рефакторинга у вас получился вполне читаемый код, который работает более или менее очевидным образом, в котором нет костылей и которым не так сложно пользоваться. Задайте себе вопрос: «А может, пора остановиться?». Да, код можно улучшать. Причём в достаточно большом проекте его можно улучшать до бесконечности. Но вот прямо сейчас он справляется со своими функциями, им удобно пользоваться, он практически не вызывает у вас дискомфорта. Очень важно определить для себя приемлемое качество кода, после которого вы перестанете его улучшать (до тех пор, пока свойство приемлемости не будет утрачено). Вспомните, что есть ещё так много разных клёвых штук, которые можно дописать. Не нужно рефакторить ради самого рефакторинга, ради идеального кода. Нужно рефакторить, когда у вас есть веские причины на это: код сложно прочитать, код сложно поддерживать, код сложно развивать, код сложно использовать и т. п. Если ни одного «сложно» не возникает, то веских причин тратить время на рефакторинг у вас нет.

Рефакторинг за день до релиза

Бывает так, что релиз послезавтра/завтра/сегодня/должен был быть вчера (нужное подчеркнуть). Это важный момент в жизни проекта. Нужно уделить особое внимание тестированию, фиксам критических багов, финальным доделкам. Поверьте, это действительно плохая идея — перерабатывать кодовую базу (а ещё хуже — качественно перерабатывать) в тот момент, когда нужно отдавать проект в продакшн. Опытная практика подсказывает, что нужно зарелизиться, а потом с чистой совестью спокойно улучшать код. Некоторые спросят: «А почему?». Если такой вопрос возник, то, наверное, вам ещё не приходилось делать сложный рефакторинг. Подскажу: при переписывании код не всегда обязательно улучшается — иногда он может сломаться. Да что там сложный рефакторинг — бывает, поправишь один метод на пять строк, не уследишь за какой-нибудь зависимостью, а на другом конце проекта выползет бага, с которой сразу же встретятся ваши любимые пользователи. Вот вроде бы ничего плохого и не делаешь, а тут внезапно на тебя нападает зверь «Это было неочевидно» и топит тебя в пруду ложной первоначальной оценки. Хотя, может, это просто я такой плохой программист — люблю что-нибудь сломать. Вполне возможно, что вы всегда рефакторите всё абсолютно правильно и с полным контролем всего проекта. В таком случае я могу вас поздравить, но от совета с запретом предрелизного рефакторинга всё-таки не откажусь. Поверьте, за несколько дней рефакторинг никуда не убежит, а сон у всей команды будет чуточку, но спокойней.

Рефакторинг очень старого кода

Вопрос тяжёлый, очень тяжёлый. Ситуация: есть огромное количество ужасных строк кода, которые достались вам от старых разработчиков (возможно, этими старыми разработчиками были вы несколько лет назад, ещё до того, как научились писать всё правильно и сразу). Код приходится поддерживать. То там, то тут возникают костыли и дублирования, энтропия растёт. С каждым днём всё больше хочется выкинуть всё и переписать с нуля. В такой момент нужно очень хорошо подумать о рисках. Да, вполне вероятно, что в перспективе такая деятельность будет полезна. Но в какой именно перспективе и насколько полезна? Скорее всего, в процессе большого рефакторинга или переписывания отдельных частей вы замените старый работающий говнокод новым, идеально написанным кодом, но с багами. И вовсе не из-за того, что вы плохой программист и пишете плохо. Просто вы можете не знать этот код в достаточной мере. Вы можете не знать, почему автор написал всё именно так, а ведь причины могли быть. Иногда приходится писать очень странный и кривой код. Я могу придумать очень много примеров: подавление хитрых оптимизаций процессора, подстройка под баги сторонней библиотеки, подавление каких-нибудь многопоточных косяков и т. д. Я не говорю, что нельзя все эти проблемы решить нормально. Просто иной раз при переписывании казалось бы абсурдного кода на нормальный появляются баги. Да, можно было всё сделать нормально, но вы можете просто не осознать всё величие шалаша из костылей вместо палок, если не узнаете у автора кода, почему он написал именно так (а подобная возможность предоставляется далеко не всегда). Будьте осторожны, когда переписываете старый код, который понимаете не до конца (а особенно, если думаете, что понимать там нечего).

А когда рефакторить-то?

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

  • Нечего делать. Бывают спокойные времена простоя, когда все важные задачи закрыты, а новых пока не поставлено. Ну, не то чтобы совсем нечего делать, но определённое количество свободного времени есть. Потратьте его на улучшение кода. Дайте сущностям понятные имена, избавьтесь от дублирования, перепишите неудачный кусок архитектуры. Хоть нового функционала и не добавляется, но вы вкладываете свою лепту в душевное спокойствие разработчиков, которые будут продолжать проект. Поверьте, это важно.
  • Каждодневные страдания. А бывает так, что есть кусок проекта, который заставляет вас тяжело вздыхать каждый день. А из-за соседних столов слышатся тяжёлые вздохи ваших коллег. Конечно, хоть и релиз и не завтра, но важных задач хватает. Тем не менее, за неделей проходит неделя, а смотреть на этот кусок проекта всё грустнее. Скажите себе: «Хватит это терпеть!». Если бизнес-план составляет начальник, то объясните ему, что этот код просто необходимо переписать. Если работаете на заказчика, то убедите его, что потраченная на рефакторинг неделя позволит сэкономить много времени на разработку в будущем. Если работаете на пользователей, то примите решение о том, что лучше бы этим пользователям в этот раз подождать релиза на недельку больше, но зато потом наслаждаться стабильным ПО и регулярными обновлениями. Да, договориться со всеми и с самим собой не всегда просто, но вы уж постарайтесь.
  • Проблема запоздалого рефакторинга. Не стоит абсолютизировать правило про слишком ранний рефакторинг. Некоторые считают так: «Я вот сейчас наулучшаю чего-нибудь, а оно не пригодится — обидно же будет». Нужно понимать, что в ядре программы вполне могут быть важные части, которым лучше бы быть написанными хорошо. Помните, что чем позже вы проводите рефакторинг — тем выше его цена, ведь вы потратите больше времени и сил на переписывание. Критические базисные вещи (которые используются по всему проекту) должны быть в максимально хорошей форме постоянно. Будет просто прекрасно, если в вашей команде будет работать тезис «Рефакторинг не опаздывает. Он приходит строго тогда, когда считает нужным».
  • Встреча с монстром. Вы начинаете пилить новый функционал, который должен использовать старый кусок проекта, который выглядит как настоящий монстр: вам становится страшно только при взгляде на внешний интерфейс. Если время позволяет, то поправьте сперва базовую часть кода, чтобы потом сосредоточиться на новом функционале и не отвлекаться на то, чтобы вбить пяток костылей ради повторного использования кода.
  • Разумный перфекционизм. Заметили плохой кусок кода? Хочется его поправить? Очень хочется его поправить? Ну, если прям очень хочется, то можно. Но обратите внимание на слово «разумный». Соотносите время, потраченное на рефакторинг, с выгодой от улучшения кода. Не стоит срывать сроки и зарываться в бесконечные улучшения. Однако если своевременно и в меру заниматься рефакторингом, то проекту от этого станет только лучше.

Вместо заключения

Всё вышеперечисленное является чисто субъективным обобщением опыта работы над рядом проектов. Разумеется, я покрыл далеко не все жизненные ситуации. В каждой команде свои требования к коду, свой бизнес-план и свои правила. Уверен, что у многих найдётся пяток историй из серии «А вот у меня был случай, когда все эти советы не работают». Это абсолютно нормально, так и должно быть. Нет универсальной серебряной пули для определения количества усилий на улучшение кода («Мы будем каждый день 47 минут 23 секунды заниматься рефакторингом — и всё у нас будет хорошо»). Вам нужно исходя из собственного опыта в вашем конкретном проекте, в вашей конкретной команде попытаться найти золотую середину между написанием нового кода и улучшением старого. Я агитирую только за то, чтобы ко всему было рациональное отношение без фанатизма («Зачем улучшать код, нового функционала от этого не появится» / «Нужно срочно весь код сделать идеальным, чтобы потом с ним можно было нормально работать»). Подходите разумно к распределению времени на работу над существующим кодом — и всё у вас будет хорошо.

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

Рефакторинг — Википедия

Рефа́кторинг (англ. refactoring), или перепроектирование кода, переработка кода, равносильное преобразование алгоритмов — процесс изменения внутренней структуры программы, не затрагивающий её внешнего поведения и имеющий целью облегчить понимание её работы[1][2]. В основе рефакторинга лежит последовательность небольших эквивалентных (то есть сохраняющих поведение) преобразований. Поскольку каждое преобразование маленькое, программисту легче проследить за его правильностью, и в то же время вся последовательность может привести к существенной перестройке программы и улучшению её согласованности и чёткости.

Цели рефакторинга

Цель рефакторинга — сделать код программы более легким для понимания; без этого рефакторинг нельзя считать успешным.

Рефакторинг следует отличать от оптимизации производительности. Как и рефакторинг, оптимизация обычно не изменяет поведение программы, а только ускоряет её работу. Но оптимизация часто затрудняет понимание кода, что противоположно рефакторингу[3].

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

Причины применения рефакторинга

Рефакторинг нужно применять постоянно при разработке кода. Основными стимулами его проведения являются следующие задачи:

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

Признаки плохого кода

Во многом при рефакторинге лучше полагаться на интуицию, основанную на опыте. Тем не менее имеются некоторые видимые проблемы в коде (англ. code smells), требующие рефакторинга:

  1. дублирование кода;
  2. длинный метод;
  3. большой класс;
  4. длинный список параметров;
  5. «жадные» функции — это метод, который чрезмерно обращается к данным другого объекта;
  6. избыточные временные переменные;
  7. классы данных;
  8. несгруппированные данные.

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

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

Рефакторинг изначально не предназначен для исправления ошибок и добавления новой функциональности, он вообще не меняет поведение программного обеспечения[3] и это помогает избежать ошибок и облегчить добавление функциональности. Он выполняется для улучшения понятности кода или изменения его структуры, для удаления «мёртвого кода» — всё это для того, чтобы в будущем код было легче поддерживать и развивать. В частности, добавление в программу нового поведения может оказаться сложным с существующей структурой — в этом случае разработчик может выполнить необходимый рефакторинг, а уже затем добавить новую функциональность.

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

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

Наиболее употребимые[4] методы рефакторинга:

Изменение сигнатуры метода (Change Method Signature)

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

Инкапсуляция поля (Encapsulate field)

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

Выделение метода заключается в выделении из длинного и/или требующего комментариев кода отдельных фрагментов и преобразовании их в отдельные методы, с подстановкой подходящих вызовов в местах использования. В этом случае действует правило: если фрагмент кода требует комментария о том, что он делает, то он должен быть выделен в отдельный метод. Также правило: один метод не должен занимать более чем один экран (25-50 строк, в зависимости от условий редактирования), в противном случае некоторые его фрагменты имеют самостоятельную ценность и подлежат выделению. Из анализа связей выделяемого фрагмента с окружающим контекстом делается вывод о перечне параметров нового метода и его локальных переменных.

Перемещение метода (Move Method)

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

Замена условного оператора полиморфизмом (Replace Conditional with Polymorphism)

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

Основные принципы:

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

Проблемы, возникающие при проведении рефакторинга

  • проблемы, связанные с базами данных;
  • проблемы изменения интерфейсов;
  • трудности при изменении дизайна.

Средства автоматизации рефакторинга

Технические критерии для инструментов рефакторинга:

  • базы данных программы;
  • деревья синтаксического разбора;
  • точность.

Практические критерии для инструментов рефакторинга:

  • скорость;
  • отмена модификаций;
  • интеграция с другими инструментами.

См. также

Примечания

Литература

  • Фаулер М., Бек К., Брант Д., Робертс Д., Апдайк У. Рефакторинг: улучшение существующего кода = Refactoring: Improving the Design of Existing Code (2000). — Спб: Символ-Плюс, 2009. — 432 с. — 3000 экз. — ISBN 5-93286-045-6.
  • Скотт В. Эмблер, Прамодкумар Дж. Садаладж. Рефакторинг баз данных: эволюционное проектирование = Refactoring Databases: Evolutionary Database Design (Addison-Wesley Signature Series). — М.: «Вильямс», 2007. — 368 с. — ISBN 0-321-29353-3.
  • Джошуа Кериевски. Рефакторинг с использованием шаблонов = Refactoring to Patterns. — Вильямс, 2008. — 400 с. — ISBN 5-93286-045-6.

Ссылки

Рефакторинг — это не задача в Backlog / Блог компании Инфопульс Украина / Хабр

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

Когда начинается новый проект — его код чист и прекрасен. Самое время проектировать красивые абстракции, писать хорошие интерфейсы и профессиональные реализации. Жизнь прекрасна! Наш проект тоже.

Мы продолжаем добавлять функционал, всё идёт гладко. Потом в некоторый момент нам приходится немного срезать угол, чуть-чуть свернуть с намеченной дорожки, добавить совсем-совсем маленькую обработку одного частного случая… Нет-нет, никаких «костылей»! Просто немного необходимого кода, приближающего красивую теорию к работающей практической реализации. Ничто не предвещает беды и разработка идёт достаточно бодро.

Тем ни менее, на полотне нашей идеальной картины кода всё-же возникают небольшие кляксы. Некоторые люди называют их «техническим долгом». Это не означает, что вы действительно кому-то что-то задолжали: это просто не очень хороший код. Но он как-то работает, решает свои задачи.

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

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

Эти новые проблемные места (в дополнение к старым) тормозят нас всё больше и больше. Мы осознаём наличие проблем, но спешка в плане решения текущих задач не позволяет сфокусироваться на чём-либо ещё. Мы вынуждены работать больше, просто ради сохранения прежней скорости.

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

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

Важность проблем теперь видна невооруженным глазом. И их нельзя исправить, просто выбросив всё и начав проект с нуля. Нам нужно выполнить много задач по рефакторингу кода, а на эти задачи нам нужно время, которое придётся просить у заказчика. Часто это время нам не будет выделено: мы ведь просим время для того, чтобы исправить собственный код, на разработку которого уже выделялось время ранее и о готовности которого мы же ранее сами и заявляли.

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

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


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

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


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


Момент осознания полезности непрерывного рефакторинга не так далёк, как вам может показаться. Некоторые люди начинали замечать его уже к концу того же спринта, в котором они начали использовать данный подход. Силы непрерывности и инкрементальности процесса дают о себе знать очень быстро. С какого-то момента на выполнение новой задачи с рефакторингом начинает уходить МЕНЬШЕ времени, чем на выполнение этой же задачи без рефакторинга (в силу потраченного ранее времени на улучшения сопутствующего кода).

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

Так что рефакторинг — это не задача в Backlog, это часть каждой задачи в нём.

Практика рефакторинга в больших проектах / Хабр

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

Итак, представьте себе следующую ситуацию. Так уж случилось, что вам надо отрефакторить очень большой кусок кода, целую подсистему. Строк, эдак, на 200К. Причем рефакторинг явно выглядит очень крупным, затрагивающим базовые концепции, по которым построена ваша подсистема. Фактически надо переписать всю архитектуру, сохранив бизнес логику. Такое бывает, если, например, вы сделали один проект и у вас впереди новый, и вы хотите в нём исправить все ошибки прошлого. Допустим, по первым прикидкам, на рефакторинг надо месяца 2, не меньше. В процессе рефакторинга всё должно работать, в том числе нельзя мешать другим программистам добавлять новые фичи и чинить баги в подсистеме. Часто такой рефакторинг бывает насколько сложен, что совершенно невозможно замерджить старый код в новый, а также невозможно выкатить результат по частям. Фактически вам надо заменить двигатель самолёта на лету.

Примеры из практики, как моей, так и моих коллег:

  • Переделать всю работу с базой данных с чистого JDBC на Hibernate.
  • Переделать архитектуру сервиса с отсылки-приёмки сообщений на удалённый вызов процедур (RPC).
  • Полностью переписать подсистему трансляции XML файлов в рантайм объекты.

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

Подготовка к рефакторингу

  • Разбить рефакторинг на части, если это возможно. Если возможно, то нет проблем. Все остальные советы про то, что надо делать, если это не удалось.
  • Постарайтесь выбрать период, когда активность добавления новых фичей в подсистему будет минимальна. Например, удобно переделывать бэкенд, в то время как все усилия команды сосредоточены на фронтенде.
  • Хорошо ознакомьтесь с кодом, зачем он вообще нужен. Какая архитектура заложена в основании подсистемы, какие стандартные подходы, которые там использовались. Чётко определить для себя, в чём заключается новая концепция, и что конкретно вы хотите поменять. Должна быть измеряемая финальная цель.
  • Определить область кода, которую захватит рефакторинг. По возможности изолируйте её в отдельный модуль/в отдельную директорию. Это в будущем будет очень полезно.
  • Рефакторинг без тестов делать очень опасно. У вас должны быть тесты. Как без них жить я не знаю.
  • Запустите тесты с подсчётом покрытия, это даст много информации для размышления.
  • Почините сломанные тесты, которые относятся к искомой подсистеме.
  • Анализируя информацию о покрытии методов можно найти и удалить неиспользуемый код. Как ни странно, такого часто бывает до 10-15%. Чем больше кода удастся удалить, тем меньше рефакторить. Профит!
  • По покрытию определите, какие части кода не покрыты. Надо дописать недостающие тесты. Если юнит тесты писать долго и утомительно, напишите, хотя бы, высокоуровневые smke тесты.
  • Постарайтесь довести покрытие до 80-90% осмысленного кода. Не надо стараться покрыть все. Убьёте много времени с малой пользой. Покройте хотя бы основной путь выполнения.
Рефакторинг

  • Оберните вашу подсистему интерфейсом. Переведите весь внешний код на использование этого интерфейса. Это не только форсирует применение хороших практик программирования, но и упростит рефакторинг.
  • Убедитесь, что ваши тесты тестируют интерфейс, а не реализацию.
  • Сделайте возможность при старте указывать, какую реализацию этого интерфейса использовать. Это возможность нужно поддержать и в тестах и в продакшне.
  • Записать ревизию системы контроля версий, на которой началось написание новой имплементации. С этой секунды каждый коммит в вашу старую подсистему – ваш враг.
  • Напишите новую реализацию интерфейса вашей подсистемы. Иногда можно начинать с нуля, иногда можно применить излюбленый метод — copy&paste. Писать её надо в отдельном модуле. Периодически гоняйте тесты на новой реализации. Ваша цель — сделать так, чтобы все тесты проходили успешно на новой и старой реализации.
  • Не надо ждать, когда вы всё полностью напишите. Заливайте код в репозиторий как можно чаще, оставляя включённой старую реализацию. Если долго держать код в загашнике, можно огрести проблем с тем, что другие люди рефакторят модули, которые вы используете. Простое переименование метода может доставить вам много проблем.
  • Не забудьте написать тесты, специфичные для новой имплементации, если такие имеются.
  • После того как всё напишите, посмотреть историю SVN в папке со старым кодом, чтобы найти, что там менялось за время вашего рефакторинга. Надо перенести эти изменения в новый код. По идее, если вы что-то забыли перенести, тесты должны это поймать.
  • После этого, все тесты должны проходить как со старой, так и с новой подсистемой.
  • Сразу после того, как вы убедились в стабильности новой версии вашего модуля, переключайте на него тесты и продакшн. Блокируйте коммиты в старую подсистему. Всеми силами старайтесь минимизировать время существования двух подсистем в параллель.
  • Подождите неделю или две, соберите всё багло, зачините его и смело удаляйте старую подсистему.

Дополнительные советы

  • Все новые фичи, создаваемые параллельно с рефакторингом, должны покрываться тестами на 100%. Это нужно для того, чтобы при переключении на новую имплементацию, упали тесты и сигнализировали о том, что в новой имплементации не хватает кода из старой.
  • Любой фикс бага надо делать по принципу — сначала пишем тест, который будет воспроизводить проблему и падать, потом его чиним. Причины те же самые.
  • Если вы используете систему а-ля TeamCity, на время рефакторинг сделайте отдельный билд, где будут гоняться все тесты на новой подсистеме. Автоматический билд делает ваш новый, ещё не используемый, код «официальным». К нему начинают применяться все те же политики и правила, что и ко всему остальному.
  • Часто бывает так, что вы не знаете, исправили ли вы всё, что хотели в старом коде на новую архитектуру. Например, вы не знаете, не использует ли ваш код где-то прямое JDBC подключение, вместо Hibernate. Или вдруг где-то проскользнуло сообщение, а не RPC вызов. Для обнаружения таких мест надо придумать способ сделать старую методу неработающей. Т.е. сломать её в тестах. Например, сломать систему доставки сообщений или подсунуть системе неработающий JDBC драйвер. Практика показывает, что таким образом обычно находится как минимум штук 5 забытых и не исправленных мест.
  • Поговорите с другими программистами, держите их в курсе вашего прогресса. Если они будут знать, что вам осталась неделя, они иногда могут подвинуть свои задачи до времени выхода новой версии вашей подсистемы. Не надо будет сливать изменения.

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

Рефакторинг — Википедия. Что такое Рефакторинг

Рефа́кторинг (англ. refactoring), или перепроектирование кода, переработка кода, равносильное преобразование алгоритмов — процесс изменения внутренней структуры программы, не затрагивающий её внешнего поведения и имеющий целью облегчить понимание её работы[1][2]. В основе рефакторинга лежит последовательность небольших эквивалентных (то есть сохраняющих поведение) преобразований. Поскольку каждое преобразование маленькое, программисту легче проследить за его правильностью, и в то же время вся последовательность может привести к существенной перестройке программы и улучшению её согласованности и чёткости.

Цели рефакторинга

Цель рефакторинга — сделать код программы более легким для понимания; без этого рефакторинг нельзя считать успешным.

Рефакторинг следует отличать от оптимизации производительности. Как и рефакторинг, оптимизация обычно не изменяет поведение программы, а только ускоряет её работу. Но оптимизация часто затрудняет понимание кода, что противоположно рефакторингу[3].

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

Причины применения рефакторинга

Рефакторинг нужно применять постоянно при разработке кода. Основными стимулами его проведения являются следующие задачи:

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

Признаки плохого кода

Во многом при рефакторинге лучше полагаться на интуицию, основанную на опыте. Тем не менее имеются некоторые видимые проблемы в коде (англ. code smells), требующие рефакторинга:

  1. дублирование кода;
  2. длинный метод;
  3. большой класс;
  4. длинный список параметров;
  5. «жадные» функции — это метод, который чрезмерно обращается к данным другого объекта;
  6. избыточные временные переменные;
  7. классы данных;
  8. несгруппированные данные.

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

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

Рефакторинг изначально не предназначен для исправления ошибок и добавления новой функциональности, он вообще не меняет поведение программного обеспечения[3] и это помогает избежать ошибок и облегчить добавление функциональности. Он выполняется для улучшения понятности кода или изменения его структуры, для удаления «мёртвого кода» — всё это для того, чтобы в будущем код было легче поддерживать и развивать. В частности, добавление в программу нового поведения может оказаться сложным с существующей структурой — в этом случае разработчик может выполнить необходимый рефакторинг, а уже затем добавить новую функциональность.

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

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

Наиболее употребимые[4] методы рефакторинга:

Изменение сигнатуры метода (Change Method Signature)

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

Инкапсуляция поля (Encapsulate field)

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

Выделение метода заключается в выделении из длинного и/или требующего комментариев кода отдельных фрагментов и преобразовании их в отдельные методы, с подстановкой подходящих вызовов в местах использования. В этом случае действует правило: если фрагмент кода требует комментария о том, что он делает, то он должен быть выделен в отдельный метод. Также правило: один метод не должен занимать более чем один экран (25-50 строк, в зависимости от условий редактирования), в противном случае некоторые его фрагменты имеют самостоятельную ценность и подлежат выделению. Из анализа связей выделяемого фрагмента с окружающим контекстом делается вывод о перечне параметров нового метода и его локальных переменных.

Перемещение метода (Move Method)

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

Замена условного оператора полиморфизмом (Replace Conditional with Polymorphism)

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

Основные принципы:

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

Проблемы, возникающие при проведении рефакторинга

  • проблемы, связанные с базами данных;
  • проблемы изменения интерфейсов;
  • трудности при изменении дизайна.

Средства автоматизации рефакторинга

Технические критерии для инструментов рефакторинга:

  • базы данных программы;
  • деревья синтаксического разбора;
  • точность.

Практические критерии для инструментов рефакторинга:

  • скорость;
  • отмена модификаций;
  • интеграция с другими инструментами.

См. также

Примечания

Литература

  • Фаулер М., Бек К., Брант Д., Робертс Д., Апдайк У. Рефакторинг: улучшение существующего кода = Refactoring: Improving the Design of Existing Code (2000). — Спб: Символ-Плюс, 2009. — 432 с. — 3000 экз. — ISBN 5-93286-045-6.
  • Скотт В. Эмблер, Прамодкумар Дж. Садаладж. Рефакторинг баз данных: эволюционное проектирование = Refactoring Databases: Evolutionary Database Design (Addison-Wesley Signature Series). — М.: «Вильямс», 2007. — 368 с. — ISBN 0-321-29353-3.
  • Джошуа Кериевски. Рефакторинг с использованием шаблонов = Refactoring to Patterns. — Вильямс, 2008. — 400 с. — ISBN 5-93286-045-6.

Ссылки

Код с душком (рефакторинг М. Фаулера) / Хабр

Всем привет.

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

Зачем? Когда и как?

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

Код с душком

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

  1. Дублирование кода.
  2. Длинный метод.
  3. Большой класс.
  4. Длинный список параметров.
  5. Расходящиеся модификации.

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

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

    Метод интересуется больше не тем классом, в котором находится, а другим.
  8. Группы данных.

    Похожие группы данных, в разных частях кода.
  9. Одержимость элементарными типами.
  10. Операторы типа switch.

    Незабываем про ООП.
  11. Параллельные иерархии наследования.

    Дублированный код.
  12. Ленивый класс.

    Не используемый или содержащий мало методов (оставшийся после рефакторинга/проектирования).
  13. Теоретическая общность.

    Переизбыток абстракциями тоже вреден.
  14. Временное поле.

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

    Глубокая последовательность вызовов до необходимой информации, через объекты по иерархии классов.
  16. Посредник.

    Большую часть методов класс делегирует другому классу.
  17. Неуместная близость.

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

    Дублирование логики.
  19. Неполнота библиотечного класса.

    Не бойтесь расширять функционал библиотечных классов: extension методы или декорировать объект библиотечного класса.
  20. Классы данных.

    Делите на логические единицы. Доступ на изменение данных должен быть осмысленным.
  21. Отказ от наследства.

    Если наследнику нужна лишь малая часть информации (данных, методов) о родителе.
  22. Комментарии.

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

Я не привожу решения этих проблем, поскольку за базу можно взять, то что описано в книге. А с учётом опыта, что-то своё.
Читайте далее, техника: Составление методов.

Какой профит.

Простота в поддержке и понимании кода, а также в написании тестов.

Послесловие

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

Что вам нужно знать об этом

Понимание рефакторинга кода: взгляд тестировщика

Термин «рефакторинг» в основном используется для обозначения необходимой очистки / редизайна кода.

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

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

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

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

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

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

Необходимость рефакторинга кода

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

  1. Код пахнет
  2. Технический долг
  3. Подход гибкой разработки программного обеспечения и т. Д.

Мы обсудим эти моменты подробно в следующих разделах.

# 1) Код Запахи:

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

Ниже приведены некоторые общие запахи кода:

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

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

# 2) Технический долг:

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

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

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

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

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

Подробнее => Что такое технический отдел

# 3) Следуя подходу гибкой разработки программного обеспечения:

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

Эта взаимосвязь изображена на диаграмме ниже

Рекомендуется прочитать => Основные инструменты анализа кода

Почему QA должен знать о рефакторинге?

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

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

# 1) Для модульных тестировщиков / разработчиков

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

# 2) Для тестировщиков

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

  • Для тестировщика рефакторинг кода примерно означает = углубленное тестирование + регрессионное тестирование. Глубокое тестирование должно включать все существующие пользовательские потоки, чтобы гарантировать, что все функции работают как раньше.Регрессионное тестирование всего приложения (или затронутых областей) необходимо, чтобы гарантировать, что обновление модуля не приведет к непреднамеренному нарушению функциональности других модулей.
  • Пользовательские приемочные тесты будут важны, и эти тесты необходимо пройти, прежде чем сборка будет объявлена ​​готовой к выпуску.
  • Кроме того, любые другие необходимые тесты, такие как нагрузочные тесты, тест безопасности и т. Д., Также должны быть реализованы по мере необходимости.

# 3) Инженеры по тестированию автоматизации

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

Это может произойти по следующим причинам:

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

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

Как разработчик тестов автоматизации, инженеры по автоматическому тестированию также должны мыслить как разработчики и стремиться создавать чистый и простой в обслуживании код. Большинство IDE, таких как IntelliJ IDEA, Eclipse и т. Д., Включают встроенное меню рефакторинга с часто используемыми методами рефакторинга для удобства.

Ниже приведен снимок экрана меню рефакторинга в IntelliJ IDEA (Community Edition).

# 4) Для руководителей тестирования / руководителей качества

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

Примеры из практики

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

Пример # 1

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

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

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

Пример № 2

Задача : Рефакторинг существующей хранимой процедуры для облегчения масштабирования приложения.

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

Теперь компания хотела продавать это приложение как «Программное обеспечение как услуга» (SaaS) с ожидаемым объемом одновременных сеансов в 300 изначально.

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

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

Проблемы:

# 1) Менеджер проекта / Аналитик продукта

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

# 2) Для разработчиков

  • Отсутствие четких требований и бизнес-правил.
  • Очистка кода без потери работоспособности.
  • Неизвестные затронутые области и / или зависимости кода.
  • Невозможно предоставить конкретные оценки времени разработки.
  • Необходимо создать новые модульные тесты.

# 3) Для тестировщиков

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

# 4) Заинтересованные стороны

  • Отсутствие четко задокументированных требований и / или потоков пользователей + сжатые сроки = более высокий риск отказа.

Подход, которого придерживается группа для снижения рисков и решения проблем :

(i) Команда следовала совместному подходу для сбора требований : Менеджер проекта / Аналитик продукта и тестировщики работали в тесном сотрудничестве с внутренним подразделением пользователям, чтобы понять и задокументировать основные функции и поток пользователей.

Разработчики также рассмотрели код и добавили соответствующую информацию в документ с требованиями. Это было сделано до дня старта спринта.

(ii) Была создана альтернативная тестовая среда для проверки вносимых изменений. : Назовем эти среды Gamma и Phi. У Gamma будет старый код, а у Phi всегда будет развернута последняя реорганизованная хранимая процедура.

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

Команда предоставила требования для альтернативной тестовой среды, которая была предоставлена ​​до даты начала спринта.

(iii) Конечные пользователи и заинтересованные стороны, участвовавшие в тестировании на раннем этапе : любые очевидные проблемы были обнаружены и сообщены на раннем этапе, что дало группе больше времени для развертывания и тестирования необходимого исправления.

(iv) Определение критериев выхода и их соблюдение: Критерии выхода были определены на начальных этапах планирования — проверено 80% пользовательских потоков, критических ошибок нет, демонстрация и подписание заинтересованных сторон перед выпуском.

(v) Установка ориентировочной даты выпуска: Установка согласованной даты выпуска и мотивация команды работать над общей конечной точкой. Основываясь на масштабе проекта, команда рекомендовала использовать трехнедельный спринт вместо обычного двухнедельного, чтобы дать команде достаточно времени для выполнения проекта.

Заключение

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

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

Для тестировщиков рефакторинг кода примерно означает = углубленное тестирование + регрессионное тестирование.

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

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

Об авторе: Это информативное руководство написано Нехой Б. В настоящее время она работает менеджером по обеспечению качества и специализируется на руководстве и управлении внутренними и внешними группами контроля качества.

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

.

Рефакторинг кода | Что такое рефакторинг кода

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

Говорят, не чинить, пока не сломается. Мы говорим обновить его, пока он не устарел.

А вот как:

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

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

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

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

Почему так важен рефакторинг вашего кода?

Теперь, когда мы выяснили, что такое рефакторинг, возникает вопрос: когда нужно проводить рефакторинг? Основные причины для рефакторинга кода следующие:

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

  • Для повышения производительности продукта

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

  • Чтобы сэкономить время и деньги в будущем

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

  • Для сокращения вашего технического долга

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

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

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

  • Если больше нет поддержки

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

  • Когда происходит резкий технологический скачок

Часто перспективная технология сразу устаревает. Winamp, ICQ, Internet Explorer были заменены новичками рынка, которые, без сомнения, тоже пострадают, когда появятся более продвинутые альтернативы. Программное обеспечение, как ничто другое, чувствительно к постоянно развивающемуся рынку, поэтому частые реинжиниринги обязательны для каждой компании, желающей оставаться актуальной.

  • Если программное обеспечение некорректно

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

Лучшие практики: рефакторинг в Agile

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

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

  • Не торопитесь, шаг за шагом

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

  • Перейти к разработке через тестирование

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

  • Всегда рефакторинг перед внедрением новых функций.

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

  • Выберите автоматизацию рефакторинга

Как и почти все, рефакторинг выполняется намного быстрее и эффективнее, если выполняется автоматически. К счастью, ряд IDE (интегрированных сред разработки) предлагают встроенную поддержку автоматического рефакторинга. Одними из самых популярных являются Eclipse, IntelliJ IDEA, VSCode для Frontend и Visual Studio IDE для.Сеть.

  • Рефакторинг не означает добавление новых функций.

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

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

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

.

Что такое рефакторинг кода? Как рефакторинг разрешает технический долг — BMC Blogs

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

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

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

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

Определение рефакторинга кода

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

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

Важность рефакторинга кода

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

Эксперты говорят, что цель рефакторинга кода — превратить грязный код в чистый, что снижает общий технический долг проекта.

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

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

Некоторые типы грязного кода включают:

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

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

Когда проводить рефакторинг

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

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

  • Рефакторинг в соответствии с Правилом 3:
    • Когда вы что-то делаете в первый раз, просто сделайте это, даже если это грязный код, чтобы программное обеспечение работало должным образом.
    • Во второй раз, когда вы делаете подобное изменение, вы можете сделать это снова тем же способом — вы узнаете это немного лучше, поэтому вы можете действовать быстрее, но код все равно не будет идеально чистым.
    • Когда вы столкнетесь с этим изменением в третий раз, начните рефакторинг.
  • Рефакторинг во время проверки кода — последний шанс очистить код, прежде чем он будет запущен. Попробуйте провести обзор с двумя людьми, чтобы вы могли быстро исправить низко висящие плоды, а затем лучше оценить, какие сложные области изменения кода стоят потраченного времени.
  • Рефакторинг в регулярные интервалы времени. Это не должно означать посвящать этому целый день, а скорее добавить это в свою рутину — потратить последний час рабочего дня на рефакторинг. (Бонус: упреждающий рефакторинг означает, что вашему менеджеру и вашей команде не нужно выделять для этого дополнительное время.)

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

Способы рефакторинга

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

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

Какие методы использовать, часто зависит от проблем в вашем коде. Вот несколько распространенных техник:

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

Контрольный список рефакторинга

Что является хорошей точкой остановки для чистого кода? Этот контрольный список может помочь вам определить, когда ваш код чист:

  • Другим программистам это очевидно. Это может быть так же просто, как создание более четких структур для именования, классов и методов или улучшение более сложных алгоритмов.
  • Не содержит дубликатов. Вероятность человеческой ошибки увеличивается каждый раз, когда вам приходится удваивать изменения
  • Он содержит минимальное количество движущихся частей, например количество классов. Меньше помнить — значит меньше поддерживать и меньше убирать.
  • Проходит все тесты. Код грязный, даже если большая его часть проходит тесты.
  • Легче в обслуживании. Вы будете тратить меньше времени на будущие улучшения.

Преимущества рефакторинга

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

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

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

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

Эти сообщения являются моими собственными и не обязательно отражают позицию, стратегию или мнение BMC.

Обнаружили ошибку или есть предложение? Сообщите нам об этом по электронной почте [email protected].

.

Рефакторинг исходного кода в Visual Studio Code

Рефакторинг исходного кода может улучшить качество и удобство сопровождения вашего проекта за счет реструктуризации кода без изменения поведения во время выполнения. Visual Studio Code поддерживает операции рефакторинга (рефакторинги), такие как Extract Method и Extract Variable, для улучшения базы кода из редактора.

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

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

Действия кода = Быстрые исправления и рефакторинг

В VS Code, Code Actions могут обеспечивать как рефакторинг, так и быстрые исправления обнаруженных проблем (выделены зелеными волнистыми линиями).Доступное действие кода обозначается лампочкой рядом с исходным кодом, когда курсор находится на волнистой линии или выделенной текстовой области. Щелкнув по лампочке Code Action или используя команду Quick Fix ⌘. (Windows, Linux Ctrl +.) Отобразит быстрые исправления и рефакторинги.

Если вы просто хотите увидеть рефакторинг без быстрых исправлений, вы можете использовать команду Refactor (⌃⇧R (Windows, Linux Ctrl + Shift + R)).

Примечание: Если вы предпочитаете не видеть лампочку Code Action в редакторе, вы можете отключить лампочки с помощью редактора .лампочка. включить настройку . Вы по-прежнему можете открыть Быстрые исправления с помощью команды Быстрое исправление и ⌘. (Windows, Linux Ctrl +.) Сочетание клавиш.

Действия по рефакторингу

Выберите исходный код, который нужно извлечь, а затем щелкните лампочку в желобе или нажмите (⌘. (Windows, Linux Ctrl +.)), Чтобы просмотреть доступные варианты рефакторинга. Фрагменты исходного кода могут быть извлечены в новый метод или в новую функцию в различных областях. Во время рефакторинга экстракта вам будет предложено ввести значащее имя.

Служба языка

TypeScript обеспечивает рефакторинг из Extract в const для создания новой локальной переменной для текущего выбранного выражения:

При работе с классами можно также извлечь значение в новое свойство.

Обозначение переименования

Переименование — это обычная операция, связанная с рефакторингом исходного кода, и VS Code имеет отдельную команду Rename Symbol (F2). Некоторые языки поддерживают переименование символов в файлах. Нажмите F2, а затем введите новое желаемое имя и нажмите Enter.Все использования символа будут переименованы в файлах.

Связывание клавиш для действий кода

Команда editor.action.codeAction позволяет настраивать привязки клавиш для определенных действий кода. Эта привязка клавиш, например, запускает функцию Extract. рефакторинг Code Actions:

.

  {
  "ключ": "ctrl + shift + r ctrl + e",
  "command": "editor.action.codeAction",
  "args": {
    "kind": "refactor.extract.function"
  }
}  

Типы действий

Code Action задаются расширениями с использованием расширенного API CodeActionProvided .Виды являются иерархическими, поэтому «kind»: «refactor» покажет все действия кода рефакторинга, тогда как «kind»: «refactor.extract.function» покажет только рефакторинги Extract function .

Используя указанную выше привязку клавиш, если доступно только одно действие кода "refactor.extract.function" , оно будет применено автоматически. Если доступно несколько Extract function Code Actions, мы вызываем контекстное меню для их выбора:

Вы также можете контролировать, как и когда автоматически применяются действия кода, используя аргумент apply :

  {
  "ключ": "ctrl + shift + r ctrl + e",
  "команда": "редактор.action.codeAction ",
  "args": {
    "kind": "refactor.extract.function",
    "применить": "первый"
  }
}  

Допустимые значения для «применить» :

  • «первый» — Всегда автоматически применять первое доступное действие кода.
  • "ifSingle" — По умолчанию. Автоматически применять действие кода, если доступно только одно. В противном случае покажите контекстное меню.
  • «никогда» — Всегда показывать контекстное меню действия кода, даже если доступно только одно действие кода.

Когда привязка клавиш Code Action настроена с «предпочтительный»: истинный , отображаются только предпочтительные быстрые исправления и рефакторинги. Предпочтительное быстрое исправление устраняет основную ошибку, в то время как предпочтительный рефакторинг является наиболее распространенным вариантом рефакторинга. Например, хотя может существовать несколько рефакторингов refactor.extract.constant , каждый из которых извлекается в разную область видимости в файле, предпочтительным рефакторингом refactor.extract.constant является тот, который извлекается в локальную переменную.

Эта привязка клавиш использует «предпочтительный»: true для создания рефакторинга, который всегда пытается извлечь выбранный исходный код в константу в локальной области:

  {
  "ключ": "shift + ctrl + e",
  "command": "editor.action.codeAction",
  "args": {
    "kind": "refactor.extract.constant",
    "предпочтительный": правда,
    "применить": "если сингл"
  }
}  

Расширения с рефакторингом

Вы можете найти расширения, поддерживающие рефакторинг, в VS Code Marketplace.Вы можете перейти в представление расширений (⇧⌘X (Windows, Linux Ctrl + Shift + X)) и ввести «рефакторинг» в поле поиска. Затем вы можете отсортировать их по количеству установок или рейтингам, чтобы узнать, какие расширения популярны.

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

Следующие шаги

Общие вопросы

Почему я не вижу лампочек, если в моем коде есть ошибки?

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

10.09.2020

.

Добавить комментарий

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