Как мы настроили покер планирования в Youtrack и выиграли дополнительное время

Kate

Administrator
Команда форума
В этой статье расскажем, как совместили Youtrack и покер планирования.

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

Наш основной инструмент для ведения задач и планирования – это Youtrack. Нам очень нравится его гибкость. Что, если попробовать совместить Youtrack и покер планирования?

Готовое решение найти не удалось, а потому мы реализовали свой вариант на основе рабочих процессов Youtrack. В этой статье вы найдете описание решения и особенности настройки.

Разберёмся, что есть что​

Youtrack – это инструмент управления проектами, созданный специально для Agile-команд. Подробнее об инструменте можно почитать по ссылке: https://www.jetbrains.com/ru-ru/youtrack/

Покер планирования – это техника, основанная на достижении договорённости и используемая для оценки трудоемкости задач в ходе разработки программного обеспечения.

Про технику покер планирования можно почитать, например, здесь:

Planning Poker: как сделать процесс постановки задач максимально прозрачным и четким

или здесь:

Как дать адекватную оценку времени, когда неопределённость бьёт по башке

Наш подход​

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

Так как задачи команда ведет в Youtrack, то и оценивать их мы решили там же: это удобно, поскольку в Youtrack есть все требования по задаче и подготовленное техническое задание. Это позволяет не копировать задачу в сторонние приложения и не использовать дополнительные инструменты для оценки.

Как проходит оценка:

  1. Сначала задача пребывает в состоянии «Анализ». Аналитик выполняет сбор требований и готовит техническое задание.
  2. Затем аналитик переводит задачу в состояние «Оценка» и выбирает в качестве исполнителя разработчика.
  3. Разработчик привлекает к оценке задачи ещё двух участников из команды разработки. Каждый участник в скрытом режиме ставит свою оценку. Как только все участники проголосуют, общий результат голосования отобразится автоматически.
  4. Если результаты голосования неоднозначные, то участники голосования после обсуждения могут вернуть задачу аналитику – для уточнения требований.
  5. Если же участники пришли к общему мнению (в результате голосования или по итогам обсуждения), то в задаче проставляется итоговая оценка. Меняется и статус задачи – «В очереди». Считается, что требования по такой задаче полностью понятны, трудозатраты оцифрованы, и можно включить ее в один из ближайших спринтов.
    989c0c9d1e1221b80f16ee297d386320.png
Для реализации описанного алгоритма в задаче Youtrack есть поля: одно для скрытого голосования, а второе для отображения результата. Правила окончания голосования можно придумать любые. Например, мы решили, что голосование завершается в тот момент, когда оценку по задаче проставили три участника.

Вот как выглядит голосование в задаче Youtrack в нашем проекте.

Голосование не завершено (результат скрыт):

92e099d97db6c0443d90365c562888f9.png

Голосование завершено (результат виден):

8e8c69791c4bd3aa8190f1dd14cc3e54.png

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

Если быстрая оценка по задаче невозможна и требуется более глубокая проработка технического решения, то это выходит за рамки покер планирований и может потребовать дополнительного времени. В таком случае проработку технического решения и детальную оценку трудозатрат берет на себя один из разработчиков. Затем команда вновь оценивает предложенное решение.

Теперь подробно рассмотрим, как настроить Youtrack для оценки задач по методике «покер планирования».

Настройка проекта​

Для оценки задач создадим в проекте Youtrack три дополнительных поля:

  1. Покер план. Оценка – для голосования по задаче.
    • тип: перечисление (одиночное значение);
    • возможные значения: ⍰,1,2,3,5,8,13,21,34,∞. За основу взяли числа Фибоначчи и добавили два значения: ⍰ - требования не понятны и ∞ – требования понятны, но задача не может быть решена в конечные сроки;
    • значение этого поля будет очищаться сразу после простановки оценки, чтобы другие участники не узнали результат до завершения голосования.
  2. Покер план. Результат – отображение результатов голосования.
    • тип: строковое значение;
    • в этом поле будем выводить результат голосования. До завершения голосования отображаем только список проголосовавших участников, а после завершения голосования отображаем участников и выбранные оценки.
  3. Покер план. Данные.
    • тип: строковое значение;
    • скрытое техническое поле, доступное на просмотр только администратору;
    • в этом поле будем хранить промежуточные итоги голосования в виде JSON.
