Управление масштабом проекта.
Как и в любой профессиональной деятельности, приступая к разработке приложения, необходимо сначала произвести реалистическую оценку ресурсов проекта, выделенного времени и поставленных целей. При разработке программного обеспечения эти факторы задают "масштаб" проекта, который определяется следующими переменными.
· Набором функций, которые необходимо предоставить для удовлетворения потребностей пользователей.
· Ресурсами, которыми располагает проект.
· Временем, выделенным на реализацию.
Площадь прямоугольника представленного на рис. 3.12 представляет достижимый масштаб проекта. Его определяют ресурсы и время.
Рисунок 3.12. Масштаб проекта.
Ресурсы в основном представлены аналитиками, проектировщиками, разработчиками, тестерами, составителями руководств, и другими участниками команды разработчиков.
Еще в 1970-х годах Фред Брукс (Fred Brooks) [6] показал, что предложение добавить ресурсы в программный проект с целью увеличить отдачу является, в лучшем случае, рискованным. Закон Брукса гласит, что дополнительное привлечение рабочей силы к запаздывающему программному проекту приведет к еще большему его запаздыванию.
Если временная шкала достаточно протяженная, то производительность работы команды действительно может возрасти, но не прямо пропорционально добавленным ресурсам. Таким образом, общая эффективность проекта снизится. Добавление ресурсов может даже замедлить проект, так как необходимость обучать и поддерживать новых сотрудников снижает производительность тех, кто уже был занят в проекте. По мере того как условия конкуренции на рынке побуждают команды сокращать сроки разработки, добавление ресурсов в ходе работы над проектом практикуется все реже и реже.
Для целей анализа масштаба предположим, что ресурсы, откладываемые по оси Y (рис. 3.12), являются неизменными на протяжении периода выполнения проекта.
В конкретном проекте ограничение по времени может оказаться "мягким", т.е. подверженным пересмотру, если имеющихся ресурсов недостаточно для достижения желаемых функциональных возможностей. При анализе масштаба будем считать время, откладываемое по оси X, фиксированной величиной.
К сожалению, предоставление программ с опозданием является "нормальным явлением". С другой стороны, многие приложения имеют фиксированные сроки сдачи. Примерами могут быть новая программа начисления налогов, которая должна быть представлена ко времени начала периода налогообложения, демонстрация нового продукта, приуроченная к торговой выставке, или оговоренный в контракте с заказчиком срок сдачи. Если команда разработчиков желает доказать свою профессиональную состоятельность и завоевать доверие клиентов, очень важно не допускать ошибок при составлении графика.
Набор функциональных возможностей, который команда в состоянии создать, естественным образом ограничен временем, выделенным на реализацию, и доступными ресурсами. Поэтому достижимый масштаб представляет собой площадь прямоугольника. Если необходимый для реализации функций объем работ равен имеющимся ресурсам, умноженным на выделенное время, масштаб проекта является достижимым и проблем не возникает. В этом случае, за исключением непредвиденных обстоятельств, команда создаст программу вовремя и с надлежащим качеством.
Однако опыт свидетельствует, что зачастую части уравнения масштаба далеки от равенства. В своей работе [5] Дин Леффингуэлл и Дон Уидриг отмечают, что масштаб проекта, задаваемый руководством, заказчиками или заинтересованными лицами лишь иногда укладывается в 100 процентов. Как правило, средний масштаб проекта составляет 200 процентов, варьируя в диапазоне от 125% до 500%. Эти данные в значительной мере совпадают с результатами исследований группы Стендиша [1], свидетельствующими, что более половины проектов будут стоить примерно вдвое больше, чем предполагалось.
Что происходит, когда проект развивается с изначально заданным масштабом 200 процентов?
· Маловероятно, что функции приложения полностью независимы друг от друга. Учитывая масштаб проекта в 200 процентов, только половина из них будет реализована к моменту сдачи. При этом функции не работают совместно и не производят никакой полезной суммарной работы. Приложение с принудительно "урезанным" масштабом быстро собирается в единое целое и отправляется. Следствием является недовольство заказчиков, чьи ожидания не оправдались; невыполнение маркетинговых обязательств; некачественные руководства пользователя и рекламные материалы, которые необходимо срочно переделать. Команда страдает и теряет мотивацию.
· К моменту сдачи каждая функция готова только на 50 процентов. Поскольку, как правило, существуют взаимозависимости между отдельными частями функции, ничто вообще не работает к окончанию срока. Все обязательства нарушаются, определяется новый срок сдачи и начинается новый "марш смерти". В худшем случае вся команда увольняется после нескольких месяцев работы сверх установленного срока, объявляется финальная "фаза" первой попытки разработки проекта и назначается новый менеджер.
Каково качество программного обеспечения в каждом из этих случаев? Код, который создавался ближе к концу, плохо сконструирован и содержит дефекты, тестирование сведено к минимуму или вообще не производится, отсутствует документация и системы подсказок. Заказчикам приходится выполнять как тестирование, так и действия по обеспечению качества. В итоге заказчики реагируют на сверхусилия команды следующим образом: “Мы сразу были разочарованы тем, насколько вы опоздали (или как мало сделали по сравнению с нашими ожиданиями), но теперь мы по-настоящему недовольны, так как обнаружили, что предоставленное нам решение - программный мусор”.
Для того чтобы команда проекта имела хоть какую-то надежду на успех, ей необходимо оценивать масштаб. В большинстве случаев задача состоит в сокращении масштаба: если команда действительно начинает разработку проекта с 200-процентным масштабом, необходимо сократить его масштаб, как минимум, в два раза, чтобы иметь шанс на успех. Перед командой встает дилемма: как сократить масштаб и удовлетворить заказчика. Это один из самых трудных вопросов.
Задача управления масштабом состоит в задании высокоуровневой базы требований для данного проекта. Базовый уровень - это разбитое на элементы множество функций или требований, которые намечено реализовать в конкретной версии приложения. Базовый уровень версии должен быть согласован как с заказчиком, так и с командой разработчиков. Другими словами, базовый уровень должен обладать следующими свойствами:
· должен быть, как минимум, "приемлемым" для заказчика;
· должен иметь разумную вероятность успеха с точки зрения команды разработчиков.
Первый шаг при задании базового уровня состоит в простом перечислении функций, которые были определены для приложения.
Этот список представляет собой разбитое на пункты высокоуровневое описание возможностей новой или модифицируемой системы. Он является исключительно важным артефактом проекта, который следует использовать для оценки масштаба проекта перед тем, как будут затрачены значительные средства на уточнение требований, проектирование, разработку программного кода, тестирование и другие действия.
В качестве примера рассмотрим некий программный продукт, для которого был составлен список из следующих восьми функций.
· Функция 1. Поддержка внешней реляционной базы данных
· Функция 2. Многопользовательская безопасность
· Функция 3. Возможность клонирования проекта
· Функция 4. Порт для новой версии операционной системы (ОС)
· Функция 5. Новый "мастер" проекта
· Функция 6. Импортирование внешних данных по стилям
· Функция 7. Реализация средств предупреждения
· Функция 8. Интеграция с подсистемой управления версиями
Задание относительных приоритетов функций является составной частью управления масштабом. Важно, чтобы заказчики и пользователи или их представители, а не команда разработчиков, определяли приоритеты. Первичная расстановка приоритетов должна производиться без заметного влияния со стороны группы разработки. В противном случае уровень сложности реализации функций будет влиять на приоритеты клиентов, результаты процесса могут исказиться и окажется, что приложение не будет удовлетворять реальные потребности клиентов. Технические моменты можно будет учесть на более поздних фазах процесса расстановки приоритетов. Для рассматриваемого примера предположим, что в результате голосования относительно приоритета каждой функции, используя шкалу "критический – важный -полезный", получены результаты, приведенные в табл. 3.7.
Таблица 3.7. Функции, упорядоченные по приоритетам
Функция | Приоритет |
Функция 1. Поддержка внешней реляционной базы данных. | Критическая |
Функция 4. Порт для новой версии ОС. | Критическая |
Функция 6. Импортирование внешних данных по стилям. | Критическая |
Функция 3. Возможность клонирования проекта. | Важная |
Функция 2. Многопользовательская безопасность. | Важная |
Функция 5. Новый "мастер" проекта. | Полезная |
Функция 7. Реализация средств предупреждения. | Полезная |
Функция 8. Интеграция с подсистемой управления версиями. | Полезная |
Расстановка приоритетов — только часть представляющей масштаб картины. Если бы команда разработчиков была в состоянии выполнить всю работу, не нужно было бы задавать приоритеты. В ситуации, когда нет возможности реализовать систему целиком, необходимо определить, какую часть можно сделать и где, следовательно, провести базовый уровень для данного проекта.
Второй шаг заключается в определении приблизительного уровня трудозатрат для каждой предлагаемых функций. Это достаточно сложно сделать, так как информации для оценки объема предстоящей работы недосточно. Команда не располагает подробными требованиями или результатами проектирования, на которых можно основывать эти оценки. Лучшее, что можно сделать в этой ситуации — определить "порядок" трудозатрат для каждой функции.
Оценка трудозатрат на столь раннем этапе является сложной задачей. Команда программистов будет неохотно проводить оценки до достижения полного понимания осуществимости проекта и требований к нему. Тем не менее, первое сокращение масштаба проекта должно состояться до того, как этот уровень детализации станет известен. Для получения оценки лидеру проекта рекомендуется проводить интервью с командой разработчиков, ранжируя трудоемкость функций по шкале "низкая / средняя / высокая". В целом поход состоит в следующем: если выявленная функция подобна той, что когда-либо доводилось создавать команде программистов, и оценена ими как простая – уровень трудоемкости – низкий. Если функция с точки зрения команды программистов является одной из самых сложных в списке – уровень трудоемкости – высокий. В противном случае функции присваивается средний уровень трудоемкости.
Безусловно, если график проекта позволяет на данном этапе выделить время для более детальной оценки трудозатрат, сделать это необходимо.
Однако очень важно уметь делать некоторые быстрые предварительные заключения о масштабе предстоящих действий без проведения более детальных оценок. В противном случае ресурсы тратятся на то, что впоследствии будет определено как "ненужные продукты", среди которых окажутся спецификации требований для нереализуемых функций, информация по проектированию этих функций, сценарии проверки требований, которые будут позднее удалены в процессе сокращения масштаба проекта, неправильное определение критического пути проекта и т.д.
В процессе управления масштабом будет уменьшено количество разрабатываемых для исходной версии функций, а так как ресурсы чрезвычайно ограничены, команда разработчиков не может тратить дополнительные средства на функции, которые не будут реализованы в текущем базовом уровне. В табл. 3.8. представлен список функций с добавлением информации о трудозатратах.
Таблица 3.8. Список функций с добавленными оценками трудоемкости
Функция | Приоритет | Трудоемкость |
Функция 1. Поддержка внешней реляционной базы данных | Критическая | Средняя |
Функция 4. Порт для новой версии ОС | Критическая | Высокая |
Функция 6. Импортирование внешних данных по стилям | Критическая | Низкая |
Функция 3. Возможность клонирования проекта | Важная | Высокая |
Функция 2. Многопользовательская безопасность | Важная | Низкая |
Функция 5. Новый "мастер" проекта | Полезная | Низкая |
Функция 7. Реализация средств предупреждения | Полезная | Низкая |
Функция 8. Интеграция с подсистемой управления версиями | Полезная | Высокая |
Третий шаг управления масштабом — это оценка риска, связанного с каждой функцией. В данном случае под риском понимается вероятность того, что разработка функции окажет негативное воздействие на график и бюджет. Риск дает возможность оценить, какими могут быть последствия включения конкретной функции в базовый уровень проекта. Функция с высоким риском может негативно повлиять на проект, даже если все остальные функции будут завершены в установленное время.
Команда разработчиков задает риск с помощью любой эвристики, используя ту же градацию "низкий-средний-высокий", что и при определении трудоемкости. В табл. 3.9 представлен список функций для нашего примера с указанием рисков.
Таблица 3.9.. Список функций с добавленными оценками риска
Функция | Приоритет | Трудоемкость | Риск |
Функция 1. Поддержка внешней реляционной базы данных | Критическая | Средняя | Низкий |
Функция 4. Порт для новой версии ОС | Критическая | Высокая | Средний |
Функция 6. Импортирование внешних данных по стилям | Критическая | Низкая | Высокий |
Функция 3. Возможность клонирования проекта | Важная | Высокая | Средний |
Функция 2. Многопользовательская безопасность | Важная | Низкая | Высокий |
Функция 5. Новый "мастер" проекта | Полезная | Низкая | Низкий |
Функция 7. Реализация средств предупреждения | Полезная | Низкая | Высокий |
Функция 8. Интеграция с подсистемой управления версиями | Полезная | Высокая | Низкий |
В различных проектах стратегии уменьшения риска отличаются. Однако для управления масштабом нам достаточно просто знать о риске, связанном с каждой функцией, чтобы можно было принимать осмысленные решения на ранней стадии осуществления проекта. Например, если функция является критической и имеет высокий риск, то нужна эффективная стратегия уменьшения риска. Если функция с высоким риском характеризуется как важная и находится в списке близко к черте базового уровня, ее можно удалить или разрабатывать в том случае, "если останется время". Если окончательное решение о включении этого элемента в данную реализацию еще не принято, никакого вреда от подобных действий не будет. Если же функция с высоким риском является всего лишь полезной, следует рассмотреть вариант ее полного удаления.
Результатом описанных выше действий является набор упорядоченных по приоритету функций, для каждой из которых определены относительная трудоемкость и риск. Необходимо отметить, что зачастую приоритет мало связан с трудоемкостью или риском. Многие критические функции требуют невысоких трудозатрат, а некоторые полезные являются очень сложными. Это может помочь команде при определении очередности реализации функций. Например, критическая функция со средней трудоемкостью и низким риском может считаться кандидатом на немедленное финансирование. Задача состоит в том, чтобы применить имеющиеся ограниченные ресурсы с наибольшей выгодой для клиента. В табл. 3.10 предлагается несколько рекомендаций, основанных на значениях указанных атрибутов относительно очередности разработки критических функций.
Таблица 3.10. Определение очередности разработки функций
Атрибуты и их значения | Рекомендации |
Приоритет: критический Трудоемкость: высокая Риск: высокий | Нужно немедленно определить стратегию снижения риска; немедленно финансировать; основное внимание необходимо уделить достижимости посредством архитектуры |
Приоритет: критический Трудоемкость: высокая Риск: низкий | По-видимому, трудоемкий элемент; немедленно финансировать |
Приоритет: критический Трудоемкость: низкая Риск: низкий | Финансировать как безрисковый фактор или отложить на потом |
Команда, которая имеет даже грубую (основанную на трудозатратах) оценку, может определить базовый уровень, суммируя оценки трудозатрат, пока сумма не станет равна произведению наличных ресурсов и выделенного времени. Однако часто команда не имеет в своем распоряжении даже этих данных, но вынуждена произвести первое сокращение объема проекта. В этом случае неизвестно, где провести базовый уровень, но если команда чувствует, что объем проекта превышает 100%, список функций, вероятно, придется сократить.
Следующий шаг наиболее сложный. Если предположить, что объем работ, необходимый для разработки существующего набора функций, составляет более 200 процентов от возможного, базовый уровень должен отсечь половину или больше.
Для решения этой задачи на первом шаге следует выяснить, можно ли за отведенное время завершить разработку функций, имеющих критический приоритет. В конечном итоге, если команда правильно расставила приоритеты, то лишь треть (или около того) элементов списка будет признана критической для данной версии за исключением случая, когда одна из критических функций имеет непропорционально большую трудоемкость. Обратите внимание, что после сокращения масштаба проекта у команды остается основа для составления плана реализации. В противном случае команда имеет дело с проектом еще большего масштаба (300-400% или более). Следует определить проект меньшего масштаба и повторить процесс расстановки приоритетов.
Учитывая, что в результате применения описанного подхода команда располагает только грубыми оценками, невозможно с уверенностью сказать, сколько элементов, помимо критических, удастся реализовать. Для дальнейшего уточнения базового уровня можно использовать оценки, основанные на более детальных требованиях и оценке технической достижимости. Параллельно можно создать подробный план проекта, чтобы проверить достоверность сделанных командой предположений.
Для многих реальных проектов достаточно провести базовый уровень по критическим требованиям, возможно, включив один или два важных элемента, и оставить на усмотрение команды разработчиков принятие дальнейших решений о включении важных элементов, в зависимости от того, как продвигается проект.
Если правильно формировать ожидания пользователей, то все, что удастся осуществить помимо базового уровня проекта, будет бонусом проекта. Табл. 3.11. содержит результат применения этой простой эвристики к рассматриваемому примеру.
Таблица 3.11. Упорядоченный список функций.
Функция | Приоритет | Трудоемкость |
Функция 1. Поддержка внешней реляционной базы данных | Критическая | Средняя |
Функция 4. Порт для новой версии ОС | Критическая | Высокая |
Функция 6. Импортирование внешних данных по стилям | Критическая | Низкая |
Функция 3. Возможность клонирования проекта | Важная | Высокая |
Базовый уровень. Функции, расположенные выше – обязательны к реализации в текущей версии системы.
Функция 2. Многопользовательская безопасность | Важная | Низкая |
Функция 5. Новый "мастер" проекта | Полезная | Низкая |
Функция 7. Реализация средств предупреждения | Полезная | Низкая |
Функция 8. Интеграция с подсистемой управления версиями | Полезная | Высокая |
Функции, находящиеся ниже базового уровня, являются “будущими” и будут рассматриваться при реализации следующих версий. Приоритет этих функций в дальнейшем может быть повышен на основании того, что сделано, и исходя из будущих пожеланий заказчика.
Конечно, функции не всегда независимы. Во многих случаях одна из функций, находящаяся ниже базового уровня, связана с некой функцией, расположенной выше базового уровня, или же ее легче реализовать с помощью другой функции. Может оказаться, что команда опережает график или находит библиотеку классов, которая существенно упрощает реализацию функции, находящейся ниже базовой линии. В таких случаях команда должна иметь право включить эту функцию в число базовых и в разрабатываемую версию, переопределить очередность и переустановить базовый уровень, естественно, уведомив всех, кого нужно.
Таким образом, команда сможет создать план проекта, по крайней мере, в первом приближении. Однако, по всей вероятности, многие из желаемых функций не войдут в первый срез, и потребуется работа с ожиданиями как внутри, так и вне компании.