mtx2s’s blog

エンジニアリングをエンジニアリングする。

兼務はチームの独立性とのトレードオフ

ソフトウェアエンジニアリングの世界では、エンジニアに、チームをまたいでプロジェクトやプロダクトを掛け持ちさせるアサインメントを強いることがある。いわゆる兼務と呼ばれるものの一形態だ(以降、この形態による兼務を単に「兼務」と呼ぶ)。

組織設計においてマネージャーを大いに悩ませるのは、人材面での制約だろう。人的リソース(human resource, 人的資源)と呼ばれるように、資源には限りがある。他の経営リソースと違って個々が無二の存在であるから、その制約はさらに、個別の事情までもが複雑に絡み合う。だから兼務による人的リソースのアロケートは、マネージャーにとって、複雑で厳しい制約に柔軟性を持たせる魔法の杖となる。

しかし、兼務には大きなコストがつきまとう。そのコスト自体の可視性が低いためか、組織を設計する上で、兼務に伴うコストが軽視されているように感じている。

いや、兼務者が、参加するチームそれぞれに100%の時間を割けないことは自明だ。これは、兼務を選択する上での前提条件であり、十分に理解されているだろう。そうではなく、兼務がチームの独立性を落とすことが問題なのだ。それがチームの足を引っ張り、プロジェクトを遅らせる。

このトレードオフによるコストを十分に評価した上で、兼務するか否かの意思決定が行われるべきだろう。コストが効果を上回るなら、その兼務は破棄すべき選択肢となる。

本稿ではこのトレードオフを扱う。兼務がどのようにチームの独立性を阻害するのか、どのようなコストを支払うことになるのかをひも解いていく。また、兼務という選択が正しい判断であるかをケースごとに検討し、より良い選択の模索を試みる。

兼務の問題点

チームの独立性はパフォーマンスの源泉

エンジニアリング組織を設計する上で、チームの独立性は、何より重視すべきパラメータだと考えている。独立性の高いチームは、チーム外部の影響を受けることなく、プロジェクトの計画を決め、実行できる。ユーザー価値、ビジネス価値を迅速に生み出せるということだ。

このように独立性は、チームのパフォーマンスを左右する重要なファクターなのだが、その評価は難しい。それ自体が、定量的な尺度ではないためだ。

しかし、いくつかの観点をもとに、チームの独立性の高低を見極めることはできる。そのひとつが、チームによる「リソースの利用」に対する独立性だ。

チームが責務を果たすには、その実行に足る権限とともに、リソースが必要だ。人材や設備、予算、情報が揃っていなければならない。これらの要素のいずれかひとつでもチームの単独判断で利用できないなら、それがチームの活動を阻害する大きな要因となる。兼務を問題視しているのは、この「人材の利用」の独立性に抵触する組織設計だからだ。

兼務によるチーム間結合度の上昇と独立性の低下

兼務は、複数のチームで人的リソースをシェアするアーキテクチャだ。シェアすれば必然的に、リソース利用にコンフリクトが生じる。このコンフリクトの解決や、そもそもコンフリクトさせないための合意アルゴリズムの導入、あるいはスケジューリングの必要性が、チームとチームの結合度を高めてしまう。

ソフトウェア設計では、モジュール間の結合度を下げることが、モジュールの独立性を高める上で良いとされている。組織設計もその原則は同じだ。チーム間の結合度が高いと、チームの独立性は低くなる。兼務は、兼務者を挟んでチームとチームを結合し、互いを縛り付けるチェーンのようなものだ。これではあまりに身動きが取りづらい。兼務の選択は、チームの独立性を失うこととトレードオフの関係にあるのだ。

では、兼務によってチーム間の結合度が上がり、チームが独立性を失うことで、具体的にどのようなコストを支払うことになるのだろうか。

兼務のコスト

チーム間の密結合状態が生むコスト

チーム間の密結合状態が直接的な原因となって生じるコストは、主に、「調整コスト」と「遅延コスト」の二種類が考えられる。

調整コスト

兼務者の作業時間をいつからいつまで確保するかは、チームの一存では決められない。兼務者を挟んで結合されたチーム間で調整することになる。この調整を行う中で消費される時間やお金といったリソースを、調整コストと言う。

ソフトウェア開発プロジェクトは、常に不確実性との戦いだ。計画に無い出来事が次々と発生する。だから、兼務者のスケジュールをチーム間で厳格に取り決めてしまうと、プロジェクトが立ち行かなくなってしまう。トラブルへの適宜対応が可能となるよう、スケジュールを臨機応変に組み替えられるようにしたい。しかし、その実現と引き換えに、調整コストはさらに大きく膨らむこととなる。

遅延コスト

調整コストを支払ったからといって、兼務者の作業時間がチームの思い通りになるわけではない。その影響は、プロジェクトのスケジュールとして現れる。

兼務者の作業時間の都合がつかないために、プロジェクトの開始予定日を、チームの希望より後ろ倒しにせざるを得ないこともある。また、兼務者という制約がクリティカルチェーンとなって、計画上のプロジェクト期間をより長くさせてしまうこともある。いずれにしても、リリース予定日は、チームの希望より先延ばしになるだろう。

ソフトウェアプロジェクトが価値を生み出すのは、その成果物がリリースされてからだ。リリースが先延ばしになればなるほど、ユーザーやビジネスが本来得られるはずであった価値が目減りする。こうして失われる利益を遅延コスト(CoD, Cost of Delay)と言う(参考『遅延コスト回避中心のPBIライフサイクルマネジメント』)。

mtx2s.hatenablog.com

遅延コストにつながる兼務の制約は、プロジェクトの計画に影響を及ぼすものだけでない。プロジェクトの実行にも強い影響力がある。プロジェクトの進捗に遅れが生じた時に、兼務者を介してその影響が通常より酷くなる傾向があるのだ。

例えば、先行タスクが遅延したとしよう。兼務者は予定日に担当タスクを開始できなくなる。それを待っている間に、別チームの担当タスクの開始日になってしまう。こうなると、マルチタスクで進めるか、いずれかのタスクの予定を変更するか、何らかの手段で乗り切ることになる。どちらにしても、プロジェクトの進捗は大きく遅延する。

兼務者自身がタスクを遅らせてしまった時も同様だ。遅延を取り戻そうと頑張っている間に、別のチームのタスクに取り掛かる予定日になってしまう。

このように、ひとつのプロジェクトの進捗の遅れが、複数のチームに飛び火していく。こうしてリリースが遅れ、遅延コストが膨らんでいく。

その他のコスト

チーム間の密結合状態が直接的な原因ではないが、「コミュニケーションコスト」と「スイッチングコスト」も、兼務によって増加するコストとして挙げられる。

コミュニケーションコスト

プロジェクトはたいてい、それごとに複数の会議体を持っている。兼務者は、兼務しているチームの数に比例して、参加しなければならない会議の数が増える。

こうして増加したコミュニケーションコストにより、兼務者の開発時間は大きく削られることになる。

スイッチングコスト

兼務者の業務は、マルチタスクが起こりやすい。マルチタスクが、コンテキストスイッチによるオーバーヘッドを生むことはよく知られている。このオーバーヘッド時間がスイッチングコストだ。

ジェラルド・M・ワインバーグによると、タスクの並列数が2になると、スイッチングコストによって稼働時間の20%をロスし、並列数が3だと40%をロスするという(『ワインバーグのシステム思考法 ソフトウェア文化を創る〈1〉』 ジェラルド・M・ワインバーグ(著) 増田信爾(訳) 共立出版 1994)。

兼務の再考

兼務を選択した目的

ここまでで、兼務によって失うものを見てきたが、逆に、兼務によって得ようとしたものとは何だったのだろうか。

兼務を選択した目的として考えられる代表的なものを、以下に挙げる。

エンジニア不足を補う

組織は複数のプロジェクトを抱えているものだ。その数や規模に対し、一時的、あるいは常態的にエンジニア不足が起きているケースも多いだろう。

こういう状態にある組織のマネージャーは、兼務ながらもメンバー数を揃えることで、チームを機能させようとする。

エキスパートに頼る

どこのチームにも、特定の領域に精通したエキスパートが存在する。そして、唯一の存在であることが多い。それゆえに、ただ一人しかいないエキスパートがチームから抜けると、担当していた業務の効率が著しく損なわれたり、業務の継続が不可能な状況に陥ってしまう。

だから、エキスパートを別のチームに参加させなければならなくなった時、元のチームに籍を置いたまま、別のチームにも参加させることを考える。そうすることで、業務効率を落とすことなく現状を維持できる。

エースに頼る

飛び抜けて優秀なエンジニアの生産性は、とてつもなく高い。平均的なエンジニアに比べ、数倍の違いがあるとも言われている。エースと呼ばれるエンジニアたちだ。

マネージャーとしてはやはり、可能な限りエースに活躍して欲しいと考えるだろう。こうして優秀なエンジニアは、多くのプロジェクトに関わることになる。

稼働率を上げる

チーム内でのタスク割り当てだけでは、一部のエンジニアが時間を持て余してしまうことがある。マネージャーにとって、エンジニアの稼働率が低い状態が続くことは、ムダに思えてしまう。

このようなケースでは、稼働率が低いエンジニアの余った時間を他のチームの業務にあてることが、全体最適だと考えることは自然だ。その手段として、チームメンバーを他のチームに兼務させることになる。

兼務以外の選択肢

はたして、兼務を選択した目的はそもそも課題定義として正しかったのだろうか。先述のケースそれぞれの原因をもう一段深掘りし、兼務以外の選択肢を検討してみよう。

現状に対するエンジニア不足を補うより、選択と集中

エンジニア不足は、ビジネスやプロダクト開発に戦略が無いからかもしれない。

「不足」とは、相対的な尺度だ。人的リソースはそもそも制約であり、プロジェクトすべてに理想的で完全なリソースを割り当てることはできない。だから、プロジェクトに優先順位を付け、今やるべきことを絞り込み、そこにリソースを集中的にあてる。この優先順位付けのアルゴリズムこそが、戦略だと考えて良い。

したがって、戦略が無ければ優先順位付けアルゴリズムも存在しない。あらゆるプロジェクトが、同列で稼働することになる。やることを絞り込んでいないから、リソースは分散する。結果、エンジニア不足に陥る。

これが当てはまるなら、戦略を立て、やるべきことの絞り込みに取り組むと良い。

とは言え、複数のチームを取りまとめる立ち場にあるマネージャーでなければ、この取り組みを進めることは難しい。そのような立ち場にないならば、適切な人物に現状を説明して協力を仰ぐのが懸命だろう。

ただ一人のエキスパートに頼るより、属人化を解消する

エキスパートが一人しか存在しない状態は、業務の属人化が深刻である証だろう。この状態を問題としてとらえ、解決しようとすると、それなりの時間を要してしまう。兼務という選択肢を選んだのは、その時間や、一時的な効率悪化を嫌ってのことだろう。

業務が属人化することを「どんな場合でも悪である」とは思わないが、少なくとも三つの観点で問題を抱えることを念頭に置く必要がある。

一つめは、リスクマネジメントの観点。属人化した業務は、会社からそのエキスパートが去ると、継続が困難になる。

二つめは、ビジネス戦略の観点。戦略が変われば組織も変わる。変化に応じて、柔軟に人を配置させたい。しかし、属人化した領域にあるエキスパートは、その領域に固定されたままとなる。結果、人材配置の面で自由が奪われ、変革が不十分なものとなってしまう。

三つめは、キャリア形成の観点。長期間、特定のエンジニアを一つの業務に縛り付けることは、エンジニアとしての可能性を奪うことになりかねない。属人化という形であれ、エキスパートになるほどだから、優秀な人材に違いない。それに、チームが手放さない人物であるからには、まわりからの信頼も厚いのだろう。だからこそ、いつまでも一所に留めておくには惜しい才能だ。これは、本人にとっても会社にとっても好ましい状態とは言えない。

属人化してしまった業務からは、あえてエキスパートを引き剥がす勇気も必要だ。一時的に業務効率は落ちるかもしれないが、長期的に見れば良い結果につながるだろう。

常にエースに頼るより、チームメンバー全体に経験を積むチャンスを

エースに頼り過ぎると、周囲のエンジニアは簡単な仕事しか経験できなくなる。その状態が続くと、エースとそうでないエンジニアの差は益々広がる。この状態も、ある意味では属人化と言える。

エースでなくとも、エンジニアは、経験し、失敗することで成長を続けられる。それはエンジニアとして働く上での彼らの権利でもある。

それに、後進が育たなければ、将来のいずれかの時点で組織が破綻することは目に見えている。目先の利益を優先するばかりでなく、将来を見据えた体制作りも考えるべきだろう。

目先の稼働率を上げるより、チームや役割の責務を見直す

ビジネスの目的を「ユーザーに価値を届けること」だと捉えると、注目すべきは「人の稼働状況」よりも「タスクの進行状況」だ。プロジェクトは、成果物をリリースするまで価値を生み出さない。そして、リリースが遅れるほど、その期間に得られるはずであった価値が、無となってしまう。だから、プロジェクトを最短距離でゴールに導くことこそ最優先とすべきなのだ。兼務によってチームの独立性を落とし、タスクの進行状況を悪化させることは、可能な限り回避したい。

業務時間を持て余すのであれば、それは組織設計を見直すべきだろう。チームのメンバー数を減らした上で役割を集約することや、チームの責務を広げるといった方法で、適正な業務量が割り当たるようになるだろう。

最後に

本稿では、兼務がどのようにチームの独立性を阻害するのか、どのようなコストを支払うことになるのかをひも解いてきた。また、兼務という選択が正しい判断であるかをケースごとに検討し、より良い選択の模索を試みた。これらを読み終えて、兼務というアサインメントの選択に対し、これまでより慎重になっただろうか。

また本文では触れなかったが、兼務について考えるなら、兼務者のメンタル面についても注意しなければならないだろう。

兼務者は、プロジェクトにオーナーシップを持てているだろうか。会議やスイッチングコストに時間を取られ、開発が進まないことにストレスはないだろうか。自分がチームのボトルネックになっていると感じていないだろうか。

1on1などを通じてケアを続けているとは思う。しかし、ただでさえ把握することが難しいメンタル面の動きを、兼務はより複雑にしかねない。これは、マネジメントコストを拡大する。そして、チームメンバーが不安定な状況にあると、チームの舵取りも難しくなる。失敗すれば、プロジェクトは価値を損なう。

兼務が直接的、間接的に引き起こす相互作用は複雑だ。ソフトウェア設計と同じように、組織設計もシンプルなアプローチを選択する方が良いだろう。

遅延コスト回避中心のPBIライフサイクルマネジメント

