mtx2s’s blog

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

クネビンフレームワークとソフトウェアエンジニアリング

2007年にクネビンフレームワークが Harvard Business Review で紹介されて以降、ソフトウェアエンジニアリングの世界では、アジャイル開発、特にスクラムを採用すべき理由の説明で本フレームワークが用いられるようになった。

リーダー向けツールとして開発された意思決定のためのフレームワークが、いったいどのようにして、ソフトウェアエンジニアリングの開発プロセスモデルや開発方法論を説明するというのだろうか。

本稿では、クネビンフレームワークがどういうものであるかを紐解きつつ、その具体例として、ソフトウェアエンジニアリングの現場に適用することを試みる。

クネビンフレームワークとは

クネビンフレームワーク(Cynefin framework)は、リーダーが直面する状況をカテゴライズし、そのそれぞれに適応した意思決定(decision making)プロセスを提供するツールだ。経営コンサルタントであり、ナレッジマネジメント複雑系科学の研究者である David J. Snowden らによって、1990年代終わり頃に第一世代が開発された。

その後、現在の第三世代が、"A Leader’s Framework for Decision Making" というタイトルで英語版 Harvard Business Review の 2007年11月号にて紹介されると、翌2008年の Outstanding Practitioner-Oriented Publication in OB アワードを受賞するなど、大きな反響を読んだ。この時の記事は、日本語版ハーバード・ビジネス・レビューの2008年3月号で『臨機応変の意思決定手法 「クネビン・フレームワーク」による』として読むことができる。

フレームワークはその後も進化を続けているが、本稿では基本的に、この日本語版ハーバード・ビジネス・レビューの2008年3月号で紹介されたバージョンをもとに書いている。

クネビンフレームワークでは、取り扱う問題が置かれた状況を次の五つの領域(domain)に分類している。

  • Simple / 単純な状況
  • Complicated / 込み入った状況
  • Complex / 複雑な状況
  • Chaotic / カオスな状況
  • Disorder / 無秩序

この五つの領域は、状況を生じさせている原因と結果の因果関係の明確さの度合いによって分類されている。そして、その領域それぞれに対し、意思決定のためのプロセスモデルが定義されている。

Simple / 単純な状況にある領域

この「単純(Simple)」という呼び名は、実はもう使われていない。2021年10月現在では、「明白(Clear)」と呼ばれ、その前は「単純(Obvious)」と呼ばれていた。いずれにしても、現時点では日本語での名称が未定義のようなので、クネビンフレームワークを紹介するドキュメントによって、若干の表記揺れがある。

単純な状況は、原因と結果の因果関係が誰の目にも明らかである問題領域だ。対応方法には必ずベストプラクティスが存在し、いずれを選択するかが重要だ。

この領域は、ソフトウェアエンジニアリングというより、アプリケーションを利用するシーンをイメージすると分かりやすい。

オンラインで開催される技術カンファレンスで、フロントエンド開発に関する5分間のライトニングトークを受け持つことになった。5分という短い時間とはいえ、トークだけで聴かせるのはなかなかハードルが高い。数枚のスライドを画面に映しながら話すことにしたので、プレゼンテーションソフトを使い、スライドを作り始めた。

ここでの意思決定プロセスモデルは、「把握 - 分類 - 対応(sense - categorize - respond)」だ。

  • 把握 - ライトニングトークのハードルを下げるため、スライドを使う
  • 分類 - プレゼンテーションソフトを使うことにした
  • 対応 - スライドを作った

エンジニアっぽい例を挙げたが、経営者の視点での例を挙げるなら、IT化が進んでいない企業が業務改善を目的としてオフィススイートやグループウェアを導入するといったケースも、単純な状況に該当するだろう。

Complicated / 込み入った状況にある領域

込み入った(Complicated)」は、「煩雑(Complicated)」と表記されることもある。

ここで扱う問題領域は、その原因と結果の因果関係を特定して適切な解決策を導き出すために、専門家の分析が必要になる。例として、業務システムの開発を考えてみよう。

事業規模の拡大によって非効率になった業務領域に対し、新たな業務システムの導入を検討している。ネットを使って様々なパッケージソフトを調べてはみたが、それらが問題を解決できるのかわからない。そこで、この業界を専門とするシステムコンサルに入ってもらうことにした。そして、コンサルによる業務分析の結果、いくつかのパッケージソフトを組み合わせ、カスタマイズした上で導入することになった。

ここでの意思決定プロセスモデルは、「把握 - 分析 - 対応(sense - analyze - respond)」だ。

  • 把握 - 事業規模の拡大によって業務が非効率になった
  • 分析 - 専門家による業務分析を行った
  • 対応 - パッケージソフトを組み合わせ、カスタマイズした上で導入した

ここで扱う問題は、当事者にとっては未体験でも、業界にとっては未知の領域ではない。様々な人が何度も対峙してきた問題であり、その対応法が型化され、いくつかのプラクティスとなっている。そうして体系化されたナレッジを有している存在である専門家が、分析によって適切なプラクティスを選び出し、より具体化された対応法を提示する。

つまりこの領域は、不確実性が低く予測可能性が高い領域だ。分析結果から得られた対応法が正しく問題を解決する可能性が高い。分析の品質が担保できればプロセスを後戻りすることもないので、段階的にプロセスを進めていくウォーターフォールモデルに向いた領域と言える。

しかし、ウォーターフォールでソフトウェアを作り上げた結果、ユーザーから「これじゃない」と言われたなら、対象としていた領域が実は複雑な状況であったのかもしれない。

Complex / 複雑な状況にある領域

複雑(Complex)」は、前述した単純な状況や込み入った状況とは違い、その状況を生じさせている原因と結果の因果関係が、後になって分かる領域だ。その因果関係を見出すために、失敗しても影響が小さい実験を繰り返し、そこから成功パターンを見つけ出す。

コンシューマー向けソフトウェアプロダクトの自社開発を例に考えてみよう。

ユーザー調査によって、ターゲットユーザーの日常生活をより便利にするための方向性が見えてきた。それを新機能としてリリースすることはできるが、想定通りのユーザー価値になる保証はない。大規模に開発してリリースした結果、使われなければ無駄だ。そこで、ユーザー価値があるという仮説を検証する最小限の機能(MVP, minimum viable product)を作り、ユーザーに使ってもらうことで、ユーザー価値の有無を確認することにした。そして検証の結果、ユーザー価値が十分に確認できなかったため、仮説を組み直して新たに検証を進めることにした。

ここでの意思決定プロセスモデルは、「探索 - 把握 - 対応(probe - sense - respond)」だ。

  • 探索 - MVP を作って検証した
  • 把握 - ユーザー価値が十分に確認できなかった
  • 対応 - 仮説を組み直すことにした

これは言うまでもなく、アジャイル開発系のソフトウェア開発方法論が得意とする開発プロセスだ。込み入った状況とは対照的に、不確実性が高く予測可能性が低い領域であり、実験を繰り返すことで正解となるパターンを見つけ出すことを重視している。

Chaotic / カオスな状況にある領域

カオス(Chaotic)」は、「混沌」と表記されることもある。

この領域は、その名の通りカオスだ。何が起きているのかを正確に把握することができない。状況は刻一刻と変わり続ける。得られる情報が断片的で、全貌が見えず、時間経過と共に様々な事象が検知され、報告されてくる。それ故、因果関係が明らかになることはなく、この段階で根本的な解決策を打ち出すことは不可能だ。

そもそも、解決策を見出すために探索したり、分析したりといった、そんな悠長な時間はない。止血することが最優先であり、とにかく、実効性のある一次対応を可能な限り打つことに集中する。そうして状況が安定してきたところで、ようやく根本的な解決策を見つけ出す活動に移行できる。

この状況をソフトウェアエンジニアリングの現場に当てはめてみると、真っ先に思い浮かぶのは、障害対応だろう。

