Идеальный программист. Как стать профессионалом разработки ПО

Мартин Роберт С.

10

Оценки

 

 

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

В 1978 году я был ведущим программистом для 32-килобайтной встроенной программы Z-80, написанной на языке ассемблера. Программа «прошивалась» на 32 перепрограммируемых микросхемах, которые вставлялись в три платы (до 12 микросхем на каждой).

У нас в эксплуатации были сотни устройств, установленных на центральных телефонных станциях по всем Соединенным Штатам. Каждый раз, когда мы исправляли ошибку или добавляли новую функцию, нам приходилось отправлять техников к каждому устройству для замены всех 32 микросхем!

Это был настоящий кошмар. Микросхемы и платы были непрочными, контакты на микросхемах гнулись и ломались. Нечаянные изгибы плат могли повредить места пайки. Риск ошибок и поломок был огромен, а затраты для компании – слишком высоки.

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

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

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

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

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

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

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

Мне понадобилось три месяца.

Я напивался только дважды в жизни и только один раз напился основательно. Это произошло на праздновании Рождества в Teradyne в 1978 году. Мне тогда было 26 лет.

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

Я сидел по-турецки на полу с Кеном (мой начальник – ему тогда было 29 лет, и он был трезв), сетуя на то, сколько времени у меня заняла векторизация. Алкоголь освободил мои скрытые страхи и неуверенность по поводу исходной оценки. Надеюсь, я не клал голову ему на плечо – впрочем, такие подробности не очень четко отложились у меня в памяти.

Помню, я спросил, не сердится ли он на меня и не считает ли, что работа заняла слишком много времени. И как бы смутно я ни помнил тот вечер, его ответ четко отложился у меня в памяти на последующие десятилетия. Он сказал: «Да, я думаю, что прошло много времени, но я вижу, что ты прилежно трудишься, а работа не стоит на месте. И нам это действительно нужно. Так что я не сержусь».

 

Что такое «оценка»?

 

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

 

Обязательства

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

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

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

 

Оценка

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

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

Оценка – это не число, а распределение. Возьмем следующий диалог:

Майк : «Сколько, по твоим оценкам, понадобится для завершения работы?»

Питер : «Три дня».

Питер действительно управится с работой за три дня? Возможно, но насколько вероятно? Правильный ответ: понятия не имеем. Что имел в виду Питер и что узнал Майк? Если Майк вернется через три дня и работа не будет выполнена, должен ли он удивляться? А почему, собственно? Питер не давал никаких обязательств. Питер не сказал ему, насколько три дня вероятнее четырех или пяти.

А если бы Майк поинтересовался у Питера, насколько высока вероятность его оценки?

Майк : «Какова вероятность того, что ты справишься за три дня»?

Питер : «Пожалуй, справлюсь».

Майк : «Можешь назвать число?»

Питер : «Пятьдесят или шестьдесят процентов».

Майк : «Значит, есть довольно высокая вероятность, что тебе понадобится четыре дня».

Питер : «Да. Может понадобиться даже пять или шесть, хотя я в этом сомневаюсь».

Майк : «До какой степени сомневаешься?»

Питер : «О, я не знаю… Я на девяносто пять процентов уверен, что работа будет сделана менее чем за шесть дней».

Майк : «То есть может быть и семь?»

Питер : «Ну, если все пойдет наперекосяк… Черт, если все пойдет наперекосяк, может быть десять и даже одиннадцать дней. Но ведь вероятность такого совпадения очень мала, верно?»

Мы постепенно начинаем видеть истину. Оценка Питера представляет собой вероятностное распределение. Своим мысленным взором он видит вероятность завершения задачи так, как показано на рис. 10.1.

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

Но Майк смотрит на происходящее иначе. Он обращает внимание на правый край распределения и беспокоится о том, что Питеру может понадобиться более 11 дней.

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

Рис. 10.1. Вероятностное распределение

 

Подразумеваемые обязательства

Майк сталкивается с проблемой. Он не уверен в том, сколько времени потребуется Питеру для выполнения работы. Чтобы свести к минимуму неопределенность, он может попробовать добиться от Питера обязательства. Питер не в состоянии что-либо обещать с полной уверенностью.

Питер : «Нет, Майк. Как я уже сказал, работа будет выполнена за три, а может, за четыре дня».

Майк : «Тогда пишем четыре?»

Питер : «Нет, теоретически может быть пять или шесть».

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

Майк : «Хорошо, Питер, но ты можешь хотя бы попытаться уложиться в шесть дней?»

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

Мы уже говорили об этом в главе 2. В это слово вкладывается разный смысл. Если Питер согласится, то он фактически возьмет на себя обязательство уложиться в шесть дней.

Какие еще возможны интерпретации? Что именно Питер собирается сделать, чтобы «попытаться»? Он собирается работать более 8 часов? Очевидно, это подразумевается в его согласии. Он собирается работать по выходным? Да, это тоже подразумевается. Пропускать семейные праздники? Да, и это тоже. Все это входит в понятие «попытаться». И если Питер чего-то не сделает, Майк сможет обвинить его в том, что он приложил недостаточно стараний.

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

 

PERT

Программа PERT (Program Evaluation and Review Technique) была создана в 1957 году ВМС США для проектирования подводных лодок Polaris. Одним из элементов PERT является способ вычисления оценок. Схема PERT предоставляет очень простой, но исключительно эффективный способ преобразования оценок в вероятностные распределения, подходящие для начальства. При оценке задачи предоставляются три числа (так называемый анализ по трем переменным):

• О: оптимистическая оценка. Это значение выбирается предельно оптимистичено. Задача может быть выполнена за это время только в том случае, если все без исключения пройдет гладко. Более того, чтобы математическая теория сработала, вероятность такого исхода должна быть менее 1%1. Как видно из рис. 10.1, в ситуации Питера это один день;