本記事は、Engineering Manager Advent Calendar 2020の21日目です。テーマとしては、プロジェクトマネジメント、プロダクトマネジメント領域を取り上げています。

--

ソフトウェアプロダクトの開発、特に、競争の激しいマーケットに置かれたプロダクトの開発は、次から次へと繰り返されるアップデートの間隔が短いほど良いとされる。背景として期待されているのは、そのスピードがユーザー価値やビジネス価値に与えるポジティブな効果だろう。それは主にふたつあると考えている。

ひとつめの効果は、価値を早期に生み出せるということ。

プロダクトのアップデートが価値に変わるのは、それがリリースされてからだ。言い換えれば、リリース時期が遅くなれば遅くなるほど、ユーザーにとってもビジネスにとっても、得られるはずであった価値の総量が目減りすることになる。遅延と引き換えにコストを支払ったと言ってもよい。

では、早くリリースすれば期待通りの価値の獲得が約束されているかと言うと、しかし現実はそんなに甘くない。開発チームが自信を持って送り出したアップデートが、ユーザーから不評を買うなんてことは、よく見られる光景だ。

そこで、もう一つの効果への期待が生まれる。それは、価値向上の学びとなるフィードバックを早期に得られること。

アップデートに対する評価は、ユーザーの反応を見なければわからない。最終的かつ最も確かなフィードバックを得る方法は、アップデートをリリースし、その真価をユーザーに問うことだ。そうすれば、そこから得た学びをプロダクトに還元できる。だから、リリースサイクルが短ければ短いほど、フィードバックループを高速に回せ、適応性を高めることにつながる。

このように、リリースを早める努力はその見返りとして、アップデートという単なるアウトプットを、価値という大きなアウトカムに変換してくれる。それだけに、この努力が開発チームの普遍的な重要成功要因であることは間違いないだろう。

本記事では、PBI(Product Backlog Item)のライフサイクルを中心に据え、「リリースを早めて価値を最大化するにはどうすれば良いのか?」という問いを、「遅延によって失われる価値(コスト)を小さくする」という観点から捉え直した上で考察を進める。つまり、先述のひとつめの効果を得ることをテーマとして扱う。もう一方の「学習サイクルを高速化して得られる価値を大きくする」という観点は、以前の記事でテーマとして扱った。興味があれば、そちらもご一読いただきたい。

mtx2s.hatenablog.com

以降ではまず、遅延そのものや、遅延によってコストが生み出されるメカニズムを明らかにする。そこでの結果に基づいて、PBIの優先順位付けアルゴリズムの改良と、リードタイムのチューニングをもって、遅延コストの積み上げを最小化する開発プロセスを考えていく。

遅延コストを生み出すメカニズム

完了の遅延と予定された遅延

あたり前の話だが、開発チームにとってリリースの遅延と言えば、リリースを予定していた日と実際にリリースが完了した日との差を指す言葉だ。12月15日にリリース予定だったものを、実際には12月22日にリリースすれば、7日間の遅延となる。この遅延による経済的影響は、「機会損失(opportunity lost)」と呼ばれたりする。

7日間の遅延
7日間の遅延

この7日間はしかしながら、開発チームから見た遅延だ。ビジネス視点の遅延としては、考慮が漏れている。それは、「機会費用(opportunity cost)」として影響するもう一つの遅延のことだ。機会費用とは、最大の利益を得るために意思決定されたトレードオフによって取り損ねる利益を言う。

開発チームにとっての最大のマイルストンであるリリース予定日は、常にトレードオフの中で決められている。同時に抱える複数のPBIを全て最優先にすることはできない。何らかの優先順位付けアルゴリズムに従い、いくつかのアップデート単位にまとめられてリリース日がプランニングされる。結果、最優先のPBI以外のリリース予定日は、それぞれが最短のリリース日に比べて数日から数週間、あるいは数ヶ月レベルで先延ばしになる。この先延ばしになった日数が、もう一つの遅延だ。この遅延によって取り損ねることになる利益が、機会費用となる。

これら二つの遅延を本記事では「完了遅延」「予定遅延」として区別する。先ほどの例で、最短のリリース日を12月1日だとすると、予定遅延は14日間となる。ビジネス視点では、完了遅延によって7日間の機会損失を支払うことになったという事実だけでなく、予定遅延によって既に14日間の機会費用を支払っているという感覚を持つことになるだろう。

14日間の予定遅延と7日間の完了遅延
14日間の予定遅延と7日間の完了遅延

ふたつの遅延に紛れ込む無自覚な遅延

プロダクトバックログから取り出されて開発を開始したワークアイテムが、一度の停滞もなく進捗を続け、リリースに至ることはまずないだろう。ほとんどのワークアイテムは、リソースが割り当たって進捗している「進行状態(work state)」と、リソースが割り当たらずに停滞している「待機状態(wait state)」を交互に繰り返しながらリリースに辿り着く。

進行状態と待機状態
進行状態と待機状態

もちろん、ワークアイテムが待機状態にあるからといって、開発チームが仕事を怠けているわけではない。むしろ忙しく働いた結果が、この待機状態を生み出していると言っても良い。チームが並行して進めている別のワークアイテムに人的リソースが奪われ、リソースが割り当たらなかった残りのワークアイテムが一時的に待機状態になっているのだ。

一般的に、プロダクトのアップデートには、複数のPBIの成果物が含まれている。単一のPBIのみでアップデートを行うケースは少ない。その理由はいくつか考えられるが、最も大きな理由は、予定遅延を最小限にとどめたいという要求だろう。

ビジネスの責任者にとって、利益を取り損ねることに繋がる予定遅延の選択は、少しでも避けたい。できる限り多くのPBIを、少しでも早いアップデートに含めてリリースしたいのだ。そのトレードオフが、機会費用の最小化、つまりは利益の最大化になると信じている。

しかしながら、この意思決定は逆効果になり得る。多くのPBIが含まれるようなバッチサイズの大きなアップデートほど、過剰なマルチタスクを引き起こし、待機状態を生み出す。頻発する待機状態が個々のワークアイテムのリードタイムを引き延ばし、結局はアップデートのリリース日を遅延させるからだ。

この遅延は、予定遅延のみ、あるいは予定遅延と完了遅延の両方に紛れ込む。

予定遅延を避けるために、一度のアップデートに多くのPBIを詰め込むほど、アップデートのリードタイムは長くなる。少なくとも、全てのPBIの合計ストーリーポイント以上には引き延ばされる。結局は予定遅延となる。

それだけではない。エンジニアなら経験的に知っている通り、PBIを多く含むような、バッチサイズの大きなアップデートは、完了遅延が起きやすい。

一方で、開発チームがその完了遅延を予測して避けようとする行為は、リードタイムに含まれる見積もりバッファを大きくし、リリース予定日を先延ばしにする。この遅延は、完了遅延としてカウントされるかわりに、予定遅延としてカウントされるようになる。遅延することには変わりがないが、この判断は、ユーザーやビジネスに対する「リリース予定日という約束の不履行」を避けられるだけマシだろう。

なお、バッチサイズが大きくなる理由は、これも含めいくつか考えられる。

  1. できる限り多くのPBIを、一つでも早いアップデートに含めてリリースしたい
  2. マーケットに対するリリースインパクトを大きくしたい
  3. 開発チームの人的リソースに空きを作りたくない
  4. リリース実施によるコストやリスクが大きいため、リリース回数を減らしたい

いずれにしても、一度のアップデートに複数のPBIを詰め込むと、マルチタスクとなりリードタイムを引き延ばす。この遅延を認識した上で、適切なトレードオフを行うべきだろう。

遅延の長さを決定付ける二種類の待機時間

遅延の長さは、二種類の待機時間によって決まる。一つは、PBIの追加日から開始日までの待機時間。もう一つは、開始からリリースまでの間に断続的に入り込む待機時間だ。

待機時間
待機時間

一度のアップデートに含めるPBIを絞れば絞るほど、開始までの待機時間が長いPBIが増える。逆に、アップデートに含めるPBIを増やすほど、開発後の待機時間が長くなってしまう。

これらのことから、どのPBIから開始すべきなのかの優先順位付けアルゴリズムの最適化と、リードタイムの短縮が、積み上がっていく遅延コストを小さくすることにつながりそうだ。以降は、それぞれの実現手段について考えていく。

優先順位付けアルゴリズムの改良

CoDを用いた遅延影響の定量

何らかの意思決定を下す時はいつでも、状況を定量化して分析することが役に立つ。下記グラフは、遅延による影響を、遅延時間に比例して拡大するモデルとして表現している。

累積遅延コストと遅延時間の関係
累積遅延コストと遅延時間の関係

このグラフの傾きが大きいPBIほど、遅延の影響が大きい。Donald G Reinertsenは、この傾きをCoD(Cost of Delay)という名前で、遅延によって失われる価値の量をコストとして定量化することを提案した。このコストには、機会費用も機会損失も含まれている。

例えば、あるPBIのリリースによって、一年間で12,000千円の利益が生み出されると仮定する。この場合、リリースがひと月遅れるごとに1,000千円の利益を失うことになる。この1,000千円がCoDだ。

このように、Reinertsenの手法では、CoDに実際の金額を使用する。新規プロダクトをローンチするケースでは収支計画などから数字を引用できるが、既存プロダクトに対する変更を金額で見積もりるのは難しい。PBIひとつが、それだけで利益を上げるようなケースは多くない。サブスクリプションモデルのアプリに対するUI改善が、利益にどれだけの影響を与えるのか。技術的負債を返済することの価値は経済的にいくらになるのか。それらを金額に換算するのは困難だろう。

一方、SAFe (Scaled Agile Framework)は、CoDに金額を使わず、三つのコンポーネントに分けてフィボナッチ数で相対的に見積もることを推奨した。これだと、ストーリーポイントと同じ感覚で見積もることができ、開発チームへの導入障壁も下げられる。

 CoD = UBV + TC + RROE

UBV(User-Business Valueは、他のPBIとの相対的な価値の大きさを表す。価値が大きいほど、UBVは大きい。

TC(Time Criticality)は、遅延のインパクトを相対的に表す。リリース時期に対する制約が強いほど、TCは大きい。

RROE(Risk Reduction and/or Opportunity Enabling valueは、将来のデリバリーリスク軽減効果や、ビジネス機会創出の可能性を表す。その価値が高いほど、RROEは大きい。技術的負債の返済効果などは、ここに含めるのが良いだろう。

SAFeのこの方式は、価値を評価するUBV, RROEと、緊急性を評価するTCを足し合わすだけであり、非常にシンプルだ。しかし、その点を問題視する議論もある。価値を表すUBV, RROEが共に0であるなら、CoDは0であるべきという考え方だ。SAFeの方式では、緊急性を表すTCの値でCoDが決定されてしまう。

この問題を指摘しているJoshua Arnoldは、価値と緊急性を掛け合わせる方法を提案している

 CoD = \left(UBV + RROE \right) \times TC

以上は、時間軸に対してCoDが一定であることを想定した標準的なタイプ(standard cost of delay)を扱った。様々なケースを想定すると、時間軸に対してCoDが一定ではないタイプも考えられる。固定の日付に強く紐づいたPBIのCoDfixed date cost of delay)や、緊急性が高いPBIのCoDcost of delay tied to urgency)などだ。

PBIの特性に合わせてCoDは様々なタイプが考えらえるが、実際に利用するのは、standard cost of delayで十分だろう。CoDの使い分けは、労力に対して得られるメリットが小さいように思う。

WSJF戦略というアルゴリズムの選択

プロダクトバックログをキューとして捉えてみて欲しい。そこに詰め込まれたアイテムのデキューアルゴリズムは、FIFO(First In, First Out)になっていないだろうか。

機会費用を最小化することに焦点を当てると、PBIの優先順位付け戦略もそれを基準に評価することになる。ここで使えるのがWSJF(Weighted Shortest Job First)と呼ばれる優先順位付けモデルだ。WSJFは、重要度を期間で割った結果に基づいて優先順位を決める戦略だ。この重要度としてCoDを使ったものがCD3(Cost of Delay Division by Duration)と呼ばれている。

WSJF = \dfrac{CoD}{Duration}

Durationは、対象とするPBIの開発に必要となる期間のことだ。推定リードタイムと言い換えても良い。代替として、PBIのストーリーポイントを利用する場合も多いだろう。

三つのPBIを例に、その優先順位を評価してみよう。

PBI CoD Duration WSJF
A 8 4 2.0
B 16 2 8.0
C 4 8 0.5

WSJFの結果に従い、B→A→Cの順に開発・リリースした場合のCoDは、Aが16, Cが24となって、トータルの遅延コストが40となる。 Aは、BのDuration分だけ遅延するため、CoDの8に2を掛けて16となる。Cは、BとAのDurationを合わせた期間である6だけ遅延するため、CoDの4に6を掛けて24。それらを合わせて40という計算だ。

WSJFの優先順位付けに従って直列化した場合
WSJFの優先順位付けに従って直列化した場合

比較のために、逆順のC→ A→ Bとした場合は、Aが64, Bが192となり、トータルで256となる。WSJFで示された順序でリリースした方が、トータルの遅延コストが小さくなり、機会費用が相対的に小さく済むことがわかる。

WSJFの優先順位付けに従わずに直列化した場合
WSJFの優先順位付けに従わずに直列化した場合

WSJFの信頼性に関わるリードタイム推定精度問題

WSJFの良いところは、優先順位付けの根拠が誰にでもわかりやすい点にある。マネージャーや開発チームにとっても、ステークホルダーからリリース順序の根拠について問われた時に答えやすいだろう。

しかし、WSJFの利用にも課題はある。Duration, すなわちリードタイムの正確な推定が難しいのだ。推定リードタイムをストーリーポイントで代替しても良さそうだが、WSJFの信頼性を下げる可能性がある。同一のストーリーポイントとして推定されたPBIでも、実際のリードタイムにはばらつきがあるからだ。

同一のストーリーポイントと推定されたPBIの実績データを集め、グラフにプロットするとロングテールになる。横軸が実績リードタイムで、縦軸がそのリードタイムごとのPBIの数だ。ロングテール分布では、平均値は代表値として使えない。多くのデータがテール側にばらついてプロットされることになる。テールが横に長いほど、リードタイムの推定が困難であることを表している。

このばらつきの主な原因は、先にも述べた開発時の断続的な待機状態にあると考えられる。したがって、待機時間を削減できれば、テールが短くなり、リードタイムの推定に信頼が持てるようになるはずだ。その結果、WSJFによる優先順位付けの信頼性も上がるうえ、リードタイムも短くなる。これに取り組まない手はない。

リードタイムのチューニングと推定精度の向上

マルチタスクによる待機時間問題

マルチタスクと待機時間の関係について、もう少し深掘りしてみよう。

