Увесь код — це неминуче технічний борг? Обговорюємо

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

Оскільки що більше коду додається в застосунок, то повільнішою стає розробка, то чи можна весь код розглядати як технічний борг? Тоді виходить, що єдиний надійний спосіб уникнути технічного боргу — це взагалі не писати код?

Розкажіть у коментарях, чи згодні ви з такою точкою зору і які рішення можна впровадити, аби не збільшувати кількість коду 👇

👍ПодобаєтьсяСподобалось1
До обраногоВ обраному0
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Навіть я вже починаю вірити, що такi теми згенеровані штучним інтелектом

Теми висмокнаті з пальця це неминучий крінж)

Усе життя це неминуча смерть ...

Його не треба уникати, ним треба керувати. Overengineering може бути значно гірше за тех борг en.wikipedia.org/wiki/Overengineering

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

Усе таки треба мати баланс. Другий раунд інвестицій може закінчитись наприклад вибухом на стартовій позиції із загибеллю усієї команди і наступним закриттям проекту. А найвідоміший тех борг як відомо — Чорнобиль. Тех борг це один із ризиків яким треба керувати.

Головне «освоїти» бюджет на першому раунді. Що там буде з продуктом після другого то вже таке.
Хата построєна, діти вчаться, а погромісти ще напишуть))

Я згоден з думкою
Ну і банально що будь-який код майже завжди з часом обновлюється або і зовсім переписується(навіть той найсвіжіше написаний код, який ви ще зараз не вважаєте технічний боргом)
Бо банально оновлюються бібліотеки, мови програмування, з‘являються нові підходи

Це — проблема не тільки ІТ, а і загально — інженерна. Навіть якщо щось спроектовано і зроблено ідеально і без «технічного боргу» — то усе одно є фактор технічного застарівання. У вас може бути раритетна BMW в ідеальному стані — але раптом що то знайти запчастини обійдеться дорожче за нову BMW. І рішення для такої проблеми вже давно знайдено і підтверджено на практиці. Зветься «гарантійний термін» та «період підтримки».
Недоліки можуть бути навіть у найкращій системі — тому деякий час потрібен на «обкатку». Досвідчені адміни колись казали що не варто ставити новий софт поки до нього не випустять хочаб перший сервіс пак.
Деякий час система розвивається, туди додають нових фіч, при цьому різні клієнти хочуть різні фічи, усяких налаштувань під різних юзерів стає все більше, ціна тестування та підтримки росте, а прибуток поступово падає — бо система вже не нова, з’являються альтернативи, бізнес-потреби змінюються, мода на технології теж — і кількість юзерів падає.
Хрестоматійний приклад — це славно-відомий Internet Explorer: свого часу він переміг такого титана як Netscape (тепер його пам’ятають тільки старпери) і декілька «золотих» років був майже монопольним браузером. Потім з’явилися альтернативи, але ще довгий час усе робили «під IE», а підтримка усяких «маргінальних» браузерів (Firefox, Opera) була кошмаром верстальників. Сила IE була у повній сумісності усіх версій: усе, що колись було зроблено під IE мало працювати завжди. Фактично кожна наступна версія IE включала усі попередні — важко навіть уявити які там були сорси! І потім історія повторилася: нові HTML 5 браузери швидко «поховали» IE так само як раніше він. Були спроби оновити IE, додати підтримку HTML 5, але враховуючи увесь легасі код і функціонал — IE просто ніяк не міг конкурувати по перфомансу з новими браузерами.
У житті кожного продукту наступає момент коли ціна його підтримки та модернізації стає вищою за випуск нового продукту «з нуля». І тоді тільки питання часу: чи автор випустить цю нову версію — чи це зроблять конкуренти!
Тому більшість сучасних продуктів не розраховані на багато років використання. Більшість людей не будуть користуватися смартфоном 5 років — вони захочуть купити новий. Більшість людей не будуть лагодити улюблену «копійку» 30 років — через 5 років вони поміняють авто на нове (можливо вже — електро). Навіть комп’ютер, зібраний 5 років тому вже «не дуже»: бо змінилося вже ціле покоління процесорів, відеокарт і т.і.
Підсумовуючи: технічний БОРГ — це також гроші. Гроші заощаджені на розробці — і їх фактично отримано тут і зараз. А повертати борг доведеться поступово — при цьому він буде зростати. Отже якщо оптимізувати прибуток — то брати в борг має сенс тільки до той пори — поки не доведеться повертати більше!
Якщо софт робиться на замовлення чи на продаж і після релізу борг буде вже не наш — то можна себе не стримувати! (чим і користується багато галер). Купа мобільних аплікушечек та «інді-ігор» які тестуються прямо на юзерах — знаходять достатньо «лохів» аби бути прибутковими.
Якщо продукт «наш» — то зробивши технічний борг занадто великим можна не встигнути отримати прибуток. Наприклад як дочасно випустити круту, але забаговану гру (Cyberpunk) — і замість золотого дощу отримати гнилих томатів.
Важливо вчасно розуміти коли виплати борга вже починають з’їдати прибуток. Тому розумний власник десь через 5 років має почати робити нову, сучасну версію продукта «з нуля», а стару, наприкдад, продати поки вона ще не стала збитковою.
Класична історія появлення легасі — ентерпайз проєктів на галерах: якийсь лох купив успішний великий проєкт 5 річної давності. Не розуміючи що продали його саме тому, що ціна підтримки і модернізації (додавання нових фіч) вже починає перевищувати прибуток. Якийсь час новий власник ще буде виживати за рахунок передачі проєкту дешевший команді в Україну. Потім коли прибуток ще впаде — може віддасть на сапорт в Індію де усе остаточно поховають.
Тим часом старий власник зробить новий продукт з нуля, чи хтось з конкурентів це зробить — і поступово усі клієнти перейдуть зі старого «Титаніка» на новий модний лайнер. Який поплаває свої 5 років поки не почне протікати.
Висновок: робити продукт «на віки» без технічного боргу — не окупається. Робить продукт на 5 років — а потім, якщо він ще актуальний — стартуйте нову версію «з нуля» — на наступні 5 років.

