Разработка
Григорий Петров: Технический долг и как его отдавать
Сегодня расскажу о более простой, но не менее важной вещи — о техническом долге.
В предыдущей колонке я рассказал про проблемы проектирования — получилось объемно, но, надеюсь, послужит хорошим фундаментом в дальнейшем. Сегодня расскажу о более простой, но не менее важной вещи — что такое технический долг. Не так-то просто описать, что это такое в двух словах, поэтому не буду пытаться и традиционно поймаю для вас концепцию путем выстраивания вокруг нее забора из большого количества слов и примеров.
Откуда возникает технический долг
Как я рассказывал в прошлой колонке, направления развития программы часто взаимоисключающие — мы можем строить либо танк на гусеничном ходу, либо гоночный болид — и будет очень трудно на середине разработки сменить концепцию. Но часто возникают ситуации, когда прозревший заказчик (резкое изменение рынка или же «ой, кажется мы про это забыли») требует таких серьезных изменений в программе, которые несовместимы с выбранной архитектурой. В таком случае есть два варианта:
- Поменять архитектуру. Это правильно с точки зрения долговременного планирования, но потребует времени и денег. А заказчику часто бывает нужно внести изменения еще вчера.
- Использовать «костыли». Надеюсь, большинство моих читателей знают этот программерский жаргонизм. Для тех, кто не уверен, расскажу чуть подробнее.
Что такое костыли
Я не знаю где этот термин появился впервые, но сейчас, когда разработчики и менеджеры говорят про «костыли в коде», они имеют в виде изменения, несовместимые с текущей архитектурой и приделанные к ней снаружи, только чтобы удовлетворить требования заказчика. Как человеку с больной ногой выдают костыль, чтобы он мог хоть как-то передвигаться, так и в программу добавляют код-костыль, чтобы хоть как-то выполнить задачу. Огромная разница заключается в том, что у человека нога рано или поздно заживет сама. А вот костыли, добавленные в код, сами никуда не денутся, и останутся в нем, формируя технический долг. Говоря иными словами, внося несовместимые с архитектурой изменения, разработчик «берет в долг» время разработки, обещая в будущем «сделать все как надо».
На практике это будущее никогда не наступает — у незнакомого с концепцией технического долга заказчика всегда есть срочная работа, которую надо делать вместо того, чтобы делать «непонятно что». Технический долг копится, парализуя архитектуру программы — ведь он добавляет гораздо больше сложностей, чем обычные изменения, так как костыли, добавленные в код, «по живому» модифицируют архитектуру непредусмотренным способом.
Пример из жизни, которым я часто иллюстрирую костыли и технический долг на тренингах и консультациях — это полки. Обычные полки, которые крепятся к несущей стене перфоратором, дюбелями и шурупами. Предположим, у нас уже висят две полки и нам нужно повесить между ними третью. И тут, беда-печалька, ломается перфоратор. С точки зрения архитектуры, правильным решением будет починить перфоратор и сделать, как полагается. Но если полки надо кровь из носу повесить до вечера, то делается костыль — третью полку гвоздями или шурупами прикручивают к уже висящим двум. Торжественно при этом обещая, когда починится перфоратор, все переделать. Данное решение, кроме очевидных минусов меньшего поддерживаемого веса, повышает сложность системы и затрудняет ее изменение. Через два года, когда про костыль все забудут, пришедшие монтировать шкаф для встроенного холодильника сборщики мебели решат снять крайнюю полку…
Ну вы догадываетесь, что будет. С техническим долгом все абсолютно то же самое — костыли копятся в коде, раскладывая по нему ловушки и мины, повышая сложность. Если не отдавать технический долг вовремя, то даже небольшая программа может в один далеко не прекрасный момент оказаться совершенно неподдерживаемой, потому что ее сложность за счет костылей уже давно вышла за пределы кошелька Миллера.
Как работать с техническим долгом
Первое и основное правило работы с техническим долгом — не упоминать о техническом долге о нем нужно знать. Чем больше участников разработки знает о техническом долге в проекте — тем проще следить за его объемом и выделять время на его устранение.
О техническом долге должен знать заказчик. На примере полок ему объясняется, что это такое, при согласовании сроков на задачи явно указывается, будет ли добавлен технический долг. Во всех отчетах о состоянии проекта должен фигурировать текущий объем технического долга и добавляемые им риски.
О техническом долге должен знать Team Lead, он же должен как-то фиксировать добавление технического долга в проект. Один из хороших способов — это ведение блога проекта, где Team Lead каждое утро записывает в свободной форме как вчера велась разработка проекта, какие были приняты решение, с какими сложностями столкнулись.
О техническом долге должны знать разработчики. Hindsight Bias (здесь и далее я буду использовать перевод «ретроспективное когнитивное искажение», если кто знает перевод лучше — пишите) заставит их сопротивляться и хором говорить, что «это же очевидно и мы всегда об этом знали», успешно забывая на следующий день. Один из хороших способов — это введение регламента о маркировке технического долга в коде, например, комментарием «//TODO:» или «//FIXME:». Первое время тим лиду придется отслеживать корректное добавление и удаление таких комментариев, но в целом команда привыкнет к таким практикам довольно быстро.
Все надо обсуждать заранее
Человеческие инстинкты — забавная штука, доставшаяся нам в наследство от стайных животных. Или не доставшаяся — точно пока неизвестно. Большинству в коллективе трудно отказывать коллегам и обсуждать негативную информацию — считается, что это связано со стайными инстинктами, иерархией в стае и инстинктом обеспечения выживаемости группы. Но современное общество вообще, и команда разработки софта в частности, это совсем не стая обезьян. Диктуемое инстинктами поведение только вредит процессу. Как показывает опыт, отключить инстинкты «усилием воли» практически невозможно, но их достаточно легко обмануть, если знать о том, что они есть.
Один из самых простых способов обмана стайных инстинктов — это использование регламентов. Регламент, с которым согласились все участники процесса разработки, с точки зрения инстинктов становится «высшей сущностью» — следование регламенту инстинкты уже не воспринимают как угрозу стае.
К примеру, для работы с техническим долгом достаточно использовать простой регламент: если технический долг есть, то команда тратит 10% времени итерации (или любой другой оговоренный промежуток времени) на его устранение. Заранее утвержденный с заказчиком регламент позволяет довольно легко контролировать технический долг и не допускать гниение проекта из-за его накопления.