Коли варто переписувати код проекту і як це донести до замовника
Всім привіт! Мене звуть Олена Шароварів, я 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 проекту розробляється на місяці вперед, і раптово додати в план великі зміни не вийде. Також ви можете бути не в курсі фінансового стану проекту — він «дихає на ладан і намагається вижити» або «отримав третій раунд інвестицій, і планується розвиток»? Отримати час та ресурси на рефакторинг простіше у другому випадку.
Можна обговорити з Product Owner, коли, на його думку, все це можна буде реалізувати, і запастися терпінням. Подумайте: чи можна переписати не всі, а частина? Визначте найбільш проблемні частини проекту, переглянувши історію баг-репортов або скарг користувачів.
Запитаємо колег
Oleksandr Brychuk , Head of IT Department at UniSender
На початку роботи в UniSender ми стикнулися з тим, що продукт за своєю природою був страшним легасі з практик початку 2000-х.Час на адаптацію нової людини в проєкті був немалим, деякі частини проєкту взагалі було важко підтримувати, один баг нам обійшовся в кругленьку суму. Їх було багато, і зменшити кількість нам не вдавалося.
Я і колеги взяли ініціативу в свої руки. Нікого документ, в якому описали бачення того, куди потрібно рухатися з технічної точки зору. Приблизно оцінили терміни. Варіантів було два: переписувати все з нуля або рефакторити. Запрошували зовнішніх експертів для аудиту і перевірки власних гіпотез. І презентували це власникам. У кінці-кінців вирішили рефакторити, і почали з найбільш важливого для нашого бізнесу.
Ми рефакторили, а не переписувати з нуля, тому що часто зупинялися в процесі і робили те, що було потрібно на ту мить, а не у перспективи — це додало гнучкості. Перші півроку нічого не робили, крім рефакторінгу, потім займалися ним по-різному: від 30-40% до 60-70% часу. Все залежало від цілей на тій момент.
На початку роботи в UniSender ми стикнулися з тим, що продукт за своєю природою був страшним легасі з практик початку 2000-х. Час на адаптацію нової людини в проєкті був немалим, деякі частини проєкту взагалі було важко підтримувати, один баг нам обійшовся в кругленьку суму. Їх було багато, і зменшити кількість нам не вдавалося. Я і колеги взяли ініціативу в свої руки. Нікого документ, в якому описали бачення того, куди потрібно рухатися з технічної точки зору. Приблизно оцінили терміни. Варіантів було два: переписувати все з нуля або рефакторити. Запрошували зовнішніх експертів для аудиту і перевірки власних гіпотез. І презентували це власникам. У кінці-кінців вирішили рефакторити, і почали з найбільш важливого для нашого бізнесу.Ми рефакторили, а не переписувати з нуля, тому що часто зупинялися в процесі і робили те, що було потрібно на ту мить, а не у перспективи — це додало гнучкості. Перші півроку нічого не робили, крім рефакторінгу, потім займалися ним по-різному: від 30-40% до 60-70% часу. Все залежало від цілей на тій момент.
Eugene Naumenko , Founder at Adferret.tech
Коли говорять «все переписати» — саме в такому абсолютному формулюванні — це у більшості випадків просто непрофесійно. Коли справді є потреба переписати, найчастіше це робиться інкрементально — нові версії з новими можливостями, еволюція, а не революція. У випадках, коли переписати все справді потрібно, програмісти мають навести раціональні і логічні обґрунтування для бізнес-людей і разом сформувати бізнес-потребу, бізнес-цінність такого рішення і його загальну стратегію. Коли говорять «все переписати» — саме в такому абсолютному формулюванні — це у більшості випадків просто непрофесійно. Коли справді є потреба переписати, найчастіше це робиться інкрементально — нові версії з новими можливостями, еволюція, а не революція. У випадках, коли переписати все справді потрібно, програмісти мають навести раціональні і логічні обґрунтування для бізнес-людей і разом сформувати бізнес-потребу, бізнес-цінність такого рішення і його загальну стратегію.Eugene Bogatyriov , VP of Engineering, Waverley Software
Розрахунки — це ключовий момент: потрібно надати розрахунки ROI проекту з переписування/рефакторінгу. ROI — час, за яке окупиться інвестиція в переписування. Якщо переписування окуповувався за рік-півтора — цю ідею візьмуть і «спасибі» скажуть. Розрахунки бажано презентувати стейкхолдерам по одному, індивідуально, починаючи знизу по ієрархії. Є неписане правило про те, що продукт треба переписувати з нуля мінімум кожні 10 років у зв'язку з старінням технологій. У мене був приклад саме такого типу, де десктопний продукт переписували з нуля під веб. Команда 80 чоловік, три роки. Розрахунки — це ключовий момент: потрібно надати розрахунки ROI проекту з переписування/рефакторінгу. ROI — час, за яке окупиться інвестиція в переписування. Якщо переписування окуповувався за рік-півтора — цю ідею візьмуть і «спасибі» скажуть. Розрахунки бажано презентувати стейкхолдерам по одному, індивідуально, починаючи знизу по ієрархії. Є неписане правило про те, що продукт треба переписувати з нуля мінімум кожні 10 років у зв'язку з старінням технологій. У мене був приклад саме такого типу, де десктопний продукт переписували з нуля під веб. Команда 80 чоловік, три роки.Summary
Загалом, якщо вам здається, що ваш проект потрібно переписати:
- Переконайтеся, що вагомі причини, а не просто «мені не подобається цей код».
- Знайдіть точку перетину ваших інтересів та інтересів інших стейкхолдерів.
- Визначте побоювання стейкхолдерів та способи зниження їх побоювань.
- Складіть детальний опис того, що хочете отримати в результаті: схеми, діаграми, design document.
- Подумайте, чому не можна прийти до того ж результату шляхом рефакторінгу.
- Зробіть оптимістичний, реалістичний та песимістичний естімейт.
- Порівняйте витрати і вигоди, одержувані в результаті.
- Виберіть відповідний час.
- Заручіться довірою з боку ОПР (осіб, що приймають рішення).
- Спробуйте міняти поетапно і почати з самих критичних частин.
Корисні посилання
- стаття Things you should never do by Joel Spolsky;
- книга Object-Oriented Reingeneering Patterns ;
- відео про те, як листувався Concert.ua ;
- відео — кейс від UniSender ;
- презентація про проходження всіх стадій рефакторінгу від заперечення до прийняття ;
- презентація «Цей код поганий, його треба переписати» ;
- велика й весела підбірка доповідей про роботу з Legacy ;
- Wiki-стаття, присвячена rewrite from scratch ;
Опубліковано: 03/03/20 @ 11:00
Розділ Різне
Рекомендуємо:
Ви підприємець чи науковець? Як продакт-менеджера обирати компанію відповідно до схильностей
Arti, Langkah serta Taktik Tepat dalam Main Koa/Ceki/Pei
DevOps дайджест #30: гонка клаудов за перевагу в Kubernetes, Thanos operator, стрімке зростання Sentry
Зростання органічного трафіку для мережі медичних клінік з 162,5 тис. до 2,5 млн відвідувань за рік роботи
Підвищення податків vs здоровий глузд, або За податками бритвою Оккама