複雑な影響を無視して言えば、チームがひとつのワークアイテムに割り当てられる作業時間の割合 w は、同時に抱えるワークアイテムの数 n に反比例する。n=1 なら、開発チームはそれだけに作業時間の全てを割り当てられ、w=100\% になる。n=2 なら w=50\%, n=3 なら w=33\% になる。

作業時間の割合とワークアイテム数の関係
作業時間の割合とワークアイテム数の関係

シングルタスクである場合の、あるワークアイテムのリードタイムを 1 とすると、マルチタスクによる並列数が n=2 なら、1日あたりの作業時間の割り当てが w=50\% になり、リードタイムは 1 \div 50\%2 になる。n=3 なら、3 となる。リードタイムの長さは、ワークアイテムの並列数に比例する。

リードタイムとワークアイテム数の関係
リードタイムとワークアイテム数の関係

実際には、マルチタスクの作業の切り替えにスイッチングコストによるオーバーヘッドが発生するので、リードタイムはさらに延びることになる。スイッチ回数が多いほどそのコストは大きくなるが、その回数を推測できないから、影響の大きさを読むことができない。

さらに、マルチタスクの並列数は毎日一定ではない。だから、同じストーリーポイントのワークアイテムでも、そのリードタイムにばらつきがでる。

したがって、開発チームのマルチタスクを抑制することが、リードタイムを短縮することに有効な手段となり得る。

Flow Efficiencyを用いた進行効率の定量

ワークアイテムの進行時間(work time)待機時間(wait time)に焦点をあてるならば、まずはそれを可視化することが第一ステップとなる。そこでFlow Efficiencyというメトリクスを使う。Process Cycle Efficiencyや、Task Efficiencyとも呼ばれる。日本語では「フロー効率」と呼ばれているようだ。

Flow Efficiency = \dfrac{Work Time}{Lead Time}

一目瞭然であるが、Flow Efficiencyは、リードタイム(lead time)に占める進行時間(work time)の割合という形で、PBIの開発に要した期間の効率性を示す。このメトリクス値が大きいほど、待機状態による遅延が小さく、開発が効率よく進行したと言える。

チームのFlow Efficiencyを算出するには、ワークアイテムごとの進行時間の計測を始めなければならない。開発プロセスをいくつかのフェーズに分け、フェーズごとの開始日、終了日を記録する程度で良いだろう。少々粗いデータにはなるが、正確さを追い求め過ぎても、労力ばかりで大きな見返りは期待できない。チームがリーン開発のカンバンボードを導入しているのなら、ステージごとに開始日、終了日を記録していくイメージだ。

カンバンボードは、直線的な順序を持ついくつかのステージ(工程)で構成されている。このパイプラインを、カードと呼ばれるワークアイテムが流れていくことで、リリースにいたる。ひとつのステージを終えたカードは、次のステージでの作業が始まるまでの間、その手前のバッファに入る。カードがステージに入っている期間が進行時間、バッファにいる期間が待機時間となる。

カンバンボードの例
カンバンボードの例

もし、算出したスコアが8%程度でも、落胆する必要はない。Flow Efficiencyをどのように計測するかにもよるが、スコアは概ね、1%から25%の範囲に入るようだ。

いずれにしても、スコアを絶対値として他のチームと比較することにはあまり意味はない。ベロシティと同様に、チームの成熟度を知るための相対的な指標として利用できれば良い。

WIP制限でのマルチタスクの抑制とボトルネックの可視化

ワークアイテムごとのFlow Efficiencyを得たところで、次にやるべきことは、そのスコアの改善だ。その手段として、マルチタスクをコントロールする。メトリクスを悪化させる要因である無自覚な待機時間を抑制するということだ。

マルチタスクをコントロールするために、その状況を定量化・可視化し、並列数に閾値を設ける。先述のFlow Efficiencyの計測では、開発プロセスに含まれるフェーズをマネジメントする単位とした。ここでもフェーズごとに、仕掛かり中のワークアイテムの数を制限するのが良いだろう。

その最適な方法として、リーン開発ではお馴染みの 「WIP制限」というプラクティスを使う。WIPとは、Work In Progressの略で、仕掛かり中のカードを意味する。WIP制限では、カンバンボード上のステージごとに、チームが同時に取り組めるWIPの数を制限することで、過剰なマルチタスクを抑制する。

ステージ内のカード数が制限に達すると、そのステージでは新たなカードに取り組むことができなくなる。この状態を放置すると、ステージに入れないカードがバッファにどんどん積み上がっていく。これはボード上を流れるカードをせき止めるボトルネックだ。開発チームは、ボトルネックとなったステージのWIPを減らすことに注力することになるだろう。

WIP制限で可視化されたボトルネック
WIP制限で可視化されたボトルネック

WIP制限の良いところは、マルチタスクを減らして待機時間を短くするだけでなく、フロー上のボトルネックを明らかにして、リードタイムを縮める方向に開発チームの行動を誘導する点にある。

逆にWIP制限を導入しないと、いくつものカードをステージに入れることだって出来てしまう。そうすると、バッファで待機しているはずのカードが不可視になる。見かけ上の待機時間がなくなるので、当然ながら、Flow Efficiencyのスコアが上がってしまう。これではメトリクスが意味をなさない。こういった問題からも、WIP制限はぜひ導入すべきプラクティスだと言えそうだ。

制限数をどの程度にすれば良いかは、運用しながら調節するしかない。大まかな基準としてはチームのメンバー数だろう。これより大きな数字は、確実にマルチタスクになるからだ。もしペアプロやモブプロを導入しているチームなら、この基準値はさらに小さい。

これで、Flow Efficiencyのスコアが向上し始める。また、待機時間が減ることでワークアイテムのリードタイムが安定する。この安定が、リードタイム分布のテールを短くし、結果としてリードタイムの推定精度が高まるだろう。これでようやく、WSJFの分母の信頼性が上がり、PBIの優先順位付け精度も向上する。

なお、Flow Efficiencyは、100%を目指すようなものでもない。カンバンコミュニティで報告された最高のケースでも40%程度のようだ。

最後に

エンジニアリングに携わっていると、システムや開発プロセスに限らず、何らかしらの主体やその機能を対象に、パフォーマンスを高めるミッションを担うことがある。

そういった時、対象に再現性がないなら、対象のポテンシャル自体を引き上げるより、対象が本来持っているはずのポテンシャルを引き出すことに注力した方が、早く大きな効果を得られることが多いと感じている。前者の取り組みは「スケール」、後者は「チューニング」という言葉がしっくりくる。

チューニングとは、ある目的に合わせ、対象が内包するプロセスやパラメータを最適化したり、阻害要因を取り除く行為だ。こうして、本来のポテンシャルを引き出し、目的に合わせたパフォーマンスを得る。本記事の内容もまさに、チューニングによって、PBIが本来持つ価値を最大限に引き出すことだった。その戦略が、遅延コストによって損なわれる価値を、全体最適の観点で最小限に抑えることだ。

この戦略の中心は、CoDとWSJFにある。これらを使い、PBIそれぞれのリリースをプランニングする。そして、そのプランにそってPBIの開発を開始し、最短距離でリリースする。この早期のリリースが、ユーザーからの早期のフィードバック獲得につながる。こうして学習したチームは、価値を生み出す確度の高いアイデアをPBIとして追加する。そしてまた、CoDとWSJFを使い、PBIのリリースをプランニングする。このサイクルを回し続ける。すべてはプロダクトのユーザー価値とビジネス価値を高めるために。

エンジニアリングによるビジネスパフォーマンスチューニング

ソフトウェアプロダクトの機能リリース頻度は益々高まっている。月に何回リリースしたか、いくつの機能をリリースしたか、開発現場はもちろん、ビジネスサイドでも度々話題になる。しかし、開発チームのこの努力と献身は、ビジネスにいったいどれほど影響を与えられているのだろうか。

皮肉なことに、リリースサイクルを高速にすればすほど、開発チームの意識は、機能をリリースすることのみに集中していく。リリース自体がゴールになってしまう。この状態で、開発チームがビジネス視点を持つのは難しいだろう。

そもそも、リリースした機能と売上との関係性を見出すこと自体、難しい。そうであればなおさら、開発チームの関心はビジネスから離れていく。売上との関係性を見出すことなど諦めてしまう。

コスト(原価)との関係性はわかりやすい。製造原価(材料費、労務費、経費)の共有を定期的に経理部門から受けられるマネージャーも多いだろうし、工数管理も行なっているだろう。だから、開発チームが、定量的なコスト削減目標を持って開発に取り組むことは容易だ。

しかし、コスト削減にばかりフォーカスして、良いプロダクトを作れるのだろうか。コスト削減で得られる効果は、最大でも現状のコストをゼロにすることまでだ。売上とは違い、利益に還元できる額に上限がある。そもそも、サービスを維持し、ユーザー体験や売上を向上させるためには、コストも必要なのだ。

これはマネージャーを悩ませるテーマのひとつだ。「このままで良いのだろうか」と、頭の片隅で違和感を感じつつも、目まぐるしく回転し続ける開発とリリースのサイクルの切り盛りに追われ続ける。そうしているうちに、考えること自体を諦めてしまう。

さて、本記事のタイトルには「チューニング」というワードを用いた。それは本記事が、システムパフォーマンスチューニングのアプローチ方法を抽象として、エンジニアリングによるビジネスパフォーマンスチューニング方法を実装しようという試みだからだ。これによりプロダクト開発チームが、リリースした機能を売上に紐付け、それを指標にプロダクトを練り上げることを可能にしたい。そしてこれを、ユーザー体験の向上を追求することによって実現する。

実際のところ、本記事に書いた内容は、個々の方法論として目新しいものではない。しかし、それらに関する知見の多くは、スタートアップやマーケティング、ウェブ担当者向けに発信されたものが多いように感じる。その点で、エンジニアリング組織向けに整理して共有することに意味があるように考えた。私自身、実践できていないことも多くあるので、これを機に取り組んでいこうと思う。

システムパフォーマンスとビジネスパフォーマンス

Notes on Programming in C ロブ・パイクUNIX哲学 - Wikipedia

ルール1: プログラムがどこで時間を消費することになるか知ることはできない。ボトルネックは驚くべき箇所で起こるものである。したがって、どこがボトルネックなのかをはっきりさせるまでは、推測を行ったり、スピードハックをしてはならない。 ルール2: 計測すべし。計測するまでは速度のための調整をしてはならない。コードの一部が残りを圧倒しないのであれば、なおさらである。

システムエンジニアリングには、システムパフォーマンスへの配慮が常につきまとう。その対象はコードの断片から、ネットワークやシステム構成といったアーキテクチャに及ぶ範囲まで様々だ。

言うまでもなく、システム全体のパフォーマンスを決定づけるのは、その制約条件となっているボトルネック要素の性能だ。パフォーマンスチューニングとは、ボトルネック要素の性能を向上させる行為に他ならない。

パフォーマンス向上の必要性が発生すると、我々エンジニアはつい、直感的に問題だと思う箇所や、以前から気になっていた箇所に手を付けてしてしまう。しかしながら、そのチューニングはシステム全体のパフォーマンスにほとんど影響しない。ボトルネック以外の箇所をチューニングしても、ボトルネックが処理の流れをせき止めるからだ。これでは改善に費やした時間が無駄に終わる。まずやるべきことは、ボトルネックを見つけ出すことだ。

では、ボトルネックを解消したら終わりかというと、大抵の場合でそうはならない。ボトルネックを解消し、せき止められていた処理やパケットが勢いよく流れ出すと、その速さや流量についていけない箇所が現れ、新たなボトルネックとして流れをせき止める。そしてまた、ボトルネックをつぶすことに専念することになる。

こうして、次から次へと現れるボトルネックを順に解消していくことで、パフォーマンスを望むレベルにまで引き上げる。パフォーマンスチューニングは、この地道な努力の積み重ねだ。もし、パフォーマンス向上が限界に達したと判断した時は、アーキテクチャごと作り直すこともあるだろう。

ビジネスパフォーマンスチューニングも、原理は同じではないか。プロダクト上のどこでボトルネックが発生しているのかを見つけ出し、機能開発や機能改善を施してパフォーマンスを引き上げる。次のボトルネックを探す。この繰り返しが、ビジネスパフォーマンスを理想とするレベルにまで引き上げる。もし、ビジネスパフォーマンスがチューニングの限界をむかえたら、ビジネスモデルや戦略自体を変更する、と。

具体的にどうすればよいか。それを次の図にある流れに沿って考えていく。

チューニングの手順
チューニングの手順

フローの明確化

ビジネスに影響するユーザー行動フロー

システムパフォーマンス上のボトルネックは、通信経路も含めた処理フローのどこかで発生する。このフローを把握しておかなければ、正確なボトルネックを見つけ出すことはできない。

では、ビジネスにとっての「フロー」とは何だろうか。それは、ビジネスモデルや戦略によって導き出された KGI や KPI に対して、強い影響を与え得る「ユーザー行動フロー」だとは考えられないだろうか。

シンプルな E コマースビジネスを例に、ビジネスにとってのフローを考えてみる。

ビジネスモデルや戦略とユーザー行動フローの関係性

この架空の E コマースでは、専用のスマホアプリでサービスを提供している。こういった自社独自の E コマースサービスは、オンラインモールへの出店とは異なり、自力での集客が必要となる。つまり、アプリダウンロード数を伸ばすために、広告やキャンペーンといったマーケティング活動に大きなコストを割くことになる。

こうしてコストをかけて集めたユーザーだからこそ、サービスを長く、繰り返し利用して欲しい。短期間で利用をやめられるようでは、ユーザーひとり当たりから得られる全購入金額が小さくなり、集客施策にコストを回せなくなってしまう。こういった背景から、ビジネス上の主要な KPI として「CPA」と「LTV」をモニタしている。

CPA(cost per acquisition, 顧客獲得単価) は、顧客一人を獲得するために費やしたマーケティングや営業のコスト(販管費)を言う。

LTV(lifetime value, 顧客生涯価値)は、一人のユーザーが、サービスを利用開始した日から利用しなくなるまでの間に支払ったサービス利用料などの総合計を言う。この LTV が小さいと、集客施策などに向けて CPA を割くことができなくなる。

なお、ここで言う「顧客」とは、商品を購入したユーザーを指している。

LTV を大きくするためには、ユーザーひとり当たりの購入単価、購入回数、利用期間というメトリクスを向上させることになる。今回の E コマースの戦略は、複数回の購入経験を持つ「リピーター」を増やすことで LTV の向上につなげることだ。開発チームのミッションは、それを、ソフトウェアプロダクトのチューニング、つまりは機能開発や機能改善を通して実現すること、となる。