企業向けに提供しているマルチテナントの SaaS プロダクトをアップデートし、新機能をリリースした。数時間後、ある顧客から「既存機能でエラーが出て、業務に必要なデータがダウンロードできない」という問い合わせが入った。他の顧客では同様の事象が発生していないようだったので、問い合わせのあった顧客が必要としているデータをひとまず手動で取得し、顧客に渡した。その直後ぐらいから、様々な機能からアラートが飛び始め、問い合わせが増え始めた。対応に追われ、社内はパニックだ。事象としては、いずれもデータベースとの接続で失敗しているようであった。しかし、調査・対策するにも時間がかかる。ひとまず今回のアップデートをロールバックすることで状況は落ち着いた。やはり、先程まで発生していた問題は、アップデートによる影響のようだ。被害状況を調査しつつ、原因の特定と対策に取り掛かった。

ここでの意思決定プロセスモデルは、「行動 - 把握 - 対応(act - sense - respond)」だ。

  • 行動 - 手動でのデータダウンロードや、ロールバックなどの手を打った
  • 把握 - ロールバックによって状況が安定したことで、アップデートによる影響であることがわかった
  • 対応 - 被害状況の調査と、原因の特定と対策を進めた

このように、カオスな状況では、唐突に未知なる状況に追い込まれ、その緊急対応に追われる。

ソフトウェアエンジニアリングでは、カオスな状況を意図的に生み出すことで、前もって未知な問題への対応能力を高め、ソフトウェアシステムの信頼性をより高めようとする手法がある。それが、カオスエンジアリングだ。命名の由来は異なるようだが、「カオス」と名付けられている点が興味深い。

Disorder / 無秩序な領域

無秩序(Disorder)」は現在、「混乱(confused)」と呼ばれているようだ。これは、現在の状況が、前述の四つの領域のいずれにあるのか、当事者が理解していない混乱した状態のことだ。そもそも、理解していないこと自体を本人が認識していない可能性もある。

この状態にある意思決定者は、自分の経験や好みに基づいて、意思決定プロセスモデルを選択する。よくある、アジャイル開発とウォーターフォールモデルの論争も、この辺りに起因しているのかもしれない。取り扱っている問題領域が複雑な状況にあるにもかかわらず、ウォーターフォールを採用している、といったように。さすがに、カオスな状況の中で、スクラムウォーターフォールを使って問題解決しようとするなんてことは無いと思うが。

プロセスモデルや手法の選択は、個々のモデルの長所・短所や、モデル同士の比較だけで決定するのではなく、取り扱う問題領域がいずれの状況にあるのかを理解し、そこから導きだすべきなのだろう。

スクラムの祖 野中郁次郎との関係性

クネビンフレームワークの構築にあたり、David J. Snowden 自身が、一橋大学名誉教授の野中郁次郎らの著書『知識創造企業』に刺激を受けたと述べている点が興味深い。

He also recalls being particularly provoked by Ikujiro Nonaka and Hirotaka Takeuchi’s book The Knowledge-Creating Company around converting tacit knowledge into explicit knowledge and around the whole Socialization, Externalization, Combination and Internalization (SECI) approach.

野中郁次郎と言えば、一般的には書籍『失敗の本質―日本軍の組織論的研究』の著者の一人として知られているが、ソフトウェアエンジニアリングの世界では、「スクラムの祖」としての方が知られているのではないだろうか。スクラムを作り上げたメンバーの一人である Jeff Sutherland が、その着想を得る原点が、野中郁次郎らが1986年に Harvard Business Review で公開した論文 “The New New Product Development Game” だ。

実際、Jeff Sutherland は、スクラムに関する自著で、スクラム理論の中心として David J. Snowden が参考にしたものと同じ書籍『知識造像企業』の「SECIモデル」を紹介しているようだ

このような点からも、クネビンフレームワークアジャイル開発の間接的な関係性がうかがえる。Cynefin.io にも、アジャイル開発に関する次のような記述がある。

Alongside this, the Cynefin® framework "took off" in a world of "Agile" software development, coming together with the "Agile Manifesto" in ways which have been "a rich source of ideas and practice ever since."

最後に - 複雑な領域に挑む「攻め」の姿勢とイノベーション

不確実性が低く、予測可能性の高い環境では、新しいものは生まれない。不確実性が高く、予測可能性の低い、複雑な状況にある領域に挑んでこそ、イノベーション創発される。では、その観点で日本の現状を見てみるとどうだろうか。

ガートナージャパンによる2018年5月の調査では、日本国内でのアジャイル開発の採用状況は 17% 程度にとどまっている。ウォーターフォールの採用状況である 43% と比較するとかなり低い状況だ。

これは、日本国内でのIT投資の対象が「込み入った領域」であり、よりイノベーティブな「複雑な領域」に踏み込めていない現状を表しているのではないだろうか。これが、日本のIT投資が「攻め」ではなく「守り」だと言われる所以だろう。調査結果からは、ウォーターフォール採用の縮小と、アジャイル開発採用の拡大が読み取れるため、これからは期待が持てるようにも読み取れる。

また、『DX白書2021』で、日本のアジャイル開発の採用状況をアメリカと比較してみると(『DXを支える手法と技術』p.213)、日本の 19.3% に対し、アメリカは 45.8% と、大きく差が開いている。インターネットの登場以降、GAFAをはじめとするアメリカのテック企業に日本企業が後塵を拝しているのは、ここに起因するのではないだろうか。

note.com

よく言われるように、世の中は否応なしに複雑化している。少なくとも、複雑な状況にある領域にも関わらず、分析に時間をかけて機能要件を網羅するようなソフトウェアプロダクト開発は、無秩序な領域にはまり込んでいると言わざるを得ないだろう。

note.com

開発組織を分散モノリスにしないチーム分割と協働のデザイン

複数チームに分かれたプロダクト開発スタイルをかえって不自由に感じてはいないだろうか。チーム間に張り巡らされた無数のチェーンが自由を奪い、チームの活動を束縛する。そんな感覚だ。

組織を複数のプロダクト開発チームに分割する組織アーキテクチャは、マイクロサービスアーキテクチャに例えることができる。そこから見いだせる原則は、チームをコンポーネントとして捉え、凝集度を高く、結合度を低く設計することだ。この原則を軽視すると、チーム間の依存関係が互いをチェーンのように繋ぎ、絡み合い、組織全体を「分散されたモノリス」に変えてしまう。その結果として、チームは日々、多大な調整コストや遅延コストを支払い続ける羽目になる。

では、既存のソフトウェアプロダクト開発において、個々のチームが活動しやすい分散型組織の設計とはどういうものだろうか。あくまでも私の経験や考えに基づくものではあるが、本稿はこれをテーマに書いてみたい。

「分散されたモノリス」と化したプロダクト開発組織

チーム間を縛りつける制約というチェーン

凝集度(cohesion)」と「結合度(coupling)」は、ソフトウェアコンポーネントモジュール性(modularity)の程度を示す尺度だ。 凝集度が高いほど、また、結合度が低いほど良いとされる。

凝集度が高いコンポーネントは、それが提供しようとする特定の機能に対し、関係性の高い責務を網羅的に含み、関係性の低い責務をほとんど(あるいは全く)含まない。凝集度が高いと結合度が低く、凝集度が低いと結合度が高い傾向がある。

チームとは、組織を構成するコンポーネントだ。ソフトウェアコンポーネントと同様に、チームにも凝集度と結合度がある。そして、チーム間の結合は、チームの活動に制約を課す。

チーム間の結合によってチーム活動に課される制約
チーム間の結合によってチーム活動に課される制約

本来、デリバリパフォーマンス上で好ましい組織の状態とは、チーム間が疎結合であり、それぞれのチームが独立してミッション遂行が可能であることだろう。チームが何かをしようとするたびに、他のチームに何らかの協力を依頼せざるを得ないようでは、高いパフォーマンスは期待できない。