a99c831a025f2c87e3b6a36ac50375d1.png

Видимость полей в проекте настраиваем через свойство «Отображать для» в дополнительных параметрах полей. Например, поле «Покер план. Данные» доступно только пользователям, входящим в группу «Покер план. админ». Обычный участник команды не видит содержимое этого поля, так как оно по сути является техническим.



1b2391ad20dfb7564ee159322c1e6c7f.png

Поля «Покер план. Оценка» и «Покер план. Результат» доступны для просмотра только участникам команды, входящим в специальную группу покер планирования. Так удобнее управлять процессом и скрывать лишнюю информацию в Youtrack при необходимости.

Поле «Покер план. Результат» доступно для редактирования (настройка «Могут обновлять») только участникам группы «Покер план. админ». Остальные участники могут только просматривать содержимое поля без возможности редактировать.

Фактически у нас нет участников, которые входят в группу «Покер план. админ». Группа создана только для того, чтобы обеспечить режим «только чтение» для поля «Покер план. Результат» и скрыть поле «Покер план. Данные». Прямое редактирование указанных полей не разрешается.

Настройка рабочего процесса​

Итак, мы настроили проект и добавили все необходимые поля. Однако чтобы всё заработало так, как задумано, необходимо реализовать логику голосования и отображения результата. Для этой задачи будем использовать «Рабочие процессы» Youtrack, которые позволяют автоматизировать процесс обработки задач на языке JavaScript.

  1. В настройках Youtrack заходим в меню «Рабочие процессы».
    fba818abd6cecb3280261df08eece606.png
  2. Создаем новый рабочий процесс.
    e9addd6305963a90d5518d37fe9d4bbb.png
  3. В рабочем процессе создаем модуль, который будет выполняться при применении изменений к задачам.
    ad878217d3a419d4782e9be69068785a.png
Модуль представляет из себя скрипт, который выполняется при внесении изменений в задачу. Приведу скрипт, который автоматизирует обработку голосования, и прокомментирую несколько основных моментов.

/**
* Метод "Покер планирования" средствами Youtrack
*/

var entities = require('@jetbrains/youtrack-scripting-api/entities');
var MIN_VOTE_COUNT = 3; //минимальное количество проголосовавших
var EMOJI = ['♣', '♠', '♥', '♦'];
//наименования полей для Покер планирования
var FIELD_POKER_VOTE = "Покер план. Оценка"; // поле для голосования
var FIELD_POKER_RESULT = "Покер план. Результат"; // отображение результата
var FIELD_POKER_DATA = "Покер план. Данные"; // хранение результатов голосования

