Как стать автором
Обновить

IT для неайтишников: Технический долг или почему теперь всё так долго?

Время на прочтение15 мин
Количество просмотров24K

Срыв сроков и выход за оценки в IT — большая и многогранная тема. На что-то бизнес-заказчик может повлиять напрямую, на что-то лишь косвенно. При работе с IT очень желательно понимать и знать такие понятия, как технический долг и «технический дефолт» (имеет иное значение, нежели в экономике). Что это такое, какие последствия имеет и как с эти бороться сейчас разберём.

Меня зовут Константин Митин. 15 лет занимаюсь коммерческой IT-разработкой, прошёл путь от простого программиста до сооснователя и руководителя группы IT-компаний (АйТи Мегастар/АйТи МегаБокс/АйТи Мегагруп). Успел побыть тим-лидом, руководителем филиала разработки крупной федеральной IT-компании. Являюсь одним из идеологов концепции IT~BP (партнёрство между IT и бизнесом).

Если говорить совсем коротко, то в области информационных технологий мы работаем с информационными (техническими) системами, которые во многом ведут себя, как живые организмы. У таких систем есть некоторый запас прочности и адаптационный потенциал, не бесконечный, но есть. Им можно воспользоваться, взяв «займ» у системы, как это водится «под проценты». Проценты выражаются в росте накладных расходов на сопровождение и развитие системы. Если ресурса для погашения процентов не хватает, то наступает «технический дефолт», то есть состояние, когда развитие и поддержка системы перестаёт быть целесообразной.

Теперь рассмотрим вопрос более подробно и начнём со знакомых бизнес-среде аналогий.

Эмоциональный банковский счёт

Одной из ближайших аналогий является эмоциональный банковский счет (ЭБС), который описал Стивен Кови в своей книге «Семь навыков высокоэффективных людей». При описании ЭБС автор использовал аналогию банковского счета, на который делают вклад для формирования резерва, из которого при необходимости можно снимать средства. Но вместо денег выступало чувство уверенности и надёжности в отношениях между людьми.

Когда вы проявляете доброту, уважительное и честное отношение к кому-либо, надёжно выполняете свои обязательства, вы делаете вклад на ЭБС, то есть создаёте резерв доверия. Когда вы делаете какую-то ошибку, злоупотребляете доверием, ведёте себя грубо либо вынужденно подводите кого-либо, то сформированный эмоциональный резерв может скомпенсировать последствия ошибки. При высоком счёте доверия общение протекает легко, быстро и эффективно.

Для формирования долгосрочных отношений ЭБС имеет критическое значение. Все мы иногда ошибаемся и кого-то подводим. Если у вас много средств на ЭБС, то случайная ошибка не приводит к разрыву отношений, давая время на их «выравнивание».

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

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

Конечно, если вы давно не общаетесь с человеком, то есть ваши отношения ставятся на паузу, ваш ЭБС тоже «замораживается», и при встрече со старым знакомым вы чаще всего начинаете со старого же места. Такое не всегда, но бывает.

Если тема эмоционального банковского счета показалась вам новой и интересной, то имеет смысл прочитать о ней в первоисточнике. Стивен Кови неплохо раскрывает важные моменты в общении с деловыми партнёрами, супругами и детьми. ЭБС применим и полезен в бизнесе (для формирования долгосрочных отношений) и в жизни.

Ну а мы перейдём к IT и техническим системам.

Технический долг и технический дефолт

В целом, аналогия с ЭБС полностью переносима и на технические системы. Между бизнесом и техническими (информационными) системами возникают «отношения» со своим счётом, на который можно делать вклады и с которого можно снимать средства. Кроме того, точно так же действует «инфляция», которая тем больше, чем интенсивнее используется система.

В целом многое завязано на выборе, как сделать: быстро либо правильно. При этом юмор в том, что как, измерить «быстро», почти все знают, а вот что такое «правильно» - очень сложный вопрос, вызывающий много дискуссий. Сделать долго, дорого и «не правильно» - это тоже отрицательный вклад.

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

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

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

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

Что такое «плохо реагировать»? Это рост количества «регрессионных» ошибок в системе при внесении в неё изменений. Регрессионная ошибка - это ошибка которая возникает после внесения изменения в систему, но в каком-то другом месте, а не в месте внесения изменений.

Маркетолог спрашивает программиста: в чём сложность поддержки большого проекта?
Программист: ну, представь, что ты писатель и поддерживаешь проект "Война и мир". У тебя ТЗ — написать главу как Наташа Ростова гуляла под дождём по парку. Ты пишешь "шёл дождь", сохраняешь, вылетает сообщение об ошибке "Наташа Ростова умерла, продолжение невозможно". Почему умерла? Начинаешь разбираться. Выясняется, что у Пьера Безухова скользкие туфли, он упал, его пистолет ударился о землю и выстрелил в столб, а пуля от столба срикошетила в Наташу. Что делать? Зарядить пистолет холостыми? Поменять туфли? Решили убрать столб. Получаем сообщение "Поручик Ржевский умер." Выясняется, что он в следующей главе облокачивается о столб, которого уже нет...

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

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