しかし、結合による制約は、チーム間をチェーンで繋ぐかのように、互いの活動に干渉する。これらがクリティカルチェーンクリティカルパスを形成し、ソフトウェアデリバリのリードタイム(lead time for changes)を悪化させる。それはまるで、互いが無数のチェーンで繋がれた「分散されたモノリス(distributed monolith)」のようだ。

「分散されたモノリス」と化したプロダクト開発組織
「分散されたモノリス」と化したプロダクト開発組織

本来、「分散されたモノリス」という言葉は、サービス間が密結合になってしまったマイクロサービスアーキテクチャを指すアンチパターンの名だ。 しかしながら、組織設計のアンチパターンとしても、何ともしっくりくるではないか。

制約を生じさせる代表的な三つの結合要因

制約というチェーンを全て完全に断ち切ることは、おそらくできないだろう。しかし、その数を削減したり、緩和することはできる。そのためには、分散組織の凝集度を可能な限り高く、結合度を可能な限り低くなるよう、デザインする必要がある。

自組織の凝集度・結合度のレベルは、二つ以上のチームが参加するミーティングの実施頻度で把握できる。そこで話し合われているのは、互いのチーム活動に干渉し合う制約に対する調整だ。このような調整が頻繁に行われる組織は、チーム間の結合度が高い。

その調整のテーマは概ね次の三つのいずれかに大別できるのではないか。

  • 複数チームによる人員の共有
  • 複数チームによる同一案件の実施
  • 複数チームによる同一コンポーネントへの変更

ソフトウェア開発の現場でよく見られるこれらの行為が、なぜチーム間の結合要因となるのだろうか。そこで生じる制約とはどういうものなのだろうか。

「複数チームによる人員の共有」による制約

チーム間での人員の共有、すなわち「兼務」や「兼任」と呼ばれるそれは、チーム間の結合度を高める要因となる。人的リソースの利用を接点として、チームとチームが互いのスケジュールに干渉し合うからだ。

「複数チームによる人員の共有」による制約
「複数チームによる人員の共有」による制約

二つ以上のチームが、ひとりの人員に対し、同時期に作業をスケジューリングしようとすると競合が起きる。その解決方法は二つ。ひとつは優先順位を決めて順に作業を終わらせること。もうひとつは複数の作業を同時に進めること。

前者の直列方式では、優先順位が低いとされた作業を抱えるチームが、先行の作業が終わるまで待たなければならなくなる。後者の並列方式では、マルチタスキングによって、いずれのチームの作業も、実行期間が長くなる。どちらにしても、結局はリードタイムを悪化させることになる。

兼務の問題は以前の記事「兼務はチームの独立性とのトレードオフ」で詳しく書いたので、そちらも参照してほしい。

mtx2s.hatenablog.com

「複数チームによる同一案件の実施」による制約

機能追加や機能改善といった開発案件をチームが進める上で、必要となる責務をチームが網羅できていない場合、欠けた責務を担う他のチームに協力を仰ぐことになる。つまり、チーム機能の凝集度が低いのだ。

ひとつの開発案件を複数のチームで協力して進めるには、互いのスケジュールを調整する必要がある。しかし、協力を依頼されたチームも手が空いているわけではなく、常に様々な開発案件を抱えている。そのため、依頼先チームでの作業スケジューリングが、依頼元チームの期待通りになるとは限らない。結果、このような協力関係は多くの場合、リードタイムを悪化させることになる。

「複数チームによる同一案件の実施」による制約
「複数チームによる同一案件の実施」による制約

「複数チームによる同一コンポーネントへの変更」による制約

二つ以上のチームがそれぞれの開発案件の都合で、同時期に、同じコンポーネントに対して変更を加えようとすることがある。これが、チーム間の結合度を上げる。そうすると、変更しようとするコンポーネントに関するテストやデプロイの実施日について、チーム間での調整が必要となる。

「複数チームによる単一コンポーネントへの変更」による制約
「複数チームによる単一コンポーネントへの変更」による制約

テストやデプロイの実施を、チームを跨いで統合実施しようとすると、その実施タイミングはもっとも遅いチームに合わせることになる。逆に、テストやデプロイの実施をチーム間で優先順位を決めて順に実施しようとしても、優先順位が低いチームは先行チームの実施完了を待つことになる。いずれにしても、リードタイムを悪化させてしまう。

結合要因の排除

以上のように、三ついずれの結合要因においても、それぞれの制約によって、ソフトウェアデリバリのリードタイムを悪化させるに至っている。この制約が、冒頭で述べた「チームの活動を束縛する」という感覚を生じさせているのだろう。

本稿は、この三つの結合要因を可能な限り排除し、制約を削減・緩和することを戦術として、以下に具体的な施策を講じている。

チーム分割と協働のデザイン

チームというアトミックで不可分な単位としての活動

チーム内で複数の開発案件が並列で走ることはあり得る。しかし、マネジメント主体がそれぞれの開発案件ごとに分かれているなら、それはもはやチームとしての体を成していない。

こういうケースでは往々にして、個々の開発案件ごとにプロジェクト体制が敷かれ、専任のプロジェクトマネージャーが立ち、企画担当も含め、いくつかのチーム・組織から人が集められる。チームの存在は、都度発生するプロジェクトに人的リソースを提供するリソースプールでしかない。

リソースプールとしてのチーム
リソースプールとしてのチーム

このような体制に関する問題は、note に書いた記事「ソフトウェアプロダクトの機能追加・機能改善をプロジェクト体制で進めるのはもうやめよう」でも扱った。

note.com

そこでも書いた通り、プロジェクト体制は、兼務体制を生みやすい。 つまり、「複数チーム(プロジェクト)による人員の共有」による制約を受けやすくなる。

また、「複数チーム(プロジェクト)による同一コンポーネントへの変更」による制約も受けることになる。

複数プロジェクトによる同一コンポーネントへの変更
複数プロジェクトによる同一コンポーネントへの変更

だからこそ、プロダクト開発を担うチームは、アトミックでありたい。チームメンバーが個々に活動するのではなく、チームとして活動するということだ。チームは不可分な存在であり、チームとして開発案件の実行に責任を持つ。複数の開発案件が並走したとしても、チームとしてそれらをまとめてマネジメントする。これが、分散組織をデザインする上での核となる基本原則だ。

アトミックな単位としてのチーム
アトミックな単位としてのチーム

単一の担当チームによるコンポーネントの開発・保守・運用

ソフトウェアプロダクトは、複数のコンポーネントの集合体として存在するものだ。ここでは、このコンポーネントというものの粒度を、「何らかのプラットフォーム(動作環境)にデプロイする単位」としよう。この定義は、『Microservices』での component の定義とも一致する。

Our definition is that a component is a unit of software that is independently replaceable and upgradeable.

(中略)

One main reason for using services as components (rather than libraries) is that services are independently deployable.

開発組織を複数チームに分割する時は、この独立してデプロイ可能(independently deployable)なコンポーネントに着目することが鍵となる。

プロダクト開発組織を複数のチームに分割する主な理由のひとつは、それぞれのコンポーネントごとに、唯一の担当チームを割り当てることにあると言っても良い。Products not Projects にもあるように、コンポーネントの開発・保守・運用は、原則として担当チームだけで行う。

単一チームによるコンポーネントの開発・保守・運用
単一チームによるコンポーネントの開発・保守・運用

これは、Amazon.com の CTO のワーナー・ヴォゲルズの言う “You build it, you run it” にも通じる。

もし、ひとつのコンポーネントに対し、複数のチームが変更を加えようとすると、「複数チームによる同一コンポーネントへの変更」による制約を受けることになる。そしてそれは、調整コスト遅延コストとして跳ね返る。コンポーネントの開発・保守・運用を唯一の担当チームで行うことが原則である理由のひとつは、ここにある。

コンテキストと更新頻度に着目したコンポーネントの兼務

