Единый роадмап компании с помощью Structure Jira

Untitled

Привет! Меня зовут Настя Николаева, лид цифровой трансформации в компании Bimeister. И я хочу рассказать, как мы собирали единый роадмап компании с помощью плагина Structure Jira.

Наверное, в каждой компании, где есть несколько команд разработки, существуют подобные проблемы:

  1. у каждой команды свои правила и инструменты для построения роадмап

  2. некоторые роадмапы не найти, они не находятся в свободном доступе

  3. продуктовый роадмап и проектные живут в разных местах и не синхронизированы

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

Решив эти проблемы, мы сможем достигнуть поставленных целей:

  1. Прозрачные и понятные сроки исполнения проектных и продуктовых обязательств

  2. Выявление рисков на ранних этапах исполнения работ

Итак, верхнеуровнево мы наметили такие шаги:

Untitled

Шаг 1 — выбираем единый инструмент построения роадмап

Так как у нас вся продуктовая разработка ведется в Jira, то и собирать единый роадмап правильно было бы в jira, избежав копи-пасти и дублирования информации.

В процессе ресеча различных плагинов и опыта других компаний мы выбрали Structure в Jira.

Structure — плагин для Jira, с помощью которого можно гибко визуализировать и структурировать задачи в jira в виде иерархии.

Structure позволяет на основе задач jira:

  • выстроить список задач jira в любой иерархии, по любому нужному запросу либо же вручную по одной задаче

  • сгруппировать списки по любому атрибуту тикета, отфильтровать ненужные, отсортировать так, как требуется

  • отобразить и показать требуемые поля тикетов

  • с помощью формул и языка запросов можно добавить нужные аналитические параметры и отобразить любые данные по тикетам

  • добавить gantt chart и ресурсы

  • и многое-многое другое

Шаг 2 — собираем роадмап

Первая проблема, с которой столкнулись — просто так, «сходу», роадмап нам было не собрать, так как все команды ведут тикеты в jira по своим правилам; признаков или каких-то других атрибутов, по которым мы можем одним запросом вытащить все задачи, не было. Следовательно, его нужно было добавить. Для этого сделали несколько доработок по таскам:

  • унифицировали тип задач feature и story, внедрили единый флоу по ним. Это нам поможет собрать единую структуру роадмап по всем командам разработки

  • добавили обязательные поля, по которым собираем structure

Это поможет правильно сгруппировать задачи, выстроить модель рисков и сделать связь продуктового роадмап и календарно-сетевого графика проекта.

Untitled

Дальше создаем структуру, задаем название. Structure создаем пустой, без преднастроек, которые предлагает сам плагин. Всю кастомизацию делаем руками.

Untitled

Чтобы структуру наполнить можно воспользоваться 2-мя способами:

  • добавить задачи вручную — это довольно долго, подходит для небольших роадмапов и небольших команд

  • добавить задачи автоматически по какому-то условию. Этим способом мы и наполняем нашу structure.

Нас интересуют задачи с типом таски = feature, так как это для нас ключевая сущность.

Untitled

Дальше, для наглядности, фичи нужно сгруппировать. Группировать можно по любому полю тикета jira.

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

Чтобы разложить эпики по продукту — добавляем группировку по продукту. А чтобы разложить продукты по проектам — группируем по проектам.

Untitled

Итог: мы можем видеть все проекты компании, в каждом проекте видим продукты, которые подключены, и в каждом продукте видим эпики и фичи, которые разрабатываются для проекта.

Можно через связи добавить к фичам более мелкую детализацию — стори и таски на аналитику и дизайн — для этого так же через автоматизацию добавляем задачи через связь contents или содержит.

Шаг 3 — соединяем продуктовый роадмап и календарно-сетевой график проектов

Базовый вид structure для нас не самый информативный и не содержит нужные нам для анализа данные. Поэтому мы разработали свой вид structure.

Для этого добавили больше столбцов:

  • приоритет задач

  • статус задач

  • название команды, которая делает разработку

  • lead time по задачам, которые уже выполнены

  • фактические даты старта и окончания работ — даты продуктовой команды, в которые задачи будут браться в работу

  • плановые даты старта и окончания работ — проектные даты, которые были согласованы с руководителями проектов и заказчиком, и по которым и строится календарно-сетевые графики проекта

  • ФТТ — какие требования заказчика по договору решаются в рамках каждого тикета

  • прогресс по задаче — процент выполнения задачи в зависимости от ее статуса

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

