スクラムでベロシティを安定化するにはどうしたらよいか

このブログではあまりこういう話は書いてこなかったけど, 以前少しだけ触れたように, 僕はここ最近エンジニアリングマネージャをやっていて, こういう話題を考える機会はけっこう多い. 具体的には, エンジニアリングマネージャとして複数チームのテクノロジ/プロセス/プロダクト/ピープルのマネジメントを日々やっていて, そのうちのプロセスマネジメントとして, 各チームのスクラムマスタ的な人に助言したり, 開発プロセスの改善のためにチームが起こそうとしている変化を受け入れるようラインマネージャを説得したり, といったことにけっこう時間を割いている.

スクラムに関して以下のような話を見かけて, これはまさに日々悩まされていることだった.

一言で言うと「ベロシティの安定化でみんな躓く」という話. これは僕の経験上も納得できる.

この記事に寄せられたコメントを見ると, 「で, じゃあどうやってベロシティを安定化させたらいいんだよ」という部分に悩んでる人が多いように見える. 僕はこれに関してはある程度の精度で答えを持っていて言語化できそうだなと思ったので, 連投ツイートしてみた. この記事は一連のツイートをもう少し丁寧に説明したバージョン.

なぜベロシティの安定化で躓くのか

スクラムを導入してもすぐにはベロシティが安定しない. 具体的には, スプリント計画で「これくらいは消化可能なはず」と積んだポイントが消化できずに溢れる. 仕掛りのタスクが次のスプリントに持ち越され, でも次のスプリントにはまた新たなスプリントゴールもやってくるため, また溢れる.

だったら「これくらいできるはず」のポイント数に余裕を持たせて, チームのベロシティの認識を下方修正したらどうか. いったんはそれでポイントをすべて消化できるかもしれない. しかしそうやっても, 不確定要素の多いタスクがやってきただけでまた溢れてしまったり, 余裕があるからと言ってメインのスプリントゴールとは別でやりたいことを詰め込まれてしまったり, そもそも仕掛りを引き継いだ結果として複数のスプリントゴールが並立してしまって気が散ったりして, ベロシティは安定しない. なぜなのか.

こう考えていないだろうか. 開発メンバにはそれぞれ消化可能ポイント数があり, そのポイント数のチームでの総和がベロシティで, 生産性を最大化するためにはそのベロシティいっぱいまでタスクで充たさなければならない, と. なんと, これは明確に誤りで, リソース効率の誤謬に陥っている.

各メンバが忙しなく働いてアウトプットを出したとき(=リソース効率最大時)に生産性が最も高くなると思いがちだが, そんなことはぜんぜんない. 実際は, 各タスクのリードタイムが短い(=フロー効率がよい)ほど生産性は高くなり, 十分にフロー効率がよい状況ではタスクの依存関係のフローのボトルネックとなる部分(クリティカルパス)のリードタイムが全体の生産性を決定する.

リソース効率を最大化しても生産性が上がらないことの直感的なイメージは, 以下の動画を見るとわかるだろう(この動画はid:nakiwoさんが見つけてきてくれた).

あるいはもう少し細かいイメージを持ちたければ, 『ザ・ゴール』を読んでもよいかもしれない.

この本では, 商品を組み立てる工場の生産ラインを例に, フロー効率の最大化の話をしている. フロー効率が悪いときは工場の各工程に在庫(機械に投入するのを待っている部品)が溜まっていて, すべての機械がフル稼動しているにも関わらず満足いく生産性が発揮されない.

逆にフロー効率が良く各工程の在庫がゼロの場合, 大半の機械はフルでは稼動しておらず, 部品がやってくればすぐに機械に投入され, 組み上がった部品はまたすぐに次の工程の機械に投入される. そして生産能力が一番低い機械が全体の生産性を左右するため, この機械の稼動状況だけ見張っていれば発注された商品がいつ組み上がるかは正確に予測でき, またこの機械の台数を増やしたり上位機種に置き換えたりすると工場全体の生産性が良くなる.

フロー効率をよくするには

フロー効率をよくするイメージさえ持てれば, あとはそんなに難しくない. 何か対立するやり方で迷ったときは「どちらがフロー効率のよいやり方か」を考えたらいいだろう. 以下に, 僕がこれまでによく見かけた改善点を挙げておく.

同時に複数のタスクをやらない

人間は2つのことを同時にはできないので, 2つ以上のタスクを同時に抱えてしまうと, 1つを処理している間もう一方はただ待っているだけとなる. 待っているタスクは待った分だけ単純にリードタイムが加算されていく. だから一般的に複数のタスクを同時に取るとフロー効率は悪化する. タスクの在庫を抱えないようにしよう.

タスクを細かく分割する

あるタスクがいくつかのサブタスクに分解できるとして, それらのサブタスクがすべて直列の依存関係にあるなら順にやっていくしかないが, もし並行して進められるものがあるなら他の人にアサインすればリードタイムを短縮できるかもしれない. そうでなくとも, 一般的な仕事の進め方として, タスクに取りかかるときは初手でやることリストを箇条書きして見通しをよくしよう.