Костыль, как неизбежное зло

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

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

Если взять книгу Джоэла Спольски «Джоэл о программировании», то там есть очень классный пример, рассказывающий о том, почему сейчас есть такой продукт, как MS Excel, а вот бывшего лидера на рынке Lotus 123 уже давно нет. Когда-то давно, при выходе нового центрального процессора (CPU), MS Excel, выполненный на костылях и кое как под новую версию CPU, вышел немножко раньше новой версии Lotus 123. И занял весь рынок, уничтожив монополиста. Не потому, что был лучше, совершенней либо еще что-то, просто он был первый.

Кроме этого есть ещё «авиационный принцип». Допустим мы проектируем крыло самолёта и у нас есть веса крыла и прочность крыла. Прочность крыла не должна опускаться ниже требований, вес крыла должен быть как можно меньше (это влияет на экономику эксплуатации самолёта). Если прочность недостаточна, то нам приходится поднимать вес, делая эксплуатацию самолёта менее выгодной за счет меньшего коммерческого веса. Если прочность избыточная, то мы её снижаем (!!!), чтобы снизить вес и повысить коммерческую привлекательность самолёта.

Для костылей аналогично, иногда бизнес-выгода от его применения заметно выше, чем потенциальный вред, который он причинит. То есть профессионалы, как в бизнесе, так и в IT, понимают, что костыли - всегда будут. И это обусловлено внешними условиями, на которые влиять эти профессионалы не могут.

Ещё один момент. Сам тезис «нормально делай» упирается в неопределённость понятия «нормально», «правильно», «хорошо». Мы работаем в сложных системах с нелинейным поведением, обусловленным кучей внутренних взаимосвязей. Зачастую просто никто не знает, как что-то сделать «нормально» либо «правильно», вне зависимости от того, что он при этом говорит. А обсуждение «правильного подхода» может вестись полностью на техническом диалекте без использования слов, которые вообще может понять бизнес. Тут только привлекать доверенного и независимого технического эксперта, чтобы понять кто прав и прав ли вообще кто-то.

Кроме того, в области информационных технологий ощущается острый дефицит долгоживущих стандартов. Нет, какие-то есть, они уже формализованы в ГОСТы, ISO, ITIL, PMBOK, но касается это прежде всего процессов, а не технических решений. Да, есть, например, паттерны (шаблоны) проектирования, но их много, а выбор среди них не всегда очевиден. Как не очевидны случаи необходимого отказа от использования паттернов проектирования, которые описывали сами авторы понятия «паттерн проектирования».

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

Вот тут самое время вспомнить об «инфляции». За счет некоторой гонки технологий информационная система может устаревать и переставать отвечать требованиям текущего времени. В какой-то момент разрыв между возможностями и требованиями может стать непреодолимым за один прыжок. Это тоже «технический дефолт».

Конечно, ситуация не безнадёжная и давно наработаны методы и инструменты, которые позволяют нейтрализовать последствия от эпизодического появления костылей в системе и последствия технического устаревания. Для этого служат продуманная архитектура (часть которой и являются паттерны проектирования), рефакторинг и реинжиниринг (от reengineering, а не от «инженер»). Но о них немного попозже.

Нужно затронуть ещё один интересный вопрос: «велосипедостроение».

Велосипедостроение

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

Например, мы делаем какую-то информационную систему с web-интерфейсом. Интерфейсы таких систем уже не «верстаются», а собираются из компонентов. Набор готовых визуальных компонентов называется UI-kit.

Есть готовые библиотеки UI-kit с открытым исходным кодом. Компоненты из таких библиотек можно «кастомизировать», то есть настраивать их внешний вид.

Возникает вопрос: «Что делать? Брать готовый UI-kit либо реализовывать свой?». Написать свой UI-kit - это изобретать велосипед. Новые компоненты нужно разработать, отладить, протестировать, получить опыт эксплуатации, исправить их исходя из ошибок, которые выявили уже пользователи, и того пользовательского опыта, что был получен в ходе реальной эксплуатации. Это - дорого и рискованно.

Иная ситуация. А что делать, если в чужом, хоть и открытом UI-kit обнаружилась ошибка, которая мешает нам реализовать нашу систему? Нет, можно послать запрос на исправление автору UI-kit, можно даже предложить ему изменения кода, которое решает проблему. Только неизвестно, когда он вообще его просмотрит, возможно года два пройдёт.

Можно воспользоваться тем, что код открыт, и сделать себе копию библиотеки, но уже с исправлениями. Однако, при обновлении исходной библиотеки UI-kit с новыми возможностями либо просто с учётом обновлений языка программирования, придётся как-то обновить и копию со своими изменениями, о которых никто не знал. Это может быть сложно и дорого.