コンポーネントの数が、現実的に編成可能なチームの数より多いこともある。必然的に、ひとつのチームが複数のコンポーネントを担当することになる。

担当コンポーネントの組み合わせは、「境界付けられたコンテキスト(bounded context)」が同じもの同士を寄せるべきだろう。そうしなければ、チームの凝集度が下がり、「複数チームによる同一案件の実施」による制約を受けるようになるからだ。

コンテキストに着目したコンポーネントの兼務
コンテキストに着目したコンポーネントの兼務

また、それと同時にコンポーネントの更新頻度にも着目しなければならない。更新頻度が高いコンポーネントを複数抱えることになったチームは、人的リソースの枯渇が状態化し、開発案件が滞るようになる。そうなったチームは、他チームから一時的に人的リソースを借り受ける形で「複数チームによる人員の共有」を発動させることを繰り返すようになる。

このような事態を極力避けるためにも、更新頻度の高いコンポーネントと、低いコンポーネントを組み合わせるようにすることもポイントになる。チームの負荷を平準化することが狙いだ。

次の四象限のように、二つ目以降のコンポーネントの兼務は、主たるコンポーネントとコンテキストが同じかどうかと、更新頻度が低いかどうかで決定すると良いだろう。

更新頻度に着目したコンポーネントの兼務
更新頻度に着目したコンポーネントの兼務

数多くのコンポーネントの開発・保守・運用に要する負荷の軽減や平準化については、他にもいくつか方法がある。ただ、それらは本稿のテーマである組織設計とは外れるため、今回は割愛し、別の機会で取り上げたいと思っている。

依存関係に着目したコンポーネントの兼務

コンポーネント間に、強い依存関係が存在することも多い。そこに着目せずにコンポーネントの担当チームを分けてしまうと、コンポーネント間の依存関係が、そのままチーム間の依存関係になってしまう。つまり、「複数チームによる同一案件の実施」の発動だ。

コンポーネント間の依存関係によって生じる「複数チームによる同一案件の実施」
コンポーネント間の依存関係によって生じる「複数チームによる同一案件の実施」

このチェーンを完全に断ち切ることは難しい。コンポーネント同士の依存関係を弱めるには、日々の蒸留を続け、コンポーネントのコンテキスト境界を時間をかけて整理するしかないからだ。

もし、依存関係にあるコンポーネントの組み合わせが同一のコンテキストに属すものであるなら、同一のチームの担当とすると良いだろう。そうすれば、「複数チームによる同一案件の実施」の発動を回避できる。

依存関係に着目したコンポーネントの兼務
依存関係に着目したコンポーネントの兼務

一方で、依存関係にあっても、コンテキストが異なるコンポーネントであるなら、担当チームは分けておいた方が良い。このような関係にあるコンポーネントの担当をひとつのチームにまとめると、コンポーネント間の依存関係の結合度がより強くなる傾向があるからだ。

コントリビューター/コミッターモデルでのフィーチャー開発と協働

複数チームによる同一案件の実施」の必要性は、やはりどうしても発生してしまうものだ。すべてのチームの凝集度を完全に高めきることは不可能だからだ。それに、たとえ凝集度を完全に高められたとしても、境界づけられたコンテキストを横断するフィーチャー開発というものも日常的に発生する。こういう時は、制約を受けつつも複数チームで協働する道を選ぶことになるだろう。

しかし、協働するにしても、チーム間でのスケジュールが上手く噛み合わず、どうしても他のチームの協力を得られそうにないケースもある。

また、協働で進めるためのオーバーヘッドが、作業規模に対して大きすぎることもある。チームが単独で進めた方が効率が良いケースだ。

いずれのケースでも、案件の主担当チームが、他チームが担当するコンポーネントに対して変更を加えることになる。そうすると、本来の担当チームによるコンポーネントへの変更と、他チームによるコンポーネントへの変更が同時期に発生する。こうして、「複数チームによる同一コンポーネントへの変更」が発動する。

コンテキストを横断するフィーチャー開発における「複数チームによる同一コンポーネント」への変更
コンテキストを横断するフィーチャー開発における「複数チームによる同一コンポーネント」への変更

この時の制約への緩和策としては、OSS 開発のような、コントリビューター/コミッターモデルでのチーム間協働が適している。ここで言うコントリビューターは、他チームが担当するコンポーネントを変更するチームのことで、コミッターは、そのコンポーネントを本来担当するチームのことを指す。

コントリビューターチームは、必要な変更をプルリクとしてコミッターチームに投げ、コミッターチームは、それをレビューし、マージした上で、任意のタイミングでデプロイする。

コントリビューター/コミッターモデルによる協働
コントリビューター/コミッターモデルによる協働

このやり方はあくまでも「複数チームによる同一コンポーネントへの変更」や「複数チームによる同一案件の実施」の亜種であり、制約は受ける。しかし、プルリクを介してプロデューサー/コンシューマーパターンが形成されるため、コントリビューターチームとコミッターチームがそれぞれ自分たちのペースで活動することが可能になる。つまり、調整コストが下がる上、コミッターチームの負荷もコントロールしやすくなる。

プルリクを介したプロデューサー/コンシューマーパターン
プルリクを介したプロデューサー/コンシューマーパターン

とは言え、やはり課題はいくつかある。最も大きい課題は、プルリクを投げたコントリビューターチームが期待するデプロイ日と、コミッターチームが実際にそれをデプロイする日を、どうやって合わせるかだ。

チーム間でデプロイ日の調整を行うこともできるが、できれば調整コストは下げたい。それを実現する決定的な方法を、私自身もまだ見出せていないが、ブランチ戦略によってある程度はカバーできる。

その一つの方法としては、あらかじめコミッターチームが、デプロイ日ごとにブランチを複数用意しておくことだ。コントリビューターチームは、その中から任意のブランチをマージ先として選んで、プルリクを投げれば良い。

もう一つの方法は、マージした変更が、速やかに本番環境にデプロイされることを、コミッターチームが保証するというものだ。これには、継続的デプロイ(continuous deployment, CD)によって、マージされた変更が自動でデプロイされるレベルのデリバリパイプラインが実現されていることが求められる。

いずれにしても、マージ後に手動テストが必要であればそれが制約となってしまう。CI/CD のパイプラインによって、デリバリまでのテストが自動化されていることが前提となるため、コントリビューター/コミッターによる協働は、実現難易度が高いと言えるだろう。

よくある問題へのソリューション

クライアントサイドとサーバサイドの垂直統合チーム

クライアントサイドサーバサイドという切り方で、チームを分けている組織を見かける。ウェブ API をサーバサイドのサービスが提供し、それをクライアントサイドのアプリケーションが利用するという形で、コンポーネントが分かれているからだ。

しかし、両チームの活動をよく観察してみると、機能追加や機能改善といった開発案件を協力して進めていることが多く、「複数チームによる同一案件の実施」が頻発している。ひとつの開発案件に要するコンポーネントの変更が、クライアントサイドとサーバサイドの両方に及ぶからだ。

クライアントサイドとサーバサイドのコンポーネントは、このように強い依存関係にある。それは、コンポーネントを分割している理由が、システムアーキテクチャ上の都合でしかないからだ。基本的に、両者は同一のコンテキストに属している。これらのことを考慮せずに担当チームを分けてしまうと、チームの凝集度が下がり、それが「複数チームによる同一案件の実施」につながる。

この問題を回避する方法は、両方のコンポーネントを単一のチームで担当することだろう。つまり、クライアントサイドとサーバサイドを垂直統合したチームを作る。そうすれば、チームの凝集度を上げられる。それが意思決定を迅速にし、価値の提供に集中することを可能にする。

クライアントサイドとサーバサイドの垂直統合チーム
クライアントサイドとサーバサイドの垂直統合チーム

