Задолженность техническая: Как научиться не накапливать технический долг — отвечают эксперты – Почему технический долг — это хорошо / Voximplant corporate blog / Habr
if(rtbW>=960){var rtbBlockID="R-A-744041-3";} else{var rtbBlockID="R-A-744041-5";}
window.yaContextCb.push(()=>{Ya.Context.AdvManager.render({renderTo:"yandex_rtb_7",blockId:rtbBlockID,pageNumber:7,onError:(data)=>{var g=document.createElement("ins");g.className="adsbygoogle";g.style.display="inline";if(rtbW>=960){g.style.width="580px";g.style.height="400px";g.setAttribute("data-ad-slot","9935184599");}else{g.style.width="300px";g.style.height="600px";g.setAttribute("data-ad-slot","9935184599");} g.setAttribute("data-ad-client","ca-pub-1812626643144578");g.setAttribute("data-alternate-ad-url",stroke2);document.getElementById("yandex_rtb_7").appendChild(g);(adsbygoogle=window.adsbygoogle||[]).push({});}})});
window.addEventListener("load",()=>{
var ins=document.getElementById("yandex_rtb_7");if(ins.clientHeight =="0"){ins.innerHTML=stroke3;}},true);
Простые причины неизбежности технического долга / Habr
if(rtbW>=960){var rtbBlockID="R-A-744041-3";} else{var rtbBlockID="R-A-744041-5";}
window.yaContextCb.push(()=>{Ya.Context.AdvManager.render({renderTo:"yandex_rtb_6",blockId:rtbBlockID,pageNumber:6,onError:(data)=>{var g=document.createElement("ins");g.className="adsbygoogle";g.style.display="inline";if(rtbW>=960){g.style.width="580px";g.style.height="400px";g.setAttribute("data-ad-slot","9935184599");}else{g.style.width="300px";g.style.height="600px";g.setAttribute("data-ad-slot","9935184599");} g.setAttribute("data-ad-client","ca-pub-1812626643144578");g.setAttribute("data-alternate-ad-url",stroke2);document.getElementById("yandex_rtb_6").appendChild(g);(adsbygoogle=window.adsbygoogle||[]).push({});}})});
window.addEventListener("load",()=>{
var ins=document.getElementById("yandex_rtb_6");if(ins.clientHeight =="0"){ins.innerHTML=stroke3;}},true);
Вы когда-нибудь слышали о команде разработки программного обеспечения, которой бы не приходилось сталкиваться с техническим долгом?
Я тоже нет. Более того:
Инженеры тратят около трети своего времени на технический долг, что снижает боевой дух команд и обходится компаниям примерно в 85 млрд. долларов ежегодно.
Исследование Stripe
Только вдумайтесь. Это 85 миллиардов долларов.
Треть всего времени разработчиков тратится на технический долг. Это наполняет разработчиков ужасом. Это, на самом деле, худшая часть их работы — и масла в огонь подливает то, что остальная часть бизнеса часто никак им не сопереживает. Здесь нет чьей-либо вины, но технический долг повсеместно недооценивается. Из-за него софтверные компании медленно закостеневают, до тех пока не утратят способность к росту, не требующему затрачивать месяцы и годы на переписывание своих приложений с нуля… а такие сроки на сегодняшнем рынке — это целая вечность.
Технический долг — явление заурядное, так ведь? Мы начинаем писать код, технический долг накапливается, и бум, его внезапно становится слишком много. Наша кодовая база оказывается погрязшей в нём, и мы приходим к техническому банкротству. Поэтому мы с ним боремся. Мы смиряемся с мучительной необходимостью и выплачиваем часть долга. Иногда у нас получается это делать, иногда нет. В этом суть разработки программного обеспечения. Так уж у нас всё устроено.
Но разве всё должно быть именно так? Есть ли какие-то фундаментальные законы разработки программного обеспечения, которые ответственны за это? И, если да, можем ли мы использовать эти законы себе во благо? Технический долг — обычное явление, но им не должно быть техническое банкротство.
Давайте обратимся к различным областям науки за некоторыми подсказками, потому что законы термодинамики могут подарить нам ключевые идеи для понимания того, почему технический долг неизбежен.
Первый закон термодинамики
Также известен как закон сохранения энергии; утверждает, что:
Полная энергия замкнутой системы остается постоянной; говорят, что она сохраняется с течением времени.
Другими словами, энергия не может быть создана или уничтожена, однако она может переходить из одной формы в другую.
Если без лишних сложностей, давайте думать о нашей кодовой базе как о замкнутой системе. Отбросим внешние зависимости и всё, что живет за пределами нашей кодовой базы. В этих условиях — неизменное количество разработчиков, разработка фич в стабильно высоком темпе — количество энтропии (мера беспорядка и случайности в системе) в нашей кодовой базе остается постоянной.
Наши разработчики не могут стать сверхлюдьми за одну ночь, поэтому мы не можем увеличить их эффективность, если они уже и без того выкладываются на максимум. Но мы можем нанять больше разработчиков, а это увеличивает энергию в нашей системе. Вот почему верен закон Брукса: «Если проект не укладывается в сроки, то добавление рабочей силы задержит его ещё больше» — потому что это увеличивает энергию, или хаос, в системе, где хаос и без того уже велик.
Быстрорастущие софтверные компании борются с этой силой постоянно. Они поднимают раунд инвестиций, удваивают объем команды разработчиков так быстро, как им позволяет рынок труда, а затем им приходится бороться с большим скачком «энергии» в своей кодовой базе. Это часто превосходит возможности компании и может привести к резкому росту технического долга, если не принять срочных контрмер.
Но постойте. Почему это ведёт к росту технического долга?
Второй закон термодинамики
Беспорядок в замкнутой системе не может уменьшаться; он может только оставаться неизменным или увеличиваться.
Фактически, замкнутые системы переходят в состояние большего беспорядка естественным образом. Этот «беспорядок» — который мы назвали выше «энергией» или «хаосом» — называется энтропией. Ивар Якобсон и его коллеги исследовали феномен энтропии в кодовых базах и ввели термин энтропия программного обеспечения. По мере внесения изменений в кодовую базу её энтропия увеличивается. Этот ширящийся хаос является причиной технического долга.
Вернёмся к нашей быстрорастущей софтверной компании, чья клиентская база продолжает расширяться, а рынок растёт. Их увеличивающаяся команда разработчиков день и ночь выкатывает фичи, чтобы успеть за ростом. Если ничего не делать, кодовая база станет только запутаннее. Давление нарастает.
Я рассматриваю технический долг как энтропию в кодовой базе. Я не думаю, что он когда-нибудь исчезнет, борьба с ним будет постоянной.
Ron Pragides, вице-президент по разработке в Carta
Планируя каждый спринт, наша компания оказывается перед выбором: нужно ли сделать что-то для обуздания растущей сложности или стоит потратить время на разработку и доставку новых фич?
Третий и последний закон термодинамики проясняет, почему эта дилемма даже близко не отвечает истинному положению вещей.
Третий закон термодинамики
Энтропия системы достигает постоянного значения, когда температура равна абсолютному нулю.
Звучит сложно, но в действительности, довольно просто по сути, и хотя законы термодинамики имеют далеко идущие (и иногда просто ошеломляющие) последствия, их основы легко понять. Например, когда вода принимает форму пара, ее молекулы «свободны» двигаться совершенно хаотичным образом. Энтропия повсюду. Однако, когда вода замерзает, её молекулы оказываются «заперты» и остаются на месте (более или менее). Энтропия уменьшается и достигает постоянного значения.
Итак, что мы можем сделать, чтобы управлять энтропией ПО?
Ну, мы могли бы остановить разработку нового кода. По этой причине некоторым командам нравится «заморозить» код, чтобы хорошенько протестировать свою систему перед релизом для клиентов. Если кодовая база больше не изменяется, то энтропия не растет, хаос тоже, нет больше непредвиденных последствий, и технический долг не увеличивается.
Однако вечно держать код в замороженном виде невозможно — нам нужны новые фичи. Так что единственный вариант, который нам остаётся, — это рефакторить.
Процесс рефакторинга кода может способствовать поэтапному сокращению энтропии программного обеспечения.
Википедия
Бесплатное расширение для VSCode, которое поможет вам в этом. Начните сейчас, пока ситуация не вышла из-под контроля!
Пока всё неплохо. На самом деле, всё это выглядит как констатация очевидного; любой, кто что-нибудь слышал о разработке ПО, знаком со всем этим, по крайней мере интуитивно.
Почему же технический долг по-прежнему застает нас врасплох?
Это потому, что даже при том, что мы знаем о необходимости рефакторить код для снижения запутанности, существует еще мириад других довлеющих над нами сил, которые не дают нам выделять время и ресурсы, необходимые, чтобы делать рефакторинг правильно и достаточно часто. Это означает, что и в нашей, и во всех прочих кодовых базах энтропия ПО постоянно растёт.
if(rtbW>=960){var rtbBlockID="R-A-744041-3";} else{var rtbBlockID="R-A-744041-5";}
window.yaContextCb.push(()=>{Ya.Context.AdvManager.render({renderTo:"yandex_rtb_5",blockId:rtbBlockID,pageNumber:5,onError:(data)=>{var g=document.createElement("ins");g.className="adsbygoogle";g.style.display="inline";if(rtbW>=960){g.style.width="580px";g.style.height="400px";g.setAttribute("data-ad-slot","9935184599");}else{g.style.width="300px";g.style.height="600px";g.setAttribute("data-ad-slot","9935184599");} g.setAttribute("data-ad-client","ca-pub-1812626643144578");g.setAttribute("data-alternate-ad-url",stroke2);document.getElementById("yandex_rtb_5").appendChild(g);(adsbygoogle=window.adsbygoogle||[]).push({});}})});
window.addEventListener("load",()=>{
var ins=document.getElementById("yandex_rtb_5");if(ins.clientHeight =="0"){ins.innerHTML=stroke3;}},true);
Все мы знаем закон Мура, однако подумайте и о варианте закона Вирта в изложении Билла Гейтса:
Скорость программного обеспечения уменьшается наполовину каждые полтора года.
Билл Гейтс
Я убежден, что растущая энтропия наших кодовых баз — главная движущая сила этой закономерности.
Темп роста энтропии ПО напрямую связан с темпами роста таких факторов, как технологии, рынки ПО, софтверные компании и грамотность написания кода — и каждый из них растёт чертовски быстро.
Источник: The Emerging Future
Вообразите давление, которое эти ожидания оказывают на команды разработки программных продуктов. Это серьёзные общемировые тренды, и относительно небольшой группой людей они могут ощущаться как сокрушительные. Это почти как просить их побороть гравитацию и взлететь, размахивая руками.
Кадры реальной видеосъемки команды разработчиков, сражающейся с техническим долгом
В следующей статье мы рассмотрим микротренды, постоянно подталкивающие нас к техническому банкротству, а также то, как быстрорастущие софтверные компании могут с ними побороться. Оставайтесь с нами!
Как перестать растрачивать время разработчиков на технический долг / Хабр
Вы знаете, каково это. Впихнуть всё необходимое в спринт и так весьма непросто, а ведь ещё нужно где-то найти дополнительные 10–20% времени разработчиков на возврат технического долга. Если вы когда-либо отстаивали необходимость выкраивания времени на это, то вы знаете, что это походит на крестовый поход эпических масштабов.
Но сделать это можно, и в этом руководстве мы выясним, как именно.
Я повидал чересчур много собраний, где именно на этот вопрос было потрачено слишком много времени. Доводы обычно безосновательны, а эмоции могут накаляться — и побеждает тот, у кого голос громче всех в комнате.
Дилемма состоит вот в чём: если возьмёт верх давление бизнеса, ваша компания рискует набрать слишком большой технический долг — и тогда разработчики потеряют мотивацию, компания придет к техническому банкротству, а ваши конкуренты одержат над вами победу. Если же пересилит давление разработчиков, компания рискует взять слишком маленький технический долг, и тогда ваши конкуренты смогут предоставить продукты и фичи быстрее, захватят рынок, а позже используют полученную при этом прибыль, чтобы вернуть свой технический долг. Вы снова в проигрыше.
Здравый смысл подсказывает, что командам разработчиков следует развивать интуитивное понимание кодовой базы, где и таится технический долг, а также его последствий для компании, тем самым укрепляя доверие внутри организации. Если ваш главный архитектор и основатель говорит, что нужно сделать рефакторинг прямо сейчас, вы (обычно) просто берете и делаете его.
Имеет смысл пытаться удерживать своих разработчиков, чтобы создать культуру знания, обмена и доверия. Но на это уйдут годы тяжелого труда, и, заканчивая рефакторинг, мы всё ещё почти не имеем понятия, не впустую ли мы потратили своё время. Может быть, мы только что сэкономили несколько дней из будущего времени на разработку? Или же мы могли бы подождать еще чуть-чуть, чтобы погасить технический долг позже, и вместо этого добавить несколько новых фич? Мы никогда не знаем наверняка и списываем своё незнание на то, что разработка продукта — это скорее искусство, чем наука.
Что ж, самое время добавить в процесс немного науки.
Чем похожи надежность сайта и бюджет техдолга
Должным образом управляемый и целенаправленно планируемый технический долг может быть бесценным инструментом. Осознавая, что мы делаем, мы можем использовать его подобно тому, как используем финансовый долг, — в качестве плеча. Но если мы, сами того не подозревая, берем на себя слишком много — например, не понимаем до конца условий сделки (то есть влияния, которое техдолг оказывает на нашу кодовую базу, клиентов, команду и бизнес) — дело может кончиться крахом нашей компании.
Лучшие команды по управлению надежностью сайта оперируют своим бюджетом надежности сайта в понятиях управляемого технического долга. Надежность сайта (Site Reliability) — понятие, популяризованное Google; она отвечает за сохранение программных продуктов в состоянии «запущено и работает», но, что интересно, компании вроде Google не ставят своей целью довести uptime до 100%. Причина в том, что uptime в 99,99% вполне достаточен, чтобы продукты Google были исключительно надежны для реальных пользователей. А эту последнюю 0,01% добиться экспоненциально трудно, и бороться за неё просто нет смысла.
Следовательно, если это даёт в сумме 52 минуты даунтайма в год, Google будет пытаться подобраться как можно ближе к этой цифре; но всё, что меньше 52 минут в год, является упущенной возможностью взять на себя дополнительные риски и быстрее предоставить какие-либо перспективные фичи своим клиентам.
Думайте о своём бюджете технического долга как о бюджете надежности сайта. При условии, что вы берете на себя разумный технический долг и остаетесь ниже максимальной суммы долга, которую вы можете позволить себе, прежде чем это начнет влиять на ваших клиентов и бизнес, — вы должны увеличивать сумму долга, чтобы взять на себя больше рисков и победить своих конкурентов.
Если ваш технический долг находится в красной зоне, необходимо частично погасить его. Если он в зелёной зоне, вы можете взять на себя больше рисков и больше долга. Ваша цель — постоянно удерживать величину долга максимально близко к идеальной. Другими словами, если вы на пике красной части графика, идеальный бюджет технического долга A ⇒ B. Если вы во впадине зелёной части графика, то идеальный бюджет C ⇒ B. Помните лишь о том, что A ⇒ C — это слишком большой бюджет технического долга.
Так как технический долг может быть измерен (об этом мы писали в другой статье), это все теперь не просто концепции — это полностью отвечает практическим потребностям.
Как выжать максимум из своего бюджета технического долга
Вы должны стремиться к такому бюджету технического долга, который возвращает вас вниз или вверх, к максимальной сумме технического долга, которую вы можете себе позволить. Чтобы определить этот бюджет, очертите в своей кодовой базе области, где технический долг стоит погасить немедленно, то есть долги, которые помешают вашей компании достичь своих текущих целей. Для вас нежелательно возвращать как слишком мало долга, так и слишком много.
Андреас Клингер, координатор удалённых команд в AngelList, хорошо излагает это в своей статье «Рефакторинг больших баз унаследованного кода»:
Не всё нужно рефакторить. Если это не критичная часть, или никому не нужно улучшать данную функциональность в ближайшие месяцы, или это просто слишком сложно, подумайте о признании этого места техническим долгом.
if(rtbW>=960){var rtbBlockID="R-A-744041-3";} else{var rtbBlockID="R-A-744041-5";}
window.yaContextCb.push(()=>{Ya.Context.AdvManager.render({renderTo:"yandex_rtb_4",blockId:rtbBlockID,pageNumber:4,onError:(data)=>{var g=document.createElement("ins");g.className="adsbygoogle";g.style.display="inline";if(rtbW>=960){g.style.width="580px";g.style.height="400px";g.setAttribute("data-ad-slot","9935184599");}else{g.style.width="300px";g.style.height="600px";g.setAttribute("data-ad-slot","9935184599");} g.setAttribute("data-ad-client","ca-pub-1812626643144578");g.setAttribute("data-alternate-ad-url",stroke2);document.getElementById("yandex_rtb_4").appendChild(g);(adsbygoogle=window.adsbygoogle||[]).push({});}})});
window.addEventListener("load",()=>{
var ins=document.getElementById("yandex_rtb_4");if(ins.clientHeight =="0"){ins.innerHTML=stroke3;}},true);
Проще говоря, ваша цель — найти, где перекрываются две вещи: то, над чем вы будете работать в текущем спринте, месяце или квартале, и те части вашей кодовой базы, которые содержат технический долг. Выплачивайте долг в зоне этого пересечения, но не за её пределами.
И именно здесь наука дополняет искусство. Вы можете использовать данные, чтобы определить области, где вам нужно погасить технический долг в ближайшее время:
- Выделите в своей кодовой базе файлы со слабым владением, поскольку владение кодом является ведущим показателем благополучия вашей кодовой базы. Подробнее об этом — в нашей статье «Одна особенность корпоративной культуры, необходимая для благополучия кодовой базы».
- Измерьте связность (cohesion) и зацепление (coupling) для этих файлов и оставьте в списке лишь файлы со слабым владением, низкой связностью и высоким зацеплением. Вы можете узнать больше о каждом из этих показателей в нашей статье «Использование исследований лидеров отрасли для измерения технического долга».
- Рассчитайте повторяющуюся активность (churn) для каждого из этих файлов, чтобы определить подмножество проблемных файлов. Как показало исследование Microsoft, активно изменяющиеся файлы составляют лишь 2–8% от общего объема файлов в системе, но на них приходится 20–40% всех изменений, и они ответственны за 60–90% всех багов.
- Соотнесите полученный список файлов с вашими планами на квартал. Потребует ли какая-либо из фич, перечисленных в ваших планах, поработать над подмножеством проблемных файлов, которое вы очертили? Если да, поставьте цели, связанные с рефакторингом этих файлов, оцените необходимый объем работ и назначьте задачи на конкретных разработчиков, — желательно, на тех, которые являются владельцами соответствующих файлов. Впишите эту работу в свои планы.
Для начала гляньте наше бесплатное расширение VSCode — оно поможет вам постоянно отслеживать и выплачивать самые неотложные технические долги.
if(rtbW>=960){var rtbBlockID="R-A-744041-3";} else{var rtbBlockID="R-A-744041-5";}
window.yaContextCb.push(()=>{Ya.Context.AdvManager.render({renderTo:"yandex_rtb_3",blockId:rtbBlockID,pageNumber:3,onError:(data)=>{var g=document.createElement("ins");g.className="adsbygoogle";g.style.display="inline";if(rtbW>=960){g.style.width="580px";g.style.height="400px";g.setAttribute("data-ad-slot","9935184599");}else{g.style.width="300px";g.style.height="600px";g.setAttribute("data-ad-slot","9935184599");} g.setAttribute("data-ad-client","ca-pub-1812626643144578");g.setAttribute("data-alternate-ad-url",stroke2);document.getElementById("yandex_rtb_3").appendChild(g);(adsbygoogle=window.adsbygoogle||[]).push({});}})});
window.addEventListener("load",()=>{
var ins=document.getElementById("yandex_rtb_3");if(ins.clientHeight =="0"){ins.innerHTML=stroke3;}},true);
Вступите в долгосрочные отношения с техническим долгом
Мы внедрили данный подход, основанный на данных, в Stepsize, а также во многих софтверных компаниях мирового класса. Мало того, что тема технического долга стала теперь намного понятнее, так мы ещё и знаем, сколько долга мы готовы взять на себя, и когда/как его вернуть. Мы все редко задумываемся, правильно ли мы выбрали компромисс между новыми фичами и техническим долгом. Нам удалось устранить существенную часть догадок, а также множество страхов и беспокойств, сопровождавших данный выбор.
Проясним еще раз: это не серебряная пуля, которую можно использовать раз в год и потом забыть. Вам нужно познакомиться поближе со своим техническим долгом. Отслеживайте свой прогресс по всем показателям каждого спринта и продолжайте совершенствовать весь процесс, чтобы достичь технического благополучия.
Мы написали о нескольких способах сделать это, поэтому для создания правильной мотивации почитайте о взращивании культуры разработки, основанной на владении и о чествовании разработчиков, которые возвращают технический долг.
Технический долг и места его обитания / Habr
Эта статья — вольный пересказ доклада, который я посетил на конференции GOTO Berlin 2017: A Crystal Ball to Prioritize Technical Debt.
Изображения из доклада и права на них принадлежат автору @AdamTornhill.
Каждый разработчик в принципе понимает, что такое технический долг. Что в его проекте этот долг наверняка присутствует. Если повезет, он вспомнит несколько кусков кода, которые давно просятся быть переписанными.
Но как формализовать понятие технического долга, чтобы объяснить его другим? И, тем более, объяснить это менеджеру так, чтобы получить одобрение на рефакторинг? Как найти все места в проекте, которые нужно по-хорошему переписать, и как определить, какие из них должны быть переписаны в первую очередь?
Если эти вопросы неоднократно у вас возникали, прошу под кат.
Не весь коряво написанный код по определению является техническим долгом. Конечно, если есть такой код, то его лучше рано или поздно переписать. Но все мы знаем, что полировать код можно чуть ли не до бесконечности. Как же определить, какой код является техническим долгом?
Довольно хорошее описание технического долга дал Мартин Фаулер:
Like a financial debt, the technical debt incurs interest payments, which come in the form of the extra effort that we have to do in future development because of the quick and dirty design choice.
То есть, чем больше усилий во время разработки мы затрачиваем из-за какого-то куска кода, тем большим техническим долгом он является. С этим сложно не согласиться, но все же этого недостаточно для того, чтобы четко определить, какие места должны быть переписаны.
Для того, чтобы оценить, насколько каждый конкретно файл/класс/функция затрачивает наши усилия при разработке, Адам вводит такое понятие, как горячие точки, Hotspots. И для поиска этих хотспотов нужен только один инструмент, который есть практически у каждого разработчика — система контроля версий.
if(rtbW>=960){var rtbBlockID="R-A-744041-3";} else{var rtbBlockID="R-A-744041-5";}
window.yaContextCb.push(()=>{Ya.Context.AdvManager.render({renderTo:"yandex_rtb_2",blockId:rtbBlockID,pageNumber:2,onError:(data)=>{var g=document.createElement("ins");g.className="adsbygoogle";g.style.display="inline";if(rtbW>=960){g.style.width="580px";g.style.height="400px";g.setAttribute("data-ad-slot","9935184599");}else{g.style.width="300px";g.style.height="600px";g.setAttribute("data-ad-slot","9935184599");} g.setAttribute("data-ad-client","ca-pub-1812626643144578");g.setAttribute("data-alternate-ad-url",stroke2);document.getElementById("yandex_rtb_2").appendChild(g);(adsbygoogle=window.adsbygoogle||[]).push({});}})});
window.addEventListener("load",()=>{
var ins=document.getElementById("yandex_rtb_2");if(ins.clientHeight =="0"){ins.innerHTML=stroke3;}},true);
Оценить количество усилий на поддержку файла с кодом можно, взглянув на то, как часто этот файл меняется, и на то, какая сложность у этого файла. С оценкой частоты изменений все однозначно и понятно. Сложность можно оценить разными способами, в зависимости от ваших предпочтений. В простейшем случае это может быть размер файла или количество строк кода. При прочих равных условиях поддерживать файл на 100 строк кода сильно проще, чем файл на 1000 строк кода. Если же размер файла в вашем случае не является критерием оценки сложности, можно воспользоваться различными утилитами для статической оценки сложности (например, цикломатической).
Тогда хотспоты можно будет выявить следующим образом:
Вот пример поиска горячих точек в проекте Tomcat:
Большие синие круги — это папки. Маленькие — файлы.
При всем этом, наличие хотспота совсем не означает, что этот файл проблемный (но чаще всего так и есть).
Также в качестве примера приводятся графики анализа кода нескольких проектов, разных насколько это возможно. Разные языки, разное время жизни, разные компании-разработчики. По оси X у нас расположены файлы, по оси Y — частота их изменений.
У всех проектов наблюдается один и тот же паттерн. Большая часть кода расположено в «хвосте» графика. И соответственно, есть очень небольшая часть файлов, которые изменяются очень часто. Эти файлы тоже являются первыми кандидатами для рефакторинга.
При поиске хотспотов можно пойти глубже. И в проблемных файлах искать хотспоты уже на уровне отдельных функций:
Инструмент, который был использован для поиска таких хотспотов — codescene.io
Также полезной практикой будет регулярной отслеживание сложности вашего кода. Анализ таких данных в виде графиков будет очень наглядно показывать, в какие моменты вы сбились с верного пути.
if(rtbW>=960){var rtbBlockID="R-A-744041-3";} else{var rtbBlockID="R-A-744041-5";}
window.yaContextCb.push(()=>{Ya.Context.AdvManager.render({renderTo:"yandex_rtb_1",blockId:rtbBlockID,pageNumber:1,onError:(data)=>{var g=document.createElement("ins");g.className="adsbygoogle";g.style.display="inline";if(rtbW>=960){g.style.width="580px";g.style.height="400px";g.setAttribute("data-ad-slot","9935184599");}else{g.style.width="300px";g.style.height="600px";g.setAttribute("data-ad-slot","9935184599");} g.setAttribute("data-ad-client","ca-pub-1812626643144578");g.setAttribute("data-alternate-ad-url",stroke2);document.getElementById("yandex_rtb_1").appendChild(g);(adsbygoogle=window.adsbygoogle||[]).push({});}})});
window.addEventListener("load",()=>{
var ins=document.getElementById("yandex_rtb_1");if(ins.clientHeight =="0"){ins.innerHTML=stroke3;}},true);
Итоги
Мне этот доклад показался полезным в первую очередь из-за четкого определения технического долга и его размера.
Понятно, что чтобы заниматься таким серьезным анализом кода с выявлением хотспотов, это нужно очень сильно увязнуть в технических долгах. Но даже на базовом уровне, в повседневной работе, я стал обращать внимание на классы, которые чаще всего затрагиваю, и стараюсь такие классы потихоньку рефакторить.
Также, в качестве бонуса (был вопрос из зала на докладе), Адам рассказал, как правильно доносить до менеджмента необходимость в рефакторинге. Чаще всего менеджеры — не технические люди, довольно далекие от кода, иначе бы проблем не возникло. Но что эти люди хорошо понимают — это цифры и графики. Чтобы правильно донести до них информацию, нужно говорить с ними на одном языке. И как раз графики с хотспотами и временной зависимостью сложности кода могут тут помочь. На графиках можно показать, что вот такой-то функционал, который мы добавили недавно, сильно усложнил добавление новых фич. Следовательно, если мы в дальнейшем хотим ускорить темпы разработки, нужно потратить сколько-то времени на рефакторинг.
Полезные ссылки:
Пьеса «Технический долг» / Habr
Пьеса «Технический долг» в 9 частях. Ставится и показывается впервые.
Часть 0: В пустой комнате стоят Разработчик (Р) и Менеджер (М).
М: Я собрал нас тут, чтобы рассказать пренепреятнейшее известие: система КРОТОПОН, которая работает на продакшане заглючила и мы потеряли кучу денег. Кроме того нет никого, кто знает как она работает. Поэтому (с придыханием) наш СЕО дал мне священную миссию — написать новую систему. Как ты думаешь, за два месяца справишься?
Р: А что делать-то нужно?
М: Да там немного, всего лишь пару десятков систем связать и рюшечки навесить.
Р: Эй, да это же на год работы! И вообще требования будут?
М: (В телефон) Да, конечно, за пол года справимся. (Разработчику) Ну ты тут пока начинай, а я тебе требования потом донесу.
Менеджер уходит.
Р: Но тут же…
Разработчик тяжело вздыхает, затаскивает в комнату инструменты и начинает что-то сооружать.
Часть 1: Через 2 месяца. В комнате сидит Разработчик и что-то строгает. Забегает радостный Менеджер и протягивает Разработчику большую папку.
М: Знаешь что я принес? Это требования к системе составленные нашим главным писателем. А еще нашим проектом заинтересовался СЕО, так что мы релизимся на месяц раньше!
Р: (ошарашенно) Но ведь у нас всё рассчитано на пол года!
М: Не волнуйся, вот посмотри я подробные требования принёс, всё получится!
Разработчик смотрит требования.
Р: Но ведь это булшит, мы вообще об этих требованиях не слышали!
М: А, это? Это попросил сам СЕО, так что нужно обязательно сделать.
Р: Но я же не успею!
М: Не волнуйся, я что-нибудь придумаю.
Менеджер убегает. Разработчик начинает разбирать собранное в центре комнаты.
Часть 2: Через месяц, Разработчик собирает что-то совершенно не похожее на сооружение из предыдущей сцены. Входит Менеджер.
М: Радуйся, я привёл нам помощь!
Р: О, кто-то ещё будет разрабатывать этот продукт? Тогда мы справимся!
М: Не совсем. Знакомься, это наш Скрам-мастер!
Входит Скрам-мастер (С).
С: Здравствуйте дети! Всмысле приятно познакомится!
М: Он поможет тебе лучше распределять время между задачами повысит производительность нашей команды.
Р: Но я же один в команде…
С: Не волнуйся, я только что прочитал об особом виде СКРАМ, который как раз подходит для команд из 3-х человек.
Менеджер уходит, Скрам мастер сдвигает сооружение сделанное разработчиком в угол комнаты и начинает рисовать графики.
Часть 3: Месяц до релиза. Скрам мастер сидит в центре комнаты в позе йога, Разработчик пытается соединить всё в углу комнаты. Входит Менеджер.
М: О, я вижу у вас всё готово? Хорошо!
Р: Оно неидеально, но к началу тестирования я успею закончить.
М: А, ты про это… У нас не будет тестирования.
Р: Что?
М: Я поговорил с ВИПами и они хотят видеть всё за 2 недели, как мы покажем всё СЕО. Так что тестирование отменяется.
Р: Но ведь у меня нет времени укрепить всё к этому показу!
М: Не проблема, подопри костылями и прибей гвоздями.
Р: Оно не будет работать и мне стыдно будет показывать такой код!
М: Не волнуйся, мы всё исправим после релиза.
Менеджер уходит. Разработчик начинает прибивать костыли к сооружению, в результате чего оно становится похожим на ежа.
Часть 4: Неделя до релиза. В окне мелькает молния, в углу стоит противотанковый ёж из костылей. Рядом спит Разработчик. Вбегает Менеджер и будит Разработчика.
М: Надо всё переделать!
Р: Как? Что? Оно же работает!
М: Наш проект посмотрели випы и вот список доделок которые нужно сделать до показа СЕО.
Менеджер выходит из комнаты и ввозит тележку заполненную бумагой.
Р: Но… как? (Смотрит на первую попавшуюся бумажку из кучи) Это же соврешенно не так, как было написано в требованиях!
М: Забудь про требования, надо сделать так.
Р: Но ведь Скрам-мастер говорит, что мы не будем принимать новые требования!
С: Ты знаешь, новые требования принимать нельзя, но если очень хочется, то можно переключиться на особый вариант аджаил для котов и там это допустимо. Кстати меня уже позвали помочь соседнему проекту, я пойду.
Скрам-мастер уходит.
М: Не знаю, как ты, но я собираюсь сегодня ночевать в офисе. Обещаю хорошую премию по результам!
Менеджер демонстративно садится напротив Разработчика и начинает на него смотреть.
Р: Ладно, я попробую что-нибудь сделать, но после релиза нужно будет всё исправить!
М: Да, конечно, у тебя будет время на это после релиза.
Разработчик начинает разбирать бумаги в тележке, Менеджер на него смотрит.
Часть 5: В углу комнаты стоит покачиваясь неустойчивая конструкция, рядом среди стаканчиков из-под кофе спит Разработчик. Входит Менеджер.
М: (Оглядываясь вокруг) Хорошо поработали. (Тормошит разработчика) Ты знаешь, наш проект хорошо оценили. Так и сказали, что я мастер управлением персоналом, что смог вытащить этот проект за такой малый срок. Так что меня повысили. Знакомься, это твой новый менеджер!
Входит Менеджер 2 (М2), Менеджер раскланивается с ним и выходит.
М2: (смотрит на полу-спящего Разработчика) Привет! Надеюсь ты полон сил и решимости работать на благо нашей компании?
Р: (с трудом садясь) Да, надо подчистить технический долг после релиза… И Менеджер обещал мне премию…
М2: Странно, мне он забыл об этом сказать. Я спрошу его. А пока, раз ты готов решимостью, мне нужна помощь с другим проектом.
Менеджер 2 выходит и вкатывает телегу с гавном.
Р: Это же куча говна!
М2: Нет, это очень важный проект, который сделал наш Гуру. Тебе нужно всего лишь исправить пару маленьких недоделок внутри, тогда и поговорим о премии кстати.
Менеджер 2 уходит.
Часть 6: Разработчик сидит и пытается починить колесо у телеги с говном, входит Менеджер 2.
М2: Ну вот, отлично выглядит, а ты говорил что куча говна.
Р: Так можно мне премию?
М2: Да, да, конечно. Я обо всём договорился. Только мы немного опоздали и поэтому прийдётся ждать окончания следующего отчётного периода через 6 месяцев. Кстати решено выпустить вторую версию этого замечательного продукта (оглядывает покачивающегося противотанкового ежа в углу комнаты).
Р: (отряхиваясь от говна) Хорошо, наконец-то я смогу починить эти костыли!
М2: Нет, на это нет времени. У нас есть куча новых требований.
Р: Но приложение же нестабильно! Я не смогу добавлять новую функциональность, пока не исправлю старую!
М2: Не бойся, я попрошу о помощи, начинай делать.
Часть 7: Те же лица, Разработчик пытается что-то делать.
М2: Возрадуйся, я договорился о помощи!
Р: Надеюсь не Скрам-мастера?
М2: Нет, я привёл настоящего профи своего дела! Знакомься, Гуру. Ты уже видел его проект (кивает на телегу с гавном).
Входит Гуру(Г).
М2: Гуру будет руководить доработками. Вопросы?
Р: Но я же лучше знаю проект…
М2: Да, покажи проект Гуру.
Разработчик начинает показывать проект.
Р: А тут у нас куча костылей, их планировали исправить до релиза.
Г: (покачивая головой в разные стороны) Да, понимаю.
М2: Ну как, разобрались, успеете?
Г: Конечно, сделаем всё в лучшем виде. Начнём с самой важной части — платформы. Всё просто необъодимо переделать согласно последним трендам.
Р: Но…
М2: (хлопая в ладоши) ну вот и разобрались!
Часть 8: Те же лица, Гуру втаскивает в комнату ещё одну телегу и вогружает на неё противотанкового ежа. От ежа в процессе отрывается половина костылей и то, что к ним крепилось и остаётся лежать на полу. Потом он бережно переливает гавно из первой телеги в новую покрывая остатки ежа.
Г: Ну вот, я даже перевыполнил план, заодно добавил интеграцию с прошлой системой. Кстати забыл сказать, я ещё работаю на 10 других проектах и моё время для этого проекта вышло, но я буду заходить и смотреть что ты сделал. Дальше уже тривиально. Пока!
Гуру выходит из комнаты.
Р: Всё, меня всё достало, я увольняюсь!
М2: Премия. Сразу после релиза.
Р: Да мне уже больше предлагают!
М2: Тогда ещё повышение зарплаты, тоже после релиза. И вообще ты профессионал или где? Уходить сейчас непрофессионально!
Р: Ок. (начинает собирать костыли с пола)
Часть 9, заключительная: В центре комнаты стоит телега с гавном и скульптурой из костылей, сидит Разработчик. Входят Менеджер 2 и Гуру.
М2: Какие мы молодцы, что сделали эту систему! Особенно важна самоотверженность с которой ты (обращается к Гуру) в условиях жёсткой нехватки времени идеально встроил новую платформу! Обязательно выдам тебе хорошую премию.
Р: Надеюсь вы не забыли про меня?
М2: Нет, конечно нет! Только у меня для тебя новость — я вместе с Гуру перевожусь в другой отдел, так что тобой займётся уже Менеджер 3. А вот кстати и он!
Менеджер 2 и Гуру уходят, входит Менеджер 3(М3).
Р: Давай поговорим о моей премии и повышении зарплаты, о которых я договорился с Менеджером 2!
М3: Подожди, подожди, я слышал об этом, но мне кажется что там повышение слишком большое. Тем более основную работу сделал Гуру. Давай поговорим об этом через 6 месяцев, когда я присмотрюсь к тебе. Сейчас мне всё равно не выделили бюджет на увеличение зарплатного фонда.
Р: Да идите вы… (Разработчик пишет заявление ПСЖ и увольняется, уходит со сцены)
Менеджер 3 пишет записку «Так как Разработчик был недостаточно лояльным и уволился прошу выделить мне команду для поддержки этого приложения а пока мы замораживаем все работы по нему».
Через пол года всё рассыпается и компания теряет много денег. Обвиняют во всём уже ушедшего из компании Разработчика и решают сделать новую систему, так как никто не понимает как работает старая.
КОНЕЦ
При написании этого текста не пострадал ни один костыль.
Все совпадения с реальными людьми и событиями считать злонамеренными.
Белорусский разработчик — перфекционист? Компании | dev.by
Чистота кода против сроков релиза и продуктовых характеристик, техническое совершенство против сиюминутных требований рынка — диалектика качества и скорости является одним из предметов спора в ИТ-сфере. Заметили это по комментариям к интервью Онгана Мордениза, упрекнувшего белорусских разработчиков в перфекционизме, и решили развить тему.
Правда ли, что для нашего инженера технологии важнее бизнеса, как часто приходится идти на компромисс и что такое допустимое снижение качества кода ради быстрого выхода на рынок?
“Если он не сделает всё идеально с первого раза, то шанса исправить не будет»
Дорофей Пролесковский, разработчик-картограф, продакт-менеджер Kontur.io:
— У меня есть любимый вопрос, на который я пока не нашёл ответа. Компания/команда может поддерживать в нормальном состоянии в адекватной скорости разработки проект определённой сложности. То есть с какого-то момента фичи надо не добавлять, а убирать. Итак, вопрос: как понять, что уже пора, как выделить на это время и понять, что именно выпилить?
Технический долг — не про низкое качество. Он про то, что у тебя уже есть какая-никакая архитектура, и ты, разработчик, посреди неё вбиваешь костыль, заметный только для тебя, и сообщаешь о нём в будущее. Пишешь тикет на менеджера или тимлида в команде, ставишь TODO и FIXME в коде, если пилите стартап вдвоём, или записываешь в тетрадочку, если делаешь пет-проект для себя. При этом костыль может быть очень высокого качества, ведь его цель — сделать так, чтобы всё, что нужно прямо сейчас, заработало.
Код низкого качества сам по себе, без метода его учёта и планирования его «отдачи», когда тикеты будут закрываться, а костыли вытаскиваться — не долг. Случается, что разработчик погрязает в рефакторинге своего же кода, и никто его не может оттуда вытащить, потому что уже через неделю никто не помнит, что же рефакторилось и зачем, и чинятся просто все вещи, которые не нравятся — хотя они в принципе и не были поломаны. Может быть, задача была плохо сформулирована, может быть, это способ медитировать над кодом — регулярно переписывать его, чтобы удержать в голове, но это уже не про технический долг.
Бывает, что технический долг становится техническим мошенничеством: когда его регулярно «теряют» из приоритетов и очень просят разработчика сделать штуку, которая уже в пять раз сложнее из-за костыля, который пришлось вбить в прошлый раз, не вытаскивая старый костыль — на него «нет времени». Думаю, где-то на стыке этих двух проблем сосредоточена почти вся боль технического долга — кто-то забыл о нём сказать, кто-то забыл поставить в приоритет даже то, о чём сказали, в результате воспитывается инженер-перфекционист, живущий сегодняшним днём и верящий, что если он не сделает всё идеально с первого раза, то шанса всё исправить не будет.
«Мы не всегда знаем, что пишется на уровне „сделал и забил“, а что будем долго и упорно тянуть»
Арсений Кравченко, ML инженер, ods.ai:
— Если проект маленький и простой, его вряд ли нужно будет серьёзно развивать, то кажется, что можно писать код, катаясь рожей по клавиатуре, кое-как работает — и ладно. Выплаты по техническому долгу несущественны. Так и пишутся простыни говнокода, прикрытые оправданиями «ну, вот если бы у меня был сложный проект…».
Проблема в том, что мы не всегда знаем, что пишется на уровне «сделал и забил», а что будем долго и упорно тянуть. Из-за этого незнания получаются и проектики на полтора файла с любовно отполированной архитектурой, и жуткие неподдерживаемые поделия, в которых минимальное изменение занимает недели и может все развалить. Получается, проблема не только техническая, но и продуктовая.
Значит, проблема частично решается прозрачностью в отношениях менеджера и исполнителя: если продуктовые ребята честно могут сказать как «мы не уверены в будущем этой фигни», так и «все указывает на то, что мы с этим будем жить долго и упорно», то и инженерная команда может принимать более или менее адекватные решения, насколько близок к недостижимому идеалу должен быть этот кусок кода.
В задачах машинного обучения есть ещё одна похожая дихотомия: сколько сил инвестировать в сами модели и алгоритмы, а сколько — в инфраструктуру вокруг данных. Иногда эти инвестиции оказываются очень удачными: например, в Wanna Kicks однажды инвесторы похвалили последний релиз, в котором был исправлен ряд заметных пользователю проблем. Ирония была в том, что с точки зрения ML не было добавлено вообще ничего, кроме новых обучающих данных, что не потребовало никаких усилий от R&D команды благодаря вовремя сделанной инфраструктуре.
«Баги допустимы, если время на их исправление минимально»
Николай Курдесов, руководитель R&D-подразделения Gurtam:
— Буду говорить субъективно о нашей компании, но, кажется, это происходит повсеместно в Беларуси. Если не брать во внимание случайных людей в разработке, средний уровень специалиста всё же растёт. Но в этом и заключается одна из проблем: сколько времени ни выделяй хорошему специалисту для решения задачи, он потратит всё. Просто, чем выше его уровень, тем лучше он заложит архитектуру, больше нюансов учтёт, использует лучшие алгоритмы с точки зрения оптимизации и т. п.
Сейчас, как я вижу, многие пытаются оградить разработчика: между ним и клиентом/заказчиком стоит целый ряд из менеджеров проектов, бизнес-аналитиков, тестировщиков, специалистов технической поддержки и т. д. Всё понимание бизнеса переходит в игру, решение задач, а это ломает восприятие и понимание действительно важных приоритетов. Как правильно закладывать архитектуру, а чем можно пренебречь. В итоге исполнитель пытается сделать всё «на совесть», а потому и так долго. Мы пропагандируем следующее: современный разработчик общается с клиентами (в нашем случае — пользователями платформы), оценивает потребности и риски, предлагает варианты в рамках обозначенных ресурсов, будь то деньги или время, и часто меняет задачу, принимая эффективные решения.
Как часто приходится идти на компромисс, жертвуя архитектурой в угоду клиенту? По моему опыту, большинство разработчиков вопросы бизнеса прекрасно осознают и идут навстречу. Они понимают, что если продукт «выстрелит», то у них будет возможность переписать многие спорные вещи.
Сопротивление встречается тогда, когда время выделяется не на надёжность и предсказуемость системы (логи, метрики, статистика, бэкапы и т. п.), а на визуальную составляющую: например, нужно переделать меню, добавить маловажную, с точки зрения разработчиков, «фишку» или любые другие «нюансы». С одной стороны, визуальную составляющую видят и оценивают пользователи/клиенты. С другой, когда что-то идёт не так, времени разобраться, диагностировать и исправить почти не остаётся. А многие механизмы, например, отказоустойчивости, не заложены вовсе, ведь вероятность выпадения сервера «объективно не очень высока». Всё это, как дамоклов меч, висит над головой ответственной команды разработки, и, когда что-то происходит, счёт идет реально на секунды.
Что такое допустимое снижение качества кода? Давайте проведём аналогию с автомобилями. С одной стороны, производители хотят выпустить красивое, функциональное, с минимальной себестоимостью авто. С другой стороны, закладывать огромный ресурс экономически невыгодно. Да и давайте быть честными: кто захочет сесть за руль надёжного, но морально и технологически устаревшего авто? Новые технологии с каждым годом становятся всё доступнее, и каждый год есть возможность сделать продукт более совершенным «за ту же цену».
Но при этом крайне важно, чтобы он не ломался хотя бы в гарантийный период. Основная функция вашего софта должна работать всегда. Невозможность войти в систему или отказ основной функции должны быть исключены.
У нас такой принцип: баги допустимы, если время на их исправление минимально. Тут имеет значение и время доставки приложения пользователю. Есть web-интерфейсы, где обновление у клиента может произвестись просто при обновлении страницы. Есть мобильные приложения, где весомая часть пользователей обновляется редко. А есть решения, расположенные на серверах клиентов, время на обновления которых слишком велико. Согласитесь, одно дело, когда после сообщения о баге исправление приходит в тот же день, и совсем другое — когда надо ждать месяц.
Кроме того, если у вас код весь на «копипастах», то о быстром внесении изменений, например схемы БД, API, не может идти и речи. А значит, архитектура и сам код должны быть такими, чтобы максимально быстро можно было разобраться и внести правки.
Репутацию компании часто портит не столько сам факт наличия багов, а то, сколько времени тратится на их устранение. Так что даже в рамках одного продукта, если он работает в разных вариациях, могут и даже должны использоваться разные подходы.
Случаев, когда скорость решала всё, у нас просто тьма, расскажу об одном. Один из клиентов сделал запрос на интеграцию gps-трекера в нашу систему. Обычно мы просим сконфигурировать такой трекер для отправки данных на наш сервер. Процесс полноценной реализации может занимать до двух недель. Но через пару дней он сообщает о том, что авто, на котором был установлен трекер, украли. Ни о какой полноценной интеграции и тестирования речи в тот момент уже не шло. Конечно, мы пошли навстречу клиенту. В итоге он получил самое основное, что ему было нужно: координаты появились в системе. Мы — лояльного клиента. А наш разработчик-перфекционист — столько времени, сколько нужно для того, чтобы переделать всё как надо.
«Мне хорошо — жертвовать архитектурой не приходится вовсе»
Иван Подобед, Technical Fellow в Awem:
Нормального белорусского инженера я вижу не перфекционистом, а, скорее, здравомыслящим человеком, работающим на свою карьеру. В большинстве известных мне случаев «перфекционизм» объяснялся желанием инвестировать в технологическую экспертизу, иногда в ущерб балансу качество/сроки/стоимость: экспертизу потом можно и перепродать на рынке труда, а полумифическое «понимание бизнес-необходимости выпуска продукта с техническим долгом» продаётся не так бодро. У нас с командой есть хорошее взаимопонимание, и, вроде бы, найдено равновесие между инвестированием в экспертизу и поддержанием баланса качество/сроки/стоимость. Хотя многие решения со стороны всё ещё выглядят как over-engineering, за каждым из них стоит оценка рисков.
Иногда стоит допустить небрежность, потому что клиент ждёт? В целом — согласен, хотя над формулировкой стоило бы поработать.
Более того, иногда сработать надёжно, надолго, в соответствии с архитектурой значит совершить преступление перед работодателем.
Зачем полировать прототип, который создан для проверки продуктовой гипотезы? Зачем строить масштабируемую систему доставки, потолок расчётной производительности которой измеряется десятком событий в секунду? Очень вредно проектировать пользовательский интерфейс внутренней системы, когда её можно запустить на стандартной админке, а сэкономленное время направить на исследование опыта использования первой версии для получения более релевантных требований. В целом возможно много сценариев, когда работать надо именно на скорую руку, но при этом важно сохранять осознанность: фиксировать trade-offs, риски, потенциальные улучшения для следующей версии и явные причины жертвовать чем-то ради скорости.
Мне хорошо — жертвовать архитектурой не приходится вовсе, так как наши архитектурные принципы включают в себя и работу с хардкодом, и с прототипами, и условия перехода от хардкода к конфигурации, и замену своих решений на сторонние компоненты, и переход к MVP. Для нас, наоборот, «жертвовать архитектурой» означает принимать долгосрочные решения в области высокой неопределённости.
Каждое решение, ведущее к увеличению технического долга, имеет весьма определённую цену — стоимость исправления этого самого долга. И так как эта цена имеет свойство расти со временем, «грань допустимого снижения качества ради скорости» вычисляется как точка сходимости — в какой момент времени вы сможете инвестировать достаточно времени и ресурсов на исправление техдолга. Бывают случаи, когда ожидаемое время жизни системы меньше, чем время окупаемости возвращения технического долга — в этом случае борьба с долгом так себе затея. Однако важно понимать, что все прогнозы — срок жизни системы, стоимость возвращения долга, риски от создания техдолга — величины вероятностные.
Риски имеют неприятное свойство выстреливать. Недавно на проекте одно из решений на нас отыгралось — пришлось возвращать долг быстро и вне очереди. А продукт показал на рынке такой выдающийся результат, что его время жизни серьёзно выросло, и многие архитектурные решения тут же превратились из «очень хороших» в «весьма посредственные». Но ничего страшного — все решения можно пересмотреть за определённую цену, и если прибыль превысит стоимость, можно хоть весь продукт переписать. Главное — принимать решение осознанно, тогда, даже если оно окажется неправильным, это будет лишь повод извлечь урок.
Скорость в нашем домене всегда в приоритете, она идёт сразу за качеством. Именно поэтому в наших архитектурных процессах заложен принцип разблокирования — достаточно четкие градации допустимых инвестиций в инжиниринг в зависимости от потребности продукта. Если мы блокируем доставку фичи, смело влезаем в технический долг, но с оглядкой: интерфейсы фиксируем, пользовательский опыт бдительно сохраняем. Как разблокируем, тут же возвращаемся в бэклог на предмет оплаты техдолга, а в нем уже аккуратно сложены задачи по управлению конфигурацией, оптимизации, масштабированию, унификация и т. д.
Не зря говорят, что один проект никогда не будет похож на другой, даже если оба делает та же команда по тем же технологиям. Во многом потому, что каждый проект имеет свою уникальную цель, уникальный бизнес-контекст — и принимаемые архитектурные решения будут обязательно зависеть от этого бизнес-контекста. Где-то важна скорость, где-то технологичность, где-то универсальность. И, конечно, есть место проектам с фокусом на качество кода — как правило это документация возможностей API или портфолио программиста на гитхабе. В реальной жизни код нужен лишь для того, чтобы бизнес заработал деньги, и жизнь становится гораздо проще, когда инженеры становятся способны измерять цену своих решений для бизнеса — большинство вопросов про качество кода или перфекционизм обычно сразу отпадает.
«Компромиссные решения часто приводят к негативным результатам»
Сергей Щегрикович, Director of Engineering в Gismart:
— В той или иной степени перфекционизм присущ всем разработчикам, и наша компания не исключение. Что нас выделяет, это культура максимального результата при минимальных затратах. Прототипы фич и MVP мы выпускаем быстро, а дальше дорабатываем.
Компромиссные решения часто приводят к негативным результатам, поэтому мы решаем этот вопрос по-другому. Чётко определив требования к продукту и рассмотрев все возможные технические решения, мы приходим к оптимальному варианту реализации. Во многом это достигается слаженной работой продуктовой команды и пониманием того, что архитектура также преобразуется и меняется по мере развития продукта.
Продуктовая разработка предполагает большое количество экспериментов и тестирование различных гипотез. Широко распространена практика MVP — выпуска на рынок минимально жизнеспособного продукта с ограниченным функционалом, чтобы понять, насколько востребован продукт у аудитории. Если MVP оказался удачным, над ним дальше работает команда и доводит продукт до ума. Если нет, разработку можно свернуть достаточно быстро и безболезненно, так как были затрачены минимальные усилий. Тестирование гипотез — это тот случай, когда выпуск условно сырого продукта оправдан.
Приведу пример. Некоторое время назад мы выпустили фичу, которая позволяла обмениваться созданными аудиотреками в наших приложениях. Мы осознанно пошли на урезание функционала и выпустили MVP с минимальными затратами со стороны разработки. Мы не гнались за высокой производительностью или обработкой большого количества вариантов использования. После релиза мы поняли, что наши первоначальные гипотезы не оправдались, и мы удалили этот функционал. Открытая коммуникация на всех этапах разработки помогла найти нам простые решения и принять правильное решение по закрытию фичи.
Мы работаем на высококонкурентном рынке, где скорость — залог успеха. Делать продукты с максимальной скоростью — непростая задача. Для этого мы даём командам большое количество свободы, организуем отдельные команды для запуска новых продуктов и постоянно помогаем нашим коллегам наращивать экспертизу.
«Граница недопустимого там, где проценты по долгу выходят на траекторию банкротства»
Сергей Мушинский, Computer Vision Engineer, HD maps team, Mapbox:
— Мне кажется, что перфекционизм свойственен всем инженерам: если бы технологии не были важны и интересны для нас, мы бы шли заниматься бизнес-частью. Для того, чтобы компенсировать это, и нужны грамотные менеджеры — это их задача определять приоритеты, уравновешивать требования рынка и технологий.
На начальном этапе, когда еще непонятен product-market fit, конечно же, допустимо снижение качества кода ради выхода на рынок. Более того, оно может быть неизбежным, первая версия должна быть прототипом «на выброс», потому что всегда обнаруживается, что клиентам нужно что-то другое, и чем меньше было вложено в начальный вариант, тем проще выкинуть и полностью переделать.
С другой стороны, технический долг может накапливаться не только потому, что делали на скорую руку. Есть две крайности — некомпетентность, когда команда просто не знала, как можно было сделать лучше, и «оверинжиниринг» — когда были все ресурсы и пытались сделать максимально качественно, гибко и обобщенно, а в итоге получается монстр, которого невозможно понять.
Ещё один один аспект — «клиентский долг». Это когда у тебя уже есть заказчики, которым нужны новые фичи, исправление багов, поддержка и так далее, и с каждым новым пользователем у тебя остаётся всё меньше и меньше ресурсов на то, чтобы делать что-то новое. Это то, почему большие компании зачастую не могут делать то, что делают стартапы: несмотря на гигантские размеры, свободные ресурсы для новых направлений бизнеса у них могут быть даже отрицательными.
В прошлом году несколько раз нам надо было продемонстрировать готовые решения на международных выставках, то есть дедлайны были строгие. Такие моменты чётко показывают, с одной стороны, что в продукте действительно важно, а что просто рюшечки для «инженерной красоты», с другой — все слабые стороны продукта, чего не хватает и где ошибки в архитектуре. Важно после таких авралов провести ретроспективу, выделить время на то, чтобы оценить свою работу, и подумать, как сделать лучше.
Технический долг, как и любой другой, нужно выплачивать. Занимая у «себя будущего» для «релиза сейчас», надо понимать, что завтра придётся платить, значит, надо выделить время на прополку сорняков в коде. Граница недопустимого проходит там, где проценты по долгу выходят на траекторию, которая ведет к банкротству.
«Вся работа над продуктом состоит из компромиссов»
Левон Авакян, руководитель департамента разработки World of Tanks Game Logic:
— Давайте определимся: перфекционизм — это про сделать идеально, а не про технологии. Перфекционист стремится выполнить задачу отлично, а это оценка и самого решения, и его бизнес-ценности, значит, здесь не может быть перевеса «технология важнее бизнеса». Если такое происходит, это, скорее, от путаницы в голове: когда человек не может отличить собственную игрушку и амбиции от работы. Конечно, случается, что какое-то решение отвергается бизнесом, потому что его ценность не очевидна, но что мешает донести до бизнеса эту ценность? Да, кто-то из разработчиков скажет: там, в «бизнесе», никто ничего не понимает, но в большинстве случаев это искажённая оценка без учёта всех вводных. У нас есть разные сотрудники с разным уровнем скилов, и моя задача как руководителя развивать не только так называемые hard skills у сотрудников, но и в частности понимание, что мы делаем, зачем мы это делаем, почему мы это делаем. Важно донести до коллектива, что вокруг не враг «бизнес», а такой же профессионал, который видит ситуацию под другим углом, и только совместными усилиями мы можем сделать отличный проект.
Про жертвование архитектурой в угоду клиенту: архитектура — вещь фундаментальная, в ней не может быть небрежности. Тут, кстати, возникает вопрос: почему было выбрано архитектурное решение, которое не удовлетворяет такому требованию, как скорость разработки? Может, проблема не в том, что требует клиент, а в том, что изначально не были учтены все требования, включая нефункциональные? Вообще, во многих компаниях и командах любят рассуждать об архитектуре, совсем не понимая, что это такое и зачем она нужна. Да, иногда бизнесу нужно просто быстро что-то сделать, чтобы проверить какую-то гипотезу, и закапывать туда человеко-месяцы работы никто не хочет, это невыгодно, но на любом этапе бизнес-процесса нужно просто понимать, зачем мы делаем те или иные вещи, и слушать, а также слышать друг друга. В процессе разработки есть огромное количество вещей помимо архитектуры, которыми можно пожертвовать и занести в «технический долг», например, тесты, инструменты оперирования, мониторинг, документацию и так далее. И вот у каждой такой жертвы есть своя цена, которую нужно согласовать и с теми, кто отвечает за качество, и с теми, кто отвечает за надёжность, — в общем, со всеми. Вся работа над продуктом состоит из компромиссов, потому что идей и задумок много, а часов в сутках мало.
Когда мы говорим про качество, нужно понимать, как мы это качество измеряем. Чтобы что-то начать оценивать, нужно определиться, что именно конкретная компания или команда вкладывает в понятие качества. Во многих ли командах, компаниях занимаются измерением качества кода? Обычно, если инженер говорит: «Качество кода упало», — никому не известно, что он имеет в виду, это вкусовщина в чистом виде. С другой стороны, вы можете измерять 100 500 параметров, и по приборам всё будет хорошо, а по факту — не очень. Так что сначала нужно определиться, что вы вкладываете в понятие качества, потом начать его измерять, а потом уже выбирать грань между допустимым и недопустимым.
Но это просто лишь в теории, на практике дела обстоят куда сложнее, и даже на то, чтобы определиться с метриками, нужно потратить много сил и времени. Есть банальные правила, которые стоит выполнять: писать тесты, проводить код-ревью, следовать код-стайлгайду. Всё перечисленное не гарантирует качество кода, но сильно уменьшает риски отправить проект на помойку. Конкретные примеры из работы: в течение года есть определённые даты, к которым мы обязаны выпускать обновления. Никому не интересен Новый год в конце января, или Хэллоуин в декабре, при этом объём таких обновлений бывает очень большим. Очевидно, что под таким прессингом и качество технических решений, и их реализация, и контроль могут страдать. Но засорять основной продукт желания тоже нет, поэтому мы построили систему таким образом, что можем пристегнуть игровое событие, выпустить, и, если всё действительно плохо, выбросить код.
Очень часто скорость путают со спешкой. Рассчитать правильную скорость (выпустить продукт вовремя, не раньше, не позже) — это целое управленческое искусство. Если гнать сроки ради сроков, то результат получается не очень, плюс команда испытывает боль. Работа в максимально комфортных сроках для команды, по моему мнению, приведёт к общему расслаблению и потере фокуса, и это без учёта раздутых бюджетов. Где в работе действительно счёт идёт на минуты, так это в разрешении инцидентов: нужно проанализировать, что произошло, какие последствия и постараться их купировать. Обязательно нужно понять причину произошедшего, чтобы в будущем это не повторилось.
«В угоду клиенту мы жертвуем не только архитектурой, но и пожеланиями нашей бизнес-команды»
Андрей Шелег, заместитель директора ООО «Октонион технолоджи»:
— Белорусский инженер — перфекционист? Такое мнение справедливо для нашей компании в лучшем его понимании. Мне кажется, нам удалось отойти от крайних степеней перфекционизма и привить разработчикам понимание важности требований бизнеса. Более того, я считаю наличие перфекционизма двигателем развития нашей команды и архитектуры.
Бизнес-модель работы нашей компании с пл
Технический долг на проекте или выбраться из черной дыры / SimbirSoft corporate blog / Habr
Каждому разработчику знакома ситуация, когда реализация новой возможности в системе занимает большое количество времени, но релиз уже близко, а тимлид или менеджер проекта пятый раз за день задают уже надоевший вопрос: “Ну когда будет готово?”. И тогда встает непростой выбор — сделать все правильно и не уложиться в сроки релиза или реализовать минимально работающий, но не идеальный с точки зрения технического решения, функционал. Очевидно, что в большинстве случаев будет выбран второй вариант, так как релиз и предоставление результата клиентам здесь и сейчас важнее чистоты кода и архитектуры системы. Но проходит несколько месяцев, и вот уже старое не идеальное техническое решение мешает реализации другого функционала. И дальше такие решения будут накапливаться в огромный ком. Разбираясь с этой проблемой, очень важно сделать правильные выводы и выбрать нужное решение. От этого решения будет зависеть дальнейшая судьба всего проекта. В данной статье мы постараемся разобраться с природой технического долга и посоветовать пути его устранения.
Природа технического долга
Само понятие технического долга впервые ввел Уорд Каннингем (Ward Cunningham), разработчик технологии wiki и один из создателей экстремального программирования. В 1992 г. в своей статье он сформулировал это понятие в виде метафоры финансового долга: так же, как и при финансовом займе, разработчики могут получить дополнительные средства здесь и сейчас за счет использования быстрых и не оптимальных технических решений, но неизбежно будут расплачиваться за них при дальнейшей разработке, в независимости от того, как будет выплачен этот долг — постепенными выплатами процентов или одним платежом.
Но если проблема технического долга была описана еще 25 лет назад и встречается практически на любом проекте, почему еще нет методики управления проектами, которая позволяла бы избежать само появление технического долга? Ответ кроется в самом понятии проекта. Одним из ключевых отличий проекта от других видов деятельности является уникальность конечного продукта. Там где уникальность, там и непредсказуемость, и именно она порождает изменения на проекте и вносит трудности в первоначальное проектирование системы.
Конечно, можно попытаться построить архитектуру, предусматривая возможные изменения, но здесь команда столкнется с таким понятием как “кошелёк Миллера”: правилом, при котором в кратковременную память человека можно «положить» одновременно не более девяти «монет». А если количество элементов превышает это значение, то мозг пытается сгруппировать информацию так, чтобы их количество было от пяти до девяти.
Можно попытаться делить компоненты на более мелкие, чтобы уложиться в этот “кошелек”, но сложности от этого меньше не станет, да и количество абстракций при таком подходе будет расти с катастрофической скоростью. А как известно, любую проблему можно решить путём введения дополнительного уровня абстракции, кроме проблемы слишком большого количества уровней абстракции.
Другие команды предпочитают вообще отказываться от первоначального проектирования, максимально стараясь использовать по ходу разработки универсальные инструменты. С одной стороны, это проще, чем пытаться предсказывать изменения и на первых этапах система будет получаться достаточно гибкой к изменениям. Но со временем, сложность системы, согласно второму правилу Лемана, неизбежно будет расти, она станет менее гибкой, и могут возникнуть изменения, идущие вразрез с текущей архитектурой. В этом случае разработчики будут также тратить больше времени на решение архитектурных проблем.
Так или иначе, неизбежность изменений на проекте провоцирует появление технического долга.
Как определить, что на проекте есть проблема технического долга
Важнейшим показателем того, что на проекте есть проблема с техническим долгом, это, конечно же, сам код. Прежде всего, стоит сказать об особенности написания кода. Дело в том, что написание и чтение кода — два совершенно разных процесса. Когда разработчик пишет код, он сосредоточен лишь на контексте задачи. Но изменение отдельного участка кода влияет на общую картину происходящего. В свою очередь, прежде чем изменять написанный код, нужно иметь представление не только о конкретном участке, но и обо всей картине в целом. Но при чтении, границы контекстов, в рамках которых был написан код, стираются на общем представлении. Такая разница между чтением и написанием кода генерирует дополнительную сложность, которая прямым образом влияет на его качество.
На что следует обратить внимание:
- Участки кода, которые часто подвергаются изменениям. Скорее всего эти участки требуют серьезной доработки.
- Большое количество пометок FIXME и TODO и малое количество комментариев в коде должно насторожить. Современные IDE имеют встроенную поддержку работы с такими метками, так что это один из самых быстрых и надежных способов распознавания слабых мест в системе.
- Отсутствие тестов. Без них у разработчиков нет уверенности в том, что их изменения не нарушат работу системы. Команда относится к коду, не покрытому тестами как к карточному домику, стараясь избегать лишних, а порой необходимых, изменений.
- Отсутствие документации. Ситуация схожа с предыдущем пунктом. Отсутствие регламентированной информации заставляет разработчика самому додумывать картину происходящего, и есть вероятность, что у него сложится неверное представление о системе. Ситуация усугубляется тем, что в подавляющем большинстве случаев на проекте работают разработчики разного уровня подготовки и компетенции. А различие в понимании кода еще сильнее усложняют процессы чтения и написания кода.
- Устаревшие технологии и инструменты разработки. Любая библиотека или модуль обновляется, а поддерживать старые версии со временем становится все сложнее и затратнее.
- Отсутствие стандартов разработки. Каждый разработчик делает что и как он хочет.
Методы устранения технического долга
- Как и при лечении любой болезни, самый первый шаг к выздоровлению — это признание себя больным. Действительно, в первую очередь каждый участник проекта, от заказчика до разработчика должен признать проблему нарастания технического долга. Не так давно я стал тимлидом на одном крупном проекте, который достался нам в наследство, и работа по техническому долгу на нем никогда не велась. Копаясь в огромном количестве задач, я постоянно натыкался на задачи по устранению технического долга, которые создавались разными людьми в разное время, но так и не были реализованы. Это говорит о том, что попытки справиться в одиночку с технически долгом сравнимы с боем с ветряными мельницами. Очень важно, чтобы участники проекта осознавали эту проблему, ведь ее решения требуют исключительно системного подхода.
- Используйте гибкие методологии разработки (Agile). Основная суть методик состоит в разбиении разработки на небольшие, изолированные итерации длиной от одной до четырех недель. Таким образом обходится ограничение “кошелька Миллера”, ведь теперь в каждой итерации нужно работать только с ограниченным потоком информации, в котором легче управлять сложностью, и соответственно, техническим долгом.
- Введите общий и понятный всем регламент по работе с техническим долгом. Создайте бэклог, в котором будут находиться задачи на его выплату. И при добавлении нового функционала или при планировании следующей итерации уделяйте время на выполнение этих задач. Можно попробовать выделить время только на выполнение этих задач, но тогда разработка нового функционала зависнет, и скорее всего, вы столкнетесь с непониманием со стороны бизнеса. В своем проекте мы решили выделять 20%-30% времени от очередной итерации на погашение технического долга.
- Создайте метрики, по которым будет удобно следить за выполнением технического долга. Такие метрики индивидуальны для каждого проекта. Например, для своего проекта мы выделили такие метрики, как процент покрытия тестами и документацией, соответствие кода с принятыми Style Guides и сложность разворачивания системы на локальном окружении разработчика. Некоторые из метрик собираются автоматически, некоторые только субъективно каждым разработчиком. Важно, чтобы эти метрики были доступны всем, каждый участник видел прогресс и был согласен с ним.
Заключение
Проблема технического долга весьма актуальна на данный момент, и для каждого проекта требуется индивидуальный подход к проблеме его устранения.
Не стоит бояться выплат, ведь если принять правильную стратегию, то технический долг станет той силой, которая будет заставлять развиваться ваш проект. Именно работа с техническим долгом показывает уровень зрелости как самого проекта, так и команды, которая над ним трудится.
Технический долг — Википедия. Что такое Технический долг
Технический долг (также известный как долг кодинга) — это метафора программной инженерии, обозначающая накопленные в программном коде или архитектуре проблемы, связанные с пренебрежением к качеству при разработке программного обеспечения и вызывающие дополнительные затраты труда в будущем. Технический долг обычно незаметен для конечных пользователей продукта, а связан с недостатками в сопровождаемости, тестируемости, понятности, модифицируемости, переносимости. По аналогии с финансовым долгом, технический долг может обрастать «процентами» — усложнением (или даже невозможностью) продолжения разработки, дополнительным временем, которые разработчики потратят на изменение программного продукта, исправление ошибок, сопровождение и т. п. Хотя увеличение технического долга как правило негативно влияет на будущее проекта, оно может быть и сознательным, компромиссным решением, продиктованным сложившимися обстоятельствами.
Сам по себе плохой код не всегда является техническим долгом, так как ущерб («проценты по долгу») появляются из-за необходимости изменения кода со временем[1].
Термин технический долг используется в первую очередь по отношению к разработке программного обеспечения, но он также может быть применён и к другим сферам проектирования.
Иногда термин используется неправильно, обозначая более не поддерживаемый код (англ. legacy code), который является некачественным и написанный кем-то другим[1].
Причины
Общие причины технического долга (может быть несколько)[источник не указан 125 дней]:
- Давление бизнеса, когда бизнесу требуется выпустить что-то раньше, чем будут сделаны все необходимые изменения, может вылиться в накопление технического долга.
- Отсутствие процессов или понимания, когда бизнес не имеет понятия о технической задолженности и принимает решения без учёта последствий.
- Сильное зацепление компонентов, когда декомпозиция системы выполнена неправильно или недостаточно гибко, чтобы адаптироваться к изменениям бизнес-потребностей.
- Отсутствие тестов — ускоренная разработка и применение быстрых рискованных исправлений («костылей») для исправления ошибок.
- Отсутствие документации, когда код создаётся без необходимой сопроводительной документации. Работа, необходимая для создания вспомогательной документации, — это также долг, который должен быть оплачен.
- Отсутствие взаимодействия между командами, неэффективное управление знаниями в организации. Например, отсутствие наставничества в команде разработчиков.
- Отложенный рефакторинг — чем дольше задерживается рефакторинг, и чем больше написано кода, использующего текущее состояние проекта, тем больше накапливается технический долг, который нужно «оплатить» при следующем рефакторинге.
- Отсутствие опыта, когда разработчики просто не умеют проектировать программные системы или писать качественный код.
Последствия
«Процентные платежи» появляются как при локальной разработке, так и при отсутствии технической поддержки со стороны других разработчиков проекта. Продолжение развития проекта может в будущем увеличить стоимость «погашения задолженности». Оплата долга происходит посредством простого выполнения незавершённой работы.
Накопление технического долга является основной причиной для превышения сроков выполнения проектов. Трудно оценить, сколько именно работы необходимо выполнить для погашения долга. Неопределённое количество незавершённой работы добавляется в проект с каждым изменением. Сроки «горят», когда в проекте приходит понимание того, что есть ещё гораздо больше незавершённой работы (долга), чем времени для её завершения. Чтобы иметь предсказуемые графики выпуска, команда разработчиков должна ограничить количество выполняемой работы до такого, которое позволило бы минимизировать объёмы незавершённой ранее работы (долга).
Пока развивающаяся программа постоянно меняется, её сложность, отражая ухудшение структуры, увеличивается, пока не будет выполняться работа по поддержке оной[2].
— Меир Мэнни Леман, 1980
В то время как закон увеличения сложности Мэнни Лемана уже доказывал, что постоянное развитие программ увеличивает их сложность и ухудшает структуру, пока ведётся работа над ними, Уорд Каннингем впервые провёл сравнение между технической сложностью и долгом в отчёте за 1992 год:
Создание первого временного кода, — это как влезание в долги. Небольшой долг ускоряет разработку до тех пор, пока не будет своевременно оплачиваться в виде переписывания… Опасность возникает, когда долг не погашен. Каждая минута, потраченная на не-совсем-правильный код, учитывается в качестве процента по этому долгу. Целые инженерные организации могут быть привлечены к простою из-за долговой нагрузки неконсолидированной реализации, объектно-ориентированной или иной[3].
— Каннингем, Уорд, 1992
В своей статье от 2004 года «Рефакторинг с использованием шаблонов» Джошуа Кериевски представляет в качестве аргумента сравнение расходов, потраченных на решение вопросов, связанных с архитектурной халатностью, которую он описывает как «долг структуры»[4].
Действия, которые могут быть отложены, включают документацию, написание тестов, уделение внимания «TODO» комментариям, борьбе с компилятором, а также предупреждениям по статическому анализу кода. Другие случаи технического долга включают базу знаний, которая не распространяется внутри организации, и код, который является слишком запутанным, чтобы его было легко изменять.
В программном обеспечении с открытым исходным кодом откладывание отправки локальных изменений в основной проект является техническим долгом.
См. также
Примечания
Ссылки
Литература
- Adam Tornhill. Software Design X-Rays. — Pragmatic Bookshelf, 2018. — ISBN 9781680502725.