Как стать автором
Поиск
Написать публикацию
Обновить

Throughput: как научиться перестать гадать сроки и начать их предсказывать через симуляцию Monte-Carlo

Уровень сложностиПростой
Время на прочтение9 мин
Количество просмотров1.2K

Как использовать метрику потока Throughput и реалистично прогнозировать на основе симуляции Монте-Карло. Разберем динамику Throughput (пропускной способности) за значимые периоды времени, насколько она вариативна, посмотрим на кластеризацию по типам работы).

Преамбула

Заходишь убитый в пятницу в бар. Заказываешь пивной сет. Официант обдумывает в голове: "За последний час я у нас было приготовлено 12 заказов, сейчас в работе 4 заказа, новый сет будет пятый в очереди", а потом информирует нас: "Ваш заказ подадут через 20-25 минут."

Никаких субъективных оценок сложности, просто прикинул исторические данные и сделал прогноз. Голубая мечта - чтобы IT-команда планировала так же просто, честно и (относительно) предсказуемо. Мы можем попробовать приблизиться к таким прогнозам.

Вот и пост максимально практический, с паттернами и примерами. Цель не показать метрику и прогнозирование на его основе его как ультимативный silver-bullet, а дать понимание что можно и так. Тема довольно актуальная, так как сейчас в США и Европе расцвет прогнозирования на основе именно метрик потока и появляется много плагинов с Монте-Карло (но не все из них доступны в РФ).

Throughput (пропускная способность) - одна из главных метрик потока

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

Throughput — количество завершённых задач за период времени. Если команда закрыла 8 задач за неделю, throughput = 8 задач/неделю. Очень просто, объективно, невозможно подделать (но при желании всегда можно хакнуть).

Или вот: команда завершила 15 user stories за 2 недели → throughput = 7.5 историй/неделю.

Другие метрики потока - Cycle Time, Lead Time.

Три среза, через которые мы анализируем Throughput

Временные периоды

Важно понимать, какой временной период для вас значим и достаточно ли его для анализа.

Мы с вами часто считаем Velocity на уровне спринта. Будь то количество готовых элементов или пресловутых Story Points. Считать Velocity в спринте статистически недостаточно. Это всего лишь 26 точек данных в год (если у вас двухнедельные спринты) - самый минимум для базового анализа. Но на таком масштабе не видно внутренних паттернов.

Зато если замерять

  • Ежедневно: 260 точек/год — становятся видны паттерны по дням недели

  • Еженедельно: 52 точки/год — достаточно для трендов

На недельных отрезках Throughput выглядит немного иначе
На недельных отрезках Throughput выглядит немного иначе
Дневная динамика показывает что в самые пиковые дни команда просто закрыла несколько задач. Еще удивительно что в мае у команды не было просадки
Дневная динамика показывает что в самые пиковые дни команда просто закрыла несколько задач. Еще удивительно что в мае у команды не было просадки

Пример паттернов внутри недели:

Понедельник: 0 задач (планирование)
Вторник: 1 задача (разгон)  
Среда: 3 задачи (пик продуктивности)
Четверг: 2 задачи (код-ревью)
Пятница: 2 задачи (релиз)

Интерактивный пример с демо-данными можно посмотреть здесь - как меняются паттерны на масштабе.

Скажу очевидное: у Throughput может - может расти, может снижаться. На то могут быть разные причины, от роста команды до декомиссии сервиса или продукта. Но для предсказуемости нам важен другой аспект: стабильность.

Variance: математический индикатор стабильности

Пример вариативности на неделю 2-8 июня. Команда делает +-104% работы от предыдушего скользящего окна в 4 прошлых периода
Пример вариативности на неделю 2-8 июня. Команда делает +-104% работы от предыдушего скользящего окна в 4 прошлых периода

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

Variance (коэффициент вариации) = (Стандартное отклонение* / Среднее*) × 100%

*за последние 4-8 периодов. В идеале

Коэффициент Вариации показывает стабильность throughput:

  • < 15% — очень стабильно

  • 15-30% — достаточно стабильно

  • 30-50% — требует внимания

  • > 50% — критическая нестабильность

То есть в последнем случае, наша команда запилит X задач +-50%. Не очень надежно.

