Прийшов час осідлати справжнього Буцефала🏇🏻Приборкай норовливого коня разом з Newxel🏇🏻Умови на сайті
×Закрыть

Когда стоит переписывать код проекта и как это донести до заказчика

Всем привет! Меня зовут Елена Шаровар, я Lead Node.js developer в Waverley Software. В этой статье мы рассмотрим ситуацию, когда программисты говорят: «Нужно все переписать», но это тяжело донести до заказчика.

Разберемся, что с этим делать и как помирить программистов и бизнес, если вы — Lead проекта, Project Manager или тот самый программист, который хочет улучшений, а вас как будто не слышат. Скорее всего, об этой проблеме вы знаете не понаслышке: такое случается то с вами, то с вашими друзьями или коллегами, и в очередной раз начинается обсуждение: а что же делать?

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

Стейкхолдеры проекта

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

  1. Инвесторы — потому что они вкладывают свои финансовые средства в этот проект и ожидают хороший Return on Investment (ROI).
  2. Product Owner — человек, который занимается управлением этого проекта и приоритизирует функционал, который вы разрабатываете. Он общается с программистами и инвесторами.
  3. Пользователи — те, кто использует ваш продукт и, скорее всего, платит за него.
  4. Программисты — да-да, они также являются стейкхолдерами, проект должен их устраивать, иначе у вас не будет программистов.

Как проект выглядит для всех, кроме программистов

Извините, но это все! Магия, которая происходит внутри, интересна только программистам. Пока программа делает то, что нужно — она устраивает владельца продукта, инвесторов и даже пользователей.

Почему программисты хотят переписать код проекта

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

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

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

Где интересы программистов и других стейкхолдеров пересекаются

Кроме функциональных характеристик, у программ есть нефункциональные характеристики. К ним относятся:

  • скорость ответа (response time, performance);
  • отсутствие багов (reliability, usability);
  • доступность (availability);
  • устойчивость к отказам (resilience);
  • расширяемость (extendability);
  • поддерживаемость (maintainability);
  • среднее время починки (mean time to repair);
  • стоимость разработки и поддержки (cost);
  • тестируемость (testability);
  • возможность аудита и отладки (auditability).

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

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

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

Если в проекте очень сложный и запутанный код, то, скорее всего, хромает maintainability, скорость разработки и тестируемость. Если там старые библиотеки и фреймворки, то, скорее всего, у вас проблемы с расширяемостью. Если архитектура не предполагала большого количества запросов, а они ожидаются — это грядущие проблемы с scalability и performance. Если вы тратите половину рабочего времени на поиск причин багов — явно стоит улучшать auditability & traceability.

Ваши аргументы должны основываться на том, какие проблемы есть у проекта в данный момент или какие проблемы появятся в ближайшем будущем, если ситуацию не изменить (превентивный risk management).

Почему стороны не могут договориться

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

СтороныЖеланияОпасения
ИнвесторыПолучить хороший IRR и много платящих пользователейВпустую слить бюджет
ПользователиИметь надежный продукт, решающий их бизнес-задачи.Нестабильная работа продукта в тот самый момент, когда он очень нужен.
Product OwnerИдти в соответствии с разработанным roadmap, превосходить конкурентов, выпускать те фичи, которые имеют наибольшую конечную ценность.Думает об Opportunity Cost — убытках, которые понесет компания, если будет делать переписывание вместо новых фич
ПрограммистыПолучать удовольствие от работы на проекте, понимать систему, программировать, работать с новыми технологиямиНестабильная программа, в которой приходится чинить баги по ночам или выходным

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

Note: если во всем этом еще участвует аутсорсинг-компания, то к опасениям инвесторов добавляется страх, что им просто хотят продать дополнительные человеко-часы разработки. Я не вижу другого способа развеять этот страх, кроме как заказать аудит проекта у третьей незаинтересованной стороны, которой доверяет Product Owner.

Что по поводу переписывания говорят эксперты

Joel Spolsky написал 20 лет назад:

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

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

«Никто не хочет делать те части работы, которые не веселые. Чинить баги — это не весело. А писать с нуля — весело», — пишет Jamie Zawinski.

Так что же, совсем не переписывать?

Неверный вывод. Принцип «работает — не трожь» также не подходит. В книге «Object-Oriented Reengineering Patterns» упоминается, что если система функционирует, но вы не можете ее ни поддерживать ни расширять, она сломана.

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

Примерно то же самое произошло с AngularJS — когда возникло желание его переписать, был выпущен новый фреймворк Angular, и таким образом риски сломать то, что уже работает, были нивелированы.

Microsoft переписала Visual Studio и выпустила VSCode, которым многие, я думаю, пользуются. Google переписала свой Inbox, однако оставила работать обе версии — старую Inbox и новую GMail.

Достойные причины переписать проект

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

Недостойные причины переписать проект

  • Здесь написано на промисах, а я хочу async/await.
  • Здесь фреймворк N, а мои друзья говорят, сейчас модный Y.
  • Я хочу добавить парочку технологий себе в резюме.
  • Я не люблю код, который писал не я.
  • Код работает, но я не понимаю как.

Подводные камни

  • Переписывание всегда занимает больше времени, чем ожидается (по мировой статистике, упоминаемой в книге МакКоннелла «Сколько стоит программный продукт», программные проекты обычно недооцениваются на 30% и больше).
  • Простое переписывание дает мало ценности для конечного пользователя.
  • Вы «забудете» или «потеряете» часть функционала, если нет полной документации по старой системе.
  • Вы сделаете те же баги, которые уже делали и чинили до вас предыдущие программисты.
  • При переписывании с нуля вам придется какое-то время поддерживать обе версии — и старую, и новую.

Переписать или отрефакторить?

Переписывание (rewrite from scratch) — это когда вы заново, с нуля, пишете код, используя старый только для чтения. Рефакторинг — это когда путем последовательных преобразований старого кода вы приходите к новому его виду.

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

Но рефакторинг считается более безопасным по таким причинам:

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

А где ваш план!

Вы делали ремонт? Помните, что вас интересовало? Цена, качество и сроки, верно? Здесь то же самое. Чтобы заказчик сказал вам «да» — предоставьте ему информацию о цене, качестве и сроках.

Цена и сроки

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

  • Сделайте схемы и диаграммы того, что вы хотите получить в итоге.
  • Объясните в комментариях или в design document, чем новая структура лучше старой.
  • Разбейте работу на этапы и составьте эстимейт (оптимистичный, пессимистичный, реалистичный).
  • Продумайте риски (например, уход ключевого разработчика).
  • Кто и как будет тестировать результат, есть ли у вас чек-лист для полного тестирования?
  • Не забудьте включить в эстимейты работу по настройке деплоймента, переносу данных и миграции пользователей.

С этим планом вы можете обращаться к стейкхолдерам с предложением переписать.

Качество

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

Пару слов об инженерной этике

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

При вступлении в профессию программиста мы не даем [еще пока] никаких клятв, но кодекс этики программиста существует здесь и здесь, и похожий пункт там тоже есть: «Principle 2: Software engineers shall act in a manner that is in the best interests of their client and employer consistent with the public interest»

Преследовать свои личные цели, а не цели бизнеса — неэтично.

Дайте цифры

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

Стоимость переписывания посчитать проще всего, она прямо пропорциональна времени на переписывание и выкатывание новой версии.

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

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

Выберите подходящее время

Если вы привели хорошие аргументы и разработали детальный план — у Product Owner все еще может быть достойная причина для отказа: «Не сейчас».

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

Mожно обсудить с Product Owner, когда, по его мнению, все это можно будет реализовать, и запастись терпением. Подумайте: можно ли переписать не все, а часть? Определите самые проблемные части проекта, просмотрев историю баг-репортов или жалоб пользователей.

Спросим коллег

Oleksandr Brychuk, Head of IT Department at UniSender

На початку роботи в UniSender ми стикнулися з тим, що продукт за своєю природою був страшним легасі з практик початку 2000-х. Час на адаптацію нової людини в проєкті був немалим, деякі частини проєкту взагалі було важко підтримувати, один баг нам обійшовся в кругленьку суму. Їх було багато, і зменшити кількість нам не вдавалося.Я і колеги взяли ініціативу в свої руки. Зробили документ, в якому описали бачення того, куди потрібно рухатися з технічної точки зору. Приблизно оцінили терміни. Варіантів було два: переписувати все з нуля або рефакторити. Запрошували зовнішніх експертів для аудиту і перевірки власних гіпотез. І презентували це власникам. У кінці-кінців вирішили рефакторити, і почали з найбільш важливого для нашого бізнесу.

Ми рефакторили, а не переписувати з нуля, тому що часто зупинялися в процесі і робили те, що було потрібно на ту мить, а не в перспективі — це додало гнучкості. Перші півроку нічого не робили, крім рефакторингу, потім займалися ним по-різному: від 30-40% до 60-70% часу. Все залежало від цілей на той момент.

Eugene Naumenko, Founder at Adferret.tech

Коли говорять «все переписати» — саме в такому абсолютному формулюванні — це у більшості випадків просто непрофесійно. Коли справді є потреба переписати, найчастіше це робиться інкрементально — нові версії з новими можливостями, еволюція, а не революція. У випадках, коли переписати все справді потрібно, програмісти мають навести раціональні і логічні обґрунтування для бізнес-людей і разом сформувати бізнес-потребу, бізнес-цінність такого рішення і його загальну стратегію.

Eugene Bogatyriov, VP of Engineering, Waverley Software

Расчеты — это ключевой момент: нужно предоставить расчеты ROI проекта по переписыванию/рефакторингу. ROI — время, за которое окупится инвестиция в переписывание. Если переписывание окупается за год-полтора — эту идею примут и «спасибо» скажут. Расчеты желательно презентовать стейкхолдерам по одному, индивидуально, начиная снизу по иерархии. Есть неписаное правило о том, что продукт надо переписывать с нуля минимум каждые 10 лет в связи с устареванием технологий. У меня был пример как раз такого типа, где десктопный продукт переписывали с нуля под веб. Команда 80 человек, три года.

Summary

Итого, если вам кажется, что ваш проект нужно переписать:

  • Убедитесь, что причины весомые, а не просто «мне не нравится этот код».
  • Найдите точку пересечения ваших интересов и интересов других стейкхолдеров.
  • Определите опасения стейкхолдеров и способы снижения их опасений.
  • Составьте детальное описание того, что хотите получить в результате: схемы, диаграммы, design document.
  • Подумайте, почему нельзя прийти к тому же результату путем рефакторинга.
  • Сделайте оптимистичный, реалистичный и пессимистичный эстимейт.
  • Сравните затраты и выгоды, получаемые в результате.
  • Выберите подходящее время.
  • Заручитесь доверием со стороны ЛПР (лиц, принимающих решения).
  • Попробуйте менять поэтапно и начать с самых критичных частей.

Полезные ссылки

LinkedIn

Похожие статьи

32 комментария

Подписаться на комментарииОтписаться от комментариев Комментарии могут оставлять только пользователи с подтвержденными аккаунтами.

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

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

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

Никакой инвестор не будет слушать обычного разработчика, который будет предлагать что-то переписывать. Это во-первых, во-вторых, в мире аутсорсинг-проектов(которых до 90% в Украине), на разработчиков сваливают задачи поддержки и баг-фиксинга, поэтому любые призывы отсюда что-то глобально переписать будут либо проигнированы, либо выброшены в мусорную корзину быстрее скорости света

UPD: Dropbox переписали свой sync engine и делятся чеклистом как определить что таки да, нужно переписывать а не пытаться пинать мертвую лошадь dropbox.tech/...​-heart-of-our-sync-engine

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

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

Попробуйте такое провернуть в автомотив девелопменте

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

Статья отлично структурирована и оформлена.

Отличная статья, я с Вами согласна

Есть о чем подумать, большое спасибо за материал.

Кратко, метко и с напоминанием азов профессионального программирования, которые, почему-то и программисты со стажем забывают, а начинающие (<3) вообще еще не поняли.

Дякую, ДУЖЕ корисна інформація!

До речі наступний випадок

Код работает, но я не понимаю как.

за наведеним в цьому ж місці посиланням (wiki.c2.com/?RewriteCodeFromScratch) віднесений до гарних причин переписати код:

Nobody can figure out how it works.

і взагалі там більше та краще структуровані pros&contras, тому варто приділити їм більше уваги.

Есть разница между «совсем никто не понимает как» (nobody) или «я не понимаю как он работает ибо мне сложно/лениво разбираться». Цитата с той же страницы — If you can’t figure it out, you can’t rewrite it. If you can write UnitTests for it, you can figure it out.

там більше та краще структуровані pros&contras, тому варто приділити їм більше уваги.

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

Есть разница между «совсем никто не понимает как» (nobody) или «я не понимаю как он работает ибо мне сложно/лениво разбираться».

різниця насправді є. малоймовірно, що коли-небудь ви будете одноосібно приймати рішення про переписування коду.

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

то було б добре включити у списочок аргументів за переписування наступні пункти:

  • We are just doing it for fun or to exercise our development skills.
  • IntellectualProperty or licensing issues make it desirable to stop using someone else’s code.

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

Переписанный с нуля продукт — это возможность для новых и амбициозных менеджеров «поиметь его в собственность», а не унаследовать. Кстати, этим амбициозным менеджером может быть и тим/техлид.

Гораздо круче на годовом ревью смотрится ачивка «героически переписали с нуля», вместо какого-то непонятного и обидного для уха простого человека «инкрементально порефакторили».

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

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

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

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

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

Microsoft переписала Visual Studio и выпустила VSCode

інфа соточка

Это два разных продукта но второй написан с учетом информации полученной от разработки первого, нет?

Visual Studio (full version) is a „full-featured” and „convenient” development environment.
Visual Studio Code (VSCode) is a cross-platform (Linux, Mac OS, Windows) editor that can be extended with plugins to your needs.

Не хватает самого действенного пункта: Скажите, что нужно срочно переходить на микросервисы

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

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

Если проект потихонечку как-то движется и не предвидится никаких резких всплесков прибыли или пользователей — то происходил только мелкий рефакторинг. А взять и убедить заказчика на ровном месте «прямо сейчас нам нужен месяц-два на рефакторинг» никак не получалось. Максимум что делали это выделяли один спринт [две недели] на новый год или майские — чтобы закрыть что-то из tech debt.

Один раз было что мы всей командой устроили «хакатон» и много чего переделали за 3 супер-активных дня (плюс два-три дня на тестирование и релиз). Три дня не очень большое время, на такое заказчик согласен. И был QA с чеклистом который гарантировал что мы ничего не сломали.

В остальных кейсах делались только постепенные мелкие улучшения. Если на проекте всего 1-2 человека мне нравится идея привлекать кого-то стороннего чтобы он оценил идеи по улучшениям или критичность ситуации со стороны.

то есть чуда не произошло — мелкие рефакторинги — или большие нагрузки)

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

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

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

Подписаться на комментарии