Untitled

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

За основу мы взяли стандартный параметр Item Health и изменили формулу, по которой определяется риск:

формула:

WITH renderStatus(bgColor, iconId, status, padding) =
  """{panel:borderStyle=solid|borderColor=white|bgColor=#$bgColor}!}*$status*{color}!}""" :
/1 - РИСКИ ДЛЯ ФИЧИ/
if (type="feature"):
(
/*Если статус Бэклог и даты старта еще далеко впереди*/
if (StartDate - TODAY() > 0):
(
if progress = 1: renderStatus("59B161", "icn-01", "Работы завершены!", 7)
else if progress = 0 :renderStatus("652CB3", "icn-01", "Работы запланированы", 7)
else : renderStatus("59B161", "icn-01", "Опережаем сроки!", 7)
)
 
/*Если дата старта сегодня и работы начались*/
else if StartDate=TODAY():
(
if progress = 1: renderStatus("59B161", "icn-01", "Работы завершены!", 7)
else if progress>0.1: renderStatus("59B161", "icn-03", "Опережаем сроки!", 7)
else : renderStatus("B610D2", "icn-03", "Нужно поторопиться", 7)
)
 
/*Если дата старта прошла*/
else if StartDate <= TODAY() :
(
    if EndDate - TODAY() > 60: /*до конца более 60 дней*/
    (
    if progress = 1: renderStatus("59B161", "icn-01", "Работы завершены!", 7)
    else if progress >= 0.8 : renderStatus("59B161", "icn-01", "Опережаем сроки!", 7)
    else if progress >= 0.4 : renderStatus("FFAF00", "icn-02", "В рамках сроков", 7)
    else if progress > 0: renderStatus("FFAF00", "icn-02", "В рамках сроков", 7)
    else: renderStatus("B610D2", "icn-03", "Нужно поторопиться", 7)
    )
    else if EndDate - TODAY() > 30: /*до конца более 30 дней*/
    (
    if progress = 1: renderStatus("59B161", "icn-01", "Работы завершены!", 7)
    else if progress >= 0.8: renderStatus("FFAF00", "icn-02", "В рамках сроков", 7)
    else if progress >= 0.4: renderStatus("B610D2", "icn-03", "Нужно поторопиться", 7)
    else if progress > 0: renderStatus("EF4B59", "icn-03", "Есть риск не успеть", 7)
    else: renderStatus("EF4B59", "icn-03", "Есть риск не успеть", 7)
    )
    else if EndDate - TODAY() > 0: /*до конца более 0 дней*/
    (
    if progress = 1: renderStatus("59B161", "icn-01", "Работы завершены!", 7)
    else if progress >= 0.8: renderStatus("FFAF00", "icn-02", "В рамках сроков", 7)
    else if progress >= 0.4: renderStatus("B610D2", "icn-03", "Нужно поторопиться", 7)
    else if progress > 0: renderStatus("EF4B59", "icn-03", "Есть риск не успеть", 7)
    else: renderStatus("EF4B59", "icn-03", "Есть риск не успеть", 7)
    )
    /*deadline прошел*/
    else if EndDate <= TODAY():
    (
    if progress =1: renderStatus("59B161", "icn-01", "Работы завершены!", 7)
    else if progress >= 0.8: renderStatus("EF4B59", "icn-03", "Deadline наступил!", 7)
    else if progress >= 0.4: renderStatus("EF4B59", "icn-03", "Deadline наступил!", 7)
    else if progress > 0: renderStatus("EF4B59", "icn-03", "Deadline наступил!", 7)
    else: renderStatus("EF4B59", "icn-03", "Deadline наступил!", 7)
    )
 
)

/*Если прогресс=1*/
else if progress =1: renderStatus("59B161", "icn-01", "Работы завершены!", 7)
 
/*Если даты не заполнены*/
else   : renderStatus("000000", "icn-03", "Незаполнены даты", 7)

)
/-------------------------------------------------------------------/
/2 - РИСКИ ДЛЯ СТОРЕЙ И ТАСОК/
else if (type="Story" or type="Task"):
(
/*Если статус Бэклог и даты старта еще далеко впереди*/
if (StartDate - TODAY() > 0):
(
if progress = 1: renderStatus("59B161", "icn-01", "Работы завершены!", 7)
else if progress = 0 :renderStatus("652CB3", "icn-01", "Работы запланированы", 7)
else : renderStatus("59B161", "icn-01", "Опережаем сроки!", 7)
)
 
/*Если дата старта сегодня и работы начались*/
else if StartDate=TODAY():
(
if progress = 1: renderStatus("59B161", "icn-01", "Работы завершены!", 7)
else if progress>0.1: renderStatus("59B161", "icn-03", "Опережаем сроки!", 7)
else : renderStatus("B610D2", "icn-03", "Нужно поторопиться", 7)
)
 
/*Если дата старта прошла*/
else if StartDate <= TODAY() :
(
    if EndDate - TODAY() > 7: /*до конца более 7 дней*/
    (
    if progress = 1: renderStatus("59B161", "icn-01", "Работы завершены!", 7)
    else if progress >= 0.8 : renderStatus("59B161", "icn-01", "Опережаем сроки!", 7)
    else if progress >= 0.4 : renderStatus("FFAF00", "icn-02", "В рамках сроков", 7)
    else if progress > 0: renderStatus("FFAF00", "icn-02", "В рамках сроков", 7)
    else: renderStatus("B610D2", "icn-03", "Нужно поторопиться", 7)
    )
    else if EndDate - TODAY() > 4: /*до конца более 4 дней*/
    (
    if progress = 1: renderStatus("59B161", "icn-01", "Работы завершены!", 7)
    else if progress >= 0.8: renderStatus("FFAF00", "icn-02", "В рамках сроков", 7)
    else if progress >= 0.4: renderStatus("B610D2", "icn-03", "Нужно поторопиться", 7)
    else if progress > 0: renderStatus("EF4B59", "icn-03", "Есть риск не успеть", 7)
    else: renderStatus("EF4B59", "icn-03", "Есть риск не успеть", 7)
    )
    else if EndDate - TODAY() > 0: /*до конца более 0 дней*/
    (
    if progress = 1: renderStatus("59B161", "icn-01", "Работы завершены!", 7)
    else if progress >= 0.8: renderStatus("FFAF00", "icn-02", "В рамках сроков", 7)
    else if progress >= 0.4: renderStatus("B610D2", "icn-03", "Нужно поторопиться", 7)
    else if progress > 0: renderStatus("EF4B59", "icn-03", "Есть риск не успеть", 7)
    else: renderStatus("EF4B59", "icn-03", "Есть риск не успеть", 7)
    )
    /*deadline прошел*/
    else if EndDate <= TODAY():
    (
    if progress =1: renderStatus("59B161", "icn-01", "Работы завершены!", 7)
    else if progress >= 0.8: renderStatus("EF4B59", "icn-03", "Deadline наступил!", 7)
    else if progress >= 0.4: renderStatus("EF4B59", "icn-03", "Deadline наступил!", 7)
    else if progress > 0: renderStatus("EF4B59", "icn-03", "Deadline наступил!", 7)
    else: renderStatus("EF4B59", "icn-03", "Deadline наступил!", 7)
    )
 
)

	else if progress =1: renderStatus("59B161", "icn-01", "Работы завершены!", 7)
 
	/*Если даты не заполнены*/
	else   : renderStatus("000000", "icn-03", "Незаполнены даты", 7)

)