これらのことから、アプリをダウンロードしたユーザーに期待する行動として導き出されたフローは次の通り。

  1. 欲しい商品を見つけ出す
  2. カートにアイテムを追加する
  3. はじめて購入する
  4. リピーターになる

このフローでは、4 の行動によって、ユーザーがリピーターになることを「最終コンバージョン」と言う。また、そこに至るまでの 1 から 3 までのチェックポイント的なユーザー行動を「マイクロコンバージョン」と呼ぶ。

ユーザー行動フローの例
ユーザー行動フローの例

ビジネスパフォーマンスチューニングでは、いくつかのマイクロコンバージョンを経由して最終コンバージョンにつながるこのような経路をフローとし、ユーザーをより効率的に最終コンバージョンさせるために、機能開発や機能改善を通してチューニングする。

ここで、フローの設計は UI に引っ張られすぎないよう注意する。そうしなければ、UI を変更する度にフローを変更することになる。それでは長期的な改善ができない。マイクロコンバージョンは、この E コマースでの例のように、UI より抽象度の高いユーザーシナリオレベルに粒度をあわせるのが良いだろう。

なお、ここで示した E コマースの例では、集客をマーケティング活動に頼る前提としたが、ユーザーが別のユーザーを呼び込むようなバイラル型の機能をサービスが有しているなら、集客効率をプロダクトで改善することも可能だ。このケースでは、「別のユーザーを呼び込む」というユーザー行動を、最終コンバージョンに位置付けることになるだろう。

ボトルネック探索

ユーザー行動フローのプロセスとメトリクス

ボトルネックを見つけるには二段階の手順を踏む。まず、フロー内のどのプロセスに問題があるかを特定する。次にプロセス内のどのポイントがユーザーの流れをせき止めているかを見つけ出す。

プロセス」とは、フロー内の、あるコンバージョンポイントを通過した直後から、次のコンバージョンポイントを通過するまでの経路を指す。「ステージ」や、「ステップ」とも呼ばれる。

ユーザー行動フローのプロセス
ユーザー行動フローのプロセス

では、どのようにして「問題のあるプロセス」を特定するのだろうか。ここで、各プロセスの状態を可視化する主要なメトリクスとして 、「流量」「滞留数」「移行率」の三つが使える。

流量」とは、そのプロセスに到達したユーザーの総数を表す。このメトリクスには、次プロセス以降に遷移したユーザーの数(=次プロセスの流量)も含まれる。従って、上流のプロセスほど流量が大きい。

滞留数」は、プロセスに留まっているユーザーの人数を表す。対象プロセスの流量から、次プロセス以降に遷移したユーザーの人数(=次プロセスの流量)を引いた値に等しい。「滞留期間」をメトリクスとして利用することもある。

移行率」は、対象プロセスから次プロセス以降に遷移したユーザーの人数(=次プロセスの流量)を、対象プロセスの流量で割った結果を、パーセントで表現した値となる。

(※下図内のメトリクス値は適当に記載したものであり、実在の E コマースサービスを参考にした訳でもなく、特に意味はない)

流量・滞留数・移行率
流量・滞留数・移行率

問題のあるプロセスはどこか

問題のあるプロセスを特定する統一的な方法を明言するのは難しい。以下は参考までに。

移行率が最も低いプロセスこそ、優先的に改善すべきプロセスに見えてしまうが、そうとは限らない。プロセス流量が少なければ、移行率が改善したところで得られる効果は薄く、おすすめできない。

そこで注目すべきなのは、プロセスごとの滞留数だろう。他のプロセスと比較して滞留数が比較的大きいプロセスがあるなら、そのプロセス内にボトルネックがある可能性が高い。滞留数が多いプロセスは、流量が多く、かつ移行率が低い。チューニングによる移行率改善によって、大きな効果を見込める。

極端に滞留数の多いプロセスは、複数のプロセスに分割するという方法もある。例えば、「カートに入れる」というマイクロコンバージョンと、「購入する」というマイクロコンバージョンの間に、「購入フォームにアクセスする」と言うマイクロコンバージョンを入れても良い。そうすることで、問題を切り分けやすくなる。ただし先述したように、あまり細分化しすぎると、フローが UI に依存するようになり、UI を変更する度にフローを再構築することになってしまう。細分化するなら、その点の見極めが必要になる。

どのプロセスの滞留数にも大差がないなら、最終コンバージョンを含むプロセスに目星をつける。どのプロセスをチューニングしても効果に大きな差がないなら、最終コンバージョンに至るプロセスを改善する方が結果に直結するからだ。しかし、流量が不十分ならチューニング効果は薄い。それならば、流量の最も大きい最上流プロセスから順にチューニングし、下流プロセスの流量を増やしていくのが良いだろう。

もし、最上流プロセスの流量(=フロー内の全ユーザー数)が少ないなら、そもそも集客力に問題がある。この状態で、開発チームがフローのチューニングに力を注いでも、結果にはつながらない。むしろ、無駄な機能(「feature debt, 機能負債」)を作り込んでしまうかもしれない。十分な流量が得られるまで待つか、集客にフォーカスした開発を進めるなどした方が良いだろう。

このようにして問題のプロセスを特定できたら、プロセス内を精査してボトルネックとなっている箇所を見つけ出す。

ユーザー行動フローの可視化

ここまででわかるように、フローの状態を常にモニタできるよう、可視化しておくと良い。その方法としては、マーケティングでよく使われる「ファネル(funnel)」が適している。そのために必要となるログを、システムにあらかじめ仕込んでおくことも忘れてはいけない。

ファネル
ファネル

ただし、フローの可視化にはひとつ問題がある。

E コマースの例には、「はじめて購入する」というマイクロコンバージョンがあった。このマイクロコンバージョンを含むプロセス 3 の移行率には、一年前にアプリをダウンロードしたユーザーと、今月ダウンロードしたユーザーが混在している。同一プロセスに滞留しているユーザーであったとしても、一年前から滞留しているユーザーに、アプリを最近使い始めたユーザーと同等のモチベーションを期待することはできない。

このように、全数でのフローの分析はノイズが多くなり、チューニングの効果を読み取りにくくする。ここは、ユーザーをアプリダウンロード時期でグループ分けした上でフローを分析するのが良さそうだ。このように、ユーザーを任意のグループに分けて分析する手法を、「コホート分析」と言う。

可視化に向けては、こういった点も考慮した上でログ設計を行う。

チューニング

イデアバックログ

ボトルネックを特定できたら、チューニング方法を考える。開発チームによるチューニングとは、ボトルネックを解消するための機能追加や機能改善のことだ。

どのようにチューニングすべきか、そのアイデアを得るためには、更なる詳細な定量情報や、ユーザからのフィードバックといった定性情報を収集することになるだろう。それをもとに、より効果的なチューニング方法をユーザ視点で考え抜き、ユーザーストーリーエピックとしてバックログに追加する。

E コマースを例に考えてみよう。「はじめて購入する」をマイクロコンバージョンに持つプロセス 3 を問題のプロセスとし、さらに詳細に調査した結果、次プロセスに移行したユーザーの 80% は、本プロセスを開始してから移行するまでの期間が二週間以内であることがわかった。前プロセスであるプロセス 2 によって、欲しい商品をカートに追加するところまでは終わっている。そこから二週間経過しても購入に至らないユーザーのほとんどは、カートを放置したままアプリの利用が止まり、いつまでもプロセスに滞留したままになっているようだった。

更に調査を進めると、こういったユーザーの多くは、購入判断を後回しにしているうちに毎日が忙しくて時間が過ぎ、商品に対する興味が薄れ、そのうち忘れてしまうというのが実態だった。そこで、このプロセスで二週間が経過しても購入に至らないユーザーに対し、自動でリマインドメッセージを出すというアイデアを採用することにした。カートに商品が入ったままとなっていることをユーザーに思い出してもらい、商品購入を後押しする、というものだ。

バックログのアイテムは仮説

注意したいのは、バックログに追加したこういったアイデアは「仮説であり、それを機能化したからといって、必ずしもチューニングの効果を得られるわけではないということだ。

工数と時間をかけて完全な機能を作り上げても、無駄になるかもしれない。だから、バックログのアイデアを実装する時は、そのスコープを必要最小限に留めておく。小さくリリースして仮説検証を行う。これを何度も繰り返しながら、効率性の高いフローを作り上げていく。

ベンチマークテスト

本番環境が仮説検証の場

ビジネスパフォーマンスチューニングにおいてのベンチマークテストとは、仮説として立てたユーザーストーリーを「検証」することだ。そのためには、ユーザーストーリーに基づいて開発した機能を、本番環境にリリースして試してみるしかないだろう。

つまり、「リリース」とは検証の開始を意味する。この検証を経て、仮説が正解だと判断するに至るか、更なる改良が必要になるか、あるいは失敗だと判断してアプリケーションをロールバックするかなどが決まる。

ここで、「リリース」という行為の位置づけが、開発チームの中で変わることとなる。リリースはゴールではなくなり、マイルストンのひとつになるのだ。

リーン開発なら、カンバンのステータスに「検証中」を加えても良いだろう。スクラム開発なら、検証結果を得ることを Done の定義に含めても良い。

スプリットテストによる仮説検証

本番環境での検証時に困ることがひとつある。それは、検証時の計測結果から、対象機能以外の影響を除くことだ。

計測対象となる指標を、リリース前とリリース後で比較しようとしても、日々実施される様々なマーケティングキャンペーンが実績値に大きく影響を及ぼし、正確な比較ができないことも多い。できればこういった影響を排除するか、影響度合いを揃えたい。

その解決策としては、「スプリットテスト」が適している。この手法なら、複数バージョンのアプリケーションを用いて同じ期間にテストを実施するため、機能以外からの指標への影響を概ね揃えることができる。

スプリットテストでは、ユーザーを複数のグループに分け、グループごとに異なるバージョンのアプリケーションを利用することを通し、どのバージョンが最も良い結果を得られるかを計測する。

E コマースの例で言えば、リマインドを出す機能を装備した新しいアプリを利用するユーザーグループ A と、従来のままのアプリを利用するユーザーグループ B に分けて移行率を計測する。ここで、A が利用するバージョンを「バリエーション」、B が利用するバージョンを「コントロール」と呼ぶ。このテスト手法は、A/B テストとも呼ばれる。

スプリットテスト
スプリットテスト

テスト結果の分析

有意差検定による評価

スプリットテストによってコントロールとバリエーションの実績値に差が出たとしても、それをもって結論を導くことはできない。その差は偶然によるものかもしれない。ではどの程度の実績差が出れば、偶然とは言えなくなるのだろうか。どの程度のテストデータが集まれば十分なのだろうか。

スプリットテストの結果を評価する方法としては、「統計的有意差検定」がよく使われる。その検定手法はいくつかあり、どの手法を使えばよいかは、指標の特性や、得られるテストデータのサイズによって変わってくる(参考:「A/Bテストに用いられれる統計的検定手法(ロジック)のまとめ&比較 | RCO Ad-Tech Lab Blog」)。ウェブ関連のコンテキストでよく使われていそうなものは、カイ二乗検定だろう。

検定では、「帰無仮説」の確率が低いと言えれば、「対立仮説」が立証されたと見なせる。ここでは、「コントロールとバリエーションそれぞれの成果には差がない」が帰無仮説であり、その反証となる「コントロールとバリエーションそれぞれの成果には差がある」が対立仮説だ。一般的には、帰無仮説の確率が 5% 以下になれば「確率が低い」と判断する。これが「有意差」であり、この 5% という数値を「有意水準」と呼ぶ。

これらを踏まえ、スプリットテストを実施するにあたっては、まず有意水準を決める。その上で、検証期間を決める。有意水準の設定を低くすればするほど、有意だと結論づけるために必要となる実績値の差もテストデータの数も大きくなる。その分、検証期間も長く必要となるからだ。

スプリットテストによって、コントロールとバリエーションの間に有意差が出たら、検証を終了する。またもし、いつまで経っても有意な差が出ないまま検証期間が過ぎても、そこで検証を終了する。

ネクストアクションの決定

検証結果として、バリエーション側の成果が大きい状態で有意差が出れば、仮説が正しかったと結論づけられる。そうなれば、バリエーションを全ユーザーに適用して、次のボトルネック探索を開始する。

一方、検証期間内に十分に有意な差が出なかった場合や、コントロール側の実績値が大きい場合は、その原因としていくつかの候補が考えられる。

  1. 仮説としてのユーザーストーリーは正しいが、機能への落とし込み方が良くなかった
  2. ボトルネック箇所は正しいが、仮説として立てたユーザーストーリーが間違っていた
  3. ボトルネック箇所を見誤った
  4. 現在の戦略におけるビジネスパフォーマンスが限界に達した

もし、原因が 4 であると判断したなら、戦略やビジネスモデルを見直すことになる。おそらく、ビジネスパフォーマンスの限界は開発チームより先にビジネスチームで気付く。事業戦略、マーケティング戦略、プロダクト戦略が変わることになるだろう。開発チームは、それに合わせユーザー行動フローを作り直す。リーン・スタートアップ方式ではこれを、「ピボット」と呼ぶ。

最後に

本記事では、架空の E コマースビジネスを例に、コンシューマー向けサービスを想定して話を進めてきた。

コンシューマー向け(toC)ではなく、ビジネス向け(toB)サービスを扱っているケースでは、ビジネスパフォーマンスを大きく左右するのは、機能開発や機能改善より営業活動であるように感じるかもしれない。ビジネス向けサービスでは、業務でプロダクトを利用するユーザー自体の意見が、必ずしも利用契約の締結に繋がるわけではない。多くの場合、決裁者はユーザーではなくその上司であり、意思決定プロセスが、コンシューマー向けサービスに比べて複雑だ。そこに切り込んで、契約を獲得するのが営業チームであり、機能を強化してユーザー体験を上げても、契約には繋がりにくい。だから開発チームにできることは少ないように感じてしまう。

しかし、実際にはそうでもない。営業の武器になるような機能開発もあるだろうし、契約後に継続率を高めて LTV を向上させるような機能開発もある。重要なのは、プロダクト開発が、ビジネスモデルや戦略と連動していることだ。

この記事は「リーン・スタートアップ」の方法論を下地に、それを既存プロダクトの機能開発業務に応用したものだ。リーン・スタートアップと言えば、「MVP」や「BuildMesureLearn」ばかりがフィーチャーされがちだが、「成長のエンジン」や「革新会計」という考え方を押さえておかなければ、期待する結果は得られないだろう。本記事では、ビジネスモデルからユーザー行動フローを定義し、それを拠り所としてチューニングを進めることで、それらの考え方を中心部に取り込んだ。

リーン・スタートアップも、我々エンジニアにも馴染みの深い「リーン開発」や「アジャイル開発」と同様に、「トヨタ生産方式」を一般化した「リーン生産方式」を背景に持つ。その本質は、「無駄をなくし、価値に集中する」ことだろう。

エンジニアリングスキルで捉えるチームマネジメント

チームのマネージャーが、自らの責務をジョブディスクリプションとして明文化することは難しい。職務内容や権限を、断片的にしか書けないかもしれない。もしそうなるなら、実務も断片的になっている可能性がある。

チームマネジメント(組織マネジメント)という活動は、個々のマネージャーの経験や関心によって、断片的になりやすいように感じている。断片的とは、マネジメント活動が、責務の一部の領域に偏ってしまっていたり、問題を検知してはじめてその領域がマネジメント範囲であることを知る、といった様子を指している。

このような状態になる背景は、マネージャーにとって、マネジメントが、日々の実務を通して蓄積された経験に基づく活動になっているからではないか。マネージャーは孤独だ。ひとりでその責務を担う。エンジニアとは違い、チームで協働するわけではない。だから、形式知として言語化されず、個人の経験として暗黙知にとどまる。その内容は個別具体であり、モデル化(抽象化)されず、全体像を構造として捉えきれていない。これでは活動が断片的にならざるを得ない。

Engineering Management Triangle というものがある。これが作られた背景のひとつも、きっと似た問題意識からだろう。本ブログも、エンジニアリングとそのマネジメントを対象としているが、少し違ったアプローチでマネジメントを体系化してみようと思う。それは、エンジニアスキルを活用してチームマネジメントを捉えることだ。

エンジニアリング経験を持つマネージャーは多いと思う。そこで得たスキルや知識は、チームマネジメントをひも解くために非常に役立つ。「エンジニアリングとシステム」という関係は、「マネジメントとチーム」という関係によく似ているからだ。

エンジニアリングとマネジメント
エンジニアリングとマネジメント

本ブログエントリーでは、チームをシステムとして捉え、そのアーキテクチャ・構造を辿りつつ、その中にマネジメント活動をプロットしていく。これが、多岐にわたるチームマネジメント活動を、マネージャーが思考の中で整理するヒントになれば、と願っている。

なお、ここではエンジニアリングチームのマネジメント(組織マネジメント)のみを扱い、プロジェクトマネジメントやプロダクトマネジメントは含めない。特に、企業組織のツリー構造上で、リーフとなるようなチームを想定している。

サービスの枠組み

共通目的が形成するサービス

ソフトウェアシステムは、何らかの背景や目的があって生み出される。それは企業課題に対するソリューションの場合もあれば、日頃のちょっとした不便を解消するためのツールの場合もある。

組織も、目的があるから存在する。経営学者のチェスター・バーナード(Chester I. Barnard)は、組織を「協働のシステム(cooperative system)」と呼んだ。そして、集団が組織として成立する条件のひとつに、「共通目的(common purpose)」を挙げている。これは組織の存在意義のことであり、ミッションビジョンのことだと言える。

An organization comes into being when (1) there are persons able to communicate with each other (2) who are willing to contribute action (3) to accomplish a common purpose. The elements of an organization are therefore (1) communication; (2) willingness to serve; and (3) common purpose. These elements are necessary and sufficient conditions initially, and they are found in all such organizations. - The Functions of the Executive

(組織とは、(1)互いにコミュニケーションできる人々がおり、(2)活動に貢献する意思がそれらの人々にあり、(3)共通目的を達成するためにその活動を行う時に、成立する。組織の要素とはすなわち、(1)コミュニケーション、(2)協働意思、(3)共通目的だ。これらの要素は組織成立にあたり必要十分条件であり、そのような組織すべてに見られる。 - 『経営の役割』)

チームも組織であり、ミッション・ビジョンを共有(common purpose)し、その遂行・実現に向けて互いに意思疎通(communication)をはかり、協働(willingness to serve)する。この活動を、企業では事業(ビジネス)業務と言う。以降は、これらを汎化してサービスと総称する。つまりチームとは、サービスを提供するシステムなのだ。

チームとサービス(事業・業務)
チームとサービス(事業・業務)

このように、チームがシステムとして機能し、最適なサービスを提供するためには、そこに参加する人々が目的(Why)をしっかりと見据えていなければならない。こういったコンテキストでよく引用される、ドラッガーの石切り工の話がある。

三人の石切り工の昔話がある。彼らは何をしているのかと聞かれたとき、第一の男は、「これで暮らしを立てているのさ」と答えた。第二の男は、つちで打つ手を休めず、「国中でいちばん上手な石切りの仕事をしているのさ」と答えた。第三の男は、その目を輝かせ夢見心地で空を見あげながら「大寺院をつくっているのさ」と答えた。

チームの目的を理解しているのは第三の男で、第一の男は個人の目的、第二の男は手段について話している。ここでのマネージャーの活動は、第三の男として、チーム全体に目的を浸透させ、皆に同じ方向を見させることだ。そうすれば、チームは状況に応じた正しい判断を下せるようになる。

ジョナサン・ラスムッソン(Jonathan Rasmusson)は著書『アジャイルサムライ−達人開発者への道−』で、これを「みんなをバスに乗せる(原著では "How to get everyone on the bus")」と表現し、その方法としてインセプションデッキを紹介している。特に、「我われはなぜここにいるのか?」「エレベーターピッチを作る」「パッケージデザインを作る」「やらないことリストを作る」「ご近所さんを探せ」は、サービスの背景や目的を明らかにするために役立つ。チームで集まってインセプションデッキを試してみるのも良さそうだ。

サービスのコンテキスト境界と機能

ドメイン駆動設計(Domain-driven design, DDD)では、システムが扱うドメイン領域を、「境界付けられたコンテキスト(bounded context)」として、特定のモデルを共有する範囲で分割する。理想的には、分割されたひとつのコンテキストごとに、ひとつのアプリケーションを対応付ける。

企業でのコンテキスト境界は、組織構造として反映されている。その構成要素たる部門・部署が、チームとして特定の事業や業務、すなわちサービスを担う。これを、文書として記述したものが業務分掌だ。業務分掌の中では、それぞれのサービス(チーム)の責務として配分された機能が規程されている。

一般的に、組織構造はツリーを形成している。上位の包括的なサービスを実現するために、下位の部分的なサービスが存在するという構造を持つ。例えば、E コマース事業(上位サービス)には、仕入れ、カタログ製作、マーケティング、注文管理、フルフィルメント、カスタマーサービスといった業務(下位サービス)が必要となる。これらが互いに連携することで、事業として成立する。だから、サービスごとの業務分掌は、関係するサービス間で漏れや重複が出ないよう、整合性を取らなければならない。

このことから、自らが担当するサービスの業務分掌を、マネージャーが単独で定義するケースはあまりないだろう。最上位にあたるサービスの業務分掌を、経営者自身や経営企画部門・事業企画部門が定義し、そこからは、上位のサービスを受け持つマネージャーが、直下の組織分割や業務分掌定義を行う、といった運用が多いのではないだろうか。下位のサービスを受け持つマネージャーが、この活動を支援することもあるだろう。

組織構造とサービスの関係
組織構造とサービスの関係