exports.rule = entities.Issue.onChange({
title: 'Poker_plan_vote',
guard: function(ctx) {
//обрабатываем только изменения в поле голосования
return ctx.issue.fields.isChanged(FIELD_POKER_VOTE);
},
action: function(ctx) {
var emojiIndex;
var pokerVote;
var isUserFirstVote;
var issue = ctx.issue;
var user = ctx.currentUser;
//получаем значение оценки, которое выбрал участник
var voteRes = issue.fields[FIELD_POKER_VOTE].name;
//получаем данные по предыдущим результатам голосования
var pokerDataJSON = issue.fields[FIELD_POKER_DATA];
var pokerData = JSON.parse(pokerDataJSON);
var pokerResult = "";
if ((pokerData)&&(pokerData.voteResult)){
//в задаче есть данные по предыдущим результатам голосования
isUserFirstVote = true; //по умолчанию считаем, что участник голосует в первый раз
for(var i=0; i < pokerData.voteResult.length; i++){
//ищем текущего пользователя в списке проголосовавших ранее
pokerVote = pokerData.voteResult;
if (pokerVote.login == user.login){
//пользователь найден в результатах. Меняем текущую оценку
pokerVote.vote = voteRes;
//запоминаем, что пользователь голосует не первый раз
isUserFirstVote = false;
}
}
if (isUserFirstVote) {
//участник проголосовал в первый раз. Добавляем нового пользователя и оценку в список
pokerData.voteResult.push({"login": user.login,"vote": voteRes});
}
}else{
//первое голосование по задаче. Создаем список и добавляем в него пользователя и оценку
pokerData = {voteResult:[{"login": user.login,"vote": voteRes}]};
}

if (pokerData.voteResult.length > 0){
//формируем строку для отображения результата голосования
emojiIndex=0;
for(var j=0; j < pokerData.voteResult.length; j++){
pokerVote = pokerData.voteResult[j];
if (pokerResult.length > 0){
pokerResult += "\n"; //добавляем перенос строки
}
if (pokerData.voteResult.length >= MIN_VOTE_COUNT){
//если проголосовало необходимое количество участников - отображаем оценки
pokerResult += pokerVote.vote + "=" + pokerVote.login;
}else{
//если количество участников меньше минимума - отображаем эмодзи вместо оценок
pokerResult += EMOJI[emojiIndex] + "=" + pokerVote.login;
//меняем эмодзи
emojiIndex++;
if (emojiIndex >= EMOJI.length){
//эмодзи закончились, возвращаемся к первому эмодзи
emojiIndex=0;
}
}
}
}

pokerDataJSON = JSON.stringify(pokerData);
//записываем результат в поля задачи
issue.fields[FIELD_POKER_DATA] = pokerDataJSON; //данные по голосованию
issue.fields[FIELD_POKER_RESULT] = pokerResult; //отображаемый результат
//сбрасываем значение поля оценки
issue.fields[FIELD_POKER_VOTE] = null;
},
requirements: {
PokerVote: {
type: entities.EnumField.fieldType,
name: FIELD_POKER_VOTE,
multi: false
},
PokerResult: {
type: entities.Field.stringType,
name: FIELD_POKER_RESULT
},
PokerData: {
type: entities.Field.stringType,
name: FIELD_POKER_DATA
}
}
});
Отмечу несколько ключевых моментов в скрипте, а остальное, надеюсь, будет понятно из комментариев в коде:

  1. Выполнение основной части скрипта происходит только при изменении поля "Покер план. Оценка". Для этого служит проверка в секции guard:
    return ctx.issue.fields.isChanged(FIELD_POKER_VOTE);
  2. Доступ к параметрам текущего контекста Youtrack можно получить с помощью объекта ctx. Например, в коде ниже получаем текущую задачу и текущего пользователя.
    var issue = ctx.issue;
    var user = ctx.currentUser;
  3. Для получения значения поля типа «строковое» обращаемся к нему через свойство fields:
    issue.fields[FIELD_POKER_DATA];
  4. Для получения значения поля типа «перечисление» дополнительно используем свойство name:
    issue.fields[FIELD_POKER_VOTE].name;
  5. Для отладки можно вывести необходимую информацию в консоль рабочего процесса Youtrack:
    console.log(issue.fields[FIELD_POKER_DATA]);
  6. Чтобы значение оценки не отобразилось другим участникам голосования перед завершением выполнения скрипта присваиваем полю «Покер план. Оценка» значение null:
    issue.fields[FIELD_POKER_VOTE] = null; //сбрасываем значение поля оценки
  7. В блоке requirements описаны обязательные поля, которые необходимы для корректной работы скрипта. Если в проекте отсутствуют указанные поля, то при подключении процесса к проекту напротив процесса отобразится уведомление «требует настройки» и процесс не будет запускаться до тех пор, пока не будут устранены несоответствия требованиям, указанным в блоке requirements.
c643574393752936f589cb02522b7cc0.png

Скрипт готов к использованию, но, прежде чем подключать рабочий процесс к проекту, рассмотрим ещё одну важную функцию – «Сброс результатов планирования».

Сброс результатов планирования​

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

Создадим в существующем рабочем процессе дополнительное действие Youtrack для обнуления результатов покер планирования.

В настройках процесса создадим новый модуль типа «Действие». Такие действия доступны в меню задачи и выполняются по команде пользователя.

4b36b27183bb293db03d13b7dab210ef.png

