10 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Рефакторинга много не бывает

Рефакторинга много не бывает

Источник: IT-BRED.RU

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

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

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

Главенство принципов над целью

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

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

Помните мое размышление в самом начале? Это напомнило мне мантру: «Заставь это работать, сделай это правильно, сделай это быстро». Я понял, что не следовал этому порядку. Я делал все правильно, быстро, а потом делал так, чтобы это работало!

Заставьте это работать

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

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

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

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

Имейте причину для рефакторинга

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

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

Читать еще:  Как восстановить iphone 4s без itunes?

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

Посмотрите на следующий пример:

Что вы предпочитаете? Что обычно пишете в первую очередь? Конечно, класс User гораздо более расширяем, потому что он может обрабатывать не только имя и электронную почту. Он также может быть расширен дочерним классом, может быть SuperUser , который будет иметь гораздо больше методов, но все еще использует классические методы get() и set() .

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

Порядок сложности

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

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

Баланс

Недавно я слышал, что если вы скажете на собрании, «на самом деле все сводится к поиску правильного баланса», все кивнут головой на ваш бессмысленный комментарий, как будто вы сказали что-то умное. Однако, я думаю, что баланс все таки важен. Как программисты, мы должны сбалансировать качество кода, производительность и удобство обслуживания с необходимостью добиваться цели. Мы должны быть бдительными и следить за тем, чтобы обе потребности оставались на своем месте. Наш код не может быть обслуживаемым, если он не будет правильно работать. С другой стороны, трудно заставить плохой код работать правильно.

В следующий раз, когда захотите провести рефакторинг своего кода, подумайте, а стоит ли?

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

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

Рефакторинг — это переработка исходного кода программы, чтобы он стал более простым и понятным.

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

Например, вот фрагмент на Python, создающий список из строки:

При рефакторинге его можно упростить, применив конструктор списков:

Результат работы программы не изменился, но код стал проще, компактнее и понятнее.

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

Марина Демидова

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

Зачем нужен рефакторинг

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

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

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

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

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

Читать еще:  Как проверить объем памяти видеокарты?

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

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

Чем рефакторинг отличается от оптимизации

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

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

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

Когда нужно срочно улучшать код

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

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

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

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

Как делают рефакторинг

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

  1. Мёртвый код. Переменная, параметр, метод или класс больше не используются: требования к программе изменились, но код не почистили. Мёртвый код может встретиться и в сложной условной конструкции, где какая-то ветка никогда не исполняется из-за ошибки или изменения требований. Такие элементы или участки текста нужно удалить.
  2. Дублирование. Один и тот же код выполняет одно и то же действие в нескольких местах программы. Вынесите эту часть в отдельную функцию.
  3. Имена переменных, функций или классов не передают их назначение. Имена должны сообщать, почему элемент кода существует, что он делает и как используется. Если видите, что намерения программиста непонятны без комментария, — рефакторьте.

Примеры корректных имен: totalScore — переменная, означающая итоговый счёт в игре, maxWeight — максимальный вес. Для функций и методов лучше использовать глаголы, например: saveScore () — сохранить счет, setSize () — задать размер, getSpeed () — получить скорость.

  • Слишком длинные функции и методы. Оптимальный размер этих элементов — 2-3 десятка строк. Если получается больше, разделите функцию на несколько маленьких и добавьте одну общую. Пусть маленькие выполняют по одной операции, а общая функция их вызывает.
  • Слишком длинные классы. То же самое. Оптимальная длина класса — 20–30 строк. Разбейте длинный класс на несколько маленьких и включите их объекты в один общий класс.
  • Слишком длинный список параметров функции или метода. Они только запутывают, а не помогают. Если все эти параметры действительно нужны, вынесите их в отдельную структуру или класс с понятным именем, а в функцию передайте ссылку на него.
  • Много комментариев. Плохой код часто прикрывается обильными комментариями. Если почувствовали желание пояснить какой-то участок кода, попробуйте сначала его переписать, чтобы и так стал понятным. Бесполезные комментарии загромождают программу, а устаревшие и неактуальные вводят в заблуждение.
  • После каждой правки посмотрите на соседние участки кода: возможно, их тоже стоит поправить и сделать понятнее. И на те участки кода, которые давно не редактировались, — они уже могли стать некорректными.

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

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

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

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

    В чём опасности рефакторинга

    Мы всё-таки меняем рабочий код. Тут можно не только всё упростить, но и сильно напортачить. Небрежный рефакторинг может отбросить выполнение проекта на дни и недели.

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

    Рефакторьте постоянно и по чуть-чуть.

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

    Но всё равно нельзя пренебрегать усовершенствованием кода, потому что это лучший способ ускорить работу в будущем.

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

    Про рефакторинг. или переписать все заново

    Иногда (если кто-то из моих самых лучших клиентов об этом просит) я помогаю проводить глобальную ретроспективу. Глобальную, это значит не Agile-ретроспективу, которая занимает 1-3 часа и вовлекает команду, а большую ретроспективу, на 2-3 дня, в которой участвует и разработка, и бизнес, и споровождение, и дизайнеры. а еще иногда и представители клиентов или заказчиков, подрядчиков и вообще всех, кто потенциально может оказаться полезным для извлечения мудрости.

    Начальным этапом подготовки к ретроспективе является интервью 1-на-1 с участинками. ТАк вот. В продуктовых компаниях я чуть ли не в каждой слышу одну и ту же историю про. рефакторинг.

    История примерно такая:
    Была у нас система, написанная на старых технологиях. Она была не расширяемая, не масштабируемая, вся в багах (нужное подчеркнуть) и жила в таком виде 5/7/10 лет. В какой-то момент к нам пришло осознание/новый архитектор/дополнительное финансирование и мы решили наконец-то сделать все по уму. Собрались, оценили альтернативы и поняли, что за две недели/месяц/полгода мы все перепишем на современном стеке технологий и сможем наконец-то быстро добавлять новые функции/покрыть все юнит-тестами/обеспечить новые требования по производительности.

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

    Дальше были вариации.

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

    Поделитесь своими историями рефакторинга пожалуйста. Может, среди них найдется история с другой концовкой? Ну хрен с ним со сроками, хотя бы когда стало ЛУЧШЕ, чем было, пусть и дороже, чем ожидалось?

    голоса
    Рейтинг статьи
    Ссылка на основную публикацию
    Статьи c упоминанием слов: