Программирование, быстрое и медленное: разработчики и психология самоуверенности
Сегодня я собираюсь рассказать о том, что происходит в головах разработчиков программ, в тот момент, когда они делают предварительные расчеты; о том, почему им так сложно зафиксировать все задумки в своей голове; а также о том, как лично я разрешил для себя эту ситуацию, узнал, как жить и писать ПО (для счастливых владельцев бизнеса), но, уверен, мои собственные оценки трудоемкости ненадежны как никогда.
Но сначала история…
Это было <вставьте период времени, который не будет делать меня нелепо старым> в то время, когда я был молодым разработчиком (1). В колледже я был лучшим на занятиях по программированию, будучи младшим разработчиком, я мог взломать код и решить любую поставленную передо мной задачу быстрее, чем кто-либо ожидал. За выходные я мог изучить новый язык и продуктивно на нем работать (или, по крайней мере, мне так тогда казалось).
Таким образом, как и должно было произойти, у меня появился свой собственный проект. Менеджер по работе с крупными клиентами объяснил мне в общих чертах, чего хочет клиент, мы это обсудили, и я сказал: «На эту работу уйдет 3 недели.» «Хорошо», — ответил он. И так я приступил к программированию.
Как вы думаете, сколько времени у меня ушло на этот проект? Четыре недели? Может быть пять?
Мм, вообще-то: три месяца.
У меня остались четкие воспоминания о том времени – мое представление о себе было тесно связано с ощущением, что я — «хороший программист», в чем я сильно разочаровался. Я потерял сон, у меня случались небольшие приступы паники. И этому Не Было Конца. Я помню, что у меня сосало под ложечкой при разговоре с тем менеджером, я снова и снова объяснял, что у меня до сих пор нет ничего, что можно ему показать.
В один из таких черных периодов я решил, что Больше Никогда Не Буду Совершать Подобных Ошибок.
К сожалению, в ходе своей карьеры, я уяснил нечто очень тяжелое: я постоянно совершаю подобные ошибки.
На самом деле, я узнал даже нечто лучшее: мы все совершаем эти ошибки.
Недавно, я прочитал книгу Даниэля Канемана «Thinking, Fast and Slow» — обширное исследование того, что известно психологии о когнитивных процессах человека, о его поразительно сильных сторонах и (удивительно предсказуемых) слабостях.
Моя любимая часть касается Самоуверенности. В ней была показана, скажем так, некоторая связь с тем, как разработчики делают расчеты.
Почему ваши расчеты отстой, часть I: написание ПО = познание чего-то, чего вы еще не знаете
Для начала, я верю, что в действительности, есть только две причины, почему наши расчеты настолько плохи. Первая причина, своего рода не поддающаяся улучшению: написание ПО — это процесс, при котором необходимо придумать, как описать что-либо в невероятно точных подробностях, для того, чтобы можно было объяснить компьютеру, как это нужно сделать. А проблема состоит в том, что в тех частях, которые вы не до конца понимаете на начальном этапе работы, и скрываются сложности, которые вылезут наружу и жестко вас поимеют.
И это совершенно не поддается улучшению каким-либо образом. И только если вы действительно «полностью понимаете, что делать», или у вас есть библиотека или существует часть ПО, которая может это сделать за вас, тогда вы ничего не пишите. В противном случае, появляется неизвестность, и зачастую она детонирует. И на решение этих задач у вас может уйти неизвестно сколько времени, может быть один день, один год или вам может не хватить времени и до тепловой смерти вселенной.
Например, в случае, когда выясняется, что некоторые привлеченные со стороны разработки, ненадежны…, тогда вам приходится заново переписывать весь массив, содержащий ошибки; или, когда база данных не понимает какие-то критичные части кодировки…, тогда вам приходится с нуля перестраивать все ваши схемы; или, настоящая классика жанра, когда вы показываете работу клиентам, а они не принимают того, что заказывали сами, а хотят немного другого… того, что в разы труднее сделать.
Когда вы впервые сталкиваетесь с такой трудностью, то вы думаете «Впредь следует быть более внимательным на стадии разработки спецификации». Но это не лучшая идея. Почему? Главная причина в том, что, как видно из вышеперечисленных примеров, если вы будете составлять спецификацию настолько подробно, что учтете все эти случайности, то на самом деле окажется, что вы уже пишете ПО. И, действительно, нет никакого способа решить данную задачу (если, читая эту статью, вы пытаетесь оспорить данное утверждение, то я вам скажу – точно, совершенно точно, нет никакого способа. Полные спецификации — это утопичная экономическая идея. Ниже я покажу вам более выгодные, с экономической точки зрения, варианты).
Но вот где начинается самое интересное. Каждый программист, который работал в реальном мире больше пары месяцев, сталкивался с описанными выше проблемами.
И все же… мы продолжаем делать такие впечатляюще плохие расчеты.
И что еще хуже, мы верим нашим собственным расчетам. Я сам верю своим, в тот момент, когда я их произвожу.
Так, постойте, я что предлагаю, чтобы все разработчики так или иначе стали жертвой того же самого, предсказуемых ошибок в мышлении?
Да, это в точности то, что я предлагаю.
Почему ваши расчеты отстой, часть II: самоуверенность
Канеман довольно много говорит о проблеме «экспертов», делающих прогнозы. В шокирующе широком разнообразии ситуаций, эти прогнозы оказываются совершенно бесполезными. В особенности, во многих, очень многих ситуациях сохраняют справедливость следующие три утверждения:
1- Прогнозы «экспертов» о каких-либо будущих событиях настолько ненадежны, что по существу бессмысленны;
2- Тем не менее, обсуждаемые эксперты невероятно уверены в точности своих прогнозов;
3- И лучшее из всех: похоже, что абсолютно ничего не может приуменьшить это чувство самоуверенности экспертов;
И последнее утверждение, поистине выдающееся, о том, что даже если эксперты пытаются честно взглянуть в лицо своим собственным неудачам, даже если они глубоко осознают этот недостаток человеческого мышления…, они тем не менее остаются глубоко уверенными в точности своих прогнозов.
Вот как это объясняет Канеман после рассказа поразительной истории о своих собственных неудачах на данном поприще:
«Уверенность, которую вы будете чувствовать в своих будущих суждениях, не будет преуменьшена тем, что вы сейчас прочитали, даже если вы поверили каждому слову».
Занимательно то, что есть ситуации, для которых экспертные прогнозы довольно хороши, и я собираюсь продемонстрировать ниже эти ситуации, а также то, как их использовать для улучшения своих процессов по разработке. Но перед тем как это сделать, я хотел бы пройтись по некоторым деталям того, как работает ошибочная самоуверенность, на практике, возможно, вы сможете обнаружить ее в себе.
Каково это — чувствовать, что ты неправ: системы I и II, и проблема 3-х недель и 3-х месяцев
В «Thinking Fast and Slow», Канеман объясняет большую часть психологии как взаимодействие между двумя «системами», которые управляют нашими мыслями: Система I и Система II. Мое очень короткое резюме по этому поводу будет следующим: «Система II отвечает за аккуратное, рациональное, аналитическое мышление, и Система I отвечает за мышление быстрое, эвристическое и сравнительное».
И критично то, что эволюция как будто спроектировала все с одной единственной целью – чтобы Системе II не приходилось делать слишком многого. Что очень даже логично, с точки зрения эволюции – Система II медленна как патока, и невероятно дорогостояща, она должна применяться в очень и очень редких случаях. Но вы видите проблемы, без сомненья, без особых размышлений, как же тогда ваш разум должен понять когда ему запускать Систему II? С этой точки зрения, многие из различных «когнитивных искажений» психологии можно воспринимать, как утонченные инженерные решения к такой жестокой жизненной проблеме, как распределение внимания в режиме реального времени.
Чтобы посмотреть, как взаимодействие Систем I и II может привести к поистине ужасным, и в то же время честно-доверительным расчетам, я собираюсь передать ненадолго микрофон своему другу (и коллеге по Hut8Labs) Эдмунду Ёргенсену (Edmund Jorgensen). Он описал мне это в своем письме следующим образом:
«Когда я спросил себя «сколько времени уйдет на этот проект» Система I не имела никакого понятия об этом, но хотела получить ответ, и перекодировала вопрос. Во что? Я подозреваю, что во что-то вроде «на сколько я в себе уверен, что могу сделать эту вещь,» и это, в свою очередь, перекодировалось в расчет времени с неким коэффициентом, который является величиной относительной (например, когда Боб чувствует степень уверенности Х, то он всегда отвечает 3 недели; когда Сьюзи чувствует степень уверенности Х, то она всегда отвечает 5 недель).»
Поднимите руку, если вы постепенно осознали наличие у вас двух «больших» временных измерителей? Например, для меня это «3 недели» и «3 месяца». Первая подразумевает, что «это кажется сложным, но по существу я думаю, что знаю, как это сделать»; вторая же подразумевает: «Вау, это сложно, я не совсем уверен, что для этого понадобиться, но готов поспорить, что смогу это выяснить».
Аха, я считаю, что Эдмунд полностью прав.
(Для тех, кто тянет время дома: мои «3 недельные» проекты по видимому займут 5-15 недель, мои «3 месячные» проекты обычно занимают 1-3 года, в тех редких случаях, когда кто-то хочет мне за это платить).
Отлично! Теперь давайте перестанем быть такими самоуверенными!
Вы могли подумать c такой точки зрения: «Хорошо, Я вижу, куда ты клонишь, Дэн, нам нужно подходить к этим расчетам в соответствии с принципами Системы II вместо Системы I. Таким образом, наши внимательные, аналитические умы произведут лучшие расчеты».
Поздравляю, вы только что изобрели Водопад.
По существу это применение подхода о «составлении полной спецификации до начала программирования»: не позволяйте своей команде делать интуитивные расчеты, заставьте всех аккуратно мобилизовать их аналитические способности и подойти к решению вопроса с детальной спецификацией и с расчетами, разбитыми на более мелкие части.
Однако и это обречено на неудачу. Как обычно…
Настоящая проблема здесь – взаимодействие между двумя источниками ошибочных измерений: человеческая ошибка по отношению к своей самоуверенности, и неотъемлемый элемент неопределенности, присущий каждому реальному проекту по написанию ПО. Эта неопределенность настолько серьезна, что даже аккуратная рациональная Система II не может предоставить точные прогнозы.
К счастью, есть способ объединить использование сильных сторон мышления, и в то же самое время, справиться с непостоянностью реального мира.
Сначала, как использовать сильные стороны своего мышления.
Когда эксперты правы, и как это использовать в свою пользу
Канеман и другие исследователи могли определять ситуации, когда суждение экспертов не полностью ошибочно. По его словам:
«Чтобы узнать, можешь ли ты доверять определенному интуитивному суждению, необходимо задать два вопроса: Является ли окружающая среда, в которой происходит суждение, достаточно постоянной для принятия прогнозов на основании доступных доказательств? Ответ «да» — для Диагноста, «нет» — для сток-пикера. Есть ли у профессионалов соответствующая возможность для изучения сигналов и закономерностей?»
«Соответствующая возможность» означает большое количество совершенных прогнозов, а также тесная обратная связь для изучения их точности.
Теперь, 6-18 месячные проекты по написанию ПО совершенно не удовлетворяют всем этим критериям. Как я уже говорил ранее, окружающая среда довольно не «постоянна». Кроме того, эксперты не обладают сочетанием: делать много прогнозов и получать быстрые отзывы. Если на что-то требуется год или более, то обратная связь слишком долгая для тренировки интуиции (плюс, вам потребуется большое количество примеров).
Однако, есть форма расчетов, применимая к разработке ПО, которая подходит – 0-12 часовые задачи, если они затем немедленно реализовываются. Под этим углом, вещи работают иначе:
- Хотя все еще много случайностей (подробнее об этом смотрите ниже), остается надежда на «постоянство окружающей среды». Две двухчасовые задачи имеют намного больше общего, чем два шестимесячных проекта;
- Вы можете предположить сделать сотни подобных расчетов, в течение нескольких лет;
- Вы получаете очень быстрый отзыв о точности проведенных расчётов.
Наиболее оперативная команда, в которой я был, проводила еженедельные спринты, где все разбивалось на 0, 2, 4 или 8 часов (и всегда было некоторое недоверие к 8 часовым задачам – как-то, мы очень сильно старались разбить их на более мелкие отрезки). Мы рассчитывали их очень быстро и как-то случайно – мы для этого даже не пользовались педантичной техникой Покер Планирования.
С этой точки зрения, вы пользуетесь сильными сторонами Системы I – есть возможность ее натренировать, она имеет в наличии множество примеров, и в ней содержательные модели, которые можно подобрать. И благодаря коротким отрезкам спринтов, вы очень оперативно получаете отзывы относительно качества ваших расчетов.
Стоп, стоп, стоп! Давайте просто сделаем тысячу 4 часовых расчетов!
Как я могу утверждать, что вы можете производить эти микро расчеты, но каким-то образом не можете применить их к 6-18 месячным расчетам? Разве значения ошибок не усредняются?
По существу, хотя я думаю, что расчеты в подобных масштабах обычно правильны, то в случае, когда они не правильны, просто нет предела тому, насколько они могут быть неправильными. В математических терминах, я подозреваю, фактические времена следуют за распределением степенного закона. И распределения степенного закона известны тем, что не имеют стабильного значения и бесконечной дисперсии, которые, откровенно говоря, представляются мне такими же расчетами проекта большого водопада.
Вы можете подумать: как это вообще возможно, чтобы что-то, что можно сделать за 4 часа могло занять месяц или два?
Это происходит постоянно: вы собираетесь перейти к завершающему этапу, но неожиданно узнаете, что какие-то скрытые препятствия кардинальным образом все меняют. Например, в недавнем стартапе при попытке устранить определенные ошибки в системе мы поехали поставить балансировщик нагрузки перед IMAP сервером, который мы написали. С тем, чтобы, когда один сервер упадет, то балансировщик нагрузки плавно перевел процессы на другой, и клиенты бы ничего не почувствовали.
И это казалось нам 4-х часовой задачей.
Но когда мы прибыли на место, мы осознали/вспомнили, что IMAP сервер использует состояние подключения, в отличие от HTTP серверов, к которым мы так привыкли. Получается, если мы хотим, чтобы переключение на резервный сервер происходило в прозрачном режиме, мы должны будем управлять состоянием подключения на двух серверах или же написать подобие проксирующего балансировщика нагрузки, который бы отвечал за состояние подключения и устанавливался перед IMAP-сервером.
Что казалось нам 3-х месячным проектом (2).
Вот еще одна из причин того, что короткие спринты являются ключом ко всему этому: они ставят жесткий лимит на цену ужасно ошибочных расчетов.
Мы в полной заднице?
Так что же нам делать? Смириться с тем, что все наши проекты обречены на неудачу; что мы испортим отношение с остальными клиентами, из-за того, что не можем выполнить наши обещания?
Разгадка заключается в том, чтобы сначала принять тот факт, что составить точные долгосрочные расчеты в корне невозможно. Как только вы это осознаете, вы можете приниматься за следующую задачу, с которой, однако, довольно трудно справиться: как вы можете заставить вашу команду разработчиков производить тонны значений, даже при том, что вы не можете произвести более или менее значимые долгосрочные расчеты.
То, к чему мы пришли, является в основном объяснением первых принципов того, почему мир принял различные Гибкие методологии разработки. Более подробно об этом я расскажу в следующей теме: «Сроков Сдачи Проектов Нет! Как Заставить Клиентов Вас Полюбить, Даже При Том, Что Вы Не Выполняете Своих Обязательств».
1. (группа <вставьте датируемую музыкальную ссылку> играла по радио, и все обсуждали <давно забытое тв шоу>.
2. Если вы думаете: «Постой, а как же 3 месяца, как один из твоих 3-х месячных расчетов?», то я понятия не имею, о чем вы вообще говорите.
Перевод выполнен в рамках летней школы стартапов Tolstoy Summer Camp
Автор: tomshinsky