завжди є 2 варіант: не робити нічого і робити

розберемо варіант «робити»:
1) як в менеджменті та керуванні компаніями, так і більш простих питаннях з легасі кодовою базою та великим тех.боргом — можна підтримувати старий проект, а поряд новий створювати — це не просто і шлях доволі довгий, проте виправданий варіант, якщо компанія готова «грати в довгу»;
2) намагатись в існуючому проекті проаналізувати «вузькі місця» (bottlenecks) та в першу чергу їх вирішити, а потім визначити залежності проекту та поступово приймати рішення, які б зменшували генерування технічного боргу, і паралельно закривати задачі з беклогу по їхній пріоритетності

то чи можна весь код розглядати як технічний борг?

Поздоровляю і вітаю! Ви почали розуміти «всю глибину наших глибин» (tm).

Але є більший борг і менший борг.

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

Як казав Генріх Альтшуллер (мабуть, повторюючи когось з ще величніших), «Ідеальна система — це коли системи нема, але її функція виконується». Зазвичай такого ідеала не можна досягнути, тому маємо писати код.

що єдиний надійний спосіб уникнути технічного боргу — це взагалі не писати код?

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

P.S.: Я вкрай і позитивно здивований. Так звана «DOU Community» дійсно підняла важливу тему і поставила принципові запитання. Частіше б так.

P.S.[2]: Може, потім напишу окремо про конкретні приклади. Зараз — тільки про головне.

Мені двічі в житті доводилося розробляти нову codebase те, що зветься «from scratch». Перший раз в мене не було чітких строків, тому я працював у більш-менш комфортному для себе ритмі, і тому майже одразу почав покривати весь наявний код тестами. А також намагався писати так, щоб прямо зовсім без милиць. Як тільки бачив, що щось можна покращити, одразу рефакторив без найменших сумнівів. І знаєте що? В мене з тим проектом жодного разу не виникло відчуття, що я загруз в болоті і можу рухатися лише дуже повільно. Весь час роботи над тим проектом (десь півроку-рік) я доволі сміливо робив зміни всюди, де вважав за потрібне і юніт-тести не дозволяли мені зламати щось суттєво.
Прямо зараз я також роблю проект з нуля, але вхідні умови з самого початку були інші. Я розробляю сервіс, від якого залежить велика система, тобто кілька людей розробляють паралельно зі мною і використовують мій API. Тому довелося розпочати з того, що зробити просто заглушки веб-методів і задокументовати їх, для того, щоб розблокувати інших розробників. Потім довелося доволі швидко робити чорнову реалізацію, щоб якомога швидше розблокувати інтеграторів. А потім я працював в режимі, коли все що блокує інших робиться в першу чергу, а весь час, який залишається я можу витрачати на якість. Зараз вже із тиждень працюю виключно над якістю (покращення коду і юніт-тестування). В принципі, все залежить від того, чи вистачить часу завершити цю роботу до того як буде новий запрос на масовані зміни.
Ще одного разу в мене був випадок, коли я зайшов в проект, який вже був в продакшні, але розробляти його було майже неможливо через погано продуману архітектуру, яка призводила по-перше до дуже низької продуктивності роботи з БД, а по друге до крихкості коду. Довелося багато переробляти і рефакторити, причому робити це паралельно із розробкою нових фіч. Той проект так і залишився назавжди legacy, проте мені вдалося суттєво покращити архітектуру і зробити розробку набагато більше комфортною, ніж було на початку моєї роботи з ним.
В більшості проектів, де я брав участь, весь код виглядав в тій чи іншій мірі як технічний борг. Для того, щоб з цим боротися зазвичай не вистачає одного з двох (або обох) факторів.
1. Розуміння стейкхолдерів та/або керівників, що технічний борг — це реальна проблема і на роботу з цим варто постійно витрачати час (тобто бюджет).
2. Єдиного для всій команди розуміння якості коду і рішення в цілому, і як слідство, єдиного підходу до архітектури проекту.
Дуже рідко ці два фактора співпадають. Тому більшість великих проектів рано чи пізно перетворюються на суцільне болото. Тому я люблю працювати або сам, або в невеличкій команді профі з дуже відкритим до змін підходом. Те що англомовні люди звуть «openminded». В такому разі є непоганий шанс ніколи не потрапити в болото. Якось так.