垂直統合型チームでは、メンバー個々のスキルセットの垂直統合も要求される。もしチーム内で、クライアントサイド開発のスキルセットしか持たないメンバー、サーバサイド開発のスキルセットしか持たないメンバーで分かれてしまうと、一方のスキルセットのメンバーが多忙な時に、もう一方のスキルセットのメンバーが助けに入れない。

スキルセットを垂直統合するといっても、各人がどちらのスキルも同レベルで高めるまでの必要はない。メンバー各自の志向やチームの状況にあわせ、専門とするスキルを深堀させつつ、他の領域のスキルに幅を広げる。いわゆる「T 字型人材」の集まりとしてチームが構成されていれば良い。

プラットフォーム別アプリケーションチームとプラットフォーム間移植

モバイルアプリを自社ソフトウェアプロダクトとして展開する組織は、iOSAndroid、それぞれのプラットフォーム向けにアプリを開発していることが多い。このようなプラットフォーム別に存在するコンポーネントの担当を、「アプリチーム」といった形でひとつのチームに統合していないだろうか。

確かに、同一ドメインを扱うという点では悪くはないが、互いのコンポーネントの間には、クライアントサイド/サーバサイドのような依存関係はほとんどない。つまり、プラットフォームごとにチームが分かれていても、制約は生じにくいのだ。これは、デスクトップアプリの Mac 版と Windows 版や、ウェブアプリケーションの PC 版とスマホ版についても言える。

それならば、プラットフォームごとにチームを分けた方が、チームとしての小回りが効く。

プラットフォーム別アプリケーションチーム
プラットフォーム別アプリケーションチーム

もちろん、組織には人員数という制約条件があるので、無尽蔵にチームを作れる訳ではないが、可能な範囲で分けておくことをおすすめする。なぜなら、プラットフォームごとにチームを分けた体制は、互いに異なる機能を開発し、互いにそれらを移植するという、「たすきがけ」のような開発をやりやすくするからだ。同時に同じ機能を開発するより、いずれかのプラットフォームで作り上げた機能を、別のプラットフォームに移植する方が開発効率が良いはずだ。

プラットフォーム間でのたすきがけ開発と移植
プラットフォーム間でのたすきがけ開発と移植

それぞれのプラットフォームで同じ機能開発を進めることも可能だが、仮説検証を重視する昨今の開発スタイルに合わない。想定通りの価値を生み出せるかどうかわからない機能を、複数プラットフォームで同時に開発することは非効率だ。単一のプラットフォームで検証を繰り返し、機能を適度に磨き込んでから、別のプラットフォームに移植することで、無駄な開発を避けることもできる。

ただし、クリスマス向け機能といった、期限が重要な意味を持つ機能開発については、複数プラットフォーム同時で開発することになるだろう。

プラットフォーム別アプリケーションチームにおける垂直統合

ここで疑問がひとつ起きる。クライアントサイドのコンポーネントはプラットフォームごとに分かれているが、サーバサイドのコンポーネントは共有しているというケースでは、どのような分散組織をデザインすれば良いかだ。

このようなケースではまず、プラットフォームごとにクライアントサイドコンポーネントを担当するチームを分ける。その上で、サーバサイドのコンポーネントは、そのいずれかひとつのチームに垂直統合する。そして、サーバサイドのコンポーネントを担当しないチームは、必要に応じて、コントリビューター/コミッターモデルでサーバサイドコンポーネントに変更を加える。

プラットフォーム別アプリケーションチームによる垂直統合
プラットフォーム別アプリケーションチームによる垂直統合

負荷の高いチームへのコントリビュート型ヘルプ体制

あるチームが人手不足に陥った時、他のチームから、人手が貸し出されていないだろうか。このやり方は、「複数チームによる人員の共有」に該当してしまう。

とは言え、人手不足で困っているチームを放置するわけにはいかない。ここは考え方を変えてみよう。困っているチームに人を派遣するのではなく、困っているチームのタスクを切り出して、他のチームがそれを請け負うようにすれば良い。もちろん、請け負ったチームは、コントリビューターとして協働するのだ。

コントリビュート型ヘルプ体制
コントリビュート型ヘルプ体制

最後に - 組織は戦略に従い、システムは組織に従う

「うちの会社は組織を頻繁に変える」という愚痴を耳にすることがある。変化というのは受け入れられにくいものだが、そのような言葉が多く出てしまうようなら、組織を変化さる意図を、社員に上手く伝えられていないのだろう。

組織は戦略に従う(アルフレッド・チャンドラー)」と言うように、組織を変える理由は、戦略を変えることにある。組織を頻繁に変えると言うのは、見方を変えれば、ビジネスを取り巻く内外の状況変化に対する組織の適応力が高いのだ。

プロダクト開発チームも組織の一部だ。ビジネス戦略の変化に応じて、プロダクト開発組織としての変化が求められる。

ではその戦略に従って、チームの分け方を柔軟に変えられるかというと、それは難しい。本稿で話してきた通り、既存のプロダクトのコンポーネントのあり方が、チームの分け方に強く影響を及ぼすからだ。戦略に合わせて無理な変化を加えてしまうと、そこで生じた制約によって、組織が「分散されたモノリス」になってしまう。

このことから、戦略に従って形作られたビジネス組織全体と、コンポーネントの構成に従って形作られたプロダクト開発組織は、ねじれが生じやすい。そしてこのねじれは、ビジネスパフォーマンスを阻害する要因になり得る。

ジレンマだ。ねじれが無いようプロダクト開発組織を編成すると、制約によってデリバリパフォーマンスを落とし、ねじれを受け入れるとビジネスパフォーマンスを落とす。

私はやはり、制約によるデリバリパフォーマンス悪化は避けるべきものだと考えている。制約を受け入れてしまうと、デリバリパフォーマンスの悪化がビジネスパフォーマンスを悪化させる。そのことは、書籍『LeanとDevOpsの科学』の調査からも明らかだろう。

制約を受けながらもビジネスパフォーマンスに影響を与えない方法があれば良いのだが、少なくとも現時点ではその妙案が、私には考えつかない。だから、デリバリパフォーマンスを最大化するプロダクト開発組織を設計することに注力する。その上で、そこで生じたねじれに対して、短期の対策と中長期の対策を講じる。

短期的には、戦略に従った組織との接点に、ねじれによるビジネスパフォーマンス低下を解消(あるいは緩和)する構造を設ける。簡単に言えば、戦略に基づくビジネス組織の動きを、プロダクト組織へ迅速に伝搬させ、連動させることを可能にする。これについてはまだ試行錯誤中なので、ここでは割愛する。

中長期の対策については、「組織は戦略に従い、システムは組織に従う」という状態を実現することだ。そうすればねじれも制約も避けることができる。

「システムは組織に従う」と言えば、「コンウェイ戦略(Inverse Conway Maneuver)」を思い出す。しかし、既存のソフトウェアシステムに対し、その構造に関係ない組織を組んでしまうと、先述の通り制約によってデリバリパフォーマンスが悪化しかねない。その上、システムアーキテクチャが組織アーキテクチャに追いついたころには、ビジネス戦略が変わって組織も変わってしまっている。それほどまでに、ビジネスを取り巻く外部環境の変化はめまぐるしい。

だから我々にできることは、個々のコンポーネントの責務を小さく、そして凝集度を高く、結合度を低くすることで、プロダクト開発組織の分割と、担当コンポーネントの編成を柔軟に組み替えやすくすることではないか。日々の地道な蒸留を続けていくことが、その実現の唯一の方法だろう。

開発チームは本当の顧客視点を持っているか

自社ソフトウェアプロダクトのひとつが軽微な障害を起こした。

問題のコンポーネントを担当する開発チームによる一次対応がようやく落ち着き、一息ついたところで、チームリーダーから、障害に関する詳細な報告をZoom越しに受けていた。直前までリモート会議続きだった私は、この時点ではまだ、障害の内容を把握できてなかった。こういう時、流れ切ったSlackチャンネルを後から見て、情報を正確に追いかけるのはなかなか難しい。

