что такое технический долг в it
Технический долг
Программные системы склонны к накоплению мусора — внутренних недоработок, которые затрудняют дальнейшее изменение и расширение системы по сравнению с идеальным кодом. Технический долг — это метафора, придуманная Уордом Каннингемом. Она объясняет, как воспринимать этот мусор, по аналогии с финансовым кредитом. Дополнительные усилия, необходимые для добавления новых функций, — это проценты по кредиту.
Представьте, что в моей кодовой базе есть модуль путаной структуры. Нужно добавить новую функцию. Если бы структура была ясной, то работа заняла бы четыре дня, но с этим мусором требуется шесть дней. Разница в два дня — это и есть проценты по долгу.
Что меня больше всего привлекает в метафоре долга, так это ясное понимание расходов на его обслуживание или устранение. Я могу потратить пять дней на очистку модульной структуры, устранение мусора, метафорически расплатившись с «кредитором». Если я это сделаю для данной функции, то окажусь в проигрыше, потому что потрачу девять дней вместо шести. Но если появятся ещё две такие функции, то выгоднее всё-таки удалить мусор.
С такой формулировкой задача становится чисто математической. Её решит любой менеджер с электронной табличкой. К сожалению, мы не можем измерить производительность, поэтому никакие затраты объективно не измеримы. Мы можем примерно прикинуть, сколько времени требуется для разработки функции, сколько займёт работа после удаления мусора — и предположить стоимость его удаления. Но точность таких оценок довольно низкая.
Поэтому обычно лучший вариант — поступать так, как мы обычно поступаем с финансовыми долгами: постепенно выплачивать основную сумму. На первой функции я потрачу дополнительные пару дней, чтобы удалить часть мусора. Этого может быть достаточно, чтобы снизить проценты по долгу, так что в будущем его можно будет погасить за один день. Это по-прежнему дополнительное время, но после удаления мусора будущие изменения стали дешевле. Большое преимущество постепенного улучшения заключается в том, что естественным образом мы больше времени тратим на удаление мусора в часто изменяемых областях. Это именно те области кодовой базы, которые наиболее нуждаются в удалении мусора.
Сравнение выплаты процентов с выплатой основного долга помогает определить, с каким мусором разбираться. Если у меня есть какая-то особо ужасная область кодовой базы, то проблема исчезает, если выясняется, что мусор невыгодно удалять. Проценты выплачиваются только тогда, когда приходится работать с этой частью программного обеспечения (в этом месте метафора немного хромает, потому что по банковскому кредиту нужно платить всегда). Таким образом, кошмарные, но стабильные области кода можно оставить в покое.
В отличие от стабильных частей кода, области высокой активности требуют нулевой терпимости к мусору, потому что там процентные платежи чрезвычайно высоки. Это особенно важно, поскольку мусор накапливается там, где разработчики делают изменения, не обращая внимания на качество: чем больше изменений, тем больше риск появления мусора.
Метафора долга иногда используется для оправдания низкого качества кода. Аргумент состоит в том, что качественный код требует больше времени и усилий. Если срочно нужны новые функции, лучше принять на себя долг и разбираться с ним потом
Опасность здесь в том, что зачастую этот анализ ошибочен. Мусор очень быстро начинает вредить, замедляя внедрение новых функций. В итоге разработчики превышают кредитные лимиты и выпускают продукт позже, чем если бы сразу потратили время на обеспечение более высокого качества. Здесь метафора часто вводит людей в заблуждение, поскольку динамика технического долга на самом деле не соответствует динамике финансовых кредитов. Принятие на себя долга для ускорения выпуска продукта работает только в том случае, если вы остаётесь ниже линии design payoff в гипотезе об устойчивости архитектуры, а разработчики пересекают её уже через несколько недель, а не месяцев.
Регулярно ведутся дебаты о том, следует ли считать долгом различные виды мусора. Мне кажется, тут полезно учитывать, берётся долг сознательно и разумно — или безрассудно. Так появился квадрат технического долга.
Дальнейшее чтение
Насколько я могу судить, Уорд впервые представил эту концепцию в отчёте для OOPSLA 1992. Она также обсуждалось в вики.
Есть видеозапись, где Уорд Каннингем обсуждает придуманную им метафору.
Дэйв Николетт расширяет взгляд Уорда на технический долг, приводя прекрасный пример того, что я называю разумным преднамеренным долгом.
Несколько читателей предложили другие годные метафоры. Дэвид Панарити назвал некачественную разработку дефицитом программирования. Судя по всему, он начал использовать этот термин несколько лет назад, когда он соответствовал политике правительства; полагаю, теперь это снова актуально.
Скотт Вуд предложил рассматривать «техническую инфляцию как потерю почвы, когда текущий уровень технологии настолько превосходит уровень вашего продукта, что он постепенно выпадает из окружения. Программы отстают в версиях языка до такой степени, что код больше не совместим с основными компиляторами».
Стив Макконнелл выделил в метафоре несколько хороших моментов. В частности, как уменьшение непреднамеренного долга оставляет больше возможностей намеренно принять долг, когда это полезно. Мне также нравится его формулировка минимальных платежей (которые слишком высоки, чтобы исправить проблемы во встраиваемых системах, но не на сайтах).
Хенрик Книберг утверждает, что наибольшую проблему вызывает старый технический долг, и что разумно установить качественный потолок долга, чтобы им легче было управлять.
Эрик Дитрих обсуждает человеческие потери из-за технического долга: сражения в командах, деградация навыков и выгорание.
Технический долг на проекте или выбраться из черной дыры
Природа технического долга
Само понятие технического долга впервые ввел Уорд Каннингем (Ward Cunningham), разработчик технологии wiki и один из создателей экстремального программирования. В 1992 г. в своей статье он сформулировал это понятие в виде метафоры финансового долга: так же, как и при финансовом займе, разработчики могут получить дополнительные средства здесь и сейчас за счет использования быстрых и не оптимальных технических решений, но неизбежно будут расплачиваться за них при дальнейшей разработке, в независимости от того, как будет выплачен этот долг — постепенными выплатами процентов или одним платежом.
Но если проблема технического долга была описана еще 25 лет назад и встречается практически на любом проекте, почему еще нет методики управления проектами, которая позволяла бы избежать само появление технического долга? Ответ кроется в самом понятии проекта. Одним из ключевых отличий проекта от других видов деятельности является уникальность конечного продукта. Там где уникальность, там и непредсказуемость, и именно она порождает изменения на проекте и вносит трудности в первоначальное проектирование системы.
Конечно, можно попытаться построить архитектуру, предусматривая возможные изменения, но здесь команда столкнется с таким понятием как “кошелёк Миллера”: правилом, при котором в кратковременную память человека можно «положить» одновременно не более девяти «монет». А если количество элементов превышает это значение, то мозг пытается сгруппировать информацию так, чтобы их количество было от пяти до девяти.
Можно попытаться делить компоненты на более мелкие, чтобы уложиться в этот “кошелек”, но сложности от этого меньше не станет, да и количество абстракций при таком подходе будет расти с катастрофической скоростью. А как известно, любую проблему можно решить путём введения дополнительного уровня абстракции, кроме проблемы слишком большого количества уровней абстракции.
Другие команды предпочитают вообще отказываться от первоначального проектирования, максимально стараясь использовать по ходу разработки универсальные инструменты. С одной стороны, это проще, чем пытаться предсказывать изменения и на первых этапах система будет получаться достаточно гибкой к изменениям. Но со временем, сложность системы, согласно второму правилу Лемана, неизбежно будет расти, она станет менее гибкой, и могут возникнуть изменения, идущие вразрез с текущей архитектурой. В этом случае разработчики будут также тратить больше времени на решение архитектурных проблем.
Так или иначе, неизбежность изменений на проекте провоцирует появление технического долга.
Как определить, что на проекте есть проблема технического долга
Важнейшим показателем того, что на проекте есть проблема с техническим долгом, это, конечно же, сам код. Прежде всего, стоит сказать об особенности написания кода. Дело в том, что написание и чтение кода — два совершенно разных процесса. Когда разработчик пишет код, он сосредоточен лишь на контексте задачи. Но изменение отдельного участка кода влияет на общую картину происходящего. В свою очередь, прежде чем изменять написанный код, нужно иметь представление не только о конкретном участке, но и обо всей картине в целом. Но при чтении, границы контекстов, в рамках которых был написан код, стираются на общем представлении. Такая разница между чтением и написанием кода генерирует дополнительную сложность, которая прямым образом влияет на его качество.
На что следует обратить внимание:
Методы устранения технического долга
Заключение
Проблема технического долга весьма актуальна на данный момент, и для каждого проекта требуется индивидуальный подход к проблеме его устранения.
Не стоит бояться выплат, ведь если принять правильную стратегию, то технический долг станет той силой, которая будет заставлять развиваться ваш проект. Именно работа с техническим долгом показывает уровень зрелости как самого проекта, так и команды, которая над ним трудится.
Технический долг: что это такое и как с ним жить
Быть или не быть регулярному рефакторингу? Мы попытались разобраться с этой холиварной темой — не без помощи людей, которые знают врага в лицо.
Технический долг — это модули, написанные на старых фреймворках, «костыли», мелкие недоработки, нарушенные стандарты и прочий мусор в коде, который в будущем усложняет жизнь. То самое чувство, когда читаешь код и думаешь: «Ну что за нехороший человек это всё писал». А потом оказывается, что этот «редиска» — ты сам из прошлого. Сам термин — метафора пионера паттернов и изобретателя технологии Wiki Уорда Каннингема.
Недоработки постоянно накапливаются. Чем их больше, тем сложнее добавить в код новую классную функцию. Необходимые усилия, которые придётся приложить в будущем, — как проценты по кредиту. Расплаты всё равно не избежать, а долг со временем всё растёт и растёт.
Согласно исследованию Stripe, разработчики тратят на технический долг треть своего времени, а компании «сливают» на это примерно 85 млрд долларов ежегодно. Быстро вывести на рынок жизнеспособный продукт, приносящий пользу бизнесу, — неплохое решение. Но надо помнить, что технический долг рано или поздно начнёт вредить проекту.
«Нельзя прийти и создать сразу идеальный проект. Каждый день мы будем что-то узнавать о предметной области, и эти новые знания нужно сразу внедрять. Вначале это будут костыли, из которых копится технический долг, — и это нормально. Ведь мы не можем, получая новую информацию, каждый раз переписывать продукт заново. Бизнес нас не поймёт».
Алексей Некрасов,
лидер направления Python в МТС, программный директор направления Python в Skillbox
Пишет про технологии и бизнес.
Технический долг в жизни: два примера
Если вовремя не подумать о техническом долге, приложение может подхватить хроническую болезнь: многочисленные уступки «надо прямо сейчас» так въедаются в код, что рефакторинг провести просто невозможно. Вот две истории — одна об успешной оплате долга, вторая — о запущенной «болезни», справиться с которой так и не получилось.
Локализация приложения
Канадская компания разработала хороший продукт для местных клиентов и решила повторить успех, расширив рынок сбыта на ту часть страны, где говорят в основном по-французски. Разработчики управились за неделю, добавив кучу if-then-else. Решение с оператором условий было быстрым и грязным, но на тот момент — оправданным. Продукт смог заработать ещё денег.
Месяц спустя в Японии фаундер похвастался, что поддержку японского они могут добавить за неделю. Но одно дело — по-быстрому накодить один дополнительный язык, и совсем другое — добавлять так же криво все последующие. Тем более что для японского решение с новым слоем if-then-else вообще не подходило — мешали иероглифы, да и текст японцы пишут вертикально. В итоге разработчикам пришлось писать нормальную систему локализации.
Бесконечные «если» и неудавшийся рефакторинг
Разработчики написали приложение на устаревших версиях Python, PHP и Java с жёсткой структурой из бесконечных операторов if. В какой-то момент они решили полностью переписать ядро на свежих версиях языков, но на каждом шагу объёмы работы возрастали — постоянно обнаруживались какие-то новые зависимости. Да и бизнес не хотел ждать — требовал новые функции, чтобы оставаться конкурентоспособным. В итоге за год рефакторинга команда практически не продвинулась вперёд.
Как оценить технический долг
Американский программист, автор книг и статей по архитектуре ПО Мартин Фаулер определял размер техдолга простой формулой: чем больше усилий программистов тратится на какой-то недоработанный в прошлом фрагмент кода, тем больше наш технический долг. При этом консультант по разработке ПО Роберт Мартин считает, что технический долг в прототипах и краткосрочных проектах можно и нужно игнорировать.
Есть разные классификации технического долга.
Например, CTO производителя весов для угарного газа Tapad Даг Лиодден выделяет три его типа:
Как правило, самый неприятный техдолг связан с архитектурными проблемами: отсутствием инкапсуляции и модульности, плохим применением шаблонов, несоответствием типов данных модели данных. Из-за этого тормозится разработка, трудно вносить изменения в код, исправлять ошибки. Такой долг трудно или вообще невозможно обнаружить инструментами вроде IDE, PMD или Checkstyle.
Чтобы понять, как победить техдолг, нужно тщательно его проанализировать.
Как объяснить бизнесу, что рефакторинг необходим
Владельцам софта нужна прибыль, поэтому они не хотят затягивать процесс разработки и бороться с техдолгом — особенно если близок старт продаж. Однако долг всегда приходится возвращать — иначе он создаёт проблемы в будущем продукте.
Конфликт разработчиков и бизнеса из-за рефакторинга — один из самых запутанных и сложных. Если игнорировать и копить техдолг, то разработчики потеряют мотивацию, а компания станет «техническим банкротом». Если же включить режим перфекциониста и слишком сильно фокусироваться на долге, конкуренты получат преимущество в скорости, быстрее выпустят новые фичи и захватят рынок. А полученную в ходе экспансии прибыль они вложат в погашение критичного долга — и останутся в выигрыше.
Вообще, Уорд Каннингем придумал концепцию техдолга именно для того, чтобы в понятных для бизнеса терминах аргументировать необходимость рефакторинга. Метафора простая: первая версия программы — как заём в банке. А каждая минута, которая тратится на исправление «костылей» в коде, — как проценты по кредиту. Если проценты долго не гасить, банк истребует весь долг и компания может закрыться. Однако небольшой долг, как и разумно взятый кредит, ускоряет разработку и помогает расти, главное — выплачивать его вовремя.
«Представьте платформу для нескольких независимых друг от друга клиентов ( из терминологии «клиент — сервер». — Прим. ред.). У каждого есть собственный сервис, весьма требовательный к аппаратным ресурсам. Пока клиентов мало, эта схема работает. Когда же количество клиентов резко увеличивается, возникает необходимость менять архитектуру и запускать один сервис, который будет обслуживать всех, вместо нескольких копий, работающих параллельно. А это уже экономия в чистом виде и вполне убедительный аргумент для бизнеса.
Пока критической ситуации не возникло, многие воспринимают технический долг как нечто абстрактное. К сожалению, часто осознание приходит, только когда бизнес теряет деньги или несёт репутационные потери. Но после этого он сразу понимает важность рефакторинга».
Николай Мельников,
руководитель компании Sebbia
Важный момент: договариваться о ресурсах и времени команды, которые будут тратиться на рефакторинг, лучше до начала работ. Потому что вовремя гасить технический долг — критично для любого программного продукта. С заказчиком необходимо говорить на его языке: объяснять финансовые риски и приводить примеры из жизни.
«У нас в BestDoctor есть договорённость, что один день в неделю каждый программист выделяет на работу с техническим долгом и автоматизацию, которая улучшает жизнь всей команде разработки. Этот день полностью посвящён не продуктовым, а инженерным задачам. Я рекомендую ввести обязательный процесс отдачи технического долга раз в неделю или раз в две недели. Это позволит не запускать его».
Михаил Корнеев,
тимлид в BestDoctor, автор YouTube-канала «Хитрый питон»
Качественный рефакторинг возможен, только если вы «брали» техдолг осознанно, понимали, что перфекционизм в этот момент навредил бы бизнесу, и фиксировали момент создания долга. Поэтому небрежно писать код и думать, что исправишь всё когда-нибудь потом, — плохая идея.
«Если уже сложилась ситуация, когда надо немедленно реагировать и что-то делать с техдолгом, значит, что-то не так с процессами. Нужно сразу планировать работу так, чтобы оставалось время на рефакторинг — от 5% до 33% рабочей недели. Команда должна знать, что у неё есть выделенное время для таких задач».
Николай Мельников,
руководитель компании Sebbia
Чек-лист: как не накапливать технический долг
Хотите изучить новый язык программирования или неизвестный фреймворк? Выбирайте подходящий среди курсов Skillbox.
Технический долг
Будь вы простым программистом, матерым лидом, архитектором или даже ПМ-ом, вы наверняка в своей нелегкой работе сталкивались с проблемой выбора при добавлении в систему новой возможности. Одно решение гораздо проще реализовать в сжатые сроки и успеть к очередному очень важному релизу, однако оно будет более затратное в сопровождении, менее расширяемое или менее надежное. Другое решение может не обладать всеми этими недостатками, однако обладать другим, в некоторых случаях более важным недостатком – на его реализацию потребуется значительно больше времени.
При этом самым сложным при выборе того или иного решения является «коммуникация» своего выбора непосредственному руководителю, чтобы он смог принять взвешенное решение. А поскольку с точки зрения большинства руководителей «взвешивание» заканчивается сразу же после того, как он услышит сроки реализации, то «коммуникация» заканчиваются примерно через 37 секунд после ее начала (обычно именно столько времени нужно руководителю, чтобы узнать ответ на очень простой вопрос, выражаемый одним словом: «Когда?»)
Не удивительно, что многие простые программисты, матерые лиды и архитекторы, а иногда даже ПМ-ы, которые понимают, что им самим придется расхлебывать проблемы «близоруких» решений, с таким подходом не согласны. И совершенно не удивительно, что с подобной проблемой сталкивались и другие известные и не очень люди, которые придумали типовые «паттерны», описывающие подобную ситуацию. Одним из таких паттернов, является метафора технического долга, впервые описанная Вардом Каннингемом (Ward Cunningham) (*) без малого двадцать лет назад.
Технический долг в классическом понимании
В классическом понимании, т.е. в том виде, в котором эта метафора была описана Вардом Каннингемом, под техническим долгом понимается осознанное компромиссное решение, когда заказчик и ключевые разработчики четко понимают все преимущества от быстрого, пусть и не идеального технического решения, за которое придется расплатиться позднее. И хотя с точки зрения многих разработчиков ситуация, когда плохое решение может быть хорошим, может показаться безумной, на самом деле, это вполне возможно: если краткосрочное решение позволит компании получить видимые преимущества, выпустить продукт раньше конкурентов, удовлетворить ключевого заказчика или каким-то другим образом получить преимущества перед конкурентами, тогда такое решение совершенно оправданно. Иногда это может быть единственным способом, чтобы долгосрочная перспектива вообще существовала.
Можно провести параллель между техническим долгом и долгом финансовым. Финансовый долг означает, что вы получаете дополнительные средства сейчас, однако каждый месяц (или каждые пол года) вам придется выплачивать фиксированную процентную ставку, а в конце срока вернуть весь долг кредитору. Аналогичная ситуация происходит и в случае принятия неоптимального технического решения: вы получили готовую систему или новую возможность уже сегодня, однако при добавлении новой возможности вам придется платить «проценты», либо погасить ваш долг путем рефакторинга системы или части системы.
Именно такой подход к построению приложений является наиболее оптимальным с архитектурной точки зрения. Если принимая архитектурное решение вы не чувствуете компромисса между краткосрочными и долгосрочными выгодами, то в любом случае не стоит вырубать его в камне. Вполне возможно, что вы приняли неправильное решение неосознанно, а из-за своего непонимания предметной области, или из-за будущего изменения требований заказчиком. Значительно проще снизить стоимость будущих изменений путем инкапусуляции важных решений в наименьшее число модулей, нежели стараться продумать архитектуру до мельчайших подробностей, в надежде учесть все возможные и невозможные сценарии. Для определенного круга задач идеальная продуманная архитектура возможна, а иногда просто необходима, но в большинстве случаев – это не так; рано или поздно придет момент, когда ваше видение системы или видинение системы заказчиком изменится, что потребует внесения в нее существенных изменений.
Однако даже при разумном накоплении технического долга существует большая вероятность, что команда (или заказчики) пойдут по старому принципу – работает – не трогай, и никогда не вернутся к этому решению снова, чтобы расплатиться за свой технический долг. Кроме того, существует множество случаев, когда технический долг накапливается постепенно и неосознанно, и если разработчики не будут об этом задумываться, то придут к старой как мир ситуации, когда стоимость добавления новой возможности становится невероятно дорогой, все работают, устают, злятся друг на друга, не получив при этом никаких преимуществ перед конкурентами. Это приводит нас ко второму источнику технического долга – грязному коду (***)
Грязный код, как источник технического долга
Технический долг в классическом понимании является преднамеренным и в основном касается стратегических решений, поэтому и ответственность за него лежит на заказчиках матерых лидах, архитекторах и даже ПМ-ах, но вот все, что связано с грязным кодом касается по большей части простых разработчиков. На самом деле, разница между грязным кодом и неоптимальным стратегическим решением, по сути, не такая уж и большая: при добавлении новой возможности в систему вам приходится расплачиваться за недальновидность в прошлом.
Во время кодирования, как и во время принятия любых других решений, разработчик должен рассматривать краткосрочные и долгосрочные выгоды. Давайте рассмотрим юнит-тесты. Если спросить адепта TDD о необходимости юнит-тестов, то он скажет: «г@#но-вопрос, юнит-тесты должны быть для каждого класса, модуля или функции, и, конечно же, они должны писаться до написания кода». Однако если послушать Кента Бека (****), автора TDD, то его отношение к юнит-тестам более прагматичное. Принимая решение об использовании TDD или серьезном покрытии кода юнит-тестами точно так же нужно принимать во внимание краткосрочные и долгосрочные выгоды. Безусловно, юнит-тесты очень полезны, но они полезны, прежде всего, в долгосрочной перспективе, а что если вы осознаете, что существует высокая вероятность того, что этих долгосрочных перспектив не будет вовсе? Вы можете разрабатывать прототип или что-то типа proof of concepts, и пытаетесь выяснить, будет ли вообще это решение работать или нет. С аналогичной ситуацией неэкономичности юнит тестов можно столкнуться во многих реальных приложениях, когда при добавлении новой возможности стоимость написания юнит-теста может в несколько раз превышать стоимость самой реализации.
Однако это скорее исключение из правил, нежели типовая ситуация. Обычно в процессе развития приложения накапливается как груз крупных стратегических ошибок или непониманий требований, так и масса мелких тактических ошибок, типа длинных функций с неочевидными обязанностями и сложными побочными эффектами; расплывчатых классов, с нечеткими границами и обязанностями; отсутствие идиом именования и документации и т.п… Все это приводит к классическому синдрому разбитых окон, когда ни у кого не возникает идеи поступать по другому, а у кого и возникает, то она быстро пропадает из-за того, что плыть против подобного течения очень и очень сложно.
И если команда не отдает свои долги путем переосмысливания существующих решений и их последующего рефакторинга, если она не старается держать качество кода на высоком уровне, то рано или поздно это повысит стоимость развития и сопровождения кода настолько, что все существующие средства будут уходить на оплату процентов по техническому долгу. Что в свою очередь приведет к низкой продуктивности разработчиков (еще бы, ведь они только и делают, что борются с ветряными мельницами), и взаимной неудовлетворенности команды разработчиков и заказчика.
Выводы
Измерение продуктивности программиста или команды программистов дело сложное, и именно из-за этого возникают многие сложности при выборе того или иного технического решения: руководители или заказчики просто не понимают, какие последствия ждут их при выборе одного и отказе от другого решения. Использование метафоры технического долга не является панацеей и вряд ли обеспечит решающий перевес при выборе того или иного подхода, однако, как минимум, позволит понять ключевым заинтересованным людям проблему в терминах, доступных простому смертному, и покажет проблему пусть и в абстрактных, но все же в финансовых единицах.
Кроме того, даже если вам приходится идти на компромисс и влезать в долговую яму осознанно или не осознанно, старайтесь проектировать ваши системы так, чтобы влияние неоднозначных решений было минимальным, а качество кода реализации – на высоком уровне.
(*) Вард Каннингем – это известный дядька, оказавший невероятный вклад в развитие компьютерного сообщества; он «папа» wiki, а также один из авторов «паттернов» и «экстремального программирования». Информацию по поводу первого вклада можно найти в Википедии, а по поводу второго – в статье «Шаблоны проектирования. История успеха».
(**) Конечно же, речь идет только о тех случаях, когда каждое из приведенных решений кажется более оптимальным, но стоимость его применения именно сейчас кажется неоправданно высокой.
(***) Некоторые авторы, включая Боба Мартина не считают, грязный код (messy code) техническим долгом, однако подобный код увеличивает стоимость добавления новой возможности, так что мне кажется, что его тоже можно рассматривать, как один из видов технического долга.
(****) Здесь речь идет о подкасте Software Engineering Radio Episode 167: The History of JUnit and the Future of Testing with Kent Beck, в котором Кент Бек как раз и высказал эту заветную мысль.