「同時に複数のタスクをやらない」と合わせると, タスクの中に「○○さんに確認してもらう」のように自分のボールではないサブタスクが混ざっていると, そこで何もせずにただ待つことになってしまう. ボールが移るところでタスクを切って, そこまでで一旦完了として他のタスクを取れるようにしよう.

タスクを誰が取ってもいいようにする

これはスクラムお作法的には諸説ある部分で, あらかじめ得意そうな人にアサインしておいて素早くタスクを片付けてもらうという考え方もある. ただ, アサインされたが未着手のタスクは着手するまでただただリードタイムが伸びていくわけだから, フロー効率を下げる方に作用する. タスクのアサインを予め決めることは一連のタスクを直列化し, 不必要なクリティカルパスを生んでしまう可能性もある.

逆に, どのタスクを誰が取ってもいいようにするには, タスクの前提をきちんと言語化したり, 先行するタスクで不確実性を減らしてDesign DocやADRの類をきちんとまとめておく必要があるだろう. こういったことは不確実性を下げることにも寄与するから, どのみちやった方がよい.

ベロシティを安定化し生産性を上げるには

フロー効率がよくなったら, 生産フロー内のボトルネックとなる箇所が全体の生産性を左右する状態になる. 基本的にはこのボトルネックをいかに素早く駆け抜けるかが勝負となる. 以下に, 僕がこれまでに気づいたポイントを挙げておく.

不確実性を下げる

不確実性の高いタスクがあると, 万が一うまくいかなかったときにスプリントから溢れる危険がある. 予め調査タスクを積んでおく, プロトタイプを作成して技術検証しておく, Design DocやADRを書いて不明瞭な点をあぶり出しておくなど, リスクを減らす方法はたくさんある. とくにクリティカルパス上のタスクの不確実性が高い場合は気をつけよう.

不確実性に対処するのは早い方がよい. スプリントの終盤で思わぬ問題が判明しても手遅れだが, 序盤なら計画を見直してリカバリできるかもしれない.

プロダクトバックログアイテムの優先度とスプリント内のタスクの順序を混同しない

スプリント内で優先すべきはクリティカルパス上のタスク, 不確実性の高いタスクであって, プロダクトバックログアイテムの優先度はまったく関係ない. スプリントに積まれたタスクは基本的にすべて消化する(スプリントゴールは必ず達成していく)のだからそれで問題ない. プロダクトバックログアイテムの優先度は, どのアイテムを優先してスプリントに積むべきかをプロダクトオーナが決めるためにあり, スプリント内でどの順でタスクをやっていくかはスプリントゴールが達成できるなら開発チームの好きにしてよい.

タスクに詰まったらチームみんなで助ける

不確実性が高い場合の他に, クリティカルパス上のタスクがボトルネックとなり生産性を下げる場合として, 単純に作業者の力量を超える問題が発生して詰まってしまうということがある. 個人の能力には限界があり, そこを責めても仕方がないから助け合おう. そのために我々はチームで開発している.

助ける方法はなんでもよい. 問題を解決するアイディアをみんなで出し合ってもいいし, ペアプログラミングをしてもいいし, 誰かがタスクを巻き取ってもよい. 重要なのは以下の2点.

  • 問題に早期に気づく
  • いつでも助けられるように余裕を持っておく
手隙は悪ではないことを意識する

ソフトウェア開発は不確実性を孕むものだから, 問題は必ず起きる. そうなったときに対処するための余裕は常に持っておこう.

たとえば, コードレビューを待っている間に暇だからと別のタスクを取るのはあまりオススメしない. レビューの戻りがあったときに「同時に複数のタスクをやらない」に反することになるし, 暇なら他の人のためにコードレビューをした方がチーム全体のフロー効率が上がる. あるいは詰まってそうな人を探してペアプログラミングを申し出れば問題が解決するかもしれない. どうしてもやることがなければ, 普段やりたくてもやれていないDevEx改善をしたり, 読みたかった技術書を読む時間にしよう. 長期的にはこれらの活動も生産性の向上に奇与する. もちろん, レビューが終わり次第すぐに元のタスクに戻ろう.

スプリントゴールを絞る

スプリントゴールが複数並行すると, チームは二正面作戦(多正面作戦)を強いられる. これは2つの理由で生産性を下げる.

  • 詰まったときに手を貸せる人数が減って生産性が下がる
    • 複数のクリティカルパスで同時に問題が発生すると1つの問題にかけられるリソースが減る
    • 問題解決のリソースが減ると解決できる可能性が下がる
    • クリティカルパス上の問題が解消できないと全体の生産性が下がる
  • 認知負荷が上がり効率が悪くなる

各個撃破した方がトータルでは効率がよい.

まとめ

ベロシティを安定化する, あるいは生産性を向上するには, 以下の順に取り組んでいくとよい.

  1. まずはフロー効率をよくする
  2. ボトルネックがどこかを意識してスプリントを計画・遂行する