2026年5月29日

待ち行列システムとプロジェクトの同時進行の良し悪し

読了時間の目安: 5分


待ち行列システムを用いて、プロジェクトの同時進行について考える。プロジェクトの同時進行はアンチパターンとされることが多いが、それはなぜなのかを考えていきたい。

すべてのプロジェクトのリードタイムが悪化する

ここでは、2つのプロジェクト(PJA\mathrm{PJ_A}PJB\mathrm{PJ_B})を1つのチームが並行開発することを考える。PJA\mathrm{PJ_A}PJB\mathrm{PJ_B}はそれぞれ3個ずつのプロダクトバックログアイテムに分割できるとする。

PJA\mathrm{PJ_A}を完了してからPJB\mathrm{PJ_{B}}に着手する場合、プロダクトバックログはこんな感じ。

このチームの平均サービス時間(平均サイクルタイム)をTsT_sとすると、PJA\mathrm{PJ_A}の滞在時間(リードタイム)は3Ts3 T_sPJB\mathrm{PJ_B}6Ts6 T_sとなる。

一方、PJA\mathrm{PJ_A}PJB\mathrm{PJ_B}を同時並行した場合のプロダクトバックログは以下のようになる。

このとき、PJA\mathrm{PJ_A}PJB\mathrm{PJ_B}のリードタイムはそれぞれ5Ts5 T_s6Ts6 T_sとなる。PJA\mathrm{PJ_A}のリードタイムが2Ts2 T_sも遅くなっている。

ガントチャートで表現すると以下。

並列にプロジェクトを増やせば増やすほど、すべてが等しく遅くなる傾向がある。

コンテキストスイッチングの損失でさらにリードタイムが遅くなる

ワインバーグのシステム思考法 』では、スイッチングコストによる損失について経験則的に以下のように言及されている。

並行作業数スイッチングコストによる損失
10%
220%
340%
460%
575%

2並列でパフォーマンスが20%ロスする。さきほどは直列でも並列でも平均サイクルタイムは変わらずTsT_sとした。しかし、2並列の場合パフォーマンスが20%悪化する。直列ならある期間でμ\mu個のプロダクトバックログアイテムを完了させられるチームが、0.8μ0.8\mu個しか完了させられなくなる。平均サイクルタイムは平均サービス率の逆数なので、2並列の平均サイクルタイムTsT'_sは、

Ts=10.8μ=54TsT'_s = \frac{1}{0.8\mu} = \frac{5}{4} T_s

になる。ガントチャートで表すと、

PJA\mathrm{PJ_A}6.25Ts3Ts=3.25Ts6.25 T_s - 3 T_s = 3.25 T_s遅くなり、PJB\mathrm{PJ_B}7.5Ts6Ts=1.5Ts7.5 T_s - 6 T_s = 1.5 T_s遅くなる。

どうしても同時並行しなければならないならチームを分けたほうがいい

PJA\mathrm{PJ_A}PJB\mathrm{PJ_B}も諸事情によりどうしても同時並行しないといけない場合はどうしよう。それならもうチームを分けたほうがよいのではないだろうか。ただ、もとのチームと同じようなクロスファンクショナルなチームに分割できれば、だけど。

こうだったのを、

こうする。

このとき、サイクルタイムはどうなるだろう。それはやってみないとわからない。少なくとも、スイッチングコストによるロスは考えなくていい。1チーム内の労働力が減ることでサイクルタイムが増加するかもしれないし、コミュニケーションコストが減ることでサイクルタイムも減少するかもしれない。メンバーのスキルや経験の差で、サイクルタイムが良くなるチームと悪くなるチームが生まれるかもしれない。

単純にそれぞれのチームのサイクルタイムが2倍になってしまうとする。その場合、こうだ。

1チームで並列するケースよりはいい。

別の考え方もある。もともと1チーム直列のとき、PJA\mathrm{PJ_A}3Ts3 T_sのリードタイムで完了できる見込みだった。つまり、TeamA\mathrm{Team_A}TsT_s以下の平均サイクルタイムでなければ1チームのときよりリードタイムが長くなってしまう。

PJB\mathrm{PJ_B}6Ts6 T_sだったので、TeamB\mathrm{Team_B}の平均サイクルタイムは2Ts2 T_s以下である必要がある。同時に着手が必要ということは、プロジェクト内に重要なマイルストーンなどがあったのだと思うのでこんなに単純ではないだろうが、単純に考えるならこうなる。

他にも、PJA\mathrm{PJ_A}PJB\mathrm{PJ_B}のリードタイムの合計で考える方法もある。もともと合計3Ts+6Ts=9Ts3 T_s +6 T_s = 9 T_sかかっていたので、それぞれ4.5Ts4.5 T_s以内に終われば効率化されたとも言える。このとき、TeamA\mathrm{Team_A}TeamB\mathrm{Team_B}はそれぞれ1.5Ts1.5 T_s以下のサイクルタイムが求められる。

チームの一部だけしか分けられないケースは要注意

チーム分割しようとして、一部だけしか分けられないケースもよくある。もともとチームにPOやデザイナー、QAエンジニアが1人しかいないケースでは、分けられたどちらのチームにも所属することがある。エンジニアは2チームに分かれコンテキストスイッチから解放されるが他のメンバーには依然残るようなケース。

EngA\mathrm{Eng_A}EngB\mathrm{Eng_B}はチームが小さくなりコンテキストスイッチからも解放された。このふたつのサイクルタイムは良くなるかもしれない。一方で、DesignerとQAは依然コンテキストスイッチを抱えている。EngA\mathrm{Eng_A}EngB\mathrm{Eng_B}のサイクルタイムがよくなり、QAがまだコンテキストスイッチを抱えていることで、QAフェーズで待ちが長くなるかもしれない。実装は速くなってもリードタイムは長くなるケースも出てくる。ボトルネックをチームで協力し合えるなら問題ないけど。

まとめ

複数のプロジェクトを1チームで同時進行すると、コンテキストスイッチの損失により遅くなる。1チームで直列的に実施するか、2チームに分けてしまったほうがよさそう。

部分的にチームを分けるしかない場合は、コンテキストスイッチを抱えたままの部分がボトルネックになりやすい構造になる。チーム内で協力し合い、ボトルネックをなんとかできる前提があるときの選択肢になりそう。

気に入っていただけたら、
サポートもお待ちしております!
  • 名前:asato
  • 仕事:スクラムマスター
  • 好き:家族、温泉、旅行、謎解き
  • 苦手:はじめまして、あんこ、うなぎ