はじめまして、技術本部 Sansan Engineering Unit Master Data Groupの佐藤です。普段は人事異動情報、企業ニュース、役員管理職情報の収集や提供をするシステムの開発を行っています。
現在技術本部では、単月の生産量を2倍にするという目標を掲げ、生産量向上に取り組んでいます。今回は、私が所属するチームの生産性向上施策の一環として、生産性指標可視化のためのダッシュボードを作成した話をします。
生産性指標
私の所属するチームでは、"生産的"なタスクを便宜上、"計画時に積まれたタスク"として定義しました。そして生産性指標を、スプリントあたりの"計画時に積まれたタスクの消化ストーリーポイント数"として計測することにしました。
Why ベロシティ?
生産性指標として有名なものにFour Keysがあります。チームで生産性指標を決めるときにもFour Keysは候補に挙がりましたが、私のチームでの採用は見送られました。
私の所属するチームでは、実装に入る前の「何を実装すべきか」「どのように実装すべきか」などの調査や検証に一定の工数が割かれています。
チームとしては、「調査・検討・検証から開発・リリースまでの一連のプロセス全体」を生産的な活動であると考えています。そのため生産性指標としては、Four Keysではなくてベロシティを活用することにしました。
一方で、スプリントの途中で差し込まれる、問い合わせ対応や障害対応は本来チームとしてやりたいことからは外れた作業になります。そのためチームとしては差込タスクは生産的なタスクの定義からは外し、計画時に積まれたタスクの消化ストーリーポイント数のみを生産性指標としました。
Jiraでダッシュボード作れない問題
現在タスク管理ツールとして、Jiraを使用しています*1。生産性指標を計測するため、計画時に積まれたタスクのチケットには計画ラベルを付与して、スプリントの途中で発生した問い合わせ対応や障害対応などのタスクのチケットには差込ラベルを付与する運用にしてあります。
しかしJiraの機能として、ラベルでチケットを絞り込んだ上でのスプリントあたりの消化ポイント数を計測して可視化するような機能が存在しなかったため、JiraAPIを使用してダッシュボードを作成することにしました。
ダッシュボード作成
0. ダッシュボードの構成
以下のような構成でダッシュボードを作成しています。
1. APIトークンの発行
こちらの手順に従ってAPIトークンを作成し、保管します。
2. JQLの用意
APIはJQL*2を渡すことで課題の検索ができるSearch for issues using JQL (GET)を使用します。
今回は、指定期間内に完了したチケットの一覧を取得するJQLを用意します。
project = HOGE AND status = 完了 AND resolutiondate >= "20XX/XX/XX" AND resolutiondate < "20YY/YY/YY"
3. GASでチケット情報の取得・集計・スプレッドシートへの書き出し
以下にGASコードの一部を掲載します。
一度に集計できるチケット数に上限があるため、期間を絞りながら取得するようにしています。
function fetchJiraIssues(jql) { const encodedJql = encodeURIComponent(jql); const urlWithParams = `https://xxxxxxx.atlassian.net/rest/api/3/search?jql=${encodedJql}&maxResults=100`; const options = { 'method': 'get', 'headers': { 'Accept': 'application/json', 'Authorization': 'Basic ' + Utilities.base64Encode(EMAIL + ':' + JIRA_API_TOKEN) }, 'muteHttpExceptions': true }; try { const response = UrlFetchApp.fetch(urlWithParams, options); return JSON.parse(response.getContentText()); } catch (error) { Logger.log('Error fetching JIRA issues: ' + error.toString()); return null; } } // 中略 function main() { const dates = generateDatesArray(13); // 約3ヶ月 const tickets = dates.flatMap(date => { const jql = `project = JES AND status = 完了 AND resolutiondate >= "${date[0]}" AND resolutiondate < "${date[1]}"`; return fetchJiraIssues(jql)['issues'] || []; }); const summarizedTickets = summarizeTickets(tickets); writeToSpreadsheet(summarizedTickets); }
4. Looker Studioにスプレッドシートを連携してグラフを作成する
Looker Studioにスプレッドシートを連携したら、グラフを追加してあとはよしなに作成します。
生産性ダッシュボード
以下が完成したダッシュボードです。
横軸がスプリントで、縦軸が計画タスクと差込タスクそれぞれの消化ポイント数の積み上げ棒グラフとしてダッシュボードを作成しました。
また、設定している目標との差分がわかりやすいように目標消化ポイント数のラインを追加しています。
ダッシュボードの効果
現在私が所属するチームでは、朝会のコンテンツのひとつとして今回作成したダッシュボードを眺める時間を設けています。
そこでは現在の消化ポイント数、目標との差分、残っているタスクを確認しながらチーム内でどうすれば目標が達成できるか、という会話がなされています。
ダッシュボード導入による1番の効果としては、消化ポイント数と目標との差分が明確に可視化されたことによって、ダッシュボード導入前と比較してチームとして目標を達成しようとする意思が生まれたことだと思います。
レビューでタスクが滞留しがちというチームの課題があったのですが、それも徐々に解消されつつあり、消化ポイント数増加につながっています。
最後に
ダッシュボード導入後で消化ポイント数が少ない2024/02/10と2024/02/17のスプリントは祝日があり週4日稼働だったのですが、今回作成したダッシュボードを活用しつつ生産性を上げて、週4日稼働でも週5日稼働と同水準のポイントを消化できるようにしたいと思います。
私たちのチームでは Web アプリ開発エンジニアを募集しています。Web アプリ開発だけではなくデータエンジニアリングなど、幅広い業務を経験できます!