Относительное взвешивание представляет собой подход к оценке выгод от реализации функции и потерь в результате отказа от ее реализации, а также к приведению затрат к единому значению, представляющему приоритет функции.
Вопросы для обсуждения
1. Назовите сравнительные достоинства анализа Кано и относительного взвешивания в вашей организации.
2. Какие привлекательные функции предполагается включить в ваш текущий проект?
3. Можно ли сказать, что ваш текущий проект имеет оптимальное соотношение привлекательных, линейных и обязательных функций?
Глава 12
Разбивка пользовательских историй
Сегодня мы не пишем программы модуль за модулем; мы создаем программы функция за функцией.
Мэри Поппендик
По мере того как пользовательские истории перемещаются в верхние строки плана релиза, т. е. по мере приближения реализации, нередко возникает потребность в их разбивке. В самом деле, когда реализация конкретной пользовательской истории требует больше времени, чем продолжительность итерации, не остается ничего иного, как разбить историю на две части или более. Научиться разбивать истории — не такая уж трудная задача, однако она требует определенных навыков и опыта. Чем разнообразнее пользовательские истории, которые вы разбивали в прошлом, тем легче вам будет справиться с новыми. С учетом этого в настоящей главе предлагаются рекомендации по разбивке историй на нескольких примерах. Эти примеры помогают сформулировать ряд правил, которые можно применять при разбивке других историй.
Рекомендации из этой главы можно использовать в любой момент при возникновении потребности в разбивке истории. Вместе с тем правила ориентированы прежде всего на пользовательские истории или функции, которые трудно поддаются разбивке.
Когда нужно разбивать пользовательскую историю
Бывают ситуации, в которых пользовательскую историю приходится разбивать на несколько частей. Во-первых, пользовательские истории требуют разбивки, когда они слишком велики и не укладываются в одну итерацию. Иногда история не укладывается в итерацию потому, что просто больше нее. Понятно, что историю в такой ситуации необходимо разбить. Или история меньше планируемой итерации, но не укладывается в нее из-за недостатка места. Команда может решить, что времени достаточно для разработки за итерацию только части этой истории.
Во-вторых, может быть полезно разбить крупную пользовательскую историю (эпопею), если требуется более точная оценка. Приведу пример. Один из моих клиентов рассматривал возможность реализации новых функций, которые должны были обеспечить расширенный доступ в его систему работавшим в других компаниях представителям службы по поддержке клиентов. Первый вопрос, на который нужно было ответить владельцу продукта: стоит ли овчинка выделки? Вместо того чтобы составлять кучу индивидуальных пользовательских историй, он написал одну большую историю и изложил свое видение этой истории команде. Команда оценила ее в 70 пунктов. Это было достаточно хорошо, чтобы владелец продукта захотел добавить новые функции. Он знал, что с оценкой связана большая неопределенность, но, даже если бы ошибка составляла 100 %, реализация функций все равно имела бы смысл. Если бы возникла проблема с включением дополнительных 70 пунктов в один релиз, владелец продукта мог бы разбить большую историю на части и предложить команде оценить несколько более мелких историй.
Разбивка по границам данных
Лучше всего разбивать большие пользовательские истории по данным, которые будут поддерживаться. Например, в одном из проектов команда разрабатывала продукт, предназначенный для сбора финансовой информации. Она начала с одной крупной пользовательской истории: «Как пользователь я могу вводить информацию из моего баланса». Баланс в данном случае мог иметь очень много полей. На самом высоком уровне в нем находятся активы и пассивы. Активы содержат такие статьи, как денежные средства, ценные бумаги, объекты недвижимости, автомобили, кредиты. Система позволяла пользователю работать с этим балансом на различных уровнях детализации. Пользователь мог ввести одну сумму, представляющую все его активы. Или он мог ввести более детальную информацию (подробное перечисление всех кредитов). Вывод множества полей на экран и взаимодействие между этими полями представляли задачу значительно более крупную, чем команда, по ее оценкам, могла реализовать за одну двухнедельную итерацию.
Команда разбила эту историю по типам данных, которые мог вводить пользователь. Первая история выглядела так: «Как пользователь я могу вводить суммарные балансовые показатели». Эта история была очень маленькой (даже слишком маленькой), поскольку предполагала создание лишь базовой формы и двух полей: активы и пассивы. Следующая история была сформулирована следующим образом: «Как пользователь я могу вводить балансовые данные по категориям». Эта история покрывала следующий уровень детализации (денежные средства, ценные бумаги, объекты недвижимости, кредиты и т. д.). В результате реализации этой истории на экране должны были появиться два десятка полей для ввода данных. Очередная история касалась подтверждения правильности данных: «Как пользователь я хочу, чтобы была возможность подтверждения введенных данных во избежание ошибок». Команда обсудила смысл этого и пришла к выводу, что необходимо предоставить возможность ввода положительных и отрицательных чисел, что десятичные знаки могли вводиться, но суммы должны были автоматически округляться до целых чисел и т. д.
Следующая история звучала так: «Как пользователь я могу вводить детальную информацию по кредитам». Эта история должна была позволить пользователю вводить до 100 кредитов (это число обсудили, согласовали и сделали условием удовлетворенности на карточке истории). Данная история была крупнее, чем выглядела, поскольку решала несколько проблем с пользовательским интерфейсом, таких как количество новых рядов данных по кредитам, которые должны отображаться на экране. Эта история оказалась намного крупнее других, которые получились при разбивке исходной истории. Вместе с тем даже она была значительно меньше исходной истории, поскольку касалась поддержки детальных данных только по кредитам. Историю, связанную с кредитами, сделали образцом для многих других пользовательских историй, которые разбивались на части, вроде таких, как «Как пользователь я могу вводить детальную информацию по моим объектам недвижимости» и «Как пользователь я могу вводить детальную информацию по моим денежным авуарам, включая текущие и сберегательные счета».
Разбив исходную историю таким образом, команда создала около десятка пользовательских историй. Каждая новая история имела теперь такой размер, что ее можно было реализовать в течение двухнедельной итерации. Это дает нам первое правило:
Разбивайте большие истории по границам данных, поддерживаемых историей.
Разбивка пользовательской истории по границам данных — очень полезный подход, который обязательно должен быть в вашем портфеле инструментов. Приведу еще один пример. Несколько лет назад я работал с командой, разрабатывавшей автоматизированную подсистему факсимильной связи. Команда столкнулась с большими пользовательскими историями относительно того, как сконфигурировать систему. Эти истории удалось значительно уменьшить, разделив поддержку внутриамериканских и международных телефонных номеров.