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

2gam9hcz7vw9kp-513utyr0ezum.png

Субъективно: рефакторинг — это юношеское «заболевание». По личным наблюдениям, где-то после 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. Пользователю реально пофиг на рефакторинг, его интересует стабильность и функциональность, а рефакторинг не об этом.

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


Конец

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

© Habrahabr.ru