Я так і не зрозумів що таке юніт тести і як це «покривати код тестами»

Якщо казати про головне, я б сформулював так. Тест можно вважати юніт-тестом якщо:
1. Він перевіряє певний сценарій використання юніта і переконується, що поведінка юніта в цьому сценарії відповідає певному acceptance criteria.
2. Його виконання і результати не залежать від будь-якої зовнішньої інфраструктури чи зовнішнього коду — тільки від коду юніта, який тестується і коду самого теста. Будь-які зовнішні залежності юніта, якщо вони існують, мокаються, стабяться, або в інший спосіб емулюються кодом власно тесту.
Юніт-тест виконується дуже швидко, оскільки виконується в пам’яті (слідство другої умови). Юнітом, залежно від умов можна вважати клас, процедуру чи модуль. Залежить від мови і специфіки задачі. Якщо код всього проекту щільно покритий юніт-тестами, вони працюють як safety net. Тобто, якщо якась зміна ламає існуючу функціональність, це одразу видно по «поламаних» тестах. Таким чином, тести страхують розробника від неочікуваних багів. Але платити за це доводиться написанням і підтримкою коду тестів паралельно з кодом застосунку і певним способом організації коду застосунку, який дозволяє емулювати залежності. В принципі, це — головне, що треба розуміти про юніт-тести. Інше — вже деталі.

Скоріше всього ви якось перевіряєте код, який написали. Це відносно просто коли коду небагато. Коли к-ть модулів росте, ви не можете фізично вручну все перевірити. Разом з тим середовище постійно змінюється. Виходять нові версії бібліотек, операційних систем, процесорів, змінюється поведінка користувачів і т.п. По хорошому такі перевірки мають бути автоматизовані. Тоді ви менше будете чути про проблеми від користувачів (наприклад, хтось помер бо блютуз iOS-апки почав швидко садити батарейку в інсуліновій помпі). Такі автоматизовані перевірки окремих модулів і їх функцій і є юніт тестами.

Такі автоматизовані перевірки окремих модулів і їх функцій і є юніт тестами.

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

інтеграційні тести
працездатність системи в цілому
або всього ланцюжка

а що тоді таке e2e тести?)

Наскільки я розумію, якоїсь єдиної загально визнаної класифікації з цього приводу не існує. Дивіться, наприклад, ось тут en.wikipedia.org/...​ystem_integration_testing і ось тут en.wikipedia.org/wiki/System_testing. Можна, вважати, що e2e є підвидом integration testing, а можна вважати, що це взагалі окремий вид тестування. Як на мене, для розуміння цілі, це не важливо.
Наскільки я розумію, головною ознакою e2e є підхід, який відштовхується від точки зору кінцевого користувача. Тобто, тестування окремого мікросервісу не є e2e, як і тестування, наприклад, окремо фронтенду чи бекенду неможна вважати e2e. e2e — це тестування всього комплексу, так, як його бачить кінцевий користувач.

Так розробка стає набагато повільнішою. Я робив проєкт з нуля і після випуску ми з клієнтом вирішили зробити ще 1 базу данних, яка ніяк не пов’язана з продакшеном — і всі переживання щось випадково видалити відпали, щоправда треба було трохи витратити часу на копіювання статичних моделей )
Ще використання сервісів, які надають бекапи сильно допомагає

Всім гарного дня 😁

Для мене кодова база це шаблон для написання нового функціоналу

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