• N: номинальная оценка (наиболее вероятная). На гистограмме она будет представлена самым высоким столбцом. На рис. 10.1 номинальная оценка составляет 3 дня;

• P: пессимистическая оценка. Эта оценка также должна быть крайне предельно пессимистической. В ней следует учесть все возможные неприятности, кроме ураганов, ядерной войны, блуждающих «черных дыр» и других катастроф. Математическая база также работает только в том случае, если вероятность этого исхода много меньше 1 %. В ситуации Питера пессимистическая оценка представлена крайним правым столбцом (12 дней).

По этим трем оценкам вероятностное распределение описывается следующей формулой:

где µ – ожидаемая продолжительность задачи. В случае Питера она составит (1+12+12)/6, или около 4,2 дня. Для большинства задач оценка получается слегка завышенной, потому что правая часть распределения длиннее левой.

где σ – среднеквадратическое отклонение распределения времени выполнения задачи. Фактически это мера неопределенности задачи: если это число велико, то и неопределенность тоже велика. В нашем примере оно равно (12–1)/6, или около 1,8 дня.

По оценке Питера 4,2/1,8 Майк понимает, что задача, скорее всего, будет завершена за пять дней, но также может занять 6 и даже 9 дней.

Но Майк управляет не одной задачей – он ведет проект с множеством задач. Питеру поручены три задачи, над которыми он должен работать последовательно. Оценки продолжительности выполнения этих задач, представленные Питером, приведены в табл. 10.1.

Таблица 10.1. Задачи Питера

Что происходит с задачей «бета»? Похоже, Питер достаточно уверен в ней, но непредвиденные факторы могу серьезно затормозить его работу. Как Майку интерпретировать эти результаты? Сколько времени следует планировать на завершение всех трех задач?

Оказывается, путем простых вычислений Майк может объединить все задачи Питера и создать вероятностную оценку для всего набора задач. Вычисления весьма тривиальные:

Для любой последовательности задач предполагаемая продолжительность выполнения вычисляется простым суммированием продолжительностей всех задач последовательности. Таким образом, если Питер должен выполнить три задачи с оценками 4,2/1,8, 3,5/2,2 и 6,5/1,3, то вероятнее всего, на их выполнение Питеру понадобится около 14 дней: 4,2 + 3,5 + 6,5.

Среднеквадратическое отклонение последовательности равно квадратному корню из суммы квадратов среднеквадратичных отклонений задач. Таким образом, стандартное отклонение всех трех задач Питера равно примерно 3.

Из этого результата Майк узнает, что Питеру на решение его задач, вероятно, потребуется 14 дней, но с достаточно большой вероятностью может потребоваться 17 (1s) и даже 20 дней (2s). Решение задач может затянуться и на более долгий срок, но это маловероятно.

Вернемся к таблице оценок. Разве вам не хочется предположить, что все три задачи будут выполнены за 5 дней? В конце концов, оптимистические оценки равны 1, 1 и 3. Даже номинальные оценки в сумме дают всего 10 дней. Откуда взялись 14 дней с возможными 17 и даже 20? Дело в том, что суммирование неопределенности в серии задач добавляет реализма в исходный план.

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

 

Оценка времени выполнения

 

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

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

 

Широкополосный дельфийский метод

В 1970-е годы Барри Бем представил метод экспертной оценки, названный «широкополосным дельфийским методом». За прошедшие годы появилось много разновидностей этого метода – как формальных, так и неформальных. Но у всех них есть нечто общее: принцип консенсуса.

Стратегия проста. Группа экспертов собирается, обсуждает задачу и оценивает ее сложность. Обсуждение и оценка повторяются до тех пор, пока не будет достигнуто согласие.

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

 

Метод быстрого голосования

Все участники сидят за столом. Задачи рассматриваются последовательно. Для каждой задачи проводится краткое обсуждение, описываются возможные усложняющие факторы и возможная реализация. Затем участники опускают руку под стол и поднимают от 0 до 5 пальцев в зависимости от того, сколько, по их мнению, займет решение задачи. Модератор считает до трех, после чего все участники одновременно показывают руки.

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

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

Одновременность предъявления пальцев очень важна. Участники не должны изменять свои оценки на основании оценок, которые они видят у других.

 

Покер планирования

В 2002 году Джеймс Греннинг написал отличную статью с описанием «покера планирования». Эта разновидность широкополосного дельфийского метода стала настолько популярной, что несколько разных компаний использовали идею для создания маркетинговых сувениров в виде колод для покера планирования. Даже существует специальный сайт planningpoker.com, который может использоваться распределенными группами для проведения сеансов покера планирования в Интернете.

Идея очень проста. Всем участникам экспертной группы раздаются карты с разными числами. Числа от 0 до 5 работают достаточно хорошо; такая система логически эквивалентна системе с показанными пальцами.

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

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

По поводу правильного выбора номиналов карт существуют целые научные теории. Некоторые специалисты дошли до использования карт, номиналы которых определяются числами Фибоначчи. Другие включают в колоду карты со знаком бесконечности и вопросительным знаком. На мой взгляд, пяти карт 0, 1, 3, 5, 10 вполне достаточно.

 

Аффинная оценка

Несколько лет назад Лоуэлл Линдстром показал мне необычную разновидность широкополосного дельфийского метода. Я довольно успешно применял его с разными заказчиками и группами.

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

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

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

На следующем этапе между картами рисуются линии, представляющие трудоемкость задачи в днях, неделях, условных пунктах и т. д. Традиционно используются пять значений, образующих последовательность Фибоначчи (1, 2, 3, 5, 8).

 

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

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

 

Закон больших чисел

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

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

 

Заключение

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

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

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

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