Возможно, существующих компонентов либо их возможностей будет нам недостаточно и придётся дописывать свои компоненты. В какой-то момент от изначального UI-kit не останется ничего. То есть мы снимем ограничения от чужого «велосипеда», напишем свой «велосипед» и получим из этого пользу.

Помню, как-то нужно было на python реализовать выгрузку каталога номенклатуры во много сотен тысяч позиций с изображениями и характеристиками в zip-архив с XML-файлом и изображениями (формат CommerceML). Беда в том, что архив весил несколько гигабайт, исходные данные много больше, доступа к жёстким дискам и файловым хранилищам не было, оперативной памяти было в доступе на 1-2 гигабайта. Ну, мы сделали потоковую отдачу файла в zip-формате, не смотря на то, что zip потоковой архивации группы файлов никогда не предполагал. Для этого пришлось скопировать и творчески переработать библиотеку архивации в zip. Готового решения под это тогда не было.

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

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

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

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

Отсюда есть интересный эффект. Если бизнес быстро растёт и меняется, он неизбежно сталкивается с «техническим дефолтом» своих систем. Иногда из-за того, что сам бизнес вырастает из этих отношений, а не сдаёт техническая система.

Некоторые этот эффект учитывают заранее, например, реализуют MVP (minimum viable product — минимально жизнеспособный продукт) с максимальной экономией средств, чтобы протестировать рынок. Если тест окажется удачным, то MVP не дорабатывают, а пишут новую систему. Если гипотеза не подтверждается, то списываются минимальные потери на тестирование.

Значение архитектуры информационной системы

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

Почему именно «необходимой» устойчивостью? А может быть это MVP, который проживёт не более полугода. Либо мы проектируем систему, которая должна без сбоев служить лет 20. Это требует разных подходов и разных затрат.

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

Тема архитектуры программного обеспечения и информационных систем очень объёмная, мы её не будем рассматривать даже поверхностно, вместо этого просто коснёмся нескольких значимых моментов.

В 1970-е годы архитектор (строительство) Кристофер Александр составил набор шаблонов проектирования, то есть типовых решений. В 1980-е годы такой подход был скопирован для IT, то есть были составлены свои библиотеки типовых архитектурных решений. Назвали это паттернами программирования/проектирования.

На самом деле их сколько-то десятков штук. Большую часть системы обычно можно разложить на шаблонные элементы и шаблонные взаимодействия. А какую-то часть системы - нет. За счет применения шаблонных решений удаётся избежать некоторых ошибок проектирования.

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

Ну и просто к слову. В книге «банды четырёх» (Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидес) «Приёмы объектно-ориентированного проектирования. Паттерны проектирования» изданной в 1994 году тема паттернов проектирования раскрыта глубоко и подробно. Но хорошему техническому специалисту придётся её прочитать минимум дважды, чтобы усвоить материал. Просто знать названия и описание паттернов не достаточно, нужно понимать откуда и зачем они появились.

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

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

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

В информационных технологиях все точно так же, есть свои аналоги «деформационных швов» (и не только их). Кроме того, хорошая архитектура является расширяемой. То есть заранее делается так, чтобы систему можно было дорабатывать и расширять её возможности. До какого-то момента, после достижения которого может появиться необходимость поменять архитектуру всей системы либо её части.

Рефакторинг

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

По мере накопления костылей и недоработок растёт технический долг и «усталость кода». Рефакторинг - это способ снять усталость с кода. После проведения рефакторинга кода увеличивается читаемость и гибкость (лёгкость внесения изменений) кода.

Хорошая и полезная вещь, суть которой неплохо раскрыта в книге Мартина Фаулера (с соавторами) «Рефакторинг: улучшение существующего кода». Это набор простых приёмов и правил при написании кода и не более того.

Для понимания, рефакторинг это как наведение порядка на рабочем месте и заточка инструмента. Заточенным инструментом работать быстрее и приятнее, тупым инструментом работать долго, дорого и не нужно.

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

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

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

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

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

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

Реинжиниринг

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

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

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

С учётом того, что все происходит под нагрузкой, то походит больше на хирургическую операцию на работающем сердце. В общем, как в старом анекдоте:

Кардиохирург приезжает в автосервис, ему работяга машину чинит, потом говорит:
- Слышь, мужик, вот я мотор перебираю - и ты мотор перебираешь, только человеческий - почему тебе платят в разы больше?
Кардиолог кивает, идет к машине, включает зажигание и говорит работяге:
- А попробуй, при работающем двигателе теперь - перебери!

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

Подводя итоги

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

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

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

Если вы дочитали до конца, и написанное было для вас полезным, то спасибо вам.


Полезные материалы по теме:

Теги:
Хабы:
Всего голосов 33: ↑31 и ↓2+29
Комментарии10

Публикации

Истории

Работа

Ближайшие события