Примеры разной вариативности: "Американские горки" (Variance 87%)

  • Недели: 15 → 2 → 18 → 1 → 16 задач

  • Признак неконтролируемого процесса.

"Высокая предсказуемость" (Variance 12%)

  • Недели: 7 → 8 → 6 → 7 → 8 задач

  • Хорошая прогнозируемость

Распределение по типам работы

Очевидно, что типы работы влияют на количество завершенных элементов. Если вы завершаете 4-5 сторей побольше, или 10-15 багов поменьше. Поэтому, мы смотрим не только на временные тренды Throughput, но и на распределение по типам задач.

Команда начала новый этап работы в Q2 и количество исследовательских задач выросло.
Команда начала новый этап работы в Q2 и количество исследовательских задач выросло.

Метрика не говорит что команда "хорошая" или "плохая"

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

Детский страх почти всех команд и руководителей, как только ты вводишь цели по метрикам
Детский страх почти всех команд и руководителей, как только ты вводишь цели по метрикам

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

Поэтому метрики без балансирующих индикаторов не стоит засовывать в цели команде.

Throughput служит лишь входной точкой для анализа и оптимизации, если возникает такая потребность. Для полноценной оценки важно учитывать также WIP, различные показатели Cycle Time и выходить за рамки процессных метрик — анализировать сбои системы, за которую отвечает команда.

Потому что все метрики связаны законом Литтла.

Закон Литтла - универсальная закономерность в метриках потока

В метриках потока показатели связаны и на них надо смотреть вместе. Наш с вам пост сегодня затронул только Throughput, без Lead Time и WIP. Но работая с одной метрикой вы влияете на другие. Закон Литтла - это фундаментальная теорема теории очередей.

Lead Time = WIP / Throughput

  • WIP — незавершенные задачи в работе одновременно

  • Throughput — количество завершенных элементов

  • Lead Time — время от принятия обязательств до доступности ценности для клиента

Важно: все расчёты throughput, анализа потока и любые симуляции Монте-Карло работают только при наличии ограничения на количество одновременно выполняемых задач — WIP-лимита, хотя бы по верхнему пределу. Если WIP не ограничен (и вы можете напихивать бесконечное количество задач в работу), система становится хаотичной, поток нельзя анализировать, а любые прогнозы становятся ненадежными.

Monte Carlo Simulation для вероятностных прогнозов

Когда мы говорим про прогнозы, мы всегда учитываем три фактора:

  • Вероятность

  • Разброс

  • Предположение, что в будущем мы делаем примерно такую же работу.

Поэтому некорректно было бы делать прогнозы в стиле "Этот эпик (в 10 задач) сделаем ровно за 6 недель". А корректнее было бы сказать "10 задач за 5-7 недель*"

  • 5 недель = 50% всех симуляций заканчивалось за это время или раньше

  • 7 недель = 85% всех симуляций заканчивалось за это время или раньше

Как вообще работает Monte Carlo Simulation?

  1. Берём историю throughput:

  2. Симулируем 1,000 - 10,000 сценариев

  3. Получаем распределение вероятностей

1000 симуляций. В 50% получилось что за 39 дней или меньше мы добили наши 10 задач
1000 симуляций. В 50% получилось что за 39 дней или меньше мы добили наши 10 задач

Например, для 10 задач:

  • 50% вероятность: 39 дней

  • 85% вероятность: 50 дней

  • 95% вероятность: 58 дней

А вот как выглядит вероятность по нарастающей. 39 и 50 дней разброса это довольно близко.
А вот как выглядит вероятность по нарастающей. 39 и 50 дней разброса это довольно близко.

Приходим к бизнесу и явно оговариваем, что: "Наш прогноз: 4-6 недель". Если нужно, проясняем.

  • 85pp - более надежный и безопасный прогноз, судя по нашим историческим данным мы почти наверняка закроем работу за это время.

  • При этом Дэниел Ваканти (автор Actionable Agile Metrics) говорит что в целом планироваться можно и по 50pp (медианной вероятности).

Чем более предсказуемая ваша команда (чем ниже вариация) - тем ближе 50 и 85 перцентили в прогнозах. Тем точнее ваши прогнозы.