Приведем текст скрипта, который выполняет очистку результата покер планирования:

/**
* Метод "Покер планирования" средствами Youtrack
* действие: сброс результатов покер планирования
*/

var entities = require('@jetbrains/youtrack-scripting-api/entities');
//наименования полей для Покер планирования
var FIELD_POKER_RESULT = "Покер план. Результат"; // отображение результата
var FIELD_POKER_DATA = "Покер план. Данные"; // хранение результатов голосования
//группа участников Покер планирования
var POKER_PLAN_GROUP = "Покер план. Участники";

exports.rule = entities.Issue.action({
title: 'Сбросить результаты покер планирования',
command: 'poker_plan_clear',
guard: function(ctx) {
//действие доступно только для участников группы покер планирования
return ctx.currentUser.isInGroup(POKER_PLAN_GROUP);
},
action: function(ctx) {
var issue = ctx.issue;
//сбрасываем значения полей, относящихся к покер планированию
issue.fields[FIELD_POKER_DATA] = null;
issue.fields[FIELD_POKER_RESULT] = null;
},
requirements: {
PokerResult: {
type: entities.Field.stringType,
name: FIELD_POKER_RESULT
},
PokerData: {
type: entities.Field.stringType,
name: FIELD_POKER_DATA
}
}
});
Несколько ключевых моментов, на которые следует обратить внимание:

  1. В секции guard мы добавили условие при, котором будет доступно действие в меню. В данном случае пункт меню будет доступен только пользователям, входящим в группу "Покер план. Участники".
  2. Основное действие мы описали в секции action. Для очистки результатов присваиваем значение null соответствующим полям задачи.
  3. В блоке requirements описаны обязательные поля, которые необходимы для корректной работы скрипта. Если в проекте отсутствуют указанные поля, то при подключении процесса к проекту напротив процесса отобразится уведомление «требует настройки» и процесс не будет исполняться до тех пор, пока не будут устранены несоответствия требованиям, указанным в requirements.
92fc20810fe222b38225bb3f1c72baa0.png

Действие будет доступно в меню задачи после подключения процесса к проекту.

ad3d7cd36bc852cd01f6a7570ed7082d.png

Подключение к проекту рабочего процесса​

Рабочий процесс настроен, теперь нужно его подключить.

Обратите внимание: как только процесс будет прикреплен к проекту, то в соответствии с заложенным алгоритмом начинает выполняться скрипт. Если в скрипте допущена ошибка, то под угрозой работоспособность всего проекта.

Для подключения процесса необходимо перейти на закладку «Рабочие процессы» в настройках проекта и нажать кнопку «Прикрепить рабочие процессы».

b093cda1881c185c5242e991ce0c8916.png
e1817a94c8f63b1514c01e17804ffe02.png

Итак, мы создали и подключили проект; теперь можно голосовать и оценивать задачи в Youtrack.

Наш опыт​

Рабочий процесс «покер планирования», встроенный в Youtrack – это удобный инструмент, который позволяет оценивать задачи непосредственно в системе, где ведётся бэклог и где такая оценка наиболее востребована.

Основная особенность покер планирования заключается в том, что голосование проходит в закрытом режиме, и участники не видят оценки друг друга до завершения голосования. Такой подход обеспечивает неангажированность, учитывает сразу несколько экспертных мнений и снижает влияние их якорения. Не менее важно, что, обсуждая итоги голосования, участники команды обмениваются знаниями и лучше понимают суть решаемой задачи.

Голосовать участники могут в разное время и там, где им удобно – нет нужды собираться в назначенный час в одном помещении. Результаты обсуждают только в случае спорных ситуаций и делают это как очно, так и просто в комментариях к задаче. Используя Youtrack, мы повысили гибкость процесса оценки и стали проводить его параллельно разработке, подстраиваясь под текущую загрузку участников команды.

В целом оцениваем эффект от внедрения покер планирования в Youtrack как положительный. У разработчиков появился удобный инструмент для выведения консенсус-оценки по задаче.

Как результат, при оценке задач учитывается несколько экспертных мнений, что повышает качество оценки.

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

Планы на будущее​

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

 
Сверху