Почему инженер не может оценить временные затраты на написание кода

Неважно попросите вы джуна/мидла/синьора/тимлида/менеджера проекта и т.д., дать оценку по времени на разработку программного обеспечения – вы никогда не получите быстрого, легкого и точного ответа. Это связано с тем, что никто независимо от того насколько талантливым или гениальным он является не может точно знать сколько понадобится времени.

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

Обзор

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

Проблема

Проект по разработке программного обеспечения редко укладывается в срок.

Последствия

Маркетинговые усилия окажутся потраченными впустую; клиенты окажутся недовольны; разработчики испытывая стресс будут писать некачественный код, чтобы уложиться в сроки, что поставит под угрозу надежность продукта, что в конечном счете может привести к отмене проекта.

Известные причины

  • Неправильные оценки времени (тема данной статьи).
  • Невнятные требования в начале проекта и изменение требований по ходу проекта.
  • Повышенное внимание к деталям, которые выходят за рамки работы (золочение).
  • Недостаточно время для этапов исследования и проектирования архитекутры, либо же наоборот слишком много времени.
  • Игнорирование потенциальных проблем со сторонними интеграциями.
  • Желание сделать все правильно с первого раза.
  • Работа над слишком большим количеством проектов одновременно или переключение между разными проектами.
  • Несбалансированная шкала качества и производительности.

Чрезмерный оптимизм, эффект Даннинга-Крюгера, чистая неопределенность или просто математика

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

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

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

Большинство опытных разработчиков быстро приходят к выводу, что предоставление оценки времени – это решение задачи в условиях чистой неопределенности. Следовательно все оценки времени всегда будут неверными, и это жизненный факт, единственное, что мы можем с этим сделать – попытаться удовлетворить требования клиента и сказать разработчикам, чтобы они “хоть как-то сделали” или “просто ломали” если что-то пойдет не так. Но мы все знакомы со стрессом, мусорным кодом и хаосом, который несет в себе эта философия.

Существует ли способ не скатиться в подобное безумие? Действительно ли это лучший способ добиться цели? Я так не думал и именно тогда я начал свои поиски пытаясь найти рациональное математическое объяснение почему никто не может оценить время на выполнение какой-либо задачи.

Это просто математика

Однажды я выполнял задачу которая должна была занять 10 минут, но по итогу потратил 2 часа. Я начал рассуждать о причинах по которым я подумал, что эта задача займет 10 минут, а также о первопричине того, что увеличило это количество до 2 часов. Мой мыслительный процесс был интересным:

  • Я думал что это займет 10 минут посколько на 100% знал в голове тот код который мне понадобится написать.
  • На самом деле на написание кода я потратил 7-10 минут, но затем 2 часа ушло на решение неизвестной мне ошибки в фреймворке.

Это то, что люди любят называть в управлении проектами «форс-мажором»; внешней неконтролируемой причиной задержки.

Теперь вы можете подумать, что я просто доказываю аргумент о неопределенности природы оценки этим сценарием. И да, и нет. Давайте немного уменьшим масштаб. Конечно, неопределенность – основная причина задержки этой конкретной задачи, потому что я бы никогда не догадался, что эта ошибка существует. Но должна ли она отвечать за задержку всего проекта?

Вот как мы должны провести границу: отдельная задача не является репрезентативной для всего проекта и наоборот

Как мы «обычно» оцениваем время

Нас повсюду окружают нормальные распределения и человеческий мозг к ним привык. Мы являемся экспертами в оценке вещей, которые следуют принципам нормального распределения по своей природе; это основа для получения опыта путем воздействия.

Если в этом месяце вы ходили в ближайший магазин около 20 раз и каждый раз это у вас занимало 5 минут, за исключением того времени когда лифт нуждался в обслуживании и вы ожидали 10 минут, или если вы однажды решили подождать пару минут пока не перестанет идти дождь. Как вы думаете сколько времени вам понадобится прямо сейчас чтобы добраться до магазина? 5 минут?

Я имею ввиду, что не имеет смысла говорить “15”, потому что это редкий случай, или “7”, если на улице не идет дождь. И скорее всего вы будете правы. Если 18 из 20 раз процесс занял у вас 5 минут, то безусловно существует высокая вероятность, что на этот раз он займет столько же времени – 5 минут (среднее значение) и она составляет 90% (не углубляясь в сложную алгебру)

Перекос

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

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

Видите что здесь может пойти не так? Наше “естественное” предположение основано на медиане, которая максимизирует вероятность правильного предположения, однако реальное число, когда это “событие” происходит достаточное количество раз всегда будет приближаться к среднему. Иными словами: чем больше похожих задач вы выполняете, тем больше ошибочных оценок накапливается.

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

Как использовать эти знания?

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

Однако я знаю, что многие будут разочарованы таким открытым выводом, поэтому вот что я об этом думаю.

  1. Легче сказать займет ли задача X больше/меньше/столько же времени сколько похожая задача Y, чем сказать точно сколько нужно времени на задачу X. Это связано с тем, что сравнение медиан так же, как и сравнение средних значений, при схожей асимметрии кривых (что верно для похожих задач), даст практически одинаковый результат.
  2. Я не помню и не храню подобные задания и затраченное на них время, что потом взять и получить среднее значение. Поэтому я обычно оцениваю неизбежную ошибку как процент времени для выполнения задачи, которое увеличивается/уменьшается в зависимости от того насколько мне комфортно в среде разработки (нравится ли мне язык/фреймворк (40%); наличие хороших инструментов для отладки (30%); поддержка языка со стороны IDE (25%) и т.д.
  3. Я разбиваю спринты на задачи одинакового размера, просто чтобы добиться единообразия в процессе оценки времени. Это позволяет извлечь пользу из пункта 1: должно быть легко определить, являются ли две задачи примено равными по времени. Это также делает выполняемые задачи более похожими, что позволяет применять гипотезу еще точнее, и процесс оценки становится более предсказуемым.
  4. Применяя эти принципы и имея ресурсы вы можеме выполнить “тестовый запуск”. Например если за X1 дней разработчики команды Y1 выполнили Z1 однородных задач, то мы легко можем сказать что за X2 дней разработчики Y2 (если мы знаем что они доступны) выполнят Z2 задач (при условии что мы знаем общее количество оставшихся задач).