Модель рисков в виде таблицы:

Untitled

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

Ранее уже писала, что важная составляющая structure — это возможность положить список задач на ганта.

Для добавления Ганта нужно выбрать дополнительный слой структуры Gantt Chart и в параметрах Ганта определить даты, по которым будет строиться гант.

Untitled

Гант также довольно гибкий:

  • на него можно добавить важные Milestone

  • добавить маркеры, по которым отслеживаются важные проектные даты или события

  • добавить даты релизов и тд

Untitled

Итого: мы получили единый роадмап с важными для нас параметрами, с автоматическим добавлением задач и автоматическим определением рисков. Роадмап доступен каждому в компании, все прозрачно и доступно в едином месте по одной ссылке. Роадмап актуален в любое время, так как вся информацию тянется из тикетов jira, и при обновлении тикетов роадмап обновляется автоматически.

Тем самым полечили боли и достигли поставленных целей.

Вывод

Structure один из самых гибких инструментов, с помощью которых мне приходилось строить единые большие роадмапы, и самый эффективный.

Дальше в планах роадмап развивать:

  1. добавить полный цикл проекта — задачи внедрения, подготовки договоров и прочее;

  2. доработать модель рисков — добавить зависимость от этапов проекта, разработки, типов задач.

© Habrahabr.ru