バックエンドAPIが、本来であれば処理可能なリクエストに対し、特定の条件下で誤って 400 Bad Request を返していたという。リーダーは、一通りの報告が終わったところで、「何か不明点などありませんか」と私に尋ねた。

この問題の影響を受けたリクエストの件数や期間、APIの振る舞いや内部処理の問題点についてはよくわかった。しかし、その外側がわからない。ステータスコード 400 を返されたことによって、APIクライアントであるスマートフォンアプリは、どのような振る舞いをしたのだろうか。その結果、アプリを利用するユーザーには、どのような影響があったのだろうか。

「アプリ側の実装によるので、アプリチームに聞かなければわかりません」と、これが、リーダーの答えだった。

アーキテクチャの観点で言えば、その通りだろう。バックエンドAPIの仕様、それが、アプリとバックエンドの間での合意事項だ。アプリがどのようにAPIを呼び出しているのか、バックエンドがAPIをどう実装しているのか、互いにそれらに依存すべきではない。こうすることで、アプリ、バックエンドそれぞれのデプロイ容易性を上げ、デリバリパフォーマンスを高く維持しているのだ。

しかしそれは、バックエンドチームがアプリやユーザーについて知らなくて良い、ということではない。社外に公開する汎用的なAPIを提供しているわけではなく、サービスクライアントとしては専用のiOSアプリとAndroidアプリがあるだけだ。アプリのこと、その先のユーザーのことを知らなくて、良いサービスを提供できるとは思えない。そもそも、障害によってユーザーにどのような影響を与えてしまったのか、気にならないのだろうか。

――今の開発チームの目には、ソフトウェアシステムしか映っていないのかもしれない。

そのような思考を巡らす中で、私は、以前の職場でのエピソードを思い出した。

数年前、いや10年近く前だったかもしれないが――ある日の午後、企業向けSaaSプロダクト開発の責任者だった私のデスクに、紺のスーツ姿の男性が近づいてきた。当時はまだ、オフィスに集まって働くスタイルが一般的だった。私のデスクの周辺は、カジュアルな服装のエンジニアばかりが集まるエリアだ。近づいてくるのが営業部員であることはひと目でわかる。

「お疲れさまです。少し、お時間よろしいですか」と、落ち着いた口調でそう言うと、私を促すようにして、すぐ近くのミーティングルームに向かって歩き出した。

4人程度が座れる小さなミーティングルーム。テーブルを挟んで二人で向かい合って座り、彼が口を開くのをまっていた。彼と話す機会はこれまでほとんどなかったが、営業成績がナンバーワンの若手エースだったので、顔はよく知っている。

話は察しがつく。ちょうど今、開発チームが、プロダクトの障害対応にあたっている。多くのクライアントを持つプロダクトだ。彼が担当する顧客にも、おそらく影響があったに違いない。プロダクト開発の責任者である私に対し、障害対応の状況を聞きに来たのか、あるいはクレームを伝えに来たのだろう。後者だとしたら、珍しいことではあるが。

「今日開かれたA社のキャンペーンイベントは、この障害で台無しになりました」と、感情の読み取りづらい視線を私に向けた。抑制されたトーンで話してはいるが、言葉の選び方からは、怒りが滲み出ている。

障害が発生すると、営業部員は、担当する顧客からの直接の問い合わせや苦情の電話に応えたり、場合によっては、客先へ謝罪に向かうなど対応に終われる。当然ながら、本来の営業活動にあてる時間は奪われてしまう。しかし、そんな矢面に立つ中でも彼らは、私たちに文句を言うわけでもなく、むしろ「これも自分たちの仕事です。開発のみなさんは、良いプロダクトを作ることに集中してください」と言う。

しかし、ここのところ立て続けに障害を起こしてしまっている。

執務室では、声を掛け合いながら慌ただしく対応に追われるエンジニアの姿が、ここからでも壁面のガラス越しによく見える。障害を起こしたのは、企業のキャンペーンイベントでよく利用される機能だった。これまで10年以上、改修を繰り返してきた機能で、ローンチ当初から複雑だったコードは今やカオスとなり、保守が困難な状況にまで至っていた。変更を加えると多くの不具合を混入しやすい箇所であり、数日前にも軽微な問題を起こしたところだ。確かその際にも、彼が担当する別のクライアントが被害を受けていたはずだ。

「先方の担当者のBさんは、このイベントの準備に本気で取り組んでおられました」と、こちらを向いて、ゆっくり話しはじめた。「お客様の思い出になるイベントにしたい、そう、おっしゃっていて、だから、僕も、我々のプロダクトを活用したイベントが成功するよう、Bさんに全力で協力して……」

沈黙。

「くやしいです、イベントを楽しみにされていたA社のお客さまにも申し訳なくて……でも開発の人はいつも、そういったことを気にかけている様子も見えなくて、本当に、このプロダクトをお客様にすすめても良いのか、わからなく……」

そこまで話して、うつむいて泣きだした。その理由が、売り上げや成績の心配ではなく、顧客のこと、その先のエンドユーザーのことを想ってのことだと伝わってくる。彼が、ナンバーワンである理由がわかった気がした。

ソフトウェアプロダクト開発を担うエンジニアが、顧客と向き合う機会は多くない。企業向けプロダクトならまだしも、コンシューマー向けならなおさらだろう。まして、企画段階にも参画しないなら、顧客体験について思いを巡らす機会はほとんどない。エンジニアにとっての顧客とは、アプリケーションが吐き出すログや、モニタリングダッシュボード上のグラフや数字でしかないのかもしれない。これでは、エンジニアの目に、ソフトウェアシステムしか映らなくなってしまうのも当然だろう。

当時の私は、その出来事から以降、プロダクト企画部門も巻き込んで、開発プロセスもシステムも組織も大きく変えていった。顧客体験を中心に据える開発組織を作ろう、と。そして、開発チームからの障害報告にはまず、「お客さまへの影響は?」と問うことにしている。

あれから何年も経ち、いま振り返ってみて、目指す組織を作り上げられたのかと自分に問うと、自信を持って答えることはできないように思う。今はそこから離れ、こうしてまた開発チームのリーダーから障害報告を受けている。Zoom越しに映し出されたGrafanaのカラフルなグラフを眺めながら、またあそこからはじめてみようと思った。

デリバリパフォーマンス向上にはリリースに対する顧客体験の可視化が効く?

もし、開発チームのデリバリパフォーマンスが十分ではないと感じているなら、リリースした新機能や改善に対する顧客の反応を計測し、その評価結果をビジネス組織全体に対して可視化することをおすすめする。それが結果的に、デリバリパフォーマンスの向上につながると考えているからだ。

私は常々、組織を変化させるために断行されるトップダウン的な「仕組み」の変更は、即効性はあるものの、期待した効果を得にくいように感じている。そういった力技では関係者間にコンフリクトを起こしたり、始まる前から形骸化したりすることも多い。それよりも、仕組みが自然に変わっていく流れを生み出すことを考える。その流れを生み出す起点となる何かを、私は「仕掛け」と呼んでいる。

上述した「リリースに対する顧客体験の可視化」は、デリバリパフォーマンス向上に至る流れを組織内に作り出す仕掛けとして効果を期待できる。下図は、そのストーリーを描いている。

デリバリパフォーマンス改善までのストーリー
デリバリパフォーマンス改善までのストーリー

リリースに対する顧客体験を可視化する

まず最初に言っておくと、ソフトウェアプロダクトのデリバリパフォーマンスとして計測するデプロイ頻度(deployment frequency)といったメトリクスが示す値は、あくまでも結果であり、それを改善すること自体は目的ではない。デリバリパフォーマンスのメトリクスを改善すればビジネスパフォーマンス(組織パフォーマンス)が高くなるわけではなく、ビジネスパフォーマンスが高い組織はデリバリパフォーマンスのメトリクスが良い値を示している、と考えるべきだろう。