На качество прогнозов влияет:

  • Нарезка задач (предпочтительно, если она вертикальная: end-2-end, включающая в себя все этапы всегда предпочтительнее. Но и с компонентной нарезкой (отдельно FE, BE, QA тоже можно строить прогнозы, просто они хуже по качеству).

  • Промежуток времени, на основе которого вы строите прогноз.

  • Не стоит прогнозировать на данных от 6+ месяцев в прошлое. Каждые полгода работа у большинства команд либо существенно меняется, либо могут быть изменения в составе.

  • Всегда учитывайте в прогнозе дни с нулевым Throughput, это базовый паттерн работы команды.

  • Прогнозы всегда по календарным дням, а не про рабочим. Благодаря этому мы всегда учитываем праздники/выходные/больничные и все что влияет на результат.

  • Прогнозы, построенные на симуляциях Монте-Карло, имеют смысл только если команда соблюдает ограничения на количество “висящей” работы (WIP-лимиты).

На качество прогнозов очевидно влияет Garbage-In, Garbage-Out
На качество прогнозов очевидно влияет Garbage-In, Garbage-Out

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

"Но Throughput же не репрезентативен, у меня в работе разные типы и разные размеры задач!" - скажете вы.

Ключевое преимущество throughput заключается в том, что эта метрика автоматически учитывает всю гетерогенность типов работы и их размерность через действие Закона Больших Чисел. При достаточном количестве завершённых элементов работы случайная вариабельность от различий в типах задач, их сложности и размерах статистически сглаживается, обеспечивая сходимость к устойчивому среднему значению производительности. IBM Jazz делали подобные исследования на своих датасетах.

Поиграть с симуляцией Монте-Карло на демо-данных можно в соответствующем разделе на predictable.team

Почему Story Points не решают проблем с прогнозируемостью

Давайте обратим, наконец, внимание на слона в команате - зачем это все надо если есть Story Points?

Дело в том, что SP не имеют корреляции с реальным временем выполнения, так как это относительная величина. То есть 5 SP часто делается за время 2 SP, а задачи, оцененные на 8 SP скачут между абсолютным временем.

Об этом пишет, например University College London (PhD Vali Tawosi, 2023): анализ 500,000+ задач показал отсутствие корреляции между story points и реальным временем разработки. У Daniel Vacanti есть похожий кейс в Siemens.

Пример у Vasco Duarte, по сравнению точности между прогнозами по Story Points и по Work Items. Ссылка на исследование ниже.
Пример у Vasco Duarte, по сравнению точности между прогнозами по Story Points и по Work Items. Ссылка на исследование ниже.

Ну и вишенка на торте, у Vasco Duarte - автора NoEstimates, был эксперимент: "Что произойдет с прогнозами, если убрать всю информацию о стори поинтах? Что будет, если все те двойки, тройки, пятерки, восьмерки, тринадцатки превратить в единицы?" - прогнозы с SP отклонились на 20% от финального результата, а по количеству задач - на 4%. Основной вывод - прогнозирование по количеству рабочих элементов дает качество не хуже или лучше, причем требует меньше ресурсов.

SP классная техника, чтобы выровняться в понимании задачи внутри команды на PBR, но не для прогнозов.

Более того, на опыте больших организаций и финтехов, да и стартапов поменьше, SP обычно использует половина или чуть больше команд. Причем все используют по разному (если только у них нет хороших Scrum Master / Agile Coach ролей, которых высаживать в каждую команду очень дорого).

В итоге

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

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

Но на основе этой метрики можно строить прогнозы методом симуляции Монте Карло двух типов:

  • Когда команда завершит "Х" задач.

  • Сколько работы брать в следующие неделю/спринт/месяц.

Но важно, чтобы ваша система была контролируема. Так что должен быть WIP-лимит (хотя бы по верхней планке). Нет лимита — нет управляемости, нет предсказуемости. Буквальная цитата из книжки:

“No WIP limit = no flow, which means no predictability — don’t bother with Monte Carlo simulations if you don’t control WIP”

Daniel Vacanti

Инструменты визуализации

  • Jira Metrics Plugin - безопасно работающий с данными плагин для хрома. Визуализация Throughput и других метрик прямо в вашей Jira.

  • Predictable Team - stateless анализатор CSV (выгруженных из jira или youtrack). Визуализация Throughput из файла + симуляция Монте-Карло + рекомендации на основе ваших данных.

  • Jira Helper от Паши Ахметчанова. Умеет во много метрик, включая Throughput.

  • TWIG от Actionable Agile. Один из стандартов индустрии, метрики + монте-карло, но без VPN не работает в РФ.

Python example

Небольшой пример от не-программиста, как построить прогноз если у вас уже есть датасет исторических данных по Throughput.

import random
import numpy as np
from datetime import datetime, timedelta
from typing import List, Tuple

def monte_carlo_when_simulation(
    historical_throughput: List[int],  # Исторические данные пропускной способности (items per week)
    target_items: int,                 # Сколько задач нужно завершить
    simulation_count: int = 5000       # Количество симуляций
) -> dict:
    """
    Monte Carlo симуляция для ответа на вопрос: 
    "Когда мы завершим X задач?"
    
    Возвращает количество недель до завершения
    """
    
    results = []
    
    for _ in range(simulation_count):
        remaining_items = target_items
        weeks_elapsed = 0
        
        while remaining_items > 0:
            # Случайно выбираем пропускную способность из исторических данных
            weekly_throughput = random.choice(historical_throughput)
            
            # Вычитаем завершенные задачи
            remaining_items -= weekly_throughput
            weeks_elapsed += 1
            
            # Защита от бесконечного цикла (если пропускная способность очень низкая)
            if weeks_elapsed > 200:  # ~4 года максимум
                break
        
        results.append(weeks_elapsed)
    
    # Вычисляем статистики
    results.sort()
    
    return {
        'outcomes': results,
        'percentiles': {
            'p50': np.percentile(results, 50),  # 50% вероятность завершить к этому времени
            'p85': np.percentile(results, 85),  # 85% вероятность
            'p95': np.percentile(results, 95),  # 95% вероятность
        },
        'mean': np.mean(results),
        'std_dev': np.std(results),
        'min': min(results),
        'max': max(results)
    }

# Пример использования
if __name__ == "__main__":
    # Исторические данные: сколько задач команда завершала каждую неделю
    historical_throughput = [3, 5, 4, 2, 6, 4, 3, 5, 7, 2, 4, 6, 3, 5, 4, 8, 2, 5, 4, 3]
    
    # Хотим понять: когда завершим 50 задач?
    target_items = 50
    
    # Запускаем симуляцию
    result = monte_carlo_when_simulation(
        historical_throughput=historical_throughput,
        target_items=target_items,
        simulation_count=5000
    )
    
    print(f"Monte Carlo прогноз для завершения {target_items} задач:")
    print(f"50% вероятность завершить за: {result['percentiles']['p50']:.1f} недель")
    print(f"85% вероятность завершить за: {result['percentiles']['p85']:.1f} недель") 
    print(f"95% вероятность завершить за: {result['percentiles']['p95']:.1f} недель")
    print(f"Среднее время: {result['mean']:.1f} недель")
    print(f"Стандартное отклонение: {result['std_dev']:.1f} недель")
    print(f"Диапазон: {result['min']} - {result['max']} недель")
    
    # Конвертируем в календарные даты
    today = datetime.now()
    print(f"\nКалендарные прогнозы (от {today.strftime('%d.%m.%Y')}):")
    print(f"50% уверенности: {(today + timedelta(weeks=result['percentiles']['p50'])).strftime('%d.%m.%Y')}")
    print(f"85% уверенности: {(today + timedelta(weeks=result['percentiles']['p85'])).strftime('%d.%m.%Y')}")
    print(f"95% уверенности: {(today + timedelta(weeks=result['percentiles']['p95'])).strftime('%d.%m.%Y')}")
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
А как вы прогнозируете завершение работы в командах?
0%Прогнозируем по Velocity в Story Points0
0%Прогнозируем по количеству завершенных задач0
0%Прогнозируем по Монте-Карло0
25%Какой прогноз? Начальство уже закоммитилось перед клиентами на другую дату1
100%Будет готово, когда будет готово4
Проголосовали 4 пользователя. Воздержался 1 пользователь.
Теги:
Хабы:
+7
Комментарии8

Публикации

Ближайшие события