この構造によって、下位レイヤーサービスの実体(実装)は、上位レイヤーが要求するサービスの枠組み、すなわち業務分掌に依存することになる。上位のサービスが、下位のサービスの実装に影響を受けないようデザインされているということだ。これは、業務分掌を抽象(abstraction)とした依存性逆転の原則(dependency inversion principle, DIPだとみなせる。

機能を表現する振る舞いの抽象定義

ソフトウェアが持つ機能は、そこに含まれる振る舞い(behavior)の集合によって表現される。そして、外部との境界面の振る舞いをインタフェース(interface)として抽象定義することで、機能のデザインから、実装を分離可能にする。オブジェクト指向プログラミングなら、抽象型(Java 言語なら interface)として存在する。サービスレベル(REST API や RPC)では、OpenAPI Specification(OAS)Protocol Buffers といった IDL(Interface Description Language, Interface Definition Language)などで定義できる。

業務分掌も抽象ではあるが、その抽象度が高すぎるため、インタフェースとしては使えない。しかし、サービス外部との境界面となるインタフェースがなければ、サービスの実装が分離できなくなる。これでは実装の変更時に、その影響がサービス外部に伝搬してしまう。だからマネージャーは、業務分掌に規程された機能ごとに、外部接点となる振る舞いの集合をインタフェース化して抽象定義する。サービスインタフェースの仕様は、ドキュメントなどにまとめ、サービス利用者に提供する。

サービスの実体

プロセスはサービスのロジック

「プロセスを踏む」という表現がある。目的とする成果や状態に到達するために、あらかじめ定義された手順を進める、そんな意味合いだろうか。プロセスは、フローと言い換えることもできそうだ。すると、プロセスが、UMLアクティビティ図のようなものだとわかる。つまり、ロジックだ。

ビジネスプロセス業務プロセスは、サービス(事業・業務)に関するロジックを定義している。「ビジネスプロセス」や「業務プロセス」より「ビジネスロジック」や「業務ロジック」の方が、エンジニアにはなじみ深い。サービスは、複数のこういったプロセスで成り立っている。例えばソフトウェア開発業務なら、開発プロセスが主たるプロセスとなる。このような、プロセスの開発・保守は、マネージャーにとって重要な仕事のひとつだ。

サービスに関するプロセスがロジック
サービスに関するプロセスがロジック

プロセスは、一度作り上げたらそれで終わりではない。ビジネス要求の変化に応じ、プロセスに変更を加えることもある。ここで安易なロジックを組んでしまうと、プロセスの保守性拡張性を落とし、新たな変更を加えにくくする。これは技術的負債のようなものだ。加えて、長期間、運用してきたプロセスは、一部が形骸化していることもある。これらを考慮すると、定期的にプロセスをリファクタリングすることも有効だろう。

サービス利用者との接点になるようなアクティビティは、あらかじめサービスインタフェースとして規定した仕様に従い、実装する。もし、プロセスの変更によって、サービスインタフェースの仕様を変更することになった場合は、新しい仕様をサービス利用者にアナウンスすることを忘れない。新旧両方のバージョンをしばらく並行稼働させるケースもあるだろう。

日々発生する例外は、例外処理フローとして新たなロジックを組む。こうしてプロセスを洗練させ、継続的にサービス品質を向上させていく。

プロセスフレームワークの活用

ソフトウェアフレームワークは、ソフトウェアを制御する汎用的な機構、あるいは型だ。「汎用的な機構」が既にコードとして書かれた状態で配布されるため、フレームワークの利用者は、個別具体的なロジックを組むだけで、品質の高いソフトウェアを短時間で作り上げることができる。

プロセスにも、プロセスフレームワークプロセスモデルというものがある。開発プロセスなら、スクラムウォーターフォールがそうだ。これ自体ではプロセスとして機能しないが、このフレームワークに沿って、必要なロジックを組み込むことで、品質の高いプロセスを作り上げることができる。

マネージャーは、こういったプロセスフレームワークをぜひとも活用すべきだろう。ソフトウェア開発と同じで、汎用的なものを自社開発して利用することは、特別な理由がない限り避けたい。限られた時間を、汎用的なものより、個別具体的なロジックの開発にあてたい。それに、様々なプロセスで利用され、鍛え上げられたフレームワークは柔軟性も高い。プロセスを運用していく中で、後から加えていく変更にも柔軟に対応できる。『スクラムガイド』を見るとわかるように、フレームワーク自体が日々、メンテナンスされ、進化し続けているものもある。

フレームワークの仕様や思想を深く理解しなければ使いこなせないという点は、ソフトウェアフレームワークもプロセスフレームワークも同じだ。マネージャーは、チームアーキテクトとして、プロセスフレームワークの選定や、その仕様・思想の理解を進め、メンバーにその内容を浸透させることを怠らない。

PMBOK はプロセスフレームワークではないが、「5 個のプロセス群 × 10 個の知識エリア」のマトリクスでプロセスが整理されている。各プロセスにはインプット/アウトプットが定義されており、プロセス設計のガイドとして活用しやすい。

役割単位のコンポーネント

ソフトウェアコンポーネントは、ソフトウェアを関心の分離(separation of concerns、SoC)によって、任意の粒度に分割したものだ。関心とは着眼点のようなもの。これが、コンポーネント固有の責務(responsibility)を決定づけ、コンポーネントが提供しなければならない振る舞いを明らかにする。

アクティビティ図では、アクティビティパーティションを使い、アクティビティをグルーピングできる。このグルーピングという行為は、関心の分離だ。そこに紐づく責務としての振る舞いを具体化したものがアクティビティだ。そして、ビジネスプロセス・業務プロセスでは、チームメンバーが担う役割を主たる関心事として、その範囲をパーティションで表現することが多い(パーティションは、サービス利用者や情報システム等としても使う)。言い換えれば役割とは、プロセス開発を通じ、サービスを関心で分割したサービスコンポーネントなのだ。

サービスを役割で分割
サービスを役割で分割

スクラムでは役割を、プロダクトオーナー、開発チーム(メンバー)、スクラムマスターの 3 つに分離している。その中で、スクラムマスターの責務は、次のように定義されている

スクラムマスターは、スクラムガイドで定義されたスクラムの促進と支援に責任を持つ。スクラムマスターは、スクラムの理論・プラクティス・ルール・価値基準を全員に理解してもらえるように支援することで、その責任を果たす。

スクラムガイドにはもう少し詳細な責務定義がなされている。プロセス開発では、このような役割毎の責務を踏まえ、その具体であるアクティビティを定義する。

役割の凝集度と再利用性

ところで責務は、「実行責務」と「情報把握責務」に分類できる。実行責務は、「振る舞いに対する責務」とも呼ばれ、その名の通り、特定の振る舞いを提供しなければならない義務を指す。情報把握責務は、「知識に対する責務」とも呼ばれ、属性や、それを利用して導出できるような情報を把握しておかねばならない義務のことだ。関心の分離で抽出されたソフトウェアコンポーネントは、こうした責務にもとづく複数の振る舞いや知識で構成される。そして、この構成要素間の関係性の強さを、凝集度(cohesion)強度(strength)と呼び、高いほど良いとされている。

UML の開発に貢献したソフトウェア技術者であるグラディ・ブーチ(Grady Booch)は、凝集度について次のように述べている。ここで「機能的凝集(functional cohesion)」とは、凝集度のレベルを 7 段階で分類した、最善のレベルのことだ。

high functional cohesion as existing when the elements of a component (such as a class) "all work together to provide some well-bounded behavior"

(高い機能的凝集は、コンポーネント(クラスなど)内の要素が「適切に境界付けられた何らかの振る舞いを提供するために全てが協働する」ときに存在する)

コンポーネントの凝集度が高いと、他のコンポーネントとの結合度(coupling)が低くなると言われている。結合度が低くなれば、コンポーネント単体での再利用性(reusability)が高まる。凝集度が高いことが良いとされる理由のひとつは、ここにある。

サービスコンポーネントとしての役割にとって、再利用性とは何だろうか。それは、定義したそのままの形で、役割を他の人に交代したり、冗長化したりできることだ。もちろん、役割を果たすために必要なスキルや知識を保有していることが前提となる。

もし、役割を交代する時に、役割定義の一部を変更しなければならなかったり、責務の一部だけを引き渡すことになったり、あるいは他の役割とセットにしなければならないようなら、役割の凝集度が低いのだ。役割定義をそのままで再利用できていない。

だから、マネージャーは、再利用性に着目しながら役割の凝集度を上げていく。そこに含まれる実行責務として、プロセス内で必要十分かつ最小限のアクティビティを保有させる。情報把握責務としては、必要な情報が、必要なタイミングで揃うように、プロセス内での情報の流れにも注意しておきたい。

情報把握責務という点では、データや情報の保存場所も整備すべき対象となる。メンバーが、データや情報を自身のローカル環境にため込んでしまうと、役割の冗長化がしづらい上に、情報をロストする危険性もある。一時的なデータや情報ならそれでも構わないが、永続化が必要なデータや情報は、メンバー間で共有できる場所に保存する。ソフトウェア開発業務なら、Git のローカルリポジトリにコミットしたソースコードを、リモートリポジトリに push する行為などが、これにあたる。ステートレス(stateless)な設計を心掛けよう。

凝集度を最適に設計することは難しい。マネージャーはこのようにして、日々、プロセスを見直しながら役割の定義を洗練させていく。

非同期メッセージング

メッセージキューを介した非同期メッセージングは、メッセージを生産するプロデューサーと、それを処理するコンシューマーを分離する。プロデューサーは、コンシューマーが過負荷な状態であっても、それを気にすることなくメッセージをキューに追加できる。コンシューマーは、プロデューサーからのメッセージ投入が一時的にスパイクしても、その影響を直接的に受けることはない。例えコンシューマーがダウンしても、メッセージは失われにくく、キューに残ったメッセージで処理を再開できる。プロデューサー、コンシューマーともに、スケールさせやすい。

チームが提供するサービスには日々、外部からの依頼が次々と届く。受託開発業務の見積プロセスなら、営業から見積依頼が届けられる。これを、チームメンバーが口頭で受け、そのまま処理するようなプロセスになっているなら問題がある。この方式はマネージャーにとって、依頼のトラフィック量やチーム内での負荷の偏りが見えにくく、マネジメント不能な状態に陥りやすい。口頭でのやり取りが行われるシーンをイメージしてみよう。どんな問題が起きるのだろうか。

  • プロデューサーからの依頼が一時的にスパイクすると、コンシューマー役となるチームメンバーに過負荷を引き起こす。
  • チーム内に、同じ役割を持つコンシューマー役を複数配置してスケールさせていても、依頼者となるプロデューサーは、依頼先をお気に入りのコンシューマーに偏らせる傾向がある。そして、そういう対象になるコンシューマーは、他のプロデューサーからも人気者だ。だから、一部のメンバーに負荷が偏りやすくなる。
  • コンシューマー役のメンバーが、依頼を握ったまま体調不良で数日休んでしまうと、マネージャーにもチームにも、その状況がわからなくなる。
  • プロデューサーからの任意のタイミングでの口頭依頼は、コンシューマー役のコンテキストスイッチを引き起こす。コンテキストスイッチは、仕事のオーバーヘッドになり、業務効率を低下させる。

このような状況を生み出さないよう、マネージャーは、プロセス設計を工夫すべきだ。プロセスを開始させるプロデューサーが、コンシューマー役と直接コミュニケーションを取らず、メッセージキューを介すよう設計する。もちろん、全てのプロセスに、メッセージキューを配置できるわけではない。業務効率とのバランスで決める。

メッセージキューとして一番シンプルなものは、メーリングリストだろう。凝ったものなら、入力フォームからメッセージを登録する方法もある。ITS(Issue Tracking System)といったツールも使える。この場合、窓口役となるメンバーを置いて、依頼者からのメッセージをイシューやチケットに登録しても構わない。

一方、メッセージを受け取る方法は、コンシューマーによるポーリングと、メッセージキューの管理者からコンシューマーへの通知という、2 つの方法が考えられる。前者は分散型であり、後者は中央集権型と言える。どちらが好ましいか一概には言えない。分散型の方が自律的であるが、コンシューマー役が複数人で冗長化されていると、考慮すべき点が出てくる。キュー内のメッセージは、適切な優先順序で取り出し、重複なく、負荷の偏りがないよう、担当するコンシューマーを決定しなければならない。分散型ではこれを決定する判断基準やルールを、冗長化された複数のメンバーで共有し、協調して実行することになる。

メッセージのフォーマットも定義しておきたい。プロデューサーごとにばらつきがあると、受け取る側のコンシューマー役が、メッセージを解釈するコストを支払うことになる。不足する情報を確認するために余分なコミュニケーションが発生することもあるだろう。これについては先述した通り、サービスインタフェースの中で定義しておく。

ここではサービス外部からの依頼にフォーカスをあてたが、実際は、担当者をまたぐアクティビティ間のメッセージング(コミュニケーション)はすべて、同じことが言える。例えばコードのレビュー依頼であれば、Github や Gitlab を通してプルリクエスト(マージリクエスト)を送り、Github, Gitlab 上でレビューを行うことで、キューとインタフェースを実現すると良いだろう。

チームのアーキテクチャアサイ

役割ベースのマイクロサービスアーキテクチャとしてデザインされたチーム

コンテナベースアプリケーションは、アプリケーションも含めたファイルシステムコンテナイメージとしてパッケージングし、それをホスト上で、コンテナに格納して実行する。コンテナは、コンテナイメージをプリミティブとするインスタンスであり、容易にスケールアウトできる。

メンバーを役割にアサインすることは、これに似ている。アサインにおけるプリミティブとは、役割の定義と、それを担うために必要なスキルや知識をパッケージにした単位だ。メンバーは、このパッケージを単位として役割を担う。同一の役割を複数のメンバーが担うこともあれば、複数の役割を単一のメンバーが担うこともある。

これを、コンテナベースアプリケーションとマッピングするなら、役割はアプリケーションであり、役割に前提となるスキルや知識を合わせたパッケージがコンテナイメージ、メンバーがホスト、といったところか。アサインとは、デプロイのようなものだ。

デプロイとアサイン
デプロイとアサイ

このようにとらえると、チームというものがシステムとして機能しているとよくわかる。そして、役割とはサービスを関心で分離したコンポーネント、つまりマイクロサービスだと考えると、チームは、役割ベースのマイクロサービスアーキテクチャとしてデザインされたシステムに見えてくる。

役割ベースのマイクロサービスアーキテクチャ
役割ベースのマイクロサービスアーキテクチャ

役割のポータビリティ

コンテナイメージの存在は、アプリケーションにポータビリティ(portability)をもたらした。コンテナイメージには、アプリケーションを実行するために必要なライブラリやファイルが全て格納されている。ポータビリティに注意してアプリケーションを設計・実装すれば、コンテナイメージは基本的にどのホストでもコンテナ内での実行が可能だ。ホストに合わせてコンテナイメージをビルドし直したりはしない。これが、システムのスケールや移行を容易にしている。

役割の冗長化や交代のためにも、ポータビリティは必要となる。役割の凝集度を上げることで再利用性は上がるが、それだけではポータビリティとして不十分だ。役割を担うには、前提となるスキルや知識が必要となる。だから、役割を担う上でどんなスキルや知識を利用するかを明らかにし、役割定義と共にそれらをパッケージングする。そこには、スキル獲得のための教育コンテンツや、知識ベースの整備も伴うだろう。役割にアサインされることになるメンバーは、それらを活用してスキルや知識をインストールし、役割定義を理解した上で、稼働を始める。稼働までのリードタイムは、こういったトレーニングコストをどれだけ小さくできるかにかかっている。

コンテナイメージはレイヤー化されている。あらたなコンテナイメージをコンテナとして稼働する時、共通のレイヤを重複してストレージに格納する必要がない。こうすることで、軽量化を実現している。

役割をアサインされたメンバーが稼働を始めるまでのリードタイムを縮める方法も、ここにヒントがある。役割に必要とされるスキルや知識をメンバーが既に保有しているなら、トレーニングコストを最小化できるからだ。メンバーを新たな役割にアサインする時に、以前に経験したアサインパッケージに含まれるスキルや知識が役立つこともある。ひとりのメンバーに複数の役割を兼任させるケースなら、必要とされるスキルと知識が近い役割をアサインするのも良いだろう。

ポータビリティが下がるケースとして、特定のメンバーが、同じ役割を長期間、担い続けてしまった時が考えられる。このケースでは、役割の属人化が進んでしまう。適度な頻度での役割の振り分け変更は行うべきだろう。

役割に対する権限付与

実行中のアプリケーションが、処理に必要なリソースにアクセスできないと、アクセス違反が発生して処理に失敗してしまう。こうならないために、アプリケーションの実行に必要となるアクセス権限を、ポリシーとしてあらかじめコンテナにアタッチする。

メンバーが責務を果たすためには、アサインされた役割に応じた権限が必要となる。必要十分な権限が付与されないと、アクセス違反が発生してプロセスが止まる。これを都度、マネージャーが処理するようなプロセスであるならば、それは単なるボトルネックだ。人手を介さなければサービスが完結しないシステムのようなもの。チームを信頼し、権限委譲を適切に行う。

ここで注意したいのは、人に対して権限を付与するのではなく、役割に対して権限を付与するということ。つまり、RBAC(role-based access control) だ。それが役割の標準化につながり、ポータビリティや再利用性を高めることにつながる。

単一障害点

単一障害点(single point of failure, SPOF)を残すと、何らかの問題が発生した時に、サービス停止を引き起こしてしまうリスクとなるのは、システムもチームも同じだ。チームなら、メンバーの病欠や、退職などが起こり得る。だから、チーム体制の設計にもフォールトトレランス(fault tolerance)を持ち込む。単一障害点となるような役割があるなら冗長化して可用性(availability)を高めておく。

チームとマネージャーの責任分界点

コンテナオーケストレーションプラットフォームである Kubernetesアーキテクチャは、データプレーンコントロールプレーンに分かれている。データプレーンは、一台以上のワーカーノードのクラスターで、コンテナはここで実行される。一方、コントロールプレーンは、クラスターやコンテナの稼働を正しい状態に維持する役目を担っている。コンテナをノードに割り当てることや、コンテナのレプリカ数を正しく保つこと、ノードがダウンした場合に、コンテナを他のノードに再割り当てすることなどを含んでいる。

このアーキテクチャは、チームとマネージャーの間にある責任分界点について示唆に富んでいる。チームは、それぞれのメンバーが役割を果たし、互いに協働することを通して、サービス提供に責任を持つ。一方、マネージャーは、チームがその責任を果たせるよう、チームの稼働、すなわち信頼性(reliability)に責任を持つ。マネージャーは、サービスに対する責任はあるが、サービス提供を実施すること自体は責務ではないということだ。もし、マネージャーがサービス提供も担っているとしたら、それはチームメンバーを兼任している(プレイングマネージャー)のであって、マネージャーの責務として実施している訳ではないだろう。

ビジネスと戦略

戦略はビジネスのアルゴリズム

戦略」と聞いて、エンジニアが真っ先に思い出すのは、GoFStrategy パターンだろうか。Strategy は、オブジェクトのアルゴリズムを切り替え可能にするデザインパターンだ。

問題を解決するための方法や手順のこと。問題解決の手続きを一般化するもので、プログラミングを作成する基礎となる。アルゴリズムは1つの問題に対し、複数ある場合が多い。(アルゴリズム - 意味・説明・解説 : ASCII.jpデジタル用語辞典

例えば「ソート」という問題ひとつをとっても、様々なアルゴリズムが存在する。ソートを行うコンテキストよって、選択すべき最適なアルゴリズムが異なるからだ。

ビジネスにとっての戦略も、ビジネスの振る舞いを決定するアルゴリズムのようなもの。ビジネスにも、とり得る戦略が様々ある。ビジネスを取り巻く内外の環境にあわせ、最適な戦略を選択することが重要だ。そしてその環境は常に変わっていく。だから、戦略は不変ではない。

マネージャーは、自身が担うサービスに組み込むべき戦略を選択・設計し、それをプロセスとして実装する。戦略というアルゴリズムを、チームとして実行できる形にしたものがロジック、つまりはプロセスなのだ。

実のところ、経営における「戦略」という言葉の扱いは曖昧だ。「戦術」という言葉と使い分けられることもあれば、そうでないこともある。ビジネス現場で戦術という言葉は頻出しないように思うので、ここでは両者を「戦略」として一括りにしている。

戦略というアルゴリズムの構造

Strategy パターンでは、Strategy という抽象クラス(インタフェース)を介し、コンポジション(composition, 合成)によって処理を委譲する。委譲された側のクラスは、Strategy 抽象クラスで定義されたインタフェースを実装する形で、アルゴリズムをコードにする。

先述したように、ビジネスにおいて、戦略として選択したアルゴリズムは、プロセスとしてロジック化される。この構造では、サービスごとの戦略(アルゴリズム)を決めるのは、それぞれのサービスを担うマネージャーとなる。実装を委譲されているので、当然だろう。

しかし、注意が必要となるのは、ビジネスにとっての戦略では、サービス定義そのものが変わることがある、という点だろう。Strategy パターンで言えば、Strategy 抽象クラスの定義が変わってしまうことに相当する。これは、実装を委譲された側にとって、大きな影響がある。では、サービス定義が変わってしまうのは、なぜだろうか。

企業では、組織構造上の上位の戦略にもとづいて、下位の戦略が決まる。この時、上位の具象戦略の振る舞いの一部をいくつかの抽象戦略として規定し、下位のサービスに委譲するのだ。つまり、依存性逆転の原則を、Strategy パターンを連鎖させることで実現している。

組織構造と戦略の関係
組織構造と戦略の関係

どこかで見た構造ではないだろうか。これは、サービスの構造と一致している。つまり、サービスの構造は、戦略の構造そのものなのだ。

マネージャーは、上位の戦略変更によって、担当するサービスの業務分掌自体が変更され得ることを理解した上で、チームを運営する。サービス定義の変更は、メンバーからのネガティブな反応を招きやすい。彼らの共感が得られるよう、マネージャー自身が戦略の全体像をしっかり理解し、それをチームに説明する機会を設ける。

ところで戦略は、全社戦略事業戦略機能戦略に分類できる。全社戦略はひとつ以上の事業戦略で構成され、事業戦略はひとつ以上の機能戦略で構成される。全てをまとめて経営戦略と言う。事業がひとつだけの企業なら、全社戦略=事業戦略となる。これが、実際の組織構造にマッピングされる。チームのサービスが事業レベルであるなら事業戦略を、機能レベル(開発、セールス、マーケなど)なら機能戦略を担うことになる。

戦略が先か、組織が先か

ここまで、「組織は戦略に従う」という前提のもとに、チームマネジメントについて考察を進めてきた。しかし実際には、理想的な戦略を作り出せても、それに合った理想的な組織を作り出せることは稀だろう。経営資源による制約を受けるからだ。特に、人的資源による制約が、組織構造に大きな影響を与える。これは、人数的なものや能力的なものだけではない。新たな戦略や、既存戦略からの変化を、全ての人が共感・歓迎するわけではないからだ。これが、逆の「戦略は組織に従う」という命題だ。

「組織は戦略に従う」はアルフレッド・チャンドラー、「戦略は組織に従う」はイゴール・アンゾフの言葉として有名だ。

これは、どちらか一方が正しいというものではない。どちらも考慮しながら、最終的な戦略、組織に落とし込むのが、現実的な手法なのだろう。

戦略というアルゴリズムの開発

戦略の変更に対するマネージャーの活動内容は、チームへの影響が低い順に次のようなレベルが考えられる。

  1. 判断基準やルールの変更
  2. プロセスの変更
  3. サービスの変更
  4. ビジネスの変更

以下に、架空の企業における戦略の変化と、それに追従するプロダクト開発チームへの影響をストーリーにした。このストーリーを追った後に、そこでのマネージャーの活動について考えることにする。

戦略の変化をストーリとして追ってみる

A 社では、10 代の若者をターゲット市場とする自社プロダクトを展開している。このプロダクトはスマホアプリで、コンセプトが画期的だったこともあり、ローンチから数年は同カテゴリに競合となるようなアプリもほとんどなく、ターゲット市場を独占して大きな収益を出していた。しかし、この状況はここ数年で大きく変わり、同カテゴリに競合となる他社アプリがひしめき合い、ユーザーを奪い合う状態が続いていた。当然ながら収益は徐々に低下していった。

この状態を危惧し、マーケティングチームがアプリの利用状況を詳細に分析したところ、ローンチ当初は 10 代だった層で、現在は 20 代になった層に、アプリのコアファンが多いことが判明した。そこで、ターゲット市場を 10 代に加え、 20 代にも拡大することで、新たなユーザーを獲得する戦略を立てた。

アプリの開発業務を担うチームでは、ユーザーからの要望リストを持っている。これまでは 10 代向けの要望対応に開発リソースの多くを投下してきた。新戦略ではこの優先順位付けの基準を変更し、 20 代向けの要望対応に開発リソースを集中投下することにした(1. 判断基準やルールの変更)。

A 社では、比較的大きな単位で機能を開発し、ローンチする戦略を取っていた。それが、ターゲット市場に対するマーケティング面でのインパクトになるし、必要となる機能を一通り揃えてローンチすることが、ユーザーにとっての価値・利便性にもつながると考えていたからだ。そのため、企画からローンチまでにおよそ半年程度の期間を要していた。しかし、過当競争にある 10 代向け市場では、競合他社が次々と新たな機能を出してくる。このような外部環境の変化が、開発中の機能に対する仕様変更を引き起こすことが多くなってきた。これがプロジェクトを後戻りさせ、ローンチを延期させることに繋がり、開発期間はますます長くなっていった。

開発チームは、この開発効率性悪化の原因を、開発プロセスモデルが競争面でミスマッチを起こしているからだと考えた。これまで、マーケティング部門から受け取った機能企画を、ウォーターフォール型のプロセスモデルで開発していたが、スクラム開発に切り替え、短期間で小さな機能単位のローンチを繰り返すことで、ターゲット市場の変化に対応しやすい体制を組んだ(2. プロセスの変更)。

スクラム開発も上手く機能し、外部環境の変化へも柔軟に適応できるようになった。この成功を更に加速させるため、プロダクト企画チームメンバーを、プロダクト開発チームに異動させ、企画と開発を一体化したスクラム開発体制を組むことにした(3. サービスの変更)。

アプリは順調にユーザーを増やしていき、収益も向上していった。プロモーション担当チームの活躍により、メディアで取り上げられることも多くなった。これに目を付けた大手インターネット企業からスマホアプリ事業の買収が打診され、会社ごと吸収合併されることになった(4. ビジネスの変更)。

ストーリーの中でマネージャーがとる行動

ストーリー中の(1)は、マーケティング戦略変更に伴うプロダクト戦略の変更であるが、その影響は意外に小さかった。要望対応リスト内のアイテムに対する優先順位付けの基準を変更しただけだ。プロセスは大抵、このようなリスト(キュー)を抱えており、そのアイテムどのような順番で処理するかは、スケジューリング方針次第だ。単純に、FIFO(first in, first out) であれば良いというものではない。どういう仕事に対してリソースを優先的に投下するかの決定は、重要な判断だ。チームがこの判断を自ら行えるよう、新たなスケジューリング方針を定義することが、ここでのマネージャーの仕事であった。

(2)では、プロダクト戦略自体に変更はなかったが、開発プロセスとの相性が悪かった。そのため、開発プロセスモデルをウォーターフォールからスクラムに変更している。サービスインタフェースへの影響はなさそうだが、プロセスの変更は、役割定義に影響をおよぼす。これは、チーム構造が変わることを意味する。変更の背景と目的を、チームメンバーにしっかりと説明し、理解を得ておく。

(3)では、互いにプロダクト戦略を担っていたプロダクト企画業務とプロダクト開発業務を一体化した。業務分掌に対して機能を追加することになるため、チームが提供するサービスの範囲が拡大する。サービス定義の変更は、サービスインタフェース、プロセス、チーム構造すべてに変化を要求する。こういうケースは現状からの変化が大きすぎ、チーム内で「それはうちの仕事じゃない」といったネガティブな反応を起こしやすい。それどころか、マネージャー自身が、同様の拒否反応を示すようなこともしばしば見られる。これはきっと、マネージャーが石切り工の「第二の男」でとどまっているのだろう。まずは、戦略に対してマネージャー自身が腹落ちすることが重要だ。

(4)は、吸収合併によって、そもそも事業戦略から見直すことになった。組織構造も大きく変わるだろう。新たな組織の中で、マネージャーという役割を担い続けることになるのかもわからない。それでも、この大変化を成功させるために、現組織のマネージャーとしてリーダーシップを発揮しながら、新たな組織作りを推進していく。

目標とモニタリング

モニタリングは目標への道標

書籍『「SRE サイトリライアビリティエンジニアリング ―Googleの信頼性を支えるエンジニアリングチーム」Betsy Beyer, Chris Jones, Jennifer Petoff, Niall Richard Murphy 著、オライリージャパン(2012)』では、モニタリングについて次のように述べられている(引用はオンライン英語版より)。

Without monitoring, you have no way to tell whether the service is even working; absent a thoughtfully designed monitoring infrastructure, you’re flying blind.

(モニタリングがなければ、サービスが稼働しているかどうかを知る方法はない。思慮深くデザインされたモニタリング基盤がなければ、目隠しで飛行しているようなものだ。)

マネジメント活動にとってもモニタリングは判断の道標となる。モニタリングがなければ、サービスの状況を知ることが困難となる。問題に気づかないようなことは避けたい。サービス品質が低下すると、サービスを利用する他チームのサービス品質を低下させてしまう。サービス利用者がお客様なら、サービスに対する満足度の低下を招く。

道標と言うからには、到達しようとする目標がある。目標と現在地のギャップが、進むべき方向になるというわけだ。マネージャーは、目標を立てたら道標を頼りにチームが乗るバスを走らせていく。モニタリングによって問題を検知し、判断し、対応することを繰り返していく。

このモニタリングと目標に関する活動は、以下に述べる「サービス」「プロセス」「チーム」「ビジネス」の 4 つに分類して進めることになる。

サービスの目標とモニタリング

エンジニアリング活動で、サービスに関するモニタリングは症状指向(symptom-oriented)だ。サービス利用者に対し、既に影響を与えている症状を検知するものだからだ。当然ながら、エンジニアによる問題への対応はリアクティブにならざるを得ない。しかし、だからこそ緊急度の高い問題を検知するために必要な仕組みとなる。SRE ではこれを、ブラックボックスモニタリング(black-box monitoring)と呼び、サービス利用者の視点で選択した指標をモニタリングする。

稼働中のシステムが提供するサービスの品質評価には、SLA, SLI, SLO を使う。

  • SLA(Service Level Agreement, サービスレベル合意):サービスの提供者と利用者の間で結ばれた、サービス水準に対する合意事項。
  • SLI(Service Level Indicator)SLA を履行するために監視すべき、サーバーやネットワーク、ストレージなどに関する定量的な測定項目。
  • SLO(Service Level Objective):SLI に対する目標値やその範囲。

SLA や SLO を継続的に満たすよう、エンジニアは日々、目標と実績のギャップに注目しながらシステムを運用していく。

マネジメント活動で、チームが提供するサービス水準を取り決めるケースはあまり聞かない。しかし、SLA, SLO を目標として定義しておくことは、サービス品質に良い影響を与えるだろう。

指標の対象となるのは、サービスインタフェースに規定されている振る舞い(主に利用者からの入力、あるいは利用者への出力に関わる振る舞い)のレイテンシやスループット、エラー状況などだ。提供しているサービスがプロダクト開発業務なら、開発期間や単位期間内のデリバリー回数、障害発生件数などが考えられる。

サービス品質に対する期待値コントロールもマネージャーの務めだ。サービス利用者や関係者の期待値が過剰になると、SLA や SLO を満たしていても、彼らはサービス品質に不満を持つようになる。例えば、サービスが定常的に目標値を上回る品質を継続していたとしよう。すると、サービス利用者や関係者にとってそれが当たり前になり、期待値が上がってしまう。あるいは、目標値の定義にあいまいな表現が含まれていたために、サービス利用者や関係者との間に認識の齟齬が生まれるようなケースもある。だから、マネージャーは利用者や関係者の期待値レベルも、モニタリングすべきだろう。

可能であれば、サービス品質について、サービス利用者に聞いてみる。定期的に実施するのが良いだろう。その方法として、NPS(Net Promoter Score, ネットプロモータースコア)を利用したアンケートが考えられる。NPS は、顧客や利用者のサービス継続利用意向を知るために、アンケート回答者を「推奨者(Promoter)」「中立者(Passive)」「批判者(Detractor)」に分類する指標だ。アンケート項目も最小限で、回答者への負荷も小さい。

プロセスの目標とモニタリング

ブラックボックスモニタリングに対し、システム内部のメトリクスに基づくモニタリングを、SRE ではホワイトボックスモニタリング(white-box monitoring)と呼んでいる。

ホワイトボックスモニタリングは基本的に原因指向(cause-oriented)だ。症状として表出した問題の原因を特定可能にする。また、症状として表出していない問題を検知するケースもあり、プロアクティブな対応も可能にする。プロビジョニングを計画するための情報源としても利用できる。

プロセスに対するモニタリングでは、このホワイトボックスモニタリングを行うことになる。指標に対して目標値や基準値を設けることは言うまでもない。

プロセスのモニタリングで指標として考えられるメトリクスは、プロセス単位、アクティビティ単位でのスループットレイテンシーあたりだろう。もし、設定された目標や基準値を満たせないことが続くようなら、プロセスの設計・実装を見直すことを考える。リファクタリングによって業務効率向上が期待できる。プロセスやアクティビティの一部は、可能なら自動化してしまう。

エラーの頻度も、プロセス品質を評価する指標として使える。もし、プロセス内の特定の個所でエラーが頻発しているなら、例外処理をプロセスに組み込み、チーム内での解決を可能にする。例外が発生するたびにアラートを投げてマネージャーが処理するのは効率が悪い。

チームの目標とモニタリング

チームのモニタリングも、プロセスのモニタリングと同じようにホワイトボックスモニタリングとなる。指標として活用できそうなメトリクスは様々考えられるが、ここでの目標値や基準値は、チーム体制、人員計画、育成計画、開発計画、製造原価・販管費予算といった計画にリンクさせて管理するのが良いだろう。

チーム体制、人員計画に関係する指標には、チーム全体や個々のメンバーの「残業時間が適切な範囲に収まっているか」「休暇の取得状況が通常レベルであるか」「特定のメンバーに負荷が偏っていないか」といったものがある。これらが適正な範囲にないようなら、チーム内の負荷分散や冗長構成についてチーム体制を見直すことになるだろう。人的リソースの調達は、可能な限り人員計画に沿って進めたい。メンバーのトレーニングや育成によって、計画的にチームパフォーマンスを向上させることも怠らないようにする。

人的リソースを調達するなら、配置換え、社内異動、採用(新卒、中途、パート・アルバイト)、労働者派遣、業務委託(準委任、請負)といった方法から、状況に応じて最適なものを選択する。

開発計画に関係する指標としては、チームが投下した「製造原価工数」をみておきたい。実績が計画から乖離しすぎてはいけない。

製造原価・販管費予算に対しては、「勤務時間に対する製造原価工数の割合は適切な範囲にあるか」を見る。この割合が低すぎるなら、チームがシステム開発業務に専念できていない可能性がある。割合が適正であっても、「製造原価工数に対するソフトウェア保守工数は適切な範囲にあるか」を見ることで、その内容が妥当であるかどうかを判断できる。スマホアプリや SaaS のようなプロダクト開発業務なら、顧客価値の高い機能追加に対して、可能な限り多くの製造原価工数を割り当てたい。場合にもよるが、保守工数の比率が高すぎるなら、何らかの問題を抱えていることを疑う。

チームのヘルスチェック

Google は、Project Aristotle(プロジェクトアリストテレスにおいて、「効果的なチームを可能とする条件は何か」という問いに対し、最も重要な因子は「心理的安全性」だと突き止めた心理的安全性とは、対人関係においてリスクある行動を取ったときの結果に対する個人の認知の仕方、つまり、「無知、無能、ネガティブ、邪魔だと思われる可能性のある行動をしても、このチームなら大丈夫だ」と信じられるかどうかを意味する。

このことから、高い心理的安全性を作り出すことが、マネジメント活動の重要な要素だとよくわかる。チームの心理的安全性がどの程度のレベルであるかは、チームメンバーに、次のように質問することで把握できる。これを、アンケートの設問として活用し、チームの状態を定点観測してみてはどうだろうか。

  • チームの中でミスをすると、たいてい非難される。
  • チームのメンバーは、課題や難しい問題を指摘し合える。
  • チームのメンバーは、自分と異なるということを理由に他者を拒絶することがある。
  • チームに対してリスクのある行動をしても安全である。
  • チームの他のメンバーに助けを求めることは難しい。
  • チームメンバーは誰も、自分の仕事を意図的におとしめるような行動をしない。
  • チームメンバーと仕事をするとき、自分のスキルと才能が尊重され、活かされていると感じる。

また、心理的安全性をチーム文化として定着させるために、分報(times)を導入するという方法もある。日報は一日に一回の報告だが、分報は随時だ。その手段として、Slack などの社内チャットツールを使い、「今やっていること」や「困っていること」をメンバーが随時つぶやく。これを、メンバー一人一人に用意された公開チャンネル上で行う。メンバーは、自分専用のチャンネルなので、何かをつぶやくことに対する心理的障壁が下がる。チャンネルが公開されているので、誰かが困っている様子も可視化され、チームで助け合える。

マネージャーにとって分報は、チームの様子をリアルタイムでモニタリング可能なログとしても使える。メンバーが課題や不満、不安などを抱えている様子が見えたなら、その都度、1on1 などを通して話を聞き、対応する。

チームの成長段階と DX の関係

チェスター・バーナードの、組織が成立する 3 つの条件である「共通目的」「コミュニケーション」「協働意思」は、チームに最初から備わっている訳ではない。タックマンモデル(Tuckman's stages of group development)で描かれるような成長段階を経て、徐々に高まっていくものだ。

チームの「共通目的」とは、「ミッション」や「ビジョン」だと述べた。「コミュニケーション」は、「心理的安全性」によって活性化する。「協働意思」については、ここまで触れてこなかったが、メンバーの「従業員エンゲージメント」を引き上げることによって得られると考えている。ウイリス・タワーズワトソンの定義では、従業員エンゲージメントとは「会社・組織が成功するために、従業員が自らの力を発揮しようとする状態が存在していること」とされ、企業のパフォーマンスへの影響度を測る上で、「コミットメント」より先進的な概念とされている。

2012 年に行われた Gallup の調査では、従業員エンゲージメントの高さで上位 4 分の 1 に入るワークユニットは、下位 4 分の 1 のユニットに対し、顧客評価で 10%, 収益性で 22%, 生産性で 21% 上回った。また、離職率は 25% ~ 65%、欠勤は 37%, 品質上の欠陥は 41% 下回った。

ここで、ワークユニットごとの従業員エンゲージメントは、Gallup が独自に開発した設問に対する従業員からの回答をもとに計測されている。その内容(サンプル日本語記事)を見ると、従業員体験(employee experience, EX)が深く関わっていることがわかる。

  • Q00 - How satisfied are you with [Company Name] as a place to work? / 働き場所として、会社にどれほど満足しているか
  • Q01 - I know what is expected of me at work. / 職場で自分が何を期待されているのかを知っている
  • Q02 - I have the materials and equipment I need to do my work right. / 仕事をうまく行うために必要な材料や道具を与えられている
  • Q03 - At work, I have the opportunity to do what I do best every day. / 職場で最も得意なことをする機会を毎日与えられている
  • Q04 - In the last seven days, I have received recognition or praise for doing good work. / この7日間のうちに、よい仕事をしたと認められたり、褒められたりした
  • Q05 - My supervisor, or someone at work, seems to care about me as a person. / 上司または職場の誰かが、自分をひとりの人間として気にかけてくれているようだ
  • Q06 - There is someone at work who encourages my development. / 職場の誰かが自分の成長を促してくれる
  • Q07 - At work, my opinions seem to count. / 職場で自分の意見が尊重されているようだ
  • Q08 - The mission or purpose of my company makes me feel my job is important. / 会社の使命や目的が、自分の仕事は重要だと感じさせてくれる
  • Qv9 - My associates or fellow employees are committed to doing quality work. / 職場の同僚が真剣に質の高い仕事をしようとしている
  • Q10 - I have a best friend at work. / 職場に親友がいる
  • Q11 - In the last six months, someone at work has talked to me about progress. / この6カ月のうちに、職場の誰かが自分の進歩について話してくれた
  • Q12 - This last year, I have had opportunities at work to learn and grow. / この1年のうちに、仕事について学び、成長する機会があった

従業員体験の対象をエンジニアに絞れば、開発者体験(developer experience, DX)になる。そして、DX と言えばもうひとつ、企業のデジタル化(Digital Transformation, DX) もある。日本CTO協会ではこの 2 つの DX を一体として捉えるべきだと説いている

一つは、企業がどれだけ経営に対してデジタル技術を用いたビジネス変革ができているかを表す企業のデジタル化(Digital Transformation)です。

もう一つは先端開発者にとっての働きやすい環境と高速な開発を実現するための文化・組織・システムが実現されているかを意味する開発者体験(Developer eXperience)です。

これらの2つは、経営にとってヒト・モノ・カネが一体であるように、一体で実現されるものです。デジタル技術は目に見えないため、しばしばわかりやすいものにだけ投資して見えない品質をおろそかにしてしまいます。そのため、開発者体験は悪化し、企業のデジタル化を阻害してしまうことがあるのです。

チーム(組織)の DX を診断するには、同協会が提供する DX Criteriaを使うと良いだろう。

「コミュニケーション」「協働意思」「共通目的」はそれぞれ、心理的安全性の向上、DX 向上、ビジョンミッションの浸透によって高められる。タックマンモデルで、チームが最大のパフォーマンスを発揮する段階である「機能期(Performing)」への到達は、これら 3 つ全てを高いレベルに引き上げてようやく実現できるのだ。

チームパフォーマンス
チームパフォーマンス

ビジネスの目標とモニタリング

多くの企業は事業に対し、半期や通期(一年間)ごとに目標を決める。そして、目標達成に向けた活動を計画し、期末にその結果を評価する。ここで使われる指標が KGI, KSF, KPI だ。

  • KGI(Key Goal Indicator, 重要目標評価指標):経営戦略や事業戦略の達成度合いを評価するための測定項目と目標値のセット。
  • KSF(Key Success Factor, 重要成功要因):KGI を達成するために重要となる要因を評価するための測定項目。
  • KPI(Key Performance Indecator, 重要業績評価指標):KSF の進捗度合いを評価するための測定項目と目標値のセット。

ここでも E コマース事業を例にすると理解しやすい。目標を「顧客数を拡大して売上 1,000 万円アップ」と定義したと想定する。つまり、KGI は「売上 1,000 万円アップ」、KSF は「顧客数」だ。現在の顧客単価が 1 万円だとすると、顧客数を 1,000 人増やさなければならない。考えられる KPI は、「オンライン広告からの流入数を〇〇人増やす」や、「既存顧客からの紹介率を〇〇%上げる」などだ。

KGI, KPI を定めたら、次はそれを月次レベルでの目標値とアクションプランに落とし込み、これを計画として策定する。あとは、実績をモニタリングしながら、計画とのギャップを確認し、目標の達成に向けて軌道修正を繰り返す。その内容は、チームや関係者に対して定期的に共有・報告する。当然ながら、モニタリング可能となるよう、指標を計測できる仕組みを入れることも忘れてはいけない。

SaaS プロダクト開発業務であれば、機能単位での利用状況や、アクティブユーザー数などが、指標として考えられる。売上や粗利、営業利益を設定するケースもあるが、直接的に事業を担っているチームでない限り、活動が実績値に影響を与えにくい。これでは目標に対するメンバーのコミットメントを得にくいだろう。

目標とは別に、製造原価と販管費に関する計画を立てることも多い。「チームの目標とモニタリング」でも製造原価について話したが、その視点は工数であった。ビジネスの目標ではこれを、金額(労務費、材料費、経費)として扱う。

メンバーの個人目標も、チームの目標やアクションプランを更にブレイクダウンしたものになるだろう。こちらも定期的に 1on1 などを実施し、個人目標に対する進捗を確認する。

なお、最近では目標設定に OKR(Objectives and Key Results) を利用するケースも増えている。

最後に

本ブログエントリーでは、チームマネジメントをエンジニアリングと比較しながら、チームのアーキテクチャ・構造を辿り、そこにマネージャーの活動をプロットしてきた。チームとは、抽象としてのサービス、その実装としてのプロセスや役割、そして、それらをアプリケーションとして動作させるプラットフォームとしてのチームメンバーから構成されていた。

チームマネジメントとは、チームアーキテクトたるマネージャーの、エンジニアリング活動だ。そこには、マネージャーが、エンジニアリング経験で得てきたスキルや知識を活用できるポイントがいくつもある。

チームマネジメントとエンジニアリングの大きな違いは、前者がマシンではなく人を対象にしている点だろう。個々のメンバーの特性は均一ではない。興味も違うし、成長もする。日々、コンディションも変わる。だから、安定的で持続性のあるサービス提供を実現するには、プロセスや役割の設計・実装による標準化が鍵を握ってくる。

しかし一方で、行き過ぎた標準化は、サービスを平均的なレベルにとどめてしまう。それでは競争力がない。メンバーにとっても、標準化され過ぎた仕事は面白くないだろう。だから、メンバーそれぞれの興味や強みを生かしたいと思う。だが、それではチームに単一障害点を作ってしまいかねない……

これらのバランスを、どのようにチームデザインに落とし込むのか。マネージャーとしての能力やセンスが求められる。

ここに書いたマネージャーの仕事の多くは、チームやメンバーが担うことも可能なはず。彼らへの権限委譲を進めることで、チームは進化し、自己組織化していく。こうやって、チームマネジメントという役割を蒸留しつつ、最後に残る責務こそ、マネージャーの存在価値たる仕事になるのだろう。

Feature Parity - 機能負債がレガシーシステムのマイグレーションを失敗させる

Feature Parity とは?

ソフトウェアシステムのマイグレーションにおいて、新たに開発するシステムに、オリジナルのシステムが持つ機能セットを移植する。こういう方針や行為を、"Feature Parity" と言う。「機能等価性」とでも訳せば良いだろうか。

Feature parity の動機となるユースケースマイグレーションだけじゃない。デスクトップアプリのモバイル版を開発するような、プラットフォーム間移植でも起こり得る。スタートアップ企業が、先行企業の製品を真似るようなケースでも同様。

しかし、こういった動機による Feature parity への強い要求が、ビジネスやソフトウェアシステム開発プロジェクトをしばしば失敗に陥れる。その大きな要因のひとつが、「機能負債(Feature debt)」だ。

機能負債(Feature Debt)とは何か?

ソフトウェアエンジニアがよく知っている言葉に、「技術的負債(Technical debt)」がある。端的に言うと、「機能開発と引き換えに意識的、あるいは無意識に貶めた、システムの内部品質」のこと。

書籍「『エンジニアリング組織論への招待 ~不確実性に向き合う思考と組織のリファクタリング』広木大地著、技術評論社(2018)」でも紹介された、フィリップ・クルーシュテンの四象限で、技術的負債は「非エンジニアには見えないが、システムにとってはネガティブな価値」として定義されている。

フィリップ・クルーシュテンの技術的負債に関する四象限
フィリップ・クルーシュテンの技術的負債に関する四象

ここにもある通り、ローンチしたばかりの新機能は、ソフトウェアシステムを提供する側にとって「ポジティブな価値」として認識されている。しかし、ユーザーやビジネスにとって、実際にローンチされた機能がポジティブな価値として位置付けられているとは限らない。

ユーザーからすると、使わない機能に価値はないし、使いづらい機能は苛立たせる。ビジネスから見ても、収益に貢献しないような機能に投資したくはない。

つまり、ポジティブな価値であったはずの「新機能」が、実際にローンチしてみると、ネガティブな価値である「欠陥」に位置付けられている。これが、機能負債の正体。

機能負債となった新機能
機能負債となった新機能

Feature parity の問題は、新たに構築するソフトウェアシステムに、もとのソフトウェアシステムが抱えるこのような機能負債を再現してしまう点にある。

特に、レガシーシステムマイグレーションでは、技術的負債の返却にフォーカスがあてられ、機能面では Feature parity であることを求められる傾向が強いのではないだろうか。本ブログエントリーのタイトルを「機能負債がレガシーシステムマイグレーションを失敗させる」としたのはこのためである。

"Legacy migration feature parity" と名付けられたこのケースは、ThoughtWorks の Thechnology Radar でもアンテパターンとして、Techniques カテゴリーの Hold にプロットされている。

機能負債の影響はそれほど大きいのか?

Standish Group のレポート(2014)を見ると、ソフトウェアシステムが持つ機能の 80% がほとんど使われない。本当に価値があるのは 20% の機能のみという、パレートの法則のような結果となった。

機能の利用状況
機能の利用状況

使われない 80% の機能開発への投資が全て無駄だとは思わないが、この数字は十分にインパクトがある。

機能負債を引き継がない

機能負債を引き継がないためには、新しいソフトウェアシステムに搭載する機能を、本当に価値のある 20%  に絞り込むことになる(もちろん "20%" という数字にこだわる必要はない)。

幸い、機能負債は技術的負債と違い、エンジニアでなくとも見ることができる。ユーザー視点、ビジネス視点も交えて機能を評価し、次のような図にプロットしてみると良い。

ユーザー価値とビジネス価値による機能の評価
ユーザー価値とビジネス価値による機能の評価

ユーザー価値、ビジネス価値が共に低い(D)、あるいはいずれか一方が低い機能(B, C)は、機能負債である可能性が高い。これらは捨てる、あるいは見直す対象として整理できる。

新たな機能負債を積み上げない

搭載すべき機能リストの整理はできた。でもこのリストはあくまでも仮説に過ぎない。実際にローンチしたら、使われないかもしれないし、ビジネスに貢献しないかもしれない。どうなるか、結果は不確実で保証はされない。

だから、検証が必要になる。それぞれの機能を仮説だと考え、実験し、そこで得た学びを機能にフィードバックする。

搭載予定の機能すべてを一括でローンチするのではなく、機能に優先順位を付け、こういった仮説検証を繰り返しながら、機能を少しずつ順に積み上げていく。

この、アジャイルMVP(Minimum viable product)的なアプローチが、不確実性をコントロールしやすくし、新たな機能負債の発生を抑えることに繋がる。

最後に

本文で引用した、機能利用状況に関する 2014 年版の Standish Group の調査結果は、2002 年版と大きな違いがない。この点が、実は少し気になっている(2002 年版では Always + Often が 20% で、Sometimes + Rarely + Naver が 80%)。

2002 年当時と比べ、アジャイルも随分浸透した。それが機能負債の減少にも繋がっていると思う。

それにも関わらず、未だに "Hardly Ever" が 50% にものぼる理由は何だろうか。2014 年のレポートに書かれている数字が、2002 年の調査結果なのかもしれないが。