では、ビジネスパフォーマンスに対し、開発チームが寄与できることとは何だろうか。それは、プロダクトを顧客体験に優れ、顧客価値がより高いものになるよう洗練させ続けることだろう。これを本質として押さえておかないと、デリバリパフォーマンスのメトリクスが向上しても、ビジネスパフォーマンスが上がることはない。

デリバリパフォーマンスとビジネスパフォーマンスの関係性
デリバリパフォーマンスとビジネスパフォーマンスの関係性

そういう視点から、仕掛けとして「リリースに対する顧客体験の可視化」を選択した。プロダクトに変更を加える主な目的は、より優れた体験を顧客に提供することにある。したがって、リリース後の可視化によって明らかにされるその結果は、組織のプロダクト開発プロセスのあり方について強い影響力を持つと考えられる。その影響力によって、プロセスに変化を生じさせようというのが、今回の仕掛けの狙いだ。

ここでやることは、プロダクトに加えた変更が、顧客に想定通りの効果をもたらしたのかをリリースの度に計測することだ。計測するメトリクスは例えば、コンバージョン率、新機能の利用率、アクティブユーザー数、新規ユーザー数などだ。いずれにしても、計測結果を評価し、ビジネス組織全体に共有する。対象とするのは、リリースに含まれる全ての変更のうちの一つで構わない。

何を計測してどう評価するかは、リリースの内容次第だが、取り組みやすい方法を選択すべきだろう。はじめから力を入れ過ぎると導入障壁が上がる。簡単な方法ではじめ、回を重ねて効果を感じていくうちに、徐々に厳密にしていく方が上手くいく。

プッシュ型の問題に気づく

リリースサイクルの中にこのような顧客体験の可視化を組み込んでいる組織は、実はそれほど多くないように感じている。そのような組織は、プロダクトに加えた変更が想定通りの体験を顧客に提供できているかについて、楽観視しているということだろう。

しかし実際には、想定通りの結果とならなっていないことが多い。顧客体験を計測するメトリクスを可視化するということは、リリースの結果を客観的な事実として目の当たりにするということだ。

そんな体験を何度か繰り返せば、ビジネス組織全体の考え方に変化が起こりはじめる。自分たちが作り出す新機能や改善が、顧客に対して想定通りの体験や価値を提供できるのか、今までのように強い自信が持てなくなってくる。

これまでは、競合プロダクトと競い合うように、追加機能や改善のアイデアを企画してきた。バックログは常に、未着手のアイテムが山積み状態だ。とにかく早くリリースしたい。だから、様々な変更を詰め込んだアップデートを計画し、開発チームは常にフル回転で、期日までにリリースすることで手一杯になっている……

結果の計測と可視化というプロセスを導入することは、このような「プッシュ型」のプロダクト開発スタイルに疑問を持つきっかけを与えるのだ。よく言われるように、顧客にとって必要なものが何であるかは顧客自身にも答えられない。それを、プロダクトの作り手側が正しく言い当てることができると信じる方が、そもそも無謀だということは明らかだ。

プル型に変わっていく

組織にこのような意識の変化が生まれると、世界が一変する。組織のプロダクト開発スタイルが、プッシュ型からプル型に移行し始めるからだ。

顧客にとって必要なものが何であるかは顧客自身にも答えられないのだから、試してみてそこから学ぶしかない。プル型の組織はこのように、まず顧客に関する仮説(hypothesis about the customer)を立て、それを検証する方法を考え、そために必要最小限の機能が何であるかを導き出す。build-mesure-learn とは逆の、learn-mesure-build の順で計画を立てる。

Learn-Mesure-Buildによる計画とBuild-Mesure-Learnによる実行
Learn-Mesure-Buildによる計画とBuild-Mesure-Learnによる実行

そうすれば、無駄なものを作ってしまう時間の浪費を避け、必要とされるものを少しずつ積み上げていくことに時間を費やせるようになる。このような開発手法は、「仮説駆動型開発(hypothesis-driven development)」と呼ばれることもある。

そう、「リリースに対する顧客体験の可視化」という仕掛けは、ここでより計画性を持った形でプロダクト開発プロセスフィードバックループの中に組み込まれていくのだ。

バッチサイズが小さくなる

プル型のプロダクト開発スタイルは、組織の意識をバッチサイズ削減に向かわせる。まだ仮説段階でしかない「顧客が必要としていると思われるもの」を数多く生み出したり、フル機能で作り上げることは、ムダになりかねないからだ。

また、計測・評価プロセスの精度と効率を上げたいという欲求も、更なるバッチサイズ削減へのモチベーションを高める。大きなバッチでは、評価対象となるアイテムが複数であったり、一個あたりのアイテムが大きすぎて、評価しづらいからだ。

バッチサイズが小さくなる流れ
バッチサイズが小さくなる流れ

デリバリパフォーマンスが向上する

いよいよ、デリバリパフォーマンスが向上をはじめる。そもそもデリバリパフォーマンスを測定する代表的なメトリクスであるデプロイ頻度は、ソフトウェアでは測定しづらい概念であるバッチサイズの代替メトリクスだからだ。

ソフトウェアの場合は目に見える商品が存在しないため、バッチサイズを測定してその結果を伝えるということが難しい。そのため、我々は「バッチサイズ」の代わりに「デプロイ頻度」を測定基準とすることに決めた。

「『LeanとDevOpsの科学』p.23」

バッチサイズ削減による効果としては、二点が挙げられる。開発に要する全体の工数を削減することと、マルチタスクの並列度を緩和することだ。前者によって開発期間が短くなることは容易に想像がつく。後者は、タスク切り替えによるオーバーヘッドを削減するだけでなく、ワークアイテムごとのリードタイムに含まれるタスクの待ち時間(wait time)を削減し、開発チームのフロー効率(flow efficiency)を改善する。

デリバリパフォーマンスの向上
デリバリパフォーマンスの向上

このようにして、最終的に、デプロイ頻度を高く押し上げる仕組みができあがる。

最後に

重要なことは、仕掛けによって組織に起こる変化が、仕組みという形だけでなく、意識や文化にまで及ぶということだ。むしろ、組織における意識・文化の変化こそが、硬直化した仕組みを変化させる原動力になると言って良いだろう。

もちろん、仕掛けだけ置けばあとは想定通りの仕組みができあがるほど、組織を変化させることは容易ではない。理想とする仕組みに向かうよう、マネージャー自身が組織の変化を促していく必要があることは言うまでもない。

「体験」にコミットするチームと「仕様」にコミットするチーム

自社ソフトウェアプロダクトの内製開発チームの振る舞いが、外部ベンダー的だと感じたことはないだろうか。開発チームと企画担当の関係が、請負契約的な受発注構造になっているということだ。

ソフトウェア開発の従来的な請負契約では、何を作るかは発注側の責任で、それを形にして納品するのが受注側となるベンダーの責任となる。これを先程の企画担当と開発チームの関係に置き換えて言えば、「何を作るか」が企画担当の責任で、それを「形にしてリリースする」のが開発チームの責任となる。

このような開発チームのことを私は、「仕様にコミットするチーム」と呼んでいる。「何を作るか」を言語化した存在である「仕様」の通りにソフトウェアを開発してリリースすることが、彼らのゴールだからだ。

しかし、内製でのプロダクト開発の良いところは、開発チームが「何を作るか」にまで踏み込みやすい環境があることだろう。もしそこに挑もうとすれば、チームは必ず顧客体験について考えることになる。だから、それを実践するチームを私は、「体験にコミットするチーム」と呼んでいる。

仕様へのコミット

ソフトウェアを開発する過程では、様々な成果物が作られる。中でも最も重要なものが、最終成果物であるソフトウェア自体であることは間違いないだろう。ここでは「プロダクト」と呼ぶことにする。「フィーチャー」や「インクリメント」と読み替えてもらっても構わない。

それに対し、最初の成果物と言うべき「仕様」も、プロダクトそのものと同じぐらい重要な位置付けと言えるだろう。仕様とは言わば、「何を作るか」について定めた、企画担当と開発チームの合意事項と呼べるものだからだ。

「何を作るか」についての合意
「何を作るか」についての合意

完成したプロダクトにはたいてい、仕様とのギャップが存在する。その正体は、仕様に対する実装漏れ不適合といった欠陥だ。

仕様とプロダクトのギャップ
仕様とプロダクトのギャップ

仕様に対する網羅性適合性が低いプロダクトは、企画担当と開発チームとの合意に反する。だから開発チームは仕様とプロダクトのギャップを最小限に抑えることがミッションとなる。これが、「仕様にコミットする」ということだ。

仕様にコミットすることは必要なことだ。しかし、内製開発チームのミッションとしては、十分と言えないのではないか。

体験へのコミット

プロダクトは、顧客が抱える何らかの課題を解決するソリューションとして生み出される。では、仕様を完全に満たしたプロダクトであればソリューションたり得るかというと、そうとは限らない。いちユーザーとして思い返して見ると、残念ながらそれを肯定する経験がいくつも思い浮かぶ。利用シーンにおいて重要な機能が不足していたり、機能としては事足りていても、非常に使いづらいアプリケーションなんて、珍しくもない。

このように、顧客のソリューションとして完全な仕様を定義することは、おそらく誰にもできない。だから、仕様を「真」として考えることは危険だ。

仕様や、それに基づいて作られたプロダクトは、あくまで仮説に過ぎない。顧客に体験してもらい、その仮説を検証してこそ、プロダクトに対して本当に求められている姿が見えてくる。仕様に対するプロダクトの品質より、体験に対するプロダクトの品質を真としてそこに近づけようとする。それが、「体験にコミットする」ということだ。

自社ソフトウェアプロダクト開発の内製開発チームには、体験にコミットして欲しいと考えている。

体験にコミットするチーム
体験にコミットするチーム

体験にコミットすると顧客視点で仕様を見るようになる

体験にコミットするようになると、チームは、「顧客視点」という新たな能力を獲得する。顧客視点を持つと、仕様に対するとらえかたも変わってくる。

開発中に、仕様に関する問題点に気付くことはよくあることだ。顧客視点を得たことでさらに、今までは気付かなかったような問題点について気付くようになる。それを「仕様だから」といって、やみくもに仕様通りに作るようなことはない。そんなことをしたら、顧客体験を損ねてしまいかねない。だから、見つけた問題は、すぐに企画担当と話し合い、より良い形に見直す。この活動が仕様自体の品質を高め、プロダクトがより優れた体験を生み出す可能性を高める。

顧客視点
顧客視点

体験にコミットすると顧客の反応を計測するようになる

仕様にコミットするチームの開発スケジュールは、「リリース」が最終タスクとして配置されている。

一方で、体験にコミットするチームの開発スケジュールでは、リリースが単なる通過点でしかない。リリース日の後に、学びのための期間が組み込まれている。

彼らは、プロダクトが顧客体験に優れたものになるよう、リリース前に可能な限り努力する。しかし、それが必ずしも想定通りの結果になるとは考えていない。仕様やプロダクトを、仮説だと考えているからだ。

だから、リリースしたプロダクトが顧客体験に良い影響を与えられたのかどうかを検証する。そうしなければ、自分たちのやったことが正しかったのか間違っていたのかがわからない。間違いから学ぶこともできない。体験にコミットするチームにとって、リリースとは完了ではなく、学びの開始点なのだ。

「学び」のための期間
「学び」のための期間

顧客体験の評価方法は、開発前にあらかじめ設計する。定量評価の場合もあれば、定性評価の場合もある。とにかく重要なことは、プロダクトを利用した顧客の実際の反応に基づいて評価することだろう。そのために、顧客の反応を収集・計測する仕組みをプロダクト自体に作り込むことさえある。

体験にコミットするとデプロイ頻度が上がる

動くプロダクトがあってこそ、顧客体験に基づいた検証が可能になる。だから、動くプロダクトをまず作り、リリースする。そして、顧客に体験してもらうことによって得たフィードバックを検証する。その評価に基づいて仕様に追加・変更を行い、プロダクトをアップデートする。

このようにプロダクト品質は、顧客も巻き込んだ改善サイクルによって高められていく。

顧客を巻き込んだ改善サイクル
顧客を巻き込んだ改善サイクル

しかし、下の図からも分かるように、「開発」の中でのみ行う「仕様に対するプロダクトの品質改善」に比べ、サイクル全体に及ぶ「体験に対するプロダクトの品質改善」は、時間的に長くなる。

プロダクト品質の改善に要する時間の比較
プロダクト品質の改善に要する時間の比較

「開発」に要する時間が長くなると、「検証」「適応」に要する時間も長くなることは想像がつく。バッチサイズが大きいほど、検証すべき対象や、その評価に基づいて手を加える対象が増えるからだ。そもそも検証対象が複数あると、何がどれだけ体験に影響を与えたのかを個別に把握することが困難なこともある。

このように考えてみると、体験にコミットする開発チームにとって、大きなバッチサイズでの開発・リリースというのは、非常に効率の悪いものだとわかる。新規で作り上げたプロダクトや、既存プロダクトに対する変更は、あくまでも仮説であり、その内容が 100% 正しいという保証はない。バッチサイズが大きいほど、間違いの数は増える。

だったらバッチサイズを小さくする方が良い。ちょっと出しては検証することを繰り返す。「単位期間あたりにリリースした機能・変更の数」という意味でのスループットは変わらない(あるいは下がる)かもしれないが、変わりにデプロイ頻度(deployment frequency)があがる。この回転数の高いフィードバックループが、ムダなものを作り込むコストを最小限に抑える。

体験にコミットする開発チームと企画担当の責任分界点

ここまで読んで、ひとつ疑問が沸くかもしれない。開発チームが体験にコミットすると、企画担当の責任範囲はどこにあるのだろうか、と。

仕様とのギャップが小さいプロダクトをリリースする責任は開発チームにある。プロダクトの体験をより高める責任は、開発チームと企画担当の双方にある。そして、その体験を「ビジネス価値」に変えるのが企画チームの役割だ。

顧客体験の改善サイクルをまわし続けることで、プロダクトの「顧客価値」が高まっていく。顧客価値が高まることで、ビジネス価値が高まることも期待される。しかし、顧客価値がそのままビジネス価値に変換されるわけではない。この変換に対して責任を持つのが企画担当という構図になる。

ビジネス価値への変換
ビジネス価値への変換

最後に

顧客体験に優れたプロダクトを、たった一度のリリースで実現することは難しい。だからこそ、フィードバックループをまわす必要がある。

フォーカスすべき対象を顧客体験に定めたチームは、プロダクトを利用する顧客の実際の反応を測定し、その評価に基づいて改善を積み重ねていく。この繰り返しが、彼らの顧客視点をより研ぎ澄まし、改善の精度はより高まっていく。このようにして高められていった顧客体験が、プロダクトを顧客価値と呼ぶに相応しい存在に押し上げる。そしてその顧客価値があってこそ、ビジネス価値が生まれていくのだ。

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

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

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

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

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

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

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

兼務の問題点

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

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

mtx2s.hatenablog.com

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

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

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

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

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

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

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

兼務のコスト

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

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

調整コスト

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

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

遅延コスト

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

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

ソフトウェアプロジェクトが価値を生み出すのは、その成果物がリリースされてからだ。リリースが先延ばしになればなるほど、ユーザーやビジネスが本来得られるはずであった価値が目減りする。こうして失われる利益を遅延コスト(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のリリースをプランニングする。このサイクルを回し続ける。すべてはプロダクトのユーザー価値とビジネス価値を高めるために。