Когда стоит переписывать код проекта и как это донести до заказчика
Всем привет! Меня зовут Елена Шаровар, я Lead Node.js developer в Waverley Software. В этой статье мы рассмотрим ситуацию, когда программисты говорят: «Нужно все переписать», но это тяжело донести до заказчика.
Разберемся, что с этим делать и как помирить программистов и бизнес, если вы — Lead проекта, Project Manager или тот самый программист, который хочет улучшений, а вас как будто не слышат. Скорее всего, об этой проблеме вы знаете не понаслышке: такое случается то с вами, то с вашими друзьями или коллегами, и в очередной раз начинается обсуждение: а что же делать?
Каким бы ни было ваше итоговое решение — не переписывать, переписывать или сделать это частично, — я надеюсь, этот подробный разбор поможет сделать его мудро и взвешенно, а также донести свою идею до других стейкхолдеров.
Стейкхолдеры проекта
Чем больше заинтересованных лиц в проекте, тем более разнообразные у них цели. Давайте определим всех стейкхолдеров, участвующих в проекте. Заметьте, что с некоторыми из них вы, возможно, даже не знакомы. Но они есть, и они имеют влияние на принятие тех или иных решений.
- Инвесторы — потому что они вкладывают свои финансовые средства в этот проект и ожидают хороший Return on Investment (ROI).
- Product Owner — человек, который занимается управлением этого проекта и приоритизирует функционал, который вы разрабатываете. Он общается с программистами и инвесторами.
- Пользователи — те, кто использует ваш продукт и, скорее всего, платит за него.
- Программисты — да-да, они также являются стейкхолдерами, проект должен их устраивать, иначе у вас не будет программистов.
Как проект выглядит для всех, кроме программистов
Извините, но это все! Магия, которая происходит внутри, интересна только программистам. Пока программа делает то, что нужно — она устраивает владельца продукта, инвесторов и даже пользователей.
Почему программисты хотят переписать код проекта
Во-первых, потому что у нас есть потребность делать хорошо. К сожалению, понятие «хорошо» у всех разное. Например, код хочется переписать тогда, когда достался 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
Eugene Naumenko, Founder at Adferret.tech
Eugene Bogatyriov, VP of Engineering, Waverley Software
Summary
Итого, если вам кажется, что ваш проект нужно переписать:
- Убедитесь, что причины весомые, а не просто «мне не нравится этот код».
- Найдите точку пересечения ваших интересов и интересов других стейкхолдеров.
- Определите опасения стейкхолдеров и способы снижения их опасений.
- Составьте детальное описание того, что хотите получить в результате: схемы, диаграммы, design document.
- Подумайте, почему нельзя прийти к тому же результату путем рефакторинга.
- Сделайте оптимистичный, реалистичный и пессимистичный эстимейт.
- Сравните затраты и выгоды, получаемые в результате.
- Выберите подходящее время.
- Заручитесь доверием со стороны ЛПР (лиц, принимающих решения).
- Попробуйте менять поэтапно и начать с самых критичных частей.
Полезные ссылки
- статья Things you never should do by Joel Spolsky;
- книга Object-Oriented Reingeneering Patterns;
- видео о том, как переписывался Concert.ua;
- видео — кейс от UniSender;
- презентация о прохождении всех стадий рефакторинга от отрицания до принятия;
- презентация «Этот код плохой, его нужно переписать»;
- большая и веселая подборка докладов о работе с Legacy;
- Wiki-статья, посвященная rewrite from scratch;
Все про українське ІТ в телеграмі — підписуйтеся на канал DOU
33 коментарі
Підписатись на коментаріВідписатись від коментарів Коментарі можуть залишати тільки користувачі з підтвердженими акаунтами.