Зачем всё это?
Про то, как посчитать ёмкость задач разного уровня сложности написано немало, например эта статья. Ответу же на практический вопрос: «А сколько реально сможет взять команда?», – уделено меньше внимания. В рамках своей статьи поделюсь эмпирическим методом расчёта ёмкости на основании простых статистических данных.
Для тех, кто знаком с другими методами эмпирического прогнозирования (например, методом «Вчерашней погоды» из Scrum) материал также может быть интересен.
Исходные данные
Для работы понадобится:
Команда заинтересованных сотрудников;
Итеративный процесс разработки по любому из фреймфорков (SAFe, Scrum, каскадная модель и т.п.);
Некий принятый командой метод оценки (в нашем случае, Story Points);
Договорённости о правилах закрытия и переноса задач из спринта в спринт;
Графики отпусков/совмещений;
Статистика выполненных задач в прошлых итерациях (скорость команды).
Немного про статистику
В рамках этой статьи под статистикой подразумевается сумма оценок выполненных командой задач в группировке по спринтам – скорость команды в разрезе спринтов. Самый простой способ её получения – выгрузить из трекинговой системы по каждому интересующему спринту, сколько было выполнено задач и на сколько они были оценены.
Важно понимать, что если в трекинговой системе задачи закрываются абы как, то доверия к таким данным мало. И приходится их дублировать или вести отдельно.
Теория
Прежде чем приступить к расчёту, определимся с несколькими важными терминами:
Термин |
Описание |
Цель использования |
Уменьшает влияние |
Story Point (SP) |
Мера относительной оценки задачи команды.
|
Даёт единую методику оценки, которой достаточно легко обучить большое количество сотрудников. |
Позволяет уменьшить или исключить неопределенности с оценкой малоизвестных задач. |
Full Time Equivalent (FTE) |
Мера включенности сотрудника в проект. |
Показывает, сколько требуется человек для выполнения проекта или сколько сотрудников компания нанимает в течение финансового года. |
Убирает из рассмотрения фреймворк команды. |
Доля командных мероприятий |
Мера командных временных затрат. |
Показывает какую часть FTE участник команды тратит на командные активности. |
Убирает из расчётов организационную составляющую команды. |
Focus Factor (FF) |
Мера доли работы команды по отношению к рабочему времени. |
Является отношением единицы выполненной командной работы (SP) к дню работы эквивалентного сотрудника (FTE). |
Убирает зависимость от единиц измерения (SP, ч/час, ч/день и т.п.) и статистические флуктуации.
|
Приведенный FTE (FTE') |
Мера включенности сотрудника в работу над бизнес-задачами. |
Соответствует FTE за вычетом командных активностей. |
Исключает влияние командных активностей из процесса работы над задачей. |
Немного про FF
FF напрямую зависит от размера единицы измерения и его можно считать как по FTE, так и по приведенному FTE'.
Что интересно, поскольку FF – интегральный показатель, он меняется с течением времени. Он зависит от множества факторов, которые учитываются в SP и FTE, как во внутреннем пространстве команды, так и во внешнем.
При этом алгоритм вычисления FF не изменяется – автоматически учитывается (за счёт историчных данных) и смена состава, и изменение направления решаемых задач, и частичная занятость в проекте. То есть все те форс-мажоры, что случаются с командой в домене Complex Enterprise разработки.
Метод
Процесс определения Capacity и FTE визуально можно представить в виде 2х последовательностей действий:
Алгоритм расчёта
А у нас не SP!
Алгоритм приведен в примере единиц измерения задачи SP. Если у вас другие единицы, формулы тоже работают с единственным дополнением – флуктуации в процессе оценки сильнее влияют на прогнозируемый результат.
Тезисно
-
Вычисляем FF прошлых инкрементов:
Берем среднее значение SP прошедших трёх инкрементов за 1-4 спринты - AvgSP;
Берем среднее значение FTE' прошедших трёх инкрементов за 1-4 спринты - AvgFTE';
Получаем отношение FFprev = AvgSP/AvgFTE'.
-
Вычисляем FTE'new нового инкремента по каждому спринту:
Берём производственный календарь;
Учитываем график отпусков сотрудников;
Применяем коэффициенты совмещения и командных активностей.
-
Вычисляем Capacity на новый инкремент:
Вычисляем по каждому спринту SPsprint = FFprev * FTE'new.
Детально
Бывают ситуации, когда сразу посчитать FF прошлых инкрементов не получается в виду отсутствия информации о FTE. Поэтому приходится расчет FTE повторять 2 раза: на 0 и 2 шаге.
Если у вас с данными все хорошо и FTE' прошлых инкрементов имеется, можно сразу приступать к Шагу 1.
А если только начинаете использовать метод, то вполне достаточно ограничиться статистическими данными последнего инкремента.
А если нет статистики (новая команда или новый проект)?
Если команда новая и ещё ни разу не работала над задачей, то для первого прогноза можно взять FF = 0.75+/- 0.25. По результатам отработанного инкремента – пересчитать.
Более подробно см. Agile Estimating and Planning by Mike Cohn.
Шаг 0. Расчёт FTE' прошлого инкремента
Определяем время присутствия членов команды на проекте (FTE). Для этого необходимо взять график фактических отпусков (с отгулами, переносами, больничными и т.д.) и наложить его на производственный календарь.
Полученное значение умножаем на коэффициент совмещения, так как некоторые участники команды могут присутствовать не full time. Важно понимать, что FTE, это не оценка трудоёмкости в ч/час, а присутствие в команде.
Поскольку не все 40 часов в неделю участник команды посвящает разработке, FTE необходимо скорректировать под командные активности (Daily, грумминги, ретроспективы и обучения). Это делается с помощью коэффициента доли командных мероприятий. Эмпирические наблюдения рекомендуют брать его значение в размере 20%.
Общий принцип расчёта FTE приведен на графике.
Пример расчёта
Команда состоит из 5 человек: 3 разработчика, 1 аналитик и 1 тестировщик
Sprint |
Date Beg |
Date End |
Duration |
1 |
21.11.2022 |
04.12.2022 |
10 |
2 |
05.12.2022 |
18.12.2022 |
10 |
3 |
19.12.2022 |
01.01.2023 |
9 |
4 |
02.01.2023 |
15.01.2023 |
5 |
5 (dev) |
16.01.2023 |
22.01.2023 |
5 |
5 (planning) |
23.01.2023 |
29.01.2023 |
5 |
Присутствие в рабочие дни:
Team/Days |
Sprint 1 |
Sprint 2 |
Sprint 3 |
Sprint 4 |
Sprint 5 (dev) |
Sprint 5 (planning) |
[dev] 1 |
5 |
9 |
9 |
5 |
5 |
5 |
[dev] 2 |
10 |
0 |
5 |
5 |
5 |
5 |
[dev] 3 |
10 |
10 |
9 |
5 |
5 |
5 |
[analyst] 1 |
10 |
10 |
9 |
5 |
0 |
0 |
[q/a] 1 |
10 |
10 |
0 |
5 |
5 |
5 |
Team/FTE' |
% FullTime |
Sprint 1 |
Sprint 2 |
Sprint 3 |
Sprint 4 |
Sprint 5 |
[dev] 1 |
100 |
4 |
7 |
7 |
4 |
4 |
[dev] 2 |
80 |
6 |
0 |
3 |
3 |
3 |
[dev] 3 |
100 |
8 |
8 |
7 |
4 |
4 |
[analyst] 1 |
100 |
8 |
8 |
7 |
4 |
0 |
[q/a] 1 |
100 |
8 |
8 |
0 |
4 |
4 |
Данные из примера:
Team/FTE' |
% FullTime |
Sprint 1 |
Sprint 2 |
Sprint 3 |
Sprint 4 |
Sprint 5 |
[dev] 1 |
100 |
4 |
7 |
7 |
4 |
4 |
[dev] 2 |
80 |
6 |
0 |
3 |
3 |
3 |
[dev] 3 |
100 |
8 |
8 |
7 |
4 |
4 |
[analyst] 1 |
100 |
8 |
8 |
7 |
4 |
0 |
[q/a] 1 |
100 |
8 |
8 |
0 |
4 |
4 |
В первом приближении расчёт FTE' по участнику команды можно представить в виде формулы:
Описание коэффициентов
Коэффициент |
Описание |
n |
Количество рабочих дней спринта |
m |
Количество рабочих дней отсутствия участника команды |
k |
Процент совмещения |
l |
Доля командных активностей |
Для 5 спринта FTE рассчитывается только для тех недель, где нет SAFe-планирования, то есть в общем случае, для 1 недели.
Шаг 1. Расчет FF прошлых инкрементов
Статистика выполненных командой задач в прошлых инкрементах
Для расчёта необходимо взять статистику выполненных командой задач. При этом важно, чтобы размерность используемых данных совпадала с размерностью прогнозируемой ёмкости. Ещё в расчёт стоит брать только продуктовые спринты. В случае SAFe-планирования, когда одна итерация предназначена для багфикса и подготовки к следующему инкременту (проведение планирования), этот 5 спринт в расчётах не стоит учитывать.
Таким образом, нас интересуют только те спринты, где команда планово поставляет ценность.
Холивар о переносе задач
Ещё одним подводным камнем статистики является процесс переноса задач из спринта в спринт. В этом случае рекомендую простое правило от Майка Кона «всё или ничего» (см. книгу Agile Estimating and Planning by Mike Cohn, глава Re-Estimating Partially Completed Stories) – если цель задачи не достигнута (не проведен показ и/или доработка не принята бизнесом), она (задача) полностью переносится в следующий спринт (с полной оценкой). Для любознательных – хорошая дискуссия на тему.
И последний нюанс: в практике возникают ситуации, когда данные по трекингу задач отличаются от реальной работы команды. Например, команда массово закрывает в системе все задачи под конец спринта/инкремента, а не в реальный момент выполнения. Либо система не фиксирует (сложно выгрузить) дату начала работы над задачей.
Пример статистики
SP |
Sprint 1.1 |
Sprint 1.2 |
Sprint 1.3 |
Sprint 1.4 |
Sprint 2.1 |
Sprint 2.2 |
Sprint 2.3 |
Sprint 2.4 |
Sprint 3.1 |
Sprint 3.2 |
Sprint 3.3 |
Sprint 3.4 |
Sprint 4.1 |
Sprint 4.2 |
Sprint 4.3 |
Sprint 4.4 |
Planed |
14 |
24 |
12 |
15 |
15 |
8 |
18 |
14 |
13 |
12 |
23 |
15 |
18 |
17 |
22 |
23 |
Fact |
17 |
24 |
12 |
11 |
18 |
8 |
13 |
14 |
15 |
12 |
24 |
12 |
18 |
15 |
22 |
20 |
Здесь нас интересует строка Fact
Берем среднее значение по инкрементам и получаем AvgSP:
Sprint 1.* |
Sprint 2.* |
Sprint 3.* |
Sprint 4.* |
|
Avg SPsprint |
16 |
13.25 |
15.75 |
18.75 |
AvgSP |
15.94 |
Зачем 2 группировки?
Первое усреднение, в границах инкремента, убирает неравномерность в спринтах – когда задачи переносятся из спринта в спринт, но к концу инкремента выпускаются
Второе усреднение, в границах расчета, убирает флуктуации от разнотипных фич и сезонов отпусков.
Берем значение из примера: AvgSP = 15.94
Статистика FTE' в прошлых инкрементах
Пример статистики FTE'
Sprint 1.1 |
Sprint 1.2 |
Sprint 1.3 |
Sprint 1.4 |
Sprint 2.1 |
Sprint 2.2 |
Sprint 2.3 |
Sprint 2.4 |
Sprint 3.1 |
Sprint 3.2 |
Sprint 3.3 |
Sprint 3.4 |
Sprint 4.1 |
Sprint 4.2 |
Sprint 4.3 |
Sprint 4.4 |
|
FTE |
56 |
56 |
36 |
49 |
44 |
21 |
48 |
46 |
37 |
23 |
50 |
43 |
49 |
49 |
50 |
57 |
И среднее значение:
Sprint 1.* |
Sprint 2.* |
Sprint 3.* |
Sprint 4.* |
|
Avg FTE'sprint |
49.25 |
39.75 |
38.25 |
51.25 |
AvgFTE' |
44.625 |
Берем значение из примера: AvgFTE' = 44.625
Вычисление FF прошлых инкрементов
Используем простую математическую формулу:
Шаг 2. Расчет FTE' нового инкремента
Алгоритм подробно описан в Шаге 0
Пример расчёта
Команда состоит из 5 человек: 3 разработчика, 1 аналитик и 1 тестировщик
Sprint |
Date Beg |
Date End |
Duration |
1 |
31.01.2023 |
12.02.2023 |
10 |
2 |
13.02.2023 |
26.02.2023 |
8 |
3 |
27.02.2023 |
12.03.2023 |
9 |
4 |
13.03.2023 |
26.03.2023 |
10 |
5 (dev) |
27.03.2023 |
02.04.2023 |
5 |
5 (planning) |
03.04.2023 |
09.04.2023 |
5 |
Присутствие в рабочие дни:
Team/Days |
Sprint 1 |
Sprint 2 |
Sprint 3 |
Sprint 4 |
Sprint 5 (dev) |
Sprint 5 (planning) |
[dev] 1 |
10 |
8 |
9 |
10 |
0 |
5 |
[dev] 2 |
10 |
8 |
9 |
10 |
5 |
5 |
[dev] 3 |
10 |
4 |
7 |
10 |
5 |
5 |
[analyst] 1 |
10 |
8 |
9 |
10 |
5 |
5 |
[q/a] 1 |
10 |
8 |
9 |
10 |
5 |
5 |
Team/FTE' |
% FullTime |
Sprint 1 |
Sprint 2 |
Sprint 3 |
Sprint 4 |
Sprint 5 |
[dev] 1 |
100 |
8 |
6 |
7 |
8 |
0 |
[dev] 2 |
80 |
6 |
5 |
5 |
6 |
3 |
[dev] 3 |
100 |
8 |
3 |
5 |
8 |
4 |
[analyst] 1 |
100 |
8 |
6 |
7 |
8 |
4 |
[q/a] 1 |
100 |
8 |
6 |
7 |
8 |
4 |
Данные из примера:
Team/FTE' |
% FullTime |
Sprint 1 |
Sprint 2 |
Sprint 3 |
Sprint 4 |
Sprint 5 |
[dev] 1 |
100 |
8 |
6 |
7 |
8 |
0 |
[dev] 2 |
80 |
6 |
5 |
5 |
6 |
3 |
[dev] 3 |
100 |
8 |
3 |
5 |
8 |
4 |
[analyst] 1 |
100 |
8 |
6 |
7 |
8 |
4 |
[q/a] 1 |
100 |
8 |
6 |
7 |
8 |
4 |
Шаг 3. Расчет Capacity нового инкремента
Вычисляем по каждому спринту применяя правило математического округления:
FFprev = 35.72% |
Sprint 1 |
Sprint 2 |
Sprint 3 |
Sprint 4 |
Sprint 5 |
FTE'new |
38 |
26 |
31 |
38 |
15 |
SPsprint |
14 |
9 |
11 |
14 |
5 |
В результате, на следующий инкремент у команды есть 48 SP в 1-4 спринтах и 5 SP запаса в 5 на багфикс и переехавшие задачи.
Побочка
Как и любое лекарство, метод имеет свои побочные эффекты:
Возможность проверки сходимости оценок – можно сравнить плановые и фактические часы работы над задачей;
Исключение человеческого фактора координатора/тимлида в плане расчета ёмкости – после проведения обучения, любой заинтересованный может прогнозировать ёмкость следующих инкрементов. При этом понимание специфики работы команды, стека технологий и процессов требуется только при оценке задач, но не при планировании ёмкости;
Учёт внутрикомандных процессов – для подхода не важно, как задачи движутся внутри команды, какие есть договоренности и ограничения. Мы оперируем чистыми планом и фактом. Даже если в команде есть системные процессные проблемы, на возможность предсказания ёмкости они не оказывают сильного воздействия;
Итог
Как видим, определение capacity нового инкремента подлежит алгоритмизации. При желании, его можно встроить в свою трекинговую систему.
По опыту команды, с момента перехода на метод, большая часть проблем с планированием ёмкости нового инкремента ушла. За 2 года работы с использованием метода спринт закрывали не на 100% только по двум причинам: взяли сильно больше расчётной ёмкости и форс-мажоры (переприоритезация, внепланы, задачи с огромным количеством неизвестных, резкое изменение состава команды).
Последствия от применения метода на данных одной команды
До метода:
SP |
Sprint 5.1 |
Sprint 5.2 |
Sprint 5.3 |
Sprint 5.4 |
Sprint 6.1 |
Sprint 6.2 |
Sprint 6.3 |
Sprint 6.4 |
Planed |
45 |
37 |
41 |
29 |
34 |
34 |
27 |
35 |
Fact |
30 |
23 |
15 |
22 |
26 |
27 |
22 |
34 |
% |
66.67 |
62.16 |
36.59 |
75.86 |
76.47 |
79.41 |
81.48 |
97.14 |
Среднее значение выполнения задач – 72%
После 2х лет применения:
SP |
Sprint 18.1 |
Sprint 18.2 |
Sprint 18.3 |
Sprint 18.4 |
Sprint 19.1 |
Sprint 19.2 |
Sprint 19.3 |
Sprint 19.4 |
Sprint 20.1 |
Sprint 20.2 |
Sprint 20.3 |
Sprint 20.4 |
Planed |
13 |
12 |
23 |
15 |
18 |
17 |
22 |
23 |
19 |
18 |
16 |
13 |
Fact |
15 |
12 |
24 |
12 |
18 |
15 |
22 |
20 |
22 |
18 |
25 |
14 |
115.54 |
100 |
104.35 |
80 |
100 |
88.24 |
100 |
86.96 |
115.79 |
100 |
156.25 |
107.69 |
Среднее значение выполнения задач - 105%.
Логика и мнения коллег других направлений, подсказывает, что метод можно использовать не только в SAFe, но и в каскадных фреймворках. Буду признателен получить в комментариях примеры других практик по прогнозированию capacity. :)
Благодарности
Хочу выразить благодарность людям, без которых данная статья не появилась бы на свет: Денису Ветрову, привившему описываемый подход, Дарии Бутенко и Диме Тараскину, активно помогавшим в подготовке материалов для публикации и всем командам, которые на своём опыте дотачивали методику.