mtx2s’s blog

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

アジャイルを実践する組織であってもウォーターフォールを学ぶことには価値がある

「すべてのライフサイクルモデルの祖は、ウォーターフォールモデルである」とは、スティーブ・マコネルの言葉1。また、ソフトウェア開発ライフサイクル(SDLC)に関するGitHubの文書では、広く採用された最初のSDLCがウォーターフォールモデルであるとされている2

そこに、ウォーターフォールを学ぶことに対する価値がある。それは、スクラムを導入し、アジャイルソフトウェア開発を実践する組織にも言えることだろう。いや、そうであるからこそだ。どんなソフトウェア開発プロセスモデルであろうと、ウォーターフォールから派生したり、何らかの影響を受けていると考えられる。したがって、ウォーターフォールへの理解から、自分達がやっていることの本質を見いだせるのではないだろうか。

ウォーターフォールなんて誰でも知っていると思うかもしれないが、そうとも限らない。確かにウォーターフォール未経験のソフトウェア開発者は少ないだろう。しかし、そこで実践した手法は、組織ごとにカスタマイズされていたり、見よう見まねで実践されたものが多いのではないか。そして、ウォーターフォールを当たり前に利用する組織では、その採用理由について考えることもあまりない。

本稿は、歴史的側面からウォーターフォールの理解を深め、組織が現在採用している開発手法にその学びを活かせるようになることをテーマとしている。

ソフトウェア危機とボトムアップ・アプローチ

NATOソフトウェア工学会議がドイツのガーミッシュで開催された1968年当時は、「ソフトウェア危機」に瀕した時代だった。拡大を続けるソフトウェアの需要に対し、まだまだ未熟な分野であったソフトウェア開発の生産性が追いつかなかったのだ。「ソフトウェア工学(software engineering)」という用語も、この会議によってようやく広まった時代である3

ソフトウェア危機は、ソフトウェア開発プロジェクトを進めるうえで、次のような症状として現れる4

  • 品質が低い
  • 予算を超過する
  • 納期に遅れる/納品に至らない
  • 要求仕様を満たさない
  • コードの保守が困難
  • プロジェクトがコントロール不能に陥る

これらを見ると分かるように、残念ながらソフトウェア危機は今なお続いている。現在のソフトウェア業界でも、このようなプロジェクトを見聞きすることなど珍しくもない。

しかし、当時は今より状況が酷かったようだ。ロバート・C・マーチン(Robert C. Martin)は、18歳だった1970年当時を振り返り、ソフトウェア開発の実情を次のように述べている。疲弊していた様子が伝わってくる。

我々はどのようなプロセスを使っていたのだろうか? ウォーターフォールではなかったことは確実だ。詳細な計画に従うという概念など持っていなかった。毎日のように、ハックして、コンパイルして、テストして、バグを修正していただけだ。構造を持たない無限ループだった。アジャイルでもない。プレ・アジャイルでもなかった。我々の仕事のやり方に規律はなかった。テストスイートもなかった。決められた時間間隔もなかった。毎日のようにコードを書いて修正して、毎月のようにコードを書いて修正していた。

Robert C. Martin (著), 角 征典 (翻訳), 角谷 信太郎 (翻訳), "Clean Agile 基本に立ち戻れ", KADOKAWA, 2020, 第1章 より引用5

1960年代頃はまだ、「ボトムアップ・アプローチ」によるソフトウェア開発が行われていた。当時のその手法の詳細は不明であるが、一般的には、小さな部品をまず設計・実装し、それらを組み合わせて徐々にシステム全体を構築する手法だろう。このやり方だけでは、全体像が最初に見えにくく、後から統合する際に不整合が生じやすい。この言葉は、トーマス・E・ベル(Thomas E. Bell)とT・A・セイヤー(T. A. Thayer)による1976年の論文 "Software requirements: Are they really a problem?" 6に、過去のやり方として登場する。後述するが、この論文は、ウォーターフォールとも関連が深いものだ。

ボトムアップ・アプローチからトップダウン・アプローチへ

それまでのボトムアップ・アプローチよりトップダウン・アプローチの方が優れている、1970年前後の開発現場の多くでそう結論付けられた。ベルとセイヤーによる先述の論文で、そう述べられている。

彼らが「トップダウン・アプローチ」と呼んだソフトウェア開発は、システム全体の要件定義から始め、段階的に詳細化していくものだ。各フェーズの成果物はドキュメントとしてアウトプットされ、次のフェーズのインプットとなる。そうして実装・デバッグフェーズやテストフェーズへと続いていく。ベルとセイヤーは、それをFigure 1として次のような図であらわした。

ベルとセイヤーがFigure 1として示したトップダウン・アプローチの各フェーズ
出典: T. E. Bell, T. A. Thayer, "Software requirements: Are they really a problem?", 1976, Figure 1

フェーズは次のように分けられている。

1. システム要件
2. ソフトウェア要件
3. 予備設計と詳細設計
5. 実装とデバッグ
6. 開発テスト
7. 公式テスト
8. 運用と保守

このアプローチが優れているとされたのは、はじめに全体像を描き、何をどう作るかについて、順を追って明らかにしようとする点だ。それ以前の主流であったボトムアップ・アプローチと違い、これなら不整合を生じさせにくい。理にかなっている、誰もがそう信じられるほどの説得力があった。

トップダウン・アプローチは、ソフトウェア危機への対策となり得た。ボトムアップだけに頼った行き当たりばったりなやり方では駄目だと、皆が気づいたのだ。

トップダウン・アプローチを説明するためのウォーターフォールという概念

トップダウン・アプローチは、開発活動をウォーターフォール(滝)にたとえることでシンプルに説明できる。それを図として示したのが、ウィンストン・W・ロイス(Winston W. Royce)による1970年の論文だった7。それが次の図であり、論文内ではFigure 2として登場する。フェーズの階層を水が落ちていくようにプロジェクトが進んでいくさまが、滝のように見えるのだ。

ロイスがFigure 2として示した大規模コンピュータプログラムを開発するための実装ステップ
出典: Winston W. Royce, "Managing the development of large software systems", 1970, Figure 2

ただし、この様子を「ウォーターフォール(waterfall)」にたとえたのは、ベルとセイヤーだ。当のロイスの論文内にその単語は出てこない。彼らが1976年に書かれた先述の論文内で、参考文献として挙げたロイスの論文に対して使われた言葉であった。ロイスの論文の6年後のことである。ベルとセイヤーのFigure 1が、ロイスのFigure 2とそっくりなのはそのためだろう。なお、フェーズ分けは異なっており、ロイス版は次のように並んでいる。

1. システム要件
2. ソフトウェア要件
3. 分析
5. プログラム設計
6. 実装
7. テスト
8. 運用

ウォーターフォールという言葉は、ベルとセイヤーによるこの1976年の論文が初出ではないかとも言われているが8、その真偽は定かではない。マーチンは、それより4年早い1972年頃に、当時の業界誌でウォーターフォールをはじめて目にしたと述べている5

誤った理解に基づくウォーターフォール

マーチンによれば、当時広まり始めたウォーターフォールモデルは、誤った理解に基づくものだと言う1。ロイスの論文2ページめに現れるFigure 2だけを見て内容を推測した人たちの誤解によるものだと言うのだ。

それは、どのようなモデルとして理解され、ウォーターフォールという言葉と紐づけられて広まったのだろうか。

1996年に出版された書籍『Rapid Development』の中で、マコネルがウォーターフォールの特徴を説明している1。彼はこれを「純粋なウォーターフォール(pure waterfall)」と呼んだ。それを整理して要約すると次のようになる。これが、当時から今もなお続く、一般的なウォーターフォールの理解だろう。ドキュメントを駆使することでプロセスを動かす前提であることがうかがえる。

  • 段階的進行: ソフトウェアコンセプトからシステムテストまで、各フェーズを順番に進める
  • フェーズ完結型: 現フェーズのすべてのタスクが完了したとみなされるまで、次フェーズに進めない
  • ドキュメント駆動: 各フェーズのアウトプットはドキュメントであり、それが次フェーズのインプットとして引き継がれる
  • ドキュメントによる進捗管理: ドキュメントが全体の進捗を示す指標として機能する
  • 人員が不連続: フェーズごとに担当者が異なり、プロセス全体を通して人員の連続性がない(ドキュメントによってそれを繋いでいる)

なお、ここでのウォーターフォールの流れは、次のようにフェーズが分解されていることが前提とされている。

1. ソフトウェアコンセプト
2. 要求分析
3. アーキテクチャ設計
4. 詳細設計
5. 実装とデバッグ
6. システムテスト

マコネルはまた、ウォーターフォールが適しているプロジェクトについても述べている。それを整理・要約したものが次の内容だ。最後の項目以外は総じて、不確実性が低く、予測可能性が高いプロジェクトに向いているということだろう。

  • 要件が安定しているプロジェクト: プロジェクトの初期段階で要件が明確で変わることが少ないのであれば、計画的に進められる
  • 既存システムのメンテナンスリリースプロジェクト: 既存システムの改修であれば、不確実性が低く、要件のぬけもれなどによる手戻りが生じにくい
  • 別のプラットフォームへの移行プロジェクト: 既存システムを別のプラットフォームに移行する場合、要件が明確であるため、比較的に計画通り進めやすい
  • よく理解している技術的方法論を利用するプロジェクト: チームが十分に理解している技術や手法を用いるプロジェクトでは、比較的に精度の高い計画と設計で進められる
  • よく理解しているが複雑なプロジェクト: 複雑であっても要件が明確であるなら、その複雑性をフェーズごとに段階的に詳細化して進められる
  • 未熟なメンバーがいるプロジェクト: 技術的に弱いスタッフや経験の浅いスタッフがいても、明確なフェーズと手順により、メンバーが作業しやすくなる
  • 品質が最優先のプロジェクト: 品質が優先されるのであれば、コストや納期を超過しても、フェーズごとに十分な品質を担保しながら進められる

マーチンは、当時を振り返り、ウォーターフォールをはじめて目にした時に、「天の恵み」だと感じたと言う5。しかし、実践したものの、このようなウォーターフォールはうまくいかなかったようだ。

それでは、ロイスが本来示そうとしたソフトウェア開発モデルとはどういったものだったのだろうか。それについて詳しく見る前に、ロイスも指摘するウォーターフォール的なソフトウェア開発に関する問題点について見てみることにする。

ウォーターフォールの手戻り問題

ウォーターフォールの代表的な問題点の1つは、下流のフェーズから上流のフェーズへの手戻りリスクが大きくなることだ。ウォーターフォールでのそれぞれのフェーズは、先行フェーズのアウトプットをインプットとして進められる。そこに欠陥があれば、原因を作ったフェーズまで差し戻して修正しなければならない。上流でのその修正の影響によって、下流で既に着手したり完了していた作業を台無しにするかもしれないのだ。この問題は、ロイスの論文でも指摘されている。

これは、メタファとされる「滝」とは少々印象が異なる。滝というものは、下段に落ちた水が上段に戻ることがない。しかし、実際のトップダウン・アプローチでのソフトウェア開発では、どうしても上流のフェーズに戻ることがあるのだ。マーチンは、「天の恵み」であるはずのウォーターフォールがうまくいなかった様子を、次のように述べている5

だが、ウォーターフォールはうまくいかなかった。それから30年間、私と同僚たちは、そして世界中のプログラマーたちは、分析や設計が正しくできるように、何度も何度も何度も試行錯誤を重ねた。だが、どれだけ正しくやったと思っても、実装フェーズになると指の間からこぼれ落ちていく。マネージャーや顧客から厳しい眼差しを向けられるため、何か月もかけて慎重に計画を立ててみるが、それでも大幅に遅れてしまう。

Robert C. Martin (著), 角 征典 (翻訳), 角谷 信太郎 (翻訳),『Clean Agile 基本に立ち戻れ』, KADOKAWA, 2020, 第1章 より引用

「それから30年間」と言うのは、彼がウォーターフォールを知った1972年から数えるとおおよそ2000年頃にあたる。1980年代後半から1990年代初頭にアジャイル改革が始まったが、アジャイルソフトウェア開発宣言が2001年だ9。おそらく、30年間というのは、そこまでの期間を指しているのではないか。

ウォーターフォールの手戻りについて、ロイスの論文内ではFigure 3として、次のような図が描かれている。隣り合うフェーズの間で反復が生じている様子が分かる。いったん次のフェーズに進んでも、そこで気付いた問題によって、前のフェーズで見直しが入ることを示しているのだ。

ロイスがFigure 3として示した先行フェーズへの手戻り
出典: Winston W. Royce, "Managing the development of large software systems", 1970, Figure 3

この図のように1つ前のフェーズに戻るだけなら理想的だ。影響は最小限にとどまる。

しかし、実際には2つ以上前のフェーズに戻るリスクがあるとロイスは断言している。こうなると話は違ってくる。それが、Figure 4だ。

ロイスがFigure 4として示したフェーズを越えた手戻り
出典: Winston W. Royce, "Managing the development of large software systems", 1970, Figure 4

これについて、ロイスは次のように述べている。テストによって発見された問題が、設計変更を生じさせ、それが要件の変更にまで遡る可能性を示唆しているのだ。

The required design changes are likely to be so disruptive that the software requirements upon which the design is based and which provides the rationale for everything are violated. Either the requirements must be modified, or a substantial change in the design is required. In effect the development process has returned to the origin and one can expect up to a 100-percent overrun in schedule and/or costs.

必要な設計変更は、設計のベースでありすべての根拠となるソフトウェア要件に違反するほど破壊的になる可能性がある。要件の修正か、設計の大幅変更が求められる。事実上、開発プロセスははじめに戻り、スケジュールやコストは100%超過することが予想される。

Winston W. Royce, "Managing the development of large software systems", 1970 より引用(日本語訳は筆者によるもの)

マコネルは、ウォーターフォールにおける手戻りを、「命がけ」での鮭の滝登りにたとえているが1、ロイスの指摘はまさにそれを説明したものだ。

ベルとセイヤーの論文でも、特に要件の間違いを問題視している。初期に定義された要件は、不正確であったり、曖昧、矛盾、欠落することがある。それが、設計や実装の段階になって問題を生じさせるのだ。彼らの調査では、要件には以下のような欠陥のタイプがみられ、いずれのプロジェクトであってもその相対的な発生頻度は似通っていた。特に、4系のRequirement Incorrectや、3系のMissing/Incomplete/Inadequate, 7系のRequirement Unclearが多い。また、設計する段階になって初めて、これらの要件の欠陥を検出することが多かったようだ。

出典: T. E. Bell, T. A. Thayer, "Software requirements: Are they really a problem?", 1976, Table 2

実装を進める前に、完璧な要件や分析、設計を見出すことは難しい。それを実行するのがドメインの専門家であっても、ソフトウェア開発の専門家でもだ。単純な要件項目であっても、実際に動くソフトウェアを見るまでは、気付かないことも多い。膨大な時間をかけて要件をかため、分析し、設計したところで、おそらく状況は大きく変わらない。むしろ、要件や分析、設計が1度で完全になることなどない前提で、プロセスを組み立てた方が現実的なのだろう。

本来想定されていたウォーターフォール(ロイスのソフトウェア開発モデル)

前節の問題に対して、ロイスは論文内で5つの対策を提案している。これが、本来、彼が提示していたソフトウェア開発モデルだ。

  1. プログラム設計を先に実施する: 分析に先だってプログラム設計者が予備的なプログラム設計を行い、その結果を分析に対する技術的制約として分析者に引き継ぐ
  2. 設計をドキュメント化する: ソフトウェアの管理は、非常に高度なドキュメントなしには不可能であり、徹底したドキュメント化が重要。それを関係者や顧客とのコミュニケーションの基盤とし、エビデンスとして利用する。納品時は、予備設計に関するドキュメント以外はすべて最新の状態にすること
  3. 2回実施する(do it twice): 要件が固まった段階でパイロットプロジェクトを走らせ、初期バージョンのシステムを作って潜在的な問題を洗い出す。顧客に引き渡すシステムは、その結果を反映して開発したバージョンとする
  4. テストを計画、管理、監視する: 1~3までで品質を十分に確保したうえで、テストの専門家による網羅的で明確な基準を持ったテストを計画・実施し、その進捗を管理する
  5. 顧客を巻き込む: ソフトウェア設計で何をやるかは事前の合意後も解釈に幅があるため、最終的な納品前の早い段階で顧客がコミットするよう、彼らを巻き込むことが重要である

5つの対策を含めたロイスのソフトウェア開発モデル全体像
(1の予備的プログラム設計は3番目のフェーズとして分析フェーズの前に挿入されている / 2のドキュメントは、図中に置かれた本のような図形を指す / 3のパイロットプロジェクトは図の中央上段にある6つのフェーズのことであり、最後のusageフェーズは「試用」や「評価」を指す / 4は特にプログラム設計フェーズとテストフェーズから伸びているテスト仕様書への線付近を指す / 5での顧客の関与は図中の丸い画像でのレビューなど)
出典: Winston W. Royce, "Managing the development of large software systems", 1970, Figure 10

1で分析より先にプログラム設計を実施することで、プロセスが部分的にボトムアップ・アプローチになる。こうすれば、ウォーターフォールトップダウン・アプローチ)の弱点を補うことができる。

3の「2回実施する(do it twice)」は、フレデリック・P・ブルックス Jr.(Frederick P. Brooks, Jr.)の「一つは捨石にするつもりで(throw one away)」に似たアイデア10。最初に完成したシステムは使い物にならないから、先にパイロットシステムを作ってみる。そしてそれを破棄し、再度デザインして問題が解決したバージョンを正規版として提供する。これが、ブルックスの主張だ。考えてみれば、これが書かれた書籍『人月の神話』の初版本の出版が1975年だから、時期的にはロイスの論文と同じ頃のものである。

注意が必要なのは、ロイスの言うパイロットプロジェクトは、要件が固まり、予備的設計が終わったあとに開始される点だ。そこから、技術的な問題点を洗い出して、洗練させることがその主目的であると思われる。そこに割く時間は、本来のプロジェクト期間の4分の1から3分の1程度としている。

5の「顧客を巻き込む」の必要性について、ロイスは次のように述べている。要件や設計は、顧客との間でどれだけ精緻に言語化して事前合意していても、それだけでは不十分なのだ。

For some reason what a software design is going to do is subject to wide interpretation even after previous agreement.

ソフトウェア設計が何をしようとしているかに対しては、事前に合意を得ていても、解釈が大きく分かれることがある。

Winston W. Royce, "Managing the development of large software systems", 1970 より引用(日本語訳は筆者によるもの)

なお、顧客とプロジェクトマネージャーを除くと、ロイスの論文内には少なくとも次の役割が登場する。各フェーズごとに担当者が分かれていることを前提としているということだろう。2でドキュメント化を重視する理由には、フェーズ間での引き継ぎで利用する意図もあるのだ。

  • 分析者: 分析フェーズを担当
  • プログラム設計者: 予備的プログラム設計とプログラム設計を担当
  • プログラマ: 実装を担当
  • テスト専門家: テストを担当
  • 運用指向の人材: 運用を担当(ただし、優れたドキュメントがないなら、ソフトウェアを構築した人が運用も担当する方がましだとの記述あり)

ロイスの改善案は、あくまでも1970年頃に書かれたものだという点を忘れてはならない。そのまま鵜呑みにせず、当時のソフトウェア開発環境を考慮すべきだろう。当然、ビルド、テスト、デプロイの自動化などの技術はまだ進んでいない。おそらく、テストを実施すること自体にも、計算機リソースを気にする必要もあっただろう。彼が極端にドキュメントに頼っているように感じるのも、そういった背景もあるのではないか。マーチンの書籍にもあるが、コーディング用紙に鉛筆でコードを書き、キーパンチオペレーターがそれをカードにパンチしていた時代である。

IEEE/EIA 12207が挙げる3つの開発戦略とウォーターフォールの関係

1998年に発行されたソフトウェア開発のプロセス標準であるIEEE/EIA 12207の中で、ウォーターフォールという名が正式に登場した11。そこに至るまでの経緯は、次のブログ記事で既に詳しく解説されている。アメリカ国防総省が1985年に発行したDOD-STD-2167や、その後継の2167Aからの変遷がよく分かるだろう。それらの文書がロイスの論文に強く影響を受けていることも感じられる。

qiita.com

IEEE/EIA 12207.2の付録Iの中では、次の3つの開発戦略が比較されている12。プロジェクトの性質に合った開発戦略を選択しようという話だ。

  • Once-through: 開発サイクルを一回だけ実施する戦略。ユーザーニーズを把握し、要件を定義した後、設計、実装、テストを行い、修正を加えつつ最終的に納品する
  • Incremental: 最初にユーザーニーズとシステム全体の要件を定義した後、開発を段階的に進める戦略。最初の段階で一部の機能を実装し、次の段階でさらに機能を追加していき、最終的に全体を完成させる
  • Evolutionary: 初期の不完全なユーザーニーズや要件に基づいて開発を始め、段階的にシステムを洗練させていく戦略。各段階でユーザーニーズや要件を評価・調整しながら、完成形に向かって進化させる

文書内では、開発サイクルを1回だけ実施するonce-through戦略の別名が「ウォーターフォール」モデルだとしている。このことからも、当時のウォーターフォールには、ロイスの開発モデルの特徴の1つである「2回実施する」が含まれていないことが分かる。

「2回実施する」を発展させたものがincremental戦略に見えるかもしれないが、そうではないだろう。ロイスの開発モデルでは、先にプロトタイプを作ることで不確実性を削減し、そこで得た学びと経験によって最終プロダクトをあらためて確実に作るものであった。しかし、incrementalは、完成させるソフトウェアをいくつかに分け、それを段階的に積み上げながら全体を作り上げていくものだ。

evolutionary戦略もincrementalと同様に開発サイクルを任意の回数繰り返すものだが、最初にすべての要件を定義しない点が大きく異なる。さらに、最終的なソフトウェアを完成させるまでのアプローチも違う。incrementalでは開発サイクルを繰り返すことで段階的に機能を追加していく。しかし、evolutionaryではユーザーニーズと要件をより明確にし、ソフトウェアシステムを洗練させていくことに主眼が置かれている。

各開発戦略のイメージ

ところで、スクラムをはじめとするアジャイルソフトウェア開発のフレームワークは、incrementalとevolutionaryの特徴をかけ合わせた戦略とは言えないだろうか。スプリント(イテレーション)をまわしながらソフトウェアを段階的に作りあげる点ではincrementalだ。最初に要件をすべて定義せず、徐々に洗練・進化させていく点ではevolutionaryである。つまり、アジャイルソフトウェア開発は、once-throughであるウォーターフォールと明確に異なる特徴を持つということだろう。

なお、同文書の中では、3つの開発戦略をどのようなケースで利用すべきであるか、その例をリスク項目と機会項目分け、Figure I.2 として示している。

その内容を見ると、once-through戦略、つまりウォーターフォールは、要件が明らかで不確実性が低く、規模が大きすぎず、予算や人員に対する制限が厳しくないプロジェクトに向いているとされている。それはやはり、手戻りリスクを案じてのことではないだろうか。

これだけを見るとウォーターフォールの用途が限定的に見えてしまうが、本当にそうなのか。実際にウォーターフォール開発を実践する現場を見ると、プロジェクトを数回に分けて実施することも多い。「フェーズ・ワン」「フェーズ・ツー」などと呼んで分けるのがそれだ。そうすれば、個々のプロジェクトは小さくなり、扱いやすくなる。また、同付録I内にも、要求分析とシステムアーキテクチャ設計の後に、プロジェクトを複数のサブプロジェクトに分けて開発を進めるアイデアも載せられている。

つまり、開発現場では、プロジェクトが置かれる実情に合わせ、ウォーターフォールに改良が加えられているのだ。次の節では、ウォーターフォールの弱点を改善した修正版ウォーターフォールをいくつか見てみることにする。

修正版ウォーターフォール

マコネルが自著の中で3つの修正版ウォーターフォール(modified waterfalls)について解説している1。これらはウォーターフォールの問題点を補うために発展したものだろう。

それぞれの修正版モデルを見ると分かるが、いずれも現在はそれと知らずに開発手法に取り込まれているものではないだろうか。

Sashimi (Waterfall with Overlapping Phases)

このモデルでは、1つのフェーズが開始すると、それが完了する前に次のフェーズも開始する。2つ以上のフェーズの実施時期がオーバーラップするようにして進行するのだ。これが、サシミと命名された理由である。フェーズが重なり合うさまが、サシミの盛り付けに似ている。富士ゼロックスの新製品開発で用いられた。

フェーズ間のオーバーラップ

たとえば、要求分析フェーズを進めている最中に、次フェーズであるアーキテクチャ設計が開始され、詳細設計も始まっているかもしれない。こうすることで、より詳細なフェーズで気付いた問題点や学びを、並行して進行中の上位フェーズに反映しやすくなる。ウォーターフォールが抱えていた、段階的に詳細化していくことの難しさを考えると、これは合理的なモデルである。

純粋なウォーターフォールモデルでは、フェーズの重複をできる限り避け、段階的に詳細化を進めるので対称的だ。フェーズの完了や、アウトプットであるドキュメントの完成状況で進捗を測ることができなくなるという欠点もあるだろう。

しかし、このモデルでは、そもそも作成すべきドキュメントの数が削減される。ウォーターフォールでのドキュメントの存在意義のひとつは、フェーズ間での仕様や設計の引き継ぎであった。先行フェーズと後続フェーズで担当者が異なることが想定されているからだ。しかし、フェーズをオーバーラップさせてフィードバックサイクルを回すなら、担当者に連続性を持たせる方が合理的だろう。そうすれば引き継ぎの必要すらない。

Waterfall with Subprojects

詳細設計がすべて終わるまですべての実装を待つ必要はない、というのが、このモデルのコンセプトである。アーキテクチャ設計が完了したら、各サブシステムごとに詳細設計からテストまでを並行して進める。そして、最後にすべてをつなぎ合わせてシステムテストを実施するのだ。

このモデルでは、アーキテクチャ設計の時点でサブシステム間の依存関係をうまく整理した上でサブプロジェクトにスピンオフできなければ、プロジェクトが混乱をきたすリスクがあるだろう。

Waterfall with Risk Reduction

要件やアーキテクチャが抱える不確実性に起因するリスクをプロジェクトの最初に低減することが、このモデルの特徴だ。そのため、要求分析より前に、それらを検証するためのスパイラルを配置する。例として、マコネルは次のような活動を通して学びを得ることを挙げている。

  • ユーザーインターフェイスのプロトタイプを開発
  • システムストーリーボーディングを使用
  • ユーザーインタビューを実施
  • ユーザーが古いシステムを操作しているところを撮影

リレー方式(ウォーターフォール)からサシミ方式(修正版ウォーターフォール)、ラグビー方式へ

ロイスの論文がウォーターフォールの起源と呼ばれることに対し、竹内弘高と野中郁次郎が書いた1986年の論文は、スクラムの原点と言われる。それが、"The New New Product Development Game" だ。この中で、1970年代から1980年代にかけて、新規プロダクトの開発に新手法を取り入れた日本およびアメリカの企業6社の開発プロセスを分析している。

竹内と野中は、開発プロセスを従来の「リレー方式」と、新たな手法とする「サシミ方式」「ラグビー方式」の3つに分類した。リレー方式は、ウォーターフォールのようにフェーズからフェーズと順番に進む「昔ながらの逐次型」とされている。サシミ方式は修正版ウォーターフォールでも挙げた富士ゼロックスが用いたモデルだ。ラグビー方式も、サシミ方式と同様にフェーズをオーバーラップさせながら進めるもので、本田技研工業やキャノンに見られるモデルである。

ラグビー方式がサシミ方式と区別されているのは、前者のオーバーラップの多重度が後者より高いからだ。それは、リレー方式と比較する形で次のように述べられ、素早く柔軟に新規プロダクトを開発したい企業にとって「絶対に必要である」とされている。

一方、ラグビー方式だと、各部門から選び出されたメンバーが最初から最後まで一つのチームを構成し、製品開発プロセスは、こうしたチームの絶え間ない相互作用から生まれてくる。そのプロセスは、きちんと境界線のある高度に構造化された段階を進んでいくのではなく、チームメンバー同士の相互作用から生じるのだ。

引用: 竹内 弘高 (著), 野中 郁次郎 (著), DIAMONDハーバード・ビジネス・レビュー編集部 (編集), "新たなる新製品開発の方法(DIAMOND ハーバード・ビジネス・レビュー論文)", ダイヤモンド社, 2023

リレー方式、サシミ方式、ラグビー方式

リレー方式を用いるリスクは、競争の激しい市場の中で抜きん出るための「スピードと柔軟性」という目標と相容れないおそれがあることとされる。専門化された個々のフェーズで分業体制を取り、段階的に進めるより、一体型のラグビー方式の方が激しい競争環境により対応しやすいからだ。たとえば、リレー方式では、1つのフェーズで遅れが生じると、それが後続プロセスすべてに波及するリスクもある。しかし、ラグビー方式なら、1つのフェーズが遅れても、オーバーラップする他のフェーズも何とか進めていくことができる。

さらに、竹内と野中は、最先端企業の新規プロダクト開発プロセスには、フェーズのオーバーラップも含め、次の6つの特徴が見られると言う14

  1. 内在する不確定性: 経営陣が示すのは戦略的方向性と極めて難易度の高い目標であり、何をどうやるのかは開発担当チームに任せる
  2. 自己組織化する開発担当チーム: 情報ゼロの状況から、開発プロセスが独自の動的秩序を形成し、チームが次第にスタートアップのような動きになる。そして自律性、自己超越、異種共創という特徴を持つに至る
  3. 開発フェーズのオーバーラップ: 開発プロセスの各フェーズを重複して進める、分業という昔ながらの概念を捨てた方式。チームメンバーが開発プロセスのあらゆる側面に責任感を持つ
  4. 多重学習: 幅広い知識と多様なスキルを獲得するために、社内の各階層(個人、グループ、会社)を超えた学びと、専門を超えた学びの2つの次元で学びが生じる
  5. さりげない管理: 自己管理とピアプレッシャーによる管理、愛による管理の3つでチームを管理する
  6. 学びの組織的な伝達: プロジェクトを通して得た学びや、成功事例から得られた教訓を、次のプロジェクトに活かせるよう伝達する。また、過去の成功事例に囚われすぎないよう、アンラーニングにも努める

これら6つの特徴を見ると、そこにアジャイルやDevOpsに通じるものがある。また、分業制のウォーターフォールとは違い、開発プロセス全体を、1つの「チーム」という単位で活動することが強調されている点も興味深い。ここが、フェーズのオーバーラップがもたらすものなのだろう。

チーム立ち上げ時点では「情報ゼロ」状態だが、そのうち市場に関する知識や技術者界隈の知識をメンバー間で共有するようになる。こうしてチーム全体が一つの単位として動き始める。同時に、個々のメンバーとチーム全体とが不可分になる。個人のリズムとチーム全体のリズムが重なり始め、まったく新しい鼓動が生まれる。この鼓動が推進力となり、チームを前進させる。

引用: 竹内 弘高 (著), 野中 郁次郎 (著), DIAMONDハーバード・ビジネス・レビュー編集部 (編集), "新たなる新製品開発の方法(DIAMOND ハーバード・ビジネス・レビュー論文)", ダイヤモンド社, 2023

なお、この論文とスクラムの関係については、野中自身が登壇した下記イベントで述べられている。

www.publickey1.jp

軽量級プロセス(アジャイル開発プロセス)と重量級プロセス(ウォーターフォール

アジャイルソフトウェア開発宣言が公開されたのは、2001年だ。同年2月にユタ州スノーバードに集まった17名のソフトウェアの専門家によって原案が作成された。そこには、ロバート・C・マーチンも名を連ねている。また、スクラムの生みの親であるケン・シュウェイバー(Ken Schwaber)とジェフ・サザーランド(Jeff Sutherland)もだ。9

このスノーバードでの会合は、「軽量級プロセスのサミット(Light Weight Process Sumit)」と名付けられた点が興味深い。軽量級プロセスとはもちろん、アジャイルソフトウェア開発を指す。では重量級プロセスはと言うと、ウォーターフォールがその代表であった。アジャイル以前に主流であった、事前計画型でプロセス重視なやり方でのプロジェクト失敗の経験を積み重ねた人々が、軽量級プロセスに惹きつけられていったのだろう。5

宣言の冒頭は次のとおりだ。重量級プロセスと軽量級プロセスを比較するような形で、4つの中核価値が表現されている。

私たちは、ソフトウェア開発の実践
あるいは実践を手助けをする活動を通じて、
よりよい開発方法を見つけだそうとしている。
この活動を通して、私たちは以下の価値に至った。

プロセスやツールよりも個人と対話を、
包括的なドキュメントよりも動くソフトウェアを、
契約交渉よりも顧客との協調を、
計画に従うことよりも変化への対応を、

価値とする。すなわち、左記のことがらに価値があることを
認めながらも、私たちは右記のことがらにより価値をおく。

引用: 『アジャイルソフトウェア開発宣言 - agilemanifesto.org』, https://agilemanifesto.org/iso/ja/manifesto.html (引用内の強調は筆者によるもの)

前節までで、"純粋な" ウォーターフォールは、作り上げるソフトウェアシステムがプロジェクトの初期段階で明らかにできる場合に適していることが分かった。計画通りに作り上げれば、それが誰かに価値になるということだ。そして、計画通りに作るためには、プロジェクトの初期段階から不確実性が低いことが条件となる。この条件が成立しないままウォーターフォールで進めると、計画通りにプロジェクトが進まないか、作り上げたソフトウェアシステムが誰の価値にもならないかのいずれかなのだ。

アジャイルソフトウェア開発では逆に、不確実性が高く、計画通りに進めても、作り上げたソフトウェアシステムが誰かの価値にならないかもしれないことを前提としている。ここに、純粋なウォーターフォールアジャイルソフトウェア開発が目指すものに対する違いが読み取れる。その違いこそが、両者の開発プロセスに大きな違いを生んでいるのだ。

アジャイル側の視点にたって、両者を比較してみよう。

ウォーターフォールでは、顧客が実際にソフトウェアに触れられるのがプロジェクトの最後だ。ドキュメントであればプロジェクトの途中段階で確認できるものの、それは中間成果物でしかない。それだけでは価値とは言えず、最終成果物たるソフトウェアを待っている。顧客にとっては、待たされる間、ずっと不安だろう。本当にソフトウェアシステムができあがるのか、それが想定通りのものになっているのか分からないからだ。

アジャイルソフトウェア開発は、動くソフトウェアを重視する。スクラムを実践するプロジェクトであれば、プロジェクトの途中であっても、スプリントの度に、顧客は動くソフトウェアを目にできる。それを実際に触ってみることで、本当に価値のあるものになっているかどうかを見極められる。想定通りになっていなかったり、想定通りであってもそれが間違っていたと気付いたなら、その修正を以降の計画に組み込むことも可能だ。

顧客による動くソフトウェアのレビュー

プロジェクト途中でのそのような計画変更は、ウォーターフォールなら死活問題となる。たとえば要件が変わってしまったら、最上流の要件定義からやり直しとなるからだ。その変更が、要件定義より下流に影響する。そうなれば、変更前に作り上げた成果物は台無しになる。そして、想定していたコストや期日までにプロジェクトが終わらなくなってしまう。だから、できる限り変化を受け入れたくないという心理が働く。

アジャイルであれば変化を受け入れる。計画通りにプロジェクトが終わらなくなる点はウォーターフォールと変わらない。では、なぜ変化を受け入れるのか。その理由は2つあるのではないか。1つは、プロジェクト初期段階ですべての要件を決めきらないこと。それが、変化を柔軟に受け入れやすい素地となる。もう1つは、計画通りに作りあげることが価値になると考えないこと。変化することが価値になるのであれば、計画を変えることもいとわない。

プロジェクト途中の計画変更

変化を受け入れるという点で障壁となるのが顧客との契約だろう。変化によって、予算、期日、要件のいずれかが、契約違反となるかもしれない。これが、受託開発業務においてアジャイルソフトウェア開発手法を導入しにくい理由ではないだろうか。顧客と協調し、プロジェクトを進めながら繰り返し計画を見直すアジャイルなアプローチは、従来型の契約では実践が困難なのだ。

まとめ

ウォーターフォールモデルは、1960年代頃のボトムアップ・アプローチに代わって用いられたトップダウン・アプローチであった。トップダウン・アプローチを説明する簡易な図が滝に見えることで、そこから連想される一方向に進む開発モデルとして、世の中に広く知れ渡ることとなる。

ロイスが本来伝えようとした開発プロセスモデルは、手戻りリスクを最小化しようとするものだ。はじめにすべての要件を決定し、そこから段階的に詳細化していく進め方は、手戻りが生じやすい。それは特に、要件定義に関する問題が顕著であり、下流のフェーズで不正確であったり、曖昧、矛盾、欠落が見つけられることが多い。これが、ウォーターフォールと呼ばれるモデルが抱える代表的な問題点である。

IEEE/EIA 12207での開発戦略の比較では、不確実性が高いプロジェクトには、once-through戦略、すなわちウォーターフォールモデルが不向きであるとしている。それは、上述の通り、手戻りリスクが大きくなるからだろう。

また、竹内と野中は、ウォーターフォールのように各フェーズをリレー方式で繋ぐ開発プロセスよりも、フェーズをオーバーラップさせるサシミ方式やラグビー方式のほうが、スピードと柔軟性に優れていると述べている。これは、ウォーターフォールとは対照的に、オーバーラップ方式が不確実性の高いプロジェクトに適していることを示している。それは、彼らの論文を原点とするスクラムにも言え、アジャイルソフトウェア開発全般にも当てはまる考え方だろう。

ここで思い出すのは、クネビンフレームワークだ。ウォーターフォールは「煩雑(complicated)」な領域で役立ち、アジャイルソフトウェア開発は「複雑(complex)」な領域で役立つ。前者は事前分析によって正しい答えが導きだせる領域である。後者は、探索的なアプローチがなければ何が正しいか不明な領域だ。

ウォーターフォールが対象とするプロジェクトは、計画通りにソフトウェアシステムを作り上げれば、それが誰かの価値になる場合ということになる。逆に、アジャイルソフトウェア開発が対象とするのは、計画通りに作り上げても、それが誰の価値にもならないかもしれないことを前提としている。ここが大きく違うのだ。

しかし、純粋なウォーターフォールを諦めてアジャイルソフトウェア開発のプロセスフレームワークが作り上げられていったように、ウォーターフォールも工夫を重ねて使いこなされている。実際、私もこれまで、様々な領域で、ウォーターフォールを使って成功したプロジェクトをみてきた。それらはいずれも、純粋なウォーターフォールではなく、マコネルが紹介した修正版ウォーターフォールに近いものだった。

プロジェクトの性質によって開発プロセスを使い分けるべきとは言うが、それはなかなかに難しい。同じ組織が、複数の開発プロセスを起用に使い分け、使いこなすことなど本当に可能なのだろうか。1つの開発プロセスでさえ、なじませ、改善を重ねることに苦労する。結局のところ、なにか1つに定めて、それを組織の目的に合わせて調整し、改良し続けるのが一番なのではないだろうか。

参考文献

  1. Steve McConnell (著), "Rapid Development", 日経BP, 1996, Chapter 7
  2. SDLC とは: ソフトウェア開発ライフ サイクルの概要 - GitHub Resources
  3. NATO Software Engineering Conference 1968 - The NATO Software Engineering Conferences
  4. Software crisis - Wikipedia
  5. Robert C. Martin (著), 角 征典 (翻訳), 角谷 信太郎 (翻訳),"Clean Agile 基本に立ち戻れ", KADOKAWA, 2020, 第1章
  6. T. E. Bell, T. A. Thayer, "Software requirements: Are they really a problem?", 1976
  7. Winston W. Royce, "Managing the development of large software systems", 1970
  8. 小椋 俊秀, "ウォーターフォールモデルの起源に関する考察 ウォーターフォールに関する誤解を解く", 2013
  9. アジャイルソフトウェア開発宣言
  10. Jr FrederickP.Brooks (著), Frederick P. Brooks,Jr. (原名), 滝沢 徹 (翻訳), 牧野 祐子 (翻訳), 富澤 昇 (翻訳), "人月の神話【新装版】", 丸善出版, 2010, 第11章
  11. IEEE, "12207.0-1996 - IEEE/EIA Guide for Information Technology - Software Life Cycle Processes - Implementation Considerations", 1998
  12. IEEE, "12207.2-1997 - IEEE/EIA Guide for Information Technology - Software Life Cycle Processes - Implementation Considerations", 1998
  13. Hirotaka Takeuchi, Ikujiro Nonaka, "The New New Product Development Game", 1986
  14. 竹内 弘高 (著), 野中 郁次郎 (著), DIAMONDハーバード・ビジネス・レビュー編集部 (編集), "新たなる新製品開発の方法(DIAMOND ハーバード・ビジネス・レビュー論文)", ダイヤモンド社, 2023

SPACEでの指標選びは網羅性ではなく関連性と一貫性を持たせて絞り込むことが大切である、さらに……

SPACEフレームワークを活用するなら、選択する指標に関連性と一貫性を持たせて絞り込むことが大切です。思いつくかぎりの指標をただやみくもに集めて網羅性を高めても、そこから得られる情報はほとんどないでしょう。

これが、ニコール・フォースグレンらによる論文 "The SPACE of Developer Productivity: There's more to it than you think." を読んだ時に私が感じたことです。

queue.acm.org

本稿は、上述論文に基づいてSPACEフレームワークを解説するとともに、その活用方法についても考察しています。

特に、5つのディメンションについては、論文から読み取りづらい点をフォローするようにしました。ここが理解できないと、フレームワークの魅力がなくなってしまいます。実際、開発チームのマネージャーらやメンバーらと話していると、SPACEフレームワークが定義する5つのディメンションと、具体的な指標とがどう対応付けられるのかが判別しづらいという声も聞こえます。このような悩みが解消されることも、本稿を書くことにした動機です。

SPACEフレームワーク

SPACEフレームワークは、開発生産性(developer productivity)を計測する指標の選択に、多次元的(multidimensional)な視点をもたらすフレームワークです。DORAによって開発され、書籍『LeanとDevOpsの科学』の著者でもあるニコール・フォースグレン(Nicole Forsgren)らによって、2021年に論文が公開されています。

開発生産性の計測はこれまで、エンジニア個人の活動を計測するたった1つの指標で表せるといった誤解や誤認も多く、不適切・不正確に評価されたり、あるいはその難しさゆえに諦められていた領域です。ニコール・フォースグレンらの論文では、この領域における誤解を5つの「神話(myth)」として指摘しています。

Myth: Productivity is all about developer activity

(日本語訳)神話: 生産性は開発者の活動だけに関するものである

Myth: Productivity is only about individual performance

(日本語訳)神話: 生産性は個人のパフォーマンスだけに関するものである

Myth: One productivity metric can tell us everything

(日本語訳)神話: 1つの生産性メトリクスが全てを教えてくれる

Myth: Productivity Measures ARE useful only for managers

(日本語訳)神話: 生産性指標はマネージャーにとってのみ有用である

Myth: Productivity is only about engineering systems and developer tools

(日本語訳)神話: 生産性はエンジニアリングシステムと開発者ツールだけに関するものである

前述の論文では、これらの神話を踏まえたうえで、開発生産性を計測するために3つ以上の観点を組み合わせるべきだと説いています。SPACEでは、その観点となるものを5つのディメンションに分類し、次のように命名しました。これらの頭文字を繋いで "SPACE" なのです。

  • 満足度と幸福度 / Satisfaction and well-being
  • パフォーマンス / Performance
  • 活動 / Activity
  • コミュニケーションとコラボレーション / Communication and collaboration
  • 効率とフロー / Efficiency and flow

※日本語表記は、書籍『エンジニア組織を強くする 開発生産性の教科書』に準じています。

またSPACEでは、定量的な指標だけにこだわらず、主観的な経験や感情を評価する知覚的指標を含めることも推奨しています。定量化された指標より、状況を正しく反映した情報を与えてくれる領域もあるからです。特に、「満足度と幸福度」の計測は、アンケートなどを用いた知覚的指標に頼ることが多くなる領域でしょう。

さらに、選択しようとする指標が扱うスコープが「個人レベル」「チームレベル」「システムレベル」のいずれに該当するかを意識することも重要です。いずれかのレベルに偏ってしまうこともまた、正しい情報を得られなくなる要因となるからです。なお、「システムレベル」とは、「チームレベル」より広い範囲のフローを指しています。チーム間やプロセス間での仕事の受け渡しを含む範囲だと考えてください。

満足度と幸福度 / Satisfaction and well-being

「満足度と幸福度」の指標は、開発者らが自分たちの仕事に対してどれだけ充実し、幸福であり、健康的であるかという観点で計測されます。アンケートで計測される「従業員満足度」や、「燃え尽き症候群バーンアウト)」、「開発に必要なツールを持っているか」といった項目がその対象です。「開発者体験(developer experience, DevEx)」と言い換えることもできるかもしれません。「満足度と幸福度」はおそらく、その多くが知覚的指標になると考えられます。

満足度と生産性の間には相関関係があり、前者は後者の先行指標になるとも言われています。ジェフ・サザーランド(Jeff Sutherland)も自著の中で、その体験について述べています。彼のスクラムチームでは、スプリントが終わるごとに「幸福度の計測」と呼ばれる方法で振り返り(レトロスペクティブ)を実施していました。それは、次の4つの質問に対し、メンバーが順に答えていくというシンプルなものです。そして、4で得られた回答の中から1つだけをチームで選択して改善を進め、次のスプリントでその結果を確認するようにしたのです。

  1. 会社内での自分の役割について、一から五のスケールで表すとどう感じているか。
  2. 同じスケールで、会社全体についてどう感じているか。
  3. なぜそう感じるのか。
  4. 何を一つ変えれば次のスプリントでもっと幸せだと感じられるのか。

この取り組みを続けたところ、計測された幸福度が、チームのベロシティの変化の先行指標になっていることに気づいたのです。幸福度の上下が、そこから何回か先のスプリントでのベロシティの上下に連動する傾向がみられました。ベロシティ単体の指標を指して「生産性」と呼ぶことはできませんが、少なくともジェフ・サザーランドの観察からは、幸福度とベロシティの間に相関性がみられたのです。

パフォーマンス / Performance

「パフォーマンス」に含まれる指標は、アウトプットではなく、アウトカムを評価する観点で計測されます。何らかの作業の完了ではなく、その先にある成果をみるものです。指標例として挙げられているのは、信頼性やバグの少なさ、サービスの健全性、顧客満足度、顧客獲得やリテンション、機能の利用状況、コスト削減などです。

対象がアウトカムであると聞くと、本番リリースした後に計測可能となる指標のみが対象になるように感じてしまいますが、そんなことはありません。システムレベルでのアウトカムはその通りですが、チームレベル、個人レベルでのアウトカムも対象です。

個人レベルならば、誰かの作業のアウトプットに対して、その価値や成果を計測することができます。たとえば、設計・実装したコードの品質の評価は、パフォーマンス指標です。チームレベルでも同様です。あるチームによるプロセスのアウトプットの価値や成果を計測すれば、それはパフォーマンス指標となります。

「パフォーマンス」は、アウトカムを評価する
「パフォーマンス」は、アウトカムを評価する

活動 / Activity

アクションやアウトプットの数を計測する指標が含まれるのが、この「活動」です。5つのディメンションの中でもっともイメージしやすいのではないでしょうか。例として挙げられている指標は、設計文書や仕様書、作業項目、プルリクエスト、コミット、コードレビューの量や数です。また、CI/CDに関するビルド、テスト、デプロイメント/リリースの数も「活動」に含まれる指標です。

「活動」は、アクションやアウトプットの数を計測する

「活動」と「パフォーマンス」の違いがわかりにくいという声を聞くことがあります。たとえば、バグの数はパフォーマンス指標ですが、数えているのだから活動指標ではないのかと悩むマネージャーがいました。しかし、バグはアウトプットではなく、アウトプットされたコードの質を評価するために数えられるものです。だから、活動指標ではなく、パフォーマンス指標に位置づけられるのです。このように、アウトプットそのものを数えているのか、アウトプットの質を評価するために数えられたものなのか、そのどちらであるかを考えることも判断軸になります。

もう1つ興味深い例としては、「ストーリーポイントの合計」があります。完了したストーリーポイントの合計であれば活動指標なのですが、リリースしたストーリーポイントの合計ならパフォーマンス指標なのです。これはとても分かりにくい切り分けです。しかし前者はやはり、単なる活動状況をあらわしているだけなのです。作業が完了していたとしても、それがリリースされるまでは、その数字はプロジェクトの中での作業の進捗を表しているだけです。一方で後者は、実際にユーザーや顧客に提供されたプロダクトや機能の価値の大きさを測る代替指標のひとつとして考えられます。この違いが、どちらのディメンションに含まれるのかという違いになっているのです。

コミュニケーションとコラボレーション / Communication and collaboration

「コミュニケーションとコラボレーション」は、個人間やチーム内、チーム間の協力関係や情報連携の質を評価するディメンションです。効率的で効果的なコミュニケーションとコラボレーションは、パフォーマンスを高めるポジティブな要因となり得ます。だからと言って、単に多ければ良いものではなく、逆に少なければ良いというものでもありません。そこに、質や量、頻度、タイミングが問われるのです。

「コミュニケーションとコラボレーション」は、個人間やチーム内、チーム間の協力関係や情報連携の質を評価する
「コミュニケーションとコラボレーション」は、個人間やチーム内、チーム間の協力関係や情報連携の質を評価する

このディメンションに含まれる指標は、定量的に計測しにくいものが多いようです。

たとえば、「作業に対するレビューの質」や、「組織内のソーシャルネットワーク」を示す指標は、どうやって計測すべきか、ぱっと思い浮かびません。コードレビューにおけるレビュアーとレビュイーのネットワーク程度であれば、バージョン管理ツールのログからデータを得ることはできます。しかし、そのデータを利用してどのような指標を設計すれば有用な情報を得られるのかは、頭を悩ませることになるでしょう。

他にも、「ドキュメントと専門知識の発見容易性」という指標もあります。確かに、大量の新しいドキュメントや古いドキュメントが混在する社内wikiから、目当ての情報を検索で見つけ出すことは難しかったりもします。しかし、これを指標化するためには、検索エンジンに対する評価が必要となり、その実施にはそれなりの労力を要します。

あまりコストをかけすぎるより、計測しやすい定量指標や、アンケートなどを活用した知覚的指標を採用する方が良い結果がでるかもしれません。

効率とフロー / Efficiency and flow

「効率とフロー」は、フローの滞留や手戻りを抑え、どれだけ効率的にフローを進められているかを示すディメンションです。

「効率とフロー」は、滞留や手戻りを抑え、どれだけ効率的にフローを進められているかを示す
「効率とフロー」は、滞留や手戻りを抑え、どれだけ効率的にフローを進められているかを示す

リードタイムや、そこに含まれる待ち時間と付加価値時間は、このディメンションの代表的な指標でしょう。リードタイムは、何らかの作業やプロセスのフローが開始してから終了するまでの時間です。待ち時間は、リードタイムの中で、実際の作業が行われず、フローが停滞していた時間の合計です。付加価値時間はその逆で、実際に作業が行われ、フローが進んでいた時間の合計です。待ち時間が大きいほど、このフローの効率が悪かったと言えます。

テストやデプロイまで含む開発プロセスのリードタイムには、フェーズによって特性があるため、指標化する際には注意が必要です。

まず、開発プロセスが開始し、「設計と実装」開始から「コードレビュー」終了までのリードタイムは、開発項目によって大きくばらつき、そして正規分布に従わず、左に歪みます。この範囲のリードタイムは、付加価値時間を縮めることを考えるより、待ち時間を縮めることに集中した方が、リードタイム短縮に効果的です。付加価値時間が、開発項目の難易度やサイズに大きく影響されるからです。ここでのボトルネックの多くは「設計と実装」完了から「コードレビュー」開始までの待ち時間です。ここを削減することに力を注いだ方が良いでしょう。もちろん、1つあたりの開発項目のサイズがあまりに大きいようなら、それを小さくする努力をすることで付加価値時間と、リードタイムを短くすることも必要です。生存期間の長いブランチは、統合時のコンフリクト解消コストも大きくなるからです。

残りの「ビルド」開始から「デプロイ」完了までのリードタイムは、CI/CDによる自動化が進むほど安定し、一定になります。従ってこのフェーズは、自動化率と効率性を高め、品質を安定させることに注力することが、リードタイム削減に対して効果的に働くはずです。

リードタイムはフェーズによって特性が異なる
リードタイムはフェーズによって特性が異なる

指標の選択方針

SPACEを使って開発生産性を計測するなら、まずテーマを決め、それを計測する代表的な指標を1つか2つほど選び、そこからさらにテーマに沿って他のディメンションの指標を付け足していくアプローチが良いでしょう。テーマも目的も決めず、数多くの指標をただやみくもに集めて計測しても、役に立つ情報が得られるものにはなりません。関心事に基づいて指標選びに関連性と一貫性を持たせ、絞り込むことがポイントとなるのです。

フローを増やすための指標選び例

たとえば、組織のバリューストリームを通るフローを増やすことを考えているのなら、それを観察する指標を選びます。もっとも関心を向ける指標は、「効率とフロー」に位置する「デプロイの頻度(deployment frequency)」でしょう。そこを中核にして指標選びをするなら、次のようなラインナップが考えられます。

ディメンション 指標
満足度と幸福度 チームの幸福度
パフォーマンス 変更失敗率
活動 プルリクエストのサイズ、勤務時間の長さ、チームの稼働率(リソース効率)
コミュニケーションとコラボレーション プロセス間の手戻り率
効率とフロー デプロイの頻度、コードレビューの待ち時間、継続的デリバリーの自動化率とリードタイム

「満足度と幸福度」の指標としては、「チームの幸福度」が良いでしょう。いくらフローが増えても、無理を強いて実現した効率性であれば、これらの指標が悪化すると考えられるからです。特に、やりがいを持って仕事ができていないようなら、達成感が低くなります。こういった指標は、専用のツールを使って計測することをおすすめしますが、ジェフ・サザーランドがやったように、簡単な質問をチームメンバーらに投げかけるだけでも簡易に計測できます。

「変更失敗率」は、スピードを重視し過ぎて品質が犠牲になっていないかを観察するための指標として配置しています。

「プルリクエストのサイズ」は、それが大きすぎることがフローを遅くしている可能性を探るものです。大きすぎるプルリクエストは、コードレビューまでの待ち時間を長くしたり、コードレビュー自体に要する時間を長くします。また、ブランチの生存期間も長くなるため、統合ブランチへのマージ時に、コンフリクトを起こして大きな修正コストを支払うことにもなりかねません。

「勤務時間の長さ」と「チームの稼働率(リソース効率)」は、仕事量を時間でカバーしていないか、メンバーの健康面やプロジェクトの健全性を観ようとしています。後者のメトリクスは特に、チームやメンバーの勤務時間が、プロジェクトの仕事だけで埋め尽くされていないか、その余裕(遊び)を観るために使用します。私の経験では、この指標が75%から80%を超えたあたりから、メンバーらが披露や不満を頻繁に訴えるようになります。また、稼働率があまりに高すぎると、自分のタスクをこなすことだけで精一杯になり、たとえば、他のメンバーのコードレビューを放置する様子が散見されるようになります。プロジェクトやチームの問題に気づいても改善に取り組もうとしないといった状況にも陥るでしょう。チーム思考を失うのです。その結果として、フローが遅くなります。

「プロセス間での手戻り率」は、本来なら「効率とフロー」に位置づけられますが、「コミュニケーションとコラボレーション」指標としています。ここではコミュニケーションの質や量を計測するための代替指標として評価したいためです。

ソフトウェアの内部品質を改善するための指標選び例

例としてもう1つ、ソフトウェアの内部品質についても指標選びを検討してみましょう。ここでは、内部品質の指標として、「パフォーマンス」に位置する「コードカバレッジ」と「チームによる保守性の評価」という、定量指標と知覚的指標を組み合わせて計測することにします。

「コードカバレッジ」を選択する理由は、ソフトウェアの保守性を構成する3つの品質特性の1つであるテスト容易性の代替指標として、定量的に計測しやすい指標だからです。残りの2つの品質特性である理解容易性、変更容易性も、静的コード解析ツールで計測できますが、それをもってコード品質の良し悪しを判断することが難しいと感じます。いくつかの指標を組み合わせて複合的に観察することになるからです。ただし、参考情報として利用するのはとても有用でしょう。

「チームによる保守性の評価」を加えるのは、理解容易性と変更容易性を定量化しないことに対する補完です。イテレーションごとの振り返りで、チーム全員で保守性を5段階評価するといった運用を想定しています。これは、ヘンリック・クニバーグ(Henrik Kniberg)が技術的負債に関する自身のブログ記事で紹介していた手法です。日常的にコードに触れるチームメンバーらだからこそ、保守性に関する正確な状態を評することができるというわけです。

その他の指標は次の表のとおりです。

ディメンション 指標
満足度と幸福度 チームやプロダクトに対する誇り
パフォーマンス テストカバレッジチームによる保守性の評価、欠陥の数、変更失敗率、計画予実
活動 プルリクエストのサイズ、コントリビューター数、マイナーコントリビューター数
コミュニケーションとコラボレーション 他チームからのプルリク受け入れ数
効率とフロー 開発と保守・運用の投下工数比率

「チームやプロダクトに対する誇り」は、eNPS(従業員ネットプロモータースコア)などを使って計測できます。内部品質が悪いソフトウェアを抱えるチームのメンバーは、所属するチームのやり方に否定的であったり、プロダクトそのものについて自信を失っていたりします。チームやプロダクトに誇りが持てないのです。この指標を用いるのは、その点について計測する目的です。

「欠陥の数」を計測する背景は、低品質なコードに含まれる欠陥の数が、高品質なコードに比べて多いという調査結果があるからです。ここでは、リリース前に検出した欠陥も、リリース後に見つかった欠陥も両方をカウントします。また、同じ研究調査の中で、コードの品質が低いほど開発時間の予測可能性が低くなるという結果も出ています。つまり、見積りや計画どおりに開発が進まないということです。そのため「計画予実」を指標として含めています。

「プルリクエストのサイズ」はフローを遅くする原因でもありますが、コード品質との関係もあると考えられます。まず、あまりに大きなプルリクエストは、コードレビューを進めるうえで細部に目が行き届かなくなります。品質上の問題を見逃す可能性が高まるのです。次に、マージ時のコンフリクトが多くなる点です。コンフリクトの修正は、場当たり的になりがちです。コンフリクト先の設計方針との整合性をとるためには、それなりに時間を要してしまうからです。急いでいる時は特に、その時間を惜しんでしまうでしょう。また、プルリクエストのサイズが大きくなる理由は、そもそも内部設計がまとまっていないことにあるかもしれません。クラスやメソッドの切り出しが繁雑になり、互いの結合度が高すぎるために、プルリクエストを小分けにできなかったのです。

「活動」に含まれる「コントリビューター」という言葉は、コンポーネントに変更を加えてcommitした人を指しています。多くの人が変更を加えているコンポーネントは、設計の一貫性を失っている可能性があります。また、他チームメンバーによるコントリビュートが多いようなら、コンポーネントの境界が正しくない可能性もあるでしょう。

もうひとつの「マイナーコントリビューター」というのは、コンポーネントに記録されたcommitの数が特に少ないコントリビューターを指しています。つまり、コントリビューターの中でも、そのコンポーネントを扱った経験が乏しい人を指しています。マイナーコントリビューターが加えた変更は、その設計が適切でない可能性が高いということです。

「コミュニケーションとコラボレーション」に含まれる「他チームからのプルリク受け入れ数」を計測する目的は、「活動」指標の「コントリビューター数」や「マイナーコントリビューター数」と同じです。どちらか一方のディメンションの指標に絞って計測しても良いでしょう。

「開発と保守・運用の投下工数比率」は、内部品質を改善するまとまった時間を確保する時に、チームが関係者と交渉する材料にできる指標です。内部品質が低いソフトウェアを担当するチームは、保守・運用の負荷が高く、開発時間が少なくなる傾向があります。つまり、新しい価値をユーザーや顧客に届ける開発時間をチームが十分に確保できなくなるのです。また、保守・運用工数の増加は、損益計算書(PL)を悪化させる要因にもなり得ます。内部品質を起因とするプロダクト開発上の問題の可視化は、この指標が欠かせません。

アウトカムが最優先

組織やチームがもっとも優先すべきは、ユーザーや顧客の価値に資するアウトカムです。開発生産性をモニタリングし、継続的に改善していくことは重要ですが、この点を見失うわけにはいきません。

ケント・ベック(Kent Beck)は、自身のブログ記事の中で、エフォート(effort)、アウトプット(output)、アウトカム(outcome)、インパクト(impact)を次のように定義したうえで、もっとも注力すべきはアウトカムだとしています。

  • Effort. How hard are we working?
  • Output. How much are we delivering to customers?
  • Outcome. How much value are customers realizing?
  • Impact. How much value flows back to us?

(日本語訳)

  • エフォート. 我々は、どれだけ一生懸命働いているのか?
  • アウトプット. 我々は、顧客にどれだけのものを提供しているか?
  • アウトカム. 顧客は、どれだけの価値を実現しているのか?
  • インパクト. どれだけの価値が私たちに戻ってくるか?

まずは、ユーザー価値や顧客価値を実現し(アウトカム)、その対価としてビジネス価値を得ます(インパクト)。これは、価値の交換です。サービス提供者である私たちが、先に価値を提供します。そうすることで、ユーザーや顧客から直接的、あるいは間接的に、ビジネス価値がもたらされるようになるのです。

インパクトやアウトカムを得るためには、先にアウトプットが必要です。ユーザーや顧客がそのアウトプットを選び、利用することで初めて、彼らに価値がもたらされるからです。それは、新しいソフトウェアプロダクトであるかもしれないし、新しい機能かもしれません。

そして、そのアウトカムを作り上げる活動が、エフォートです。

ユーザー価値・顧客価値であるアウトカムを最優先に考える
ユーザー価値・顧客価値であるアウトカムを最優先に考える

開発生産性を高める活動は、アウトプットを増やしたり、そのリードタイムを短くすることにばかり注意が向けられ、アウトカムが蔑ろになりやすいという問題を抱えています。また、「エンジニアの人数」といった、生産性指標の分母たる「インプット」も、見落とされやすい対象でしょう。ケント・ベックの提言は、何に注力して生産性を高めるとしても、アウトカムを最優先に置いて判断すべきだと訴えているのです。

しかし、忘れてはならないのは、プロダクトに対するアイデアの多くは想定通りの価値にはならないという現実です。正しく価値を提供する鍵は、アイデアをあくまでも仮説だと自覚することです。そしてその仮説をすばやく検証し、そこから学びを得て、また新たなアイデアを試す。このサイクルを回し続けることです。アウトプットを多く、そして速くする試みは、これを実現するための手段として必要なのです。

SPACEのディメンションを活用することで、アウトカムとアウトプットの両方の観点を持つことができます。これこそ、本フレームワークの大きな魅力の1つでしょう。チームや組織が取り組むべき課題がアウトプットやエフォートにあったとしても、それらの指標とともに、アウトカムの指標をモニタリングできるからです。

SPACEのシステムレベルでの「パフォーマンス」は、アウトカムやインパクトに位置づけられる指標を扱うディメンションです。一方で、「活動」ディメンションで扱うのはエフォートやアウトプットであす。また、「コミュニケーションとコラボレーション」や「効率とフロー」は、アウトプットに至るフローを観察するものです。

SPACEのシステムレベルでのディメンションにエフォートからインパクトまでをマッピングするとこうなる
SPACEのシステムレベルでのディメンションにエフォートからインパクトまでをマッピングするとこうなる

つまり、組織やチームが取り組む対象が「活動」や「効率とフロー」などであったとしても、適切な指標を「パフォーマンス」にも配置しておくことで、アウトカムを最優先にして生産性向上に取り組むことが可能になるのです。

多次元的(multidimensional)な観点で生産性を計測する利点は、ここにあったのです。そのポイントは次のとおりです。

  • 指標選びは、網羅しようとするのではなく、チームや組織の関心事に基づいて関連性と一貫性を持たせ、絞り込むようにする
  • アウトカムをシステムレベルのパフォーマンス指標として設定し、それを意思決定のためのガイドとする

これさえ押さえておけば、SPACEフレームワークを最大限に活用して成果を出すことが可能になるでしょう。

mtx2s.hatenablog.com

デプロイ頻度やリードタイムの正確な計測にこだわらなくていい(前提はあるが)

デプロイ頻度とリードタイムは、開発チームが自らのパフォーマンスをモニタリングするうえで欠かせないメトリクスである。それらが、収益性や市場占有率といった組織パフォーマンスに影響を与えるからだ。その調査結果は、DevOps Research and Assessment(DORA)が特定した4つのキーメトリクス、いわゆる「DORAメトリクス」の要素として浸透した(後述するが、DORAメトリクスで扱うのは、リードタイムではなく「変更のリードタイム」である)。

その重要性ゆえに、チームや組織はこれらのメトリクスの計測と可視化に努める。可能な範囲で正確な値が欲しい。そうして、チケット管理ツールやバージョン管理システムからテレメトリを収集、集計し、チームのモニタリングダッシュボードにその実績値を可視化するのだ。

しかし、しばらくメトリクスを運用してみると、その扱いづらさに気づく。計測値や集計値のばらつきが大きく、それをどう理解すれば良いのか、どう評価すれば良いのか悩むのだ。

本稿はこの問題について考える。結論としては、実測値を使うまでもなく、「チームの誰もが知っているデプロイ頻度とリードタイム」を用いれば十分、というものだ。2週間のイテレーションごとにデプロイしているなら、2週間に1回のデプロイ頻度であり、リードタイムは2週間とする。これには前提も付くが、実践向きだし手軽だ。詳細は後述する。

前提とするチーム

問題を掘り下げるにあたり、前提とする開発プロセスやチームの責務について、ここで明確にする。

ここでのチームは、スクラムをはじめとするイテレーティブなプロセスを持つソフトウェア開発手法を採用している。イテレーションは、1週間や2週間といった固定の期間で繰り返される。

イテレーション終了直前のインクリメントは、本番環境へのデプロイが可能な状態となる。そして、前提とするチームでは、直近1回分のイテレーションによるインクリメントのみを対象としてデプロイする運用を採用している。複数のイテレーションを経てからデプロイするプロセスは対象外とする。

なお、イテレーション終了後から、いわゆるテストフェーズなどを経てデプロイするプロセスであっても構わない。

固定期間のイテレーションによるバッチ方式デプロイを採用するチームが対象

本番環境へのデプロイは、開発したチーム自身が責務を持つ。デプロイが手作業であるか、自動化されているかは問わない。

メトリクスの定義

次に、「デプロイ頻度」と「リードタイム」の定義について。

まずは「デプロイ頻度」であるが、これは、「どれぐらいの期間ごとに1回のデプロイを実施しているか」である。DORAメトリクスの2023年版調査アンケートでは、次のように問われている。これを見るとイメージしやすいだろう。

How often does your organization deploy code to production or release it to end users?

  • Fewer than once per six months
  • Between once per month and once every 6 months
  • Between once per week and once per month
  • Between once per day and once per week
  • Between once per hour and once per day
  • On demand (multiple deploys per day)
  • I don't know or not applicable

「リードタイム」についてもDORAのアンケート設問を見てみよう。なお、DORAメトリクスが対象とするリードタイムは、「変更のリードタイム(lead time for changes)」だ。

What is your lead time for changes (i.e., how long does it take to go from code committed to code successfully running in production)?

  • More than six months
  • Between one month and six months
  • Between one week and one month
  • Between one day and one week
  • Less than one day
  • Less than one hour
  • I don't know or not applicable

「変更のリードタイム」の定義は、設問にもあるように、「コードがコミットされてから、それが本番環境で正常に稼働するまでの時間」となっている。つまり、実装時間は含まれない。

継続的インテグレーション(CI)を重視するDevOpsの観点から考えて、これが意味する開始点は、変更したコードが統合ブランチに取り込まれた時点だろう。CIが整備されているチームであれば、変更内容がマージされてCIが動作し、それが正常終了したタイミングが、変更のリードタイムの開始点ではないだろうか。

便宜上、私は、開発項目ごとのフローとそのリードタイムを次の図のように2つに分けている。1つは、フローのうち、設計を含む開発に着手してから、その変更がレビューされ、統合ブランチに取り込まれるまで。2つめは、そこから本番環境にデプロイするまで。前者の範囲を「開発フェーズ」、後者の範囲を「製造フェーズ」と呼ぶことにする。DORAメトリクスの「変更のリードタイム」は、製造フェーズのリードタイムのことだ。

開発プロセス内でのリードタイムを2つに分ける

このように分ける理由は、両者のリードタイムの特性が大きく異なるからである。

開発フェーズのリードタイムについては、noteの記事『ブラックボックスになりがちな開発チームの内部状況を指標を用いて可視化する』の中で次のように書いた。

開発フェーズのリードタイムは、開発項目ごとの計測値に大きなばらつきがあることが特徴です。開発項目の開発規模や、担当者の稼働状況・スキルなどに大きな影響を受けるからです。これは、このフェーズのプロセスに含まれるタスク(設計・実装、コードレビュー)が現状では多くを人手に頼らざるを得ないからだとも言えるでしょう。見積りによる予測は行うものの、その通りになるとも限らず、予測困難で不確実な指標だとも言えます。また、計測値は正規分布とならないため、平均値を代表値として扱えないことにも注意が必要です。

製造フェーズについては、次のとおりだ。

製造フェーズのリードタイムは、開発フェーズとは違い、プロセスが洗練するほどばらつきが小さく、一定になる傾向があります。それは、このフェーズのプロセスに含まれるタスク(ビルド、テスト、デプロイなど)の多くが自動化可能だからです。テストは人手に頼るべき領域が多少は残るものの、全体的な自動化が進むほど予測可能で不確実性の低い指標となるのが特徴です。

以降で、デプロイ頻度とリードタイムの計測値の扱いづらさについて、いくつか例をあげてみる。

ケース1. 緊急対応

ソフトウェアシステムには本番トラブルによる緊急対応が付きものであるが、その影響が計測値にあらわれる。

緊急対応による本番環境へのデプロイが発生する回数が多いほど、デプロイ頻度が高くなる。しかし、デプロイ頻度は、その値が大きい方が「チームのパフォーマンスが優れている」とされるメトリクスだ。緊急対応によって高くなった集計値が、パフォーマンスが高い状態をあらわすわけがない。

緊急対応によるトラブルが多い時期のグラフはチームのパフォーマンスが高く見える

加えて、素早さが求められる緊急対応時のフローは、開発フェーズのリードタイムが短くなる。1時間未満、あるいは数時間程度で問題箇所の修正を終わらせることが多い。そして、製造フェーズの非自動化ステップのいくつかが簡略化されたりもする。そのため、フェーズ内に自動化されていないステップが多く含まれているチームほど、いつもより、製造フェーズのリードタイムも短くなるのだ。

結果として、任意期間におけるリードタイムの代表値(中央値など)が、これらの影響を受けて小さくなる。つまり、チームのパフォーマンスが、実態よりも優れているように見えてしまうのだ。

いずれも、緊急対応に関係する測定値を除去して集計することもできるが、それもわずらわしい。DORAメトリクスの1つである「変更失敗率(change failure rate)」と合わせて眺めることで、緊急対応による影響が読み取れなくもないが、どこまで影響したのかまでは明確にはならない。

ケース2. 開発の保留

仕掛中の開発項目が、何らかの理由でしばらく保留となることがある。そうすると、その変更内容を、フィーチャーブランチといった、統合ブランチ以外の場所に置いたままで、しばらく放置することになる。そして開発が再開したら、残った実装を進め、その変更内容を統合ブランチに取り込む。すると、開発フェーズがとんでもなく長いリードタイムが記録されることになる。

保留期間を挟んでデプロイした開発項目を含む、リードタイムのヒストグラム

このような「はずれ値」は、リードタイムの代表値を大きくする要因となる。これをどうとらえれば良いだろうか。

保留となった理由には、チームから見て外的な要因と、内的な要因があり得る。

顧客からの要求変更に影響を受け、保留せざるを得ないような場合は外的要因だろう。その結果としてリードタイムが伸びたとしても、それを「チームのパフォーマンスが低い」と言うことはできない。当初の計画のまま開発を続けても、顧客にとっての価値にならないからだ。しかし、こういったことが頻発するなら、なにか問題があるとも考えられる。

内的要因としては、たとえば、メンバーの稼働率(リソース効率)を高めようとするケースが保留を頻発させることがある。チームの時間を隙間なく埋めるために、合い間に優先度の低い開発項目に着手するからだ。そしてその途中で、もともと計画していた開発項目に着手すべきタイミングがやってきて、仕掛中の仕事は保留となる。特に、時間単価で給与を支払うメンバーに対して、顕著にこうなってしまうようだ。これは問題だろう。

いずれにしても、これらの問題は、リードタイムの計測値から検知するようなものではない。逆に、これらの問題の解決状況を、リードタイムの計測値で判断するものでもない。したがって、保留問題がリードタイムに与える影響をどうとらえれば良いのか、悩むことになる。

ケース3. 長期の連休

年末年始やゴールデンウィークのような長い連休を挟むと、リードタイムが目立って長くなる。

連休前に仕掛中だった開発項目の作業を連休後に再開させると、あいだに挟まれた連休の日数分が、開発フェーズのリードタイムに含まれて記録されてしまう。また、連休前に開発フェーズが完了している開発項目であっても、長い連休の影響でイテレーション期間が長くなることで、製造フェーズのリードタイムも伸びる。

結果として、フロー全体のリードタイムが伸びた開発項目が記録されることになる。デプロイ頻度も下がることになるだろう。

長期連休を挟んでデプロイした開発項目を含む、リードタイムのヒストグラム

メトリクスだけを見ると、チームのパフォーマンスが相対的に低くなったように見える。確かに、普段であれば、デプロイ日やリリース日を1週間ほど早くできただろう。しかしこの遅れは、単に連休の影響である。パフォーマンスとは関係がない。

この問題に対し、チーム内で「営業日だけカウントすべき」といった意見が出るかもしれない。計測値にそのような処理を加えるためには、休業日カレンダーを持たせることになる。本当にそこまで凝ったことをすべきか。また、それを言うなら次は「仕掛中の開発項目を持ったメンバーが休んだ日はどうする?」といった疑問もわいてくる。不毛だ。

そもそも、チーム内でこういった議論が起きるようなら、メトリクスが自己目的化してしまっていることを疑ってみるべきだろう。特に、メトリクスの悪化を避けることを目的に、デプロイ日を早めて連休前に済ませようとする意識が働くようになっていたら、決定的だ。

チームの誰もが知っているデプロイ頻度とリードタイム

このように、デプロイ頻度やリードタイムの計測値から、チームのパフォーマンスを読み取ることは思ったより簡単ではない。

それでは、チームのデプロイ頻度やリードタイムをどうやって知ればいいのか。その答えはシンプルだ。

イテレーション期間が2週間であれば、デプロイ頻度を「2週間に1回」とする。リードタイムは、開発フェーズと製造フェーズをあわせて「2週間」だ。もし、2週間のイテレーションのあとに1週間のテストフェーズやセキュリティチェックなどを経てデプロイしているのなら、リードタイムは「3週間」とする。もちろん、先述のとおり、これらはイテレーションごとにデプロイしていることを前提とする。

チームの誰もが知っているデプロイ頻度とリードタイム

これが、「チームの誰もが知っているデプロイ頻度とリードタイム」である。計測値がない状態で、チームメンバーに「デプロイ頻度とリードタイムは?」と問えば、おそらく誰もがこのように答えるのではないだろうか。

そもそも、本稿が前提としている開発プロセスは、バッチ方式のデプロイだ。イテレーション内で対応する開発項目がすべて同時にデプロイされるということ。イテレーション内でいつ開発に着手したとしても、リードタイムの終端であるデプロイ日が同じになる。

いつ開発に着手しても、リードタイムの終端であるデプロイ日が同じ

つまり、開発項目ごとのリードタイムの違いは、開発着手日の違いでしかない。開発着手日が遅いほど、リードタイムが短くなるということだ。この違いに着目することに、意味があるのだろうか。この待ち時間をリードタイムに加えれば、すべての開発項目のリードタイムが同じになるのだ。

開発項目ごとのリードタイムの違いは、開発着手日の違いでしかない

だから、チームが注目すべきリードタイムは、開発項目ごとに計測したリードタイムではなく、チームの誰もが知っているリードタイムで十分なのだ。デプロイ頻度についても、一定のサイクルでデプロイを実施しているのだから、計測するまでもない。

もちろん、先述した緊急対応といった例外ケースはその限りではないが、これは通常のフローとは別物だ。通常のフローと例外のフローを統合管理する必要はない。改善対象としてそれぞれ別で管理すべきだからだ。

また、通常のフローであっても、時にはイテレーション内で完了できない開発項目も出てくるだろう。しかし、そんなものはリードタイムを計測しなくてもチームは把握している。完了しないことが問題だとチームが考えるなら、原因を分析して改善を進めればいいだけの話だ。

デプロイ頻度とリードタイムは「フロー」をモニタリングするメトリクス

デプロイ頻度やリードタイムは、「フロー」をモニタリングするためのメトリクスだ。DORAメトリクスの設計者であるニコール・フォースグレン(Nicole Forsgren)らが開発した「SPACEフレームワーク」においても、デプロイ頻度と変更のリードタイムは、「Efficiency and flow」に位置づけられている。

実現したいことは、メトリクスの改善ではなく、フローの改善なのだ。「メトリクスを改善しよう」と意識しすぎると、この観点を見失いやすい。フローの改善によって、ソフトウェアデリバリのパフォーマンスを高める。そして、DORAの調査結果にもあるように、それが、収益性や市場占有率といった組織パフォーマンスを高めることに繋がる。それを期待しているのだ。

フロー改善のために考えられる戦略は2つ、「フローを速くする」ことと、「フローの数を増やす」ことだ。どのような施策を進めるにしても、このどちらが狙いの施策であるかを念頭に置いて、改善サイクルをまわすことが重要だろう。

フロー改善のために考えられる戦略は2つ

フローを速くする

固定イテレーション単位でのバッチ方式デプロイを前提とするなら、イテレーション単位のフローに目を向けることになる。開発項目単位のフローをいくら速くしても、デプロイ日が早まることはないからだ。

開発項目単位のフローをいくら速くしても、デプロイ日が早まることはない

イテレーション単位のフローを速くする方法の1つは、イテレーション期間を短くすることだ。簡単ではないし、限度もあるが、確実にフローが速くなる。結果として、デプロイ頻度が高くなり、リードタイムも短くなる。

イテレーション期間を短くする

もし、イテレーション終了後にテストなどを経てデプロイしているのなら、デプロイメントパイプラインの整備も有効だ。パイプラインの自動化率を高め、さらにその効率を高めるのだ。そうすることで、イテレーション終了からデプロイまでの期間が削減される。結果として、リードタイムが短くなる。

イテレーション終了からデプロイまでの期間が削減される

フローの数を増やす

フローの数を増やすことについては、イテレーション単位のフローに目を向けてしまうと、それは単に「チームを増やす」ことになってしまう。それは本稿のテーマとは外れるので、ここは開発項目単位のフローについて考える。

固定イテレーション単位でのバッチ方式デプロイの場合、フローの数を増やすと、バッチサイズが大きくなる。「フローの数を増やす」とは、単位期間あたりに完了させられる開発項目の数を増やすということだ。つまり、1回のイテレーションで完了させる開発項目が増える。これによって、チームのベロシティは大きくなるが、デプロイ頻度もリードタイムも変化しない。

ここで重要なことは、フローの数が増えることで、イテレーション期間の短縮を進めやすくなるという点だろう。

イテレーション期間の短縮も良し悪しなのだ。2週間のイテレーションを1週間に縮めるのはハードルが高い。期間が短くなる分、1度のイテレーションで使える開発時間は小さくなる。それに、イテレーション初日のプランニングや、最終日のレビューや振り返り、あるいはプロダクトバックログのリファインメントなどで開発時間が圧迫されてしまうかもしれない。

バッチサイズが小さい方が良いとは言え、小さすぎるのも困る。フローの数を増やすことで、その点をカバーしやすくなる。

フローの数を増やすための方法の1つとしても、デプロイメントパイプラインの整備が有効だろう。イテレーション期間内にデプロイを実施しているチームであれば、これによってコード実装に使える期間が長くなるからだ。

たとえば、2週間(10営業日)のイテレーションのうち、バッチ方式による製造フェーズのリードタイムが4営業日だったとしよう。6営業日が、開発項目フローごとの開発フェーズに使えるということだ。デプロイメントパイプラインの整備によって、製造フェーズのリードタイムが2日に改善されたとする。すると、削減された2営業日分が、開発項目フローごとの開発フェーズに使えるようになる。結果、フローの数が増えるのだ。

削減された2営業日分が、開発項目フローごとの開発フェーズに使えるようになる

フローの数を増やすもう1つの方法は、開発フェーズの作業効率を高めることだ。Copilotを導入してコード実装を効率化したり、静的解析ツールを導入してコードレビューの手間を削減したりといったアイデアが考えられる。ただし、これによってフローの数が劇的に増えるかと言うと、そこまでは期待できないだろう。

バッチ方式からオンデマンドへ

フローを速くするという観点で言えば、「待ち時間の削減」という手段がまだ残されている。

たとえば、コード実装に1日、コードレビューに1日のフローであったとする。もし、コード実装を終えてから、コードレビューが開始されるまでに2日を要したらどうなるだろうか。このフローの開発フェーズのリードタイムは、4日となる。この待ち時間が0になれば、開発フェーズのリードタイムは2日に改善する。

開発フェーズのリードタイムは短くなるが……

これは、一見すると、フローが早くなったように見える。しかし、イテレーションの中で発生するフローの待ち時間をいくら削減しても、バッチ方式である限り、実際にはフローは速くならない。削減された待ち時間が、デプロイまでのどこかの待ち時間として追加されるだけだ。

フロー全体のリードタイムは変わらない

そこで、オンデマンド方式デプロイへの移行である。ハードルは高いが、パイプラインの整備も含め、これまでの取り組みにより、その下地はできているはずだ。

あとは、WIP制限といったプラクティスを活用して、開発フェーズのフローの待ち時間を削減することで、フローをより速くする。ここまでくれば、デプロイ頻度やリードタイムの計測に、大きな意味が出てくるはずだ。

目指すはバリューストリーム全体のフローを改善すること

フロー改善の目的が「素早く仮説検証をまわす」ことにあるなら、改善対象は開発チームの範囲だけにとどまらない。バリューストリーム全体がその対象となる。

しかし、その難易度はなかなかに高い。多くの組織において、生産性を求められる対象は、開発チームのプロセスの範囲だからだ。

その理由は、改善の目的が「素早く仮説検証をまわす」ことではなく、「より早く、より多くの機能をリリースする」ことにあるからだろう。その根底には、プロダクトに対するアイデアを、間違っているかもしれない「仮説」だとは捉えていない点にある。この思い違いから見直さなければならないだろう。

mtx2s.hatenablog.com

チームの機能と配備を考えるための7つのチーム責務定義ガイドライン

前回の記事ではチーム中心の組織づくりの設計原則について書いた。今回は、それらの原則に基づくチームをソフトウェアプロダクト組織内にどう配備し、どのような機能を持たせるかについて考える。これは言わば、チームの責務を定義することに他ならない。本記事ではこれを、7つのガイドラインとして書き出してみることにした。

前回の記事:『チーム中心の組織作りのための6つのチーム設計原則 - mtx2s’s blog

mtx2s.hatenablog.com

1. ストリームアラインド

ソフトウェアプロダクト組織の開発フローは、ユーザーや市場の観察をもとにアイデアを生み出すことから始まる。そのアイデアを仮説として、それを検証するための必要最小限の機能に落とし込み、さまざまなプロセスを経てリリースにいたる。そうしてユーザーに使われることでフィードバックを得て、新たなアイデアと仮説を得る。この繰り返されるサイクルが、「バリューストリーム」だ。

特定のバリューストリームに対して、安定したチームを専属で配備する。チームをこのバリューストリームのエキスパートにすることが狙いだ。チームの仕事は常にストリームの中で発生する。そこで流れ続けているのは、ユーザーや顧客、市場に関するドメイン知識である。そうしてドメイン知識がチームに蓄積されていけば、優れたプロダクト、優れたソフトウェアシステムを生み出しやすくなるというわけだ。

このようにしてバリューストリームに配備されるチームを「ストリームアラインドチーム(stream-aligned team)」と呼ぶ。

安定したチームをバリューストリームに対して配備する

もし、バリューストリーム内での1つのプロジェクトが終了するたびにチームが解散してしまっていたら、その時点でチームの知識は失われてしまう。次のプロジェクトで編成された新チームは、知識をいちから蓄積しなければならない。それこそ失敗ケースの「不連続なチーム」だ。だから、バリューストリームに配備すべきはチームとして連続性のある「安定したチーム」なのだ。

チームの不連続性による「学び」の消失

1つのチームを複数のバリューストリームに配備することは避けるべきか。答えはYESである。

複数のストリームが流れ込むチームの内部は、河川の合流点と同様に、激流が発生しやすい。それぞれのストリームから仕事が流れ込んでくるからだ。しかし、チームにはキャパシティがある。流量をコントロールしなければならない。つまり、ストリーム間での調整コストが多く発生するということだ。生産性が悪化することは説明するまでもないだろう。私はこれを、「バリューストリームの合流点」と呼んでいる。

バリューストリームの合流点となったチームは、プロダクトバックログを2つ持つことになる。そこにはプロダクトオーナーも2人存在する。チームは2つのミッションの間で、どちらのプロダクトバックログアイテムを優先すべきか、日々、悩むことになるだろう。どちらのプロダクトオーナーからも仕事をせかされることになり、常態的に詰め込み型の計画になる。そうして、内部品質を犠牲にし、生産性を悪化させながら開発を続けることになるのだ。

バリューストリームの合流点では、仕事の調整が頻発する

しかし、現実問題として、チーム数よりバリューストリームの数が多いこともある。だからと言って、少人数チームをさらに小さく分割してそれぞれのストリームに配備するのは無理がある。やはり、1つのチームを複数のバリューストリームに配備せざるを得ないだろう。

このようなケースにおいては、ストリームの流量に着目してチームを配備することになる。チームが担当する「流れの激しいストリーム」を1つだけに絞る。残りは「流れの緩やかなストリーム」を兼務する形にする。

流れが「激しい」「緩やか」は、各ストリームで扱うプロダクト自体のライフサイクルや、社内・組織内におけるプロダクトの重要度などで決まる。すでに保守・運用モードでほとんど開発が発生しないようなプロダクトに対するバリューストリームは、追加開発の頻度も低く、流れが緩やかだ。反対に、社内で期待されてローンチしたばかりのプロダクトは、頻繁にアップデートが繰り返されるかもしれない。このようなバリューストリームは、流れが激しい。

こうして、ストリームの流量に着目してチームを配備することで、バリューストリームの合流点であっても、その流量の調整コストはぐっと下がるだろう。とは言え、チームによるバリューストリームの兼務は、無理があることは否めないのであるが。

もし、それでもまだチームの負荷が高いのであれば、流れが穏やかで重要度の低いストリームを社外に委託することも選択肢のひとつだ。社外サービスを利用するのも良い。ただし、このようなストリームで扱う対象は、社内や組織内におけるコアプロダクトやコア技術ではないという前提である。そもそも、開発者数に対してサービス(バリューストリーム)が多すぎるという問題を解決すべきケースもあるだろう。

■関連記事

2. オーナーシップ制

1つのバリューストリームに対して複数のチームを配備することは可能だろうか。バリューストリームを河川に例えれば、その幅が広いなら、分流させてそこにチームを配備することは可能である。そもそも、分流可能なほど広いバリューストリームを1つの小さなチームで担当すること自体に無理がある。バリューストリーム自体を分けられるならそうした方が良いが、それが難しいのならば分流させるしかない。

バリューストリームを分流させて、それぞれにチームを配備する

バリューストリームを分けるにしても、分流させるにしても、その分割方法は、ドメイン駆動設計で言うところの「境界づけられたコンテキスト(bounded context)」に着目することになる。そうすると必然的に、プロダクトのソースコード自体も、コンテキストで境界線を引くことになる。そしてチームは、自身が担当する分流の範囲に入る「境界づけられたコード」にオーナーシップを持つ。

境界付けられたコンテキストに着目して、バリューストリームとコードを分ける

境界づけられたコードとは、具体的にはマイクロサービス化やモジュラモノリス化をイメージすると分かりやすいだろう。しかし、必ずしもアーキテクチャをそのように明確に分離すべきということではない。分離が曖昧であればあるほど、後述する「再合流点」によるチーム間結合に悩まされることになることとのトレードオフなのだ。

コードのオーナーシップとは、オーナーたるチームがそのコードの品質に責任を持つということだ。ここで言う品質には、外部品質と内部品質の両方が含まれる。非オーナーシップ制では、コードの設計に一貫性が保てなくなり、コード品質の悪化を招きやすい。

ある調査では、高品質なコードに比べ低品質なコードに含まれる欠陥は15倍、平均開発時間は2倍、最大開発時間は9倍になるという結果が報告されている。つまり、コード品質の低下が外部品質の悪化を招き、市場投入までの時間に悪影響を与え、計画に対する予測可能性を悪化させるということだ。また、マイクロソフトの調査では、コードのオーナーシップの欠如によりリリース前後における欠陥やトラブルが増加することが明らかになっている。

これが、コードのオーナーシップ制が必要である理由だ。

境界付けられたコンテキストにあわせてコードのオーナーを分ける理由は、チーム間の結合度を下げる意図があるからだ。境界付けがうまくいけば、同じタイミングで変更されるコードをチームがまとめて扱うことができる。「閉鎖性共通の原則(CCP)」だ。こうすれば、担当する分流による開発において、他チームが所有するコードを変更する必要性が下がり、チーム間での調整コストが下がる。

なお、チームが担当する境界づけられたコードはすべて、チーム内で「共同所有(collective code ownership)」する。コードの範囲ごとにそれぞれメンバー個人をオーナーにすると、コードが属人化されやすいからだ。

一方で、チーム外に対してはポリシーを決める必要がある。「弱いコード所有(weak code ownership)」が好ましいと考えるが、「強いコード所有(strong code ownership)」を採ることも可能だ。前者は、他チームからのプルリクを受け付けるが、後者は他チームからの変更依頼を受け付けてオーナーチームがコードを変更するやり方である。つまり、強いコード所有の方が、よりオーナーチームの負荷が高く、かつチーム間でのスケジュールの調整コストも高くつくということだ。

チーム内ではコードを共同所有し、チーム間では弱いコード所有か強いコード所有にする

いったん分流させたストリームが、再び合流することは避けたい。そこでまた、チーム間の調整が発生し、チームの生産性に悪影響を及ぼすからだ。

ストリームの再合流は、チーム間の調整を頻発させる

再合流点は、ソフトウェアのテストやデプロイにおいて発生しやすい。その観点で、チームが所有する境界づけられたコードは、独立してデプロイ可能なコンポーネントとして、物理的に分割されている方が望ましいだろう。そうすれば、テストやデプロイの実施スケジュールに、チーム間での調整が不要だからだ。しかし、必ずしもそうである必要はないし、必ずしもそうできるとも限らない。

コンテキストやコードの境界づけは、考えるほど簡単ではない。境界づけが上手くいけば、ストリームや分流をまたいだコード変更は発生しないはずであるが、それはあくまでも理想だ。現実は、ある1つのチームが進めるプロダクトへの変更が、他のチームがオーナーシップを持つコードに影響を及ぼすことも多い。この影響をなるべく小さくするために、境界を繰り返し見直していくことも必要である。

■関連記事

3. バリエーション分割

開発するプロダクトに、コードベースが異なるいくつかのバリエーションがあるなら、その単位でなるべくチームを分ける。バリエーションと言うのは、たとえばAndroid版、iOS版、スマホ向けWebブラウザ版といったものだ。これらはバリューストリームを分けられる。そうすれば、プロダクトに対するアイデアの検証効率を高めたり、機能を洗練させるコストを下げることができる。

バリエーション違いの同じプロダクトだからと言って、同じ日に同じ機能をリリースする必要なんてない。iOSバイスのユーザーとAndroidバイスのユーザーのペルソナを作ってみれば、それぞれ違った人物像になるはず。そうであるなら、バリエーションごとにプロダクトバックログアイテム(PBI)の優先順位も変わってくる。つまり、プロダクトバックログは一つではないということだ。

バリエーションごとにバリューストリームが分かれる

このように分割すると、Android版、iOS版、それぞれで異なる新機能を開発・リリースし、改善を繰り返して洗練させてから、他のバリエーションに移植するといったことが可能になる。

バリエーションごとに異なる機能を並行して開発してから移植する

この開発戦略は3つの観点で効率が良い。

1つめの観点は、失敗時のコスト。リリースした新機能が期待した価値を生まなかった時、Android版とiOS版を同時リリースしていたならば、両方を大幅に改修しなければならなくなる。しかし、Android版だけ先行開発・リリースしていたなら、手戻りコストはAndroid版のみで支払えば良い。なんなら、Android版では将来的にその機能を廃止することにし、iOS版には移植しないという意思決定も可能だ。

狙い通りの価値を生み出さなかった機能は移植しない

2つめは、改善のためのコスト。どんなに優れた機能であっても、リリースしたばかりの状態では、ユーザー体験面で改善できる箇所がいくつもあるものだ。Android版だけ先行開発し、リリースしていたなら、機能を十分に洗練させてからiOS版に移植するという手段が取れる。そうすれば、iOS版は洗練するコストを支払わなくて済む。もちろん、ペルソナが違うので、iOS版では若干の違いを作る必要はあるかもしれないが。

十分に洗練させてから移植する

3つめは、アイデアの検証。プロダクトバックログはいつも、プロダクトに関するアイデアで溢れている。関係者らは、そのすべてを早く市場投入したいと考えているが、大抵の組織では、その期待に対して開発が追いつかないものだ。それに、それらのアイデアがすべて正しいとは限らない。できれば無駄な開発は避けたいところだ。

プロダクトのバリエーションごとに異なるアイデアを並行して実装すれば、アイデアの検証が速くなる。たとえば、Android版は新機能A、iOS版は新機能Bの開発・リリースを並行して進めれば2倍の速さでアイデアを検証できる。そうして、移植する・しないは、検証結果を踏まえて意思決定すれば良い。

イデアを並列で検証する

経験主義をとる組織にとって、これは「早く安全に失敗できる」方法だと言える。バリューストリームが分かれ、チームを分けているからこそ、この開発戦略を進めやすくなるのだ。

■関連記事

4. 技術横断型

フロントエンド開発とバックエンド開発を同一チームとしてまとめる。その効果は、調整コストの低減と、市場投入までの時間の短縮である。

1つの機能開発が、フロントエンドだけ、バックエンドだけで完結することは多くはない。フロントエンドは、バックエンドに依存している。両者の開発チームを分けてしまうと、1つの機能開発を進めるために、両チームが協力し合わなければならない。協力と言うと聞こえは良いが、チーム間での調整コストを頻繁に支払うということだ。さらに、そこで調整されたリリース日は、抱えている仕事の都合で対応完了日がより遅くなるチームに合わせるしかない。こうして、市場投入までの時間が延びることになる。

チームをフロントエンド開発とバックエンド開発で分割すると、チーム間での調整が頻発する

チームはそれぞれがミッションを持ち、自分たちの仕事を抱えている。チームごとにプロダクトバックログがあると言えば、イメージしやすいだろうか。そこに積まれたアイテム(PBI)は、ミッションに合わせて優先付けされている。だから、1つの機能開発を複数のチームで進めようとすると、チーム間で、対応時期にズレが生じるのだ。フロントエンド開発チームが5日後に開発を完了できるとしても、バックエンド開発チームは10日後からようやく着手できるかもしれない。こういったズレが、調整コストや市場投入までの時間に悪影響を及ぼす。

私自身、過去の組織設計において、フロントエンド開発とバックエンド開発でチームを分離する組織を設計したことがある。その理由は、両者で必要とされる技術スキルが大きく異なり、それぞれの専門性が高かったからだ。同じスキルを持つ人をチームとして集めることで、知識の共有と仕事の効率化が図れると考えたのだ。

しかし実際の活動を観察するうちに気づいた。彼らは常に、1つの機能開発を2チームで作業分担して進めていたのだ。しかし、チームが異なるため、開発プロセスはそれぞれでまわしている。そのためにチーム間の調整ごとが多く、両者でのミーティングも頻発していた。決して効率が良いとは言えなかった。

話を先ほどの例のフロントエンド開発チームとバックエンド開発チームの問題に戻そう。

両者を同一チームとしてまとめれば、ミッションもバックログも1つになる。リリース日をいつにするかは、チーム内でのコミュニケーションで完結する。だから、調整コストの低減と、市場投入までの時間の短縮を期待できる。もちろん、ここで編成するチームも、同一のバリューストリームやその分流を担うフロントエンドとバックエンドを単位とすることが前提であることは言うまでもないだろう。

フロントエンド開発とバックエンド開発を1つのチームに垂直統合する

ここで頭を悩ませるのは、バックエンドが複数のフロントエンドから利用され、そのフロントエンドのオーナーチームがそれぞれ異なるケースだ。

たとえば、Android版アプリとiOS版アプリがバックエンドのAPIを共有している場合である。どちらのアプリチームがバックエンドサービスのオーナーになるべきだろうか。私の答えは、「どちらでも構わない」だ。ただし、チーム外に対しては、バックエンドのオーナーシップを「弱いコード所有」とし、他チームからの変更を受け付けるべきだ。そうしなければ、Android版とiOS版で並行して異なる機能開発を進める戦略が取りづらくなる。

「弱いコード所有」をポリシーとして、バックエンドコンポーネントのオーナーチームが他チームからのプルリクを受け付ける

もちろん、独立したチームを作り、そこにバックエンドサービスを持たせることも考えられる。しかし、このチームが機能するのは、チーム単体でサービスを成長させられる場合だ。言い換えれば、このサービスがそれ自体にバリューストリームを持っているということだ。今回のケースは、Android版プロダクトやiOS版プロダクトのバリューストリームにバックエンドサービスの開発が組み込まれてしまうため、この組織設計は適していないだろう。

■関連記事

5. DevOps

プロダクト開発を担うチームにとって、保守・運用の経験は、開発に対するフィードバックを得られる場である。そのために、開発と保守、運用という3つの業務機能は、1つのチームにまとめる。

保守・運用の経験は、開発に対するフィードバックを得られる場である

開発と保守・運用を分業する組織構造は、そのフィードバックの遮断に他ならない。その悪影響の最たるものが、チームそれぞれのミッション遂行手段のコンフリクトという形であらわれる

ソフトウェアプロダクト組織の共通ミッションは、「プロダクトやサービスのユーザー・ビジネス価値を高める」ことだ。開発チームであろうと、保守・運用チームであろうと、それは変わらない。

しかし、チームの責務とする業務機能がそれぞれ異なるため、共通ミッションに対する責務範囲にも違いが出てくる。開発チームの個別ミッションは、「優れた機能をユーザーに届ける」ことであり、保守・運用チームは「信頼性の高いサービスを提供する」ことだ。

開発チームは、優れた機能をユーザーに少しでも早く届けようと、次々と新しい機能を作り上げる。それを、保守・運用チームに投げて、高頻度でリリースを繰り返そうとする。しかし、プロダクトに変更を加えることは、品質やサービスレベルの安定性を崩す要因になりかねない。

もし、リリースするたびに新しい既知の欠陥・未知の欠陥が大量に積み上がったり、サービスレベルをおとすことが繰り返されていたらどうなるだろうか。当然、保守・運用チームが責務とするミッションを阻害することになる。一方で、開発チームのミッションには影響がない。だから、保守・運用上の問題に対する開発チームの関心が高まらない。状況が改善されないのだ。ここにコンフリクトが生じる。典型的な、devとopsの対立である。

それぞれの個別ミッションの遂行手段の間でコンフリクトが生じる

したがって、「DevOps」である。devとopsが1つの共通ミッションのもとで活動できるようにしたい。そのシンプルな手段が、1つのチームに開発、保守、運用のすべての業務機能を集約することだ。DevOpsでは、必ずしもチームを1つにまとめる必要はないが、こうした方がミッションも統合され、自然とフィードバックサイクルも回るようになる。

1つのチームに開発、保守、運用のすべての業務機能を集約する

自分たちで開発したソフトウェアシステムの保守・運用を担うようになると、そこで生じる様々な問題がすべて自分たちに返ってくる。

欠陥だらけなら、その是正に追われることになるだろう。本番稼働システムにトラブルが頻発すれば、その都度、開発の手を止めて緊急対応することになる。緊急対応しようにも、ログが不十分であったために止血に手間取ったり、その後の原因分析が進まないかもしれない。ライブラリやフレームワークのバージョンを上げようにも、内部構造が密結合すぎて大きなコストを支払うことになるかもしれない。

そもそも、品質が安定せず、トラブルを起こしてばかりいるようなプロダクトでは、ユーザーや顧客に迷惑をかけてしまう。ビジネス向けのプロダクトであれば、営業担当とともに顧客からのクレーム対応にも追われることになるだろう。

これらは「フェイラーデマンド(failure demand)」だ。このような問題は、ある程度は開発時に軽減できていたはずだ。本来やるべきことを怠ったために、あとからコストを支払うことになったのだ。そのために開発時間も失うことになる。つまり、品質を犠牲にしたために、スピードを失ったのだ。

品質を犠牲にしたために、スピードを失った

チームは、こういったつらい経験を経て、ソフトウェアシステムをより良いものにしていく。その先に目指すのは、「プロダクトやサービスのユーザー・ビジネス価値を高める」という共通ミッションだ。そこには、「優れた機能をユーザーに届ける」ことと「信頼性の高いサービスを提供する」ことの両方の実現が含まれている。スピードと品質の両立だ。これが、保守・運用による開発へのフィードバック効果である。

Amazon.comのCTOであるワーナー・ヴォゲルス(Werner Vogels)は、インタビューで次のように話している

Giving developers operational responsibilities has greatly enhanced the quality of the services, both from a customer and a technology point of view. The traditional model is that you take your software to the wall that separates development and operations, and throw it over and then forget about it. Not at Amazon. You build it, you run it. This brings developers into contact with the day-to-day operation of their software. It also brings them into day-to-day contact with the customer. This customer feedback loop is essential for improving the quality of the service.

(開発者に運用責任を与えることで、顧客と技術の両方の観点において、サービス品質が大幅に向上した。従来のモデルは、開発と運用を隔てる壁越しにソフトウェアを投げ込んで、後は忘れてしまう方式だった。Amazonにおいては違う。作った人たちが、運用も担う。これによって開発者らは、自分たちのソフトウェアの日々の運用に携わることになる。それはまた、顧客との日々のコミュニケーションをもたらす。この顧客フィードバックループは、サービス品質の改善に不可欠だ。)

■関連記事

6. 機能横断型

機能横断型チームの優れた点は、そこに集まったメンバーが、互いの専門職種を越えて、同じサイクルでプロダクト開発に取り組むことにある。その主な効果は、意思決定や問題解決の速さ、ドメイン知識の均一化としてあらわれる。

それを理解するには、反対の形態を持つ分業組織について考えてみると良い。企画担当は企画担当だけで、エンジニアはエンジニアだけで業務サイクルをまわしているような組織だ。エンジニアだけでスクラム開発を採用している組織を例にするとイメージしやすいだろう。まず、企画担当が機能要件や仕様を定義し、それをエンジニアらに開発依頼する。それがプロダクトバックログに積まれ、エンジニアらが順に開発を進め、リリースするフローだ。

企画チームから開発チームへの開発依頼

このような分業組織では、企画と開発が非同期で業務遂行しているため、両者の同期頻度が低く、かつ情報量も小さくなる。企画担当がスクラムイベントに参加しないからだ。そのかわりに、企画から開発への「開発依頼」といった同期ポイントが作られる。随時的に同期ポイントとしてミーティング実施日を調整しようとすると、参加者全員のスケジュールに配慮せざるを得ない。そうすると、同期の実施は、理想的なタイミングより遅くなってしまう。

同期の実施は、理想的なタイミングより遅くなってしまう

また、そういった同期ポイントでのコミュニケーションでは、情報が劣化しやすい。先述の「開発依頼」であれば、機能要件や仕様についての企画担当からエンジニアへの説明は、必要最小限の情報量になる。限られた時間内で伝えなければならないからだ。そうして、企画担当が有するドメイン知識が、エンジニアらには欠落してしまう。組織内に、「ドメイン知識の過疎地」ができるのだ。

その状態のエンジニアらに、果たして優れたアーキテクチャた内部設計を作り出すことなどできるだろうか。それに失敗すれば、保守性の低下を招き、将来の生産性を悪化させることになってしまう。

チーム間での随時的なコミュニケーションでは情報が劣化しやすい

機能横断型チームの場合、同期が頻繁に行われる。機能横断型チームが、スクラムチームとして活動しているなら、プロダクト開発に必要なスキルを持った人たちが皆、スクラムイベントに参加する。それぞれのイベント内で、意思決定や問題解決、ドメイン知識の共有が、高頻度で実施されるのだ。

機能横断型チームは、プロダクト開発に必要なスキルを持った人たちが皆、スクラムイベントに参加する

実際のところ、機能横断型チームを作るのは想像するより難しい。従来やってきたプロセスが、職種間、業務機能間で違いすぎるからだ。これまでのやり方をすて、新しいプロセスを構築しなければならない。その設計が難しいし、当事者や関係者に理解を得るのも難しい。

機能横断型への移行のハードルがあまりに高いようなら、まずは、チームではなく、特定のイベントを機能横断型にしてみることからはじめると良い。たとえば、スプリントレビューを機能横断型イベントとして、皆で集まる。そうすれば、ドメイン知識の均一化が進みやすくなる。プロダクトバックログのリファインメントを機能横断で実施するのも良いだろう。こうして少しずつ、互いの業務プロセスをオーバーラップさせる領域を広げていくのだ。

品質保証についても、テストのシフトレフトによるオーバーラップによって機能横断を実現できる。品質保証を、テスターによるリリース前のテストフェーズにだけに頼るのをやめ、テストファーストという手法をとるのだ。ユニットレベルのテストであれば、エンジニアとテスターでペアプロを実践すれば良い。また、開発を始める前に、企画やテスター、エンジニアで協力して機能テスト向けのテストケースを書くことだってできるだろう。

■関連記事

7. マルチスキル

少人数チームを技術横断型や機能横断型として機能させるためには、何が必要になるだろうか。それは、メンバーそれぞれがマルチスキル(多能工)になることだ。

たとえば、フロントエンド開発のみを担当するチームであれば、メンバー全員がフロントエンドエンジニアとしてシングルスキル(単能工)であっても困らない。

しかし、技術横断型チームであればどうだろう。フロントエンドエンジニアが4人、バックエンドエンジニアが3人の編成だとする。この時、全員がシングルスキルなら、フロントエンド開発の仕事量は同時に3人分、バックエンド開発の仕事量は同時に4人分が限界になる。メンバー数が7人であるにも関わらずだ。

バックエンド開発に関する仕事が少ない時期に、フロントエンド開発に仕事が集中することもある。こんな時、フロントエンドエンジニアは多忙であるにも関わらず、バックエンドエンジニアは時間を持て余すことになる。そうすると、バックエンドエンジニアは優先順位が低い仕事や、価値の小さい仕事に手を付けるかもしれない。仕掛中の仕事に時間を費やして過剰品質なアウトプットを生み出すことに専念するかもしれない。この状況が、チーム思考と言えるだろうか。

シングルスキルばかりだと、チーム内で局所的な人員不足が発生しやすい

このような局所的な人員不足は、チームが責務とする業務機能が多く、技術領域が広いほど、その傾向が強くなる。チームに様々なスキルが必要となるからだ。少人数チームにおいてそれをシングルスキルでカバーしようとすれば、必要なスキルが多いほど、それぞれのスキル所有者数が少なくなってしまう。これでは機能横断、技術横断であるほど、チームの生産性は低くなる。

ところが、ゾンビスクラム診断の統計によれば、67%のチームが「自分の専門分野の仕事だけしかしないか、ほとんどしないメンバーで構成されている」と回答しているようだ。これでは技術横断型、機能横断型チームの実現はほど遠い。もちろん、ゾンビスクラム診断を受けるチームは、その時点で問題を抱えているだろうから、この数字はネガティブ側に偏りがある可能性はあるのだが。

このような問題の解決策として、フロントエンドエンジニアをチームに追加するという手段をとるべきではない。そんなことをしていたら、チームメンバー数はどんどん増えていく。

だから、マルチスキルが必要となるのだ。バックエンドエンジニアが、フロントエンド開発に参加することを期待しているということだ。もちろんその逆も然り。これは、様々な専門分野の間で生じ得る問題なのだ。

マルチスキルのメンバーが多ければ、局所的な人員不足が発生しにくくなる

マルチスキルと言っても、求める人材像は、いわゆるT型やπ型だ。自身の専門分野を1つ、あるいは2つ深堀りしつつも、専門外の分野のスキルも浅く広く身に着けていく。先の例では、フロントエンドエンジニアとバックエンドエンジニアの話であったが、企画、デザイン、テスト、開発、保守、運用、その他、チームが責務とする業務機能や技術領域すべてに言えることだ。

T型、π型人材によるマルチスキル化

マルチスキル化を促進するためには、専門分野が異なるメンバー同士がペアを組んで仕事するのが良いだろう。あるいは型化、自動化を進めるのも手だ。たとえば、デザインシステムを構築しておけば、エンジニアがUIデザインをカバーする敷居も下がるだろう。

■関連記事

組織設計とはアーキテクティングである

組織マネージャーが責務を負う「組織設計」とは、「設計」と言いつつも実際は「アーキテクティング」だ。ソフトウェアと同じように、組織にもアーキテクチャと設計がある。マネージャーがアーキテクチャを示し、現場のチームがそれに沿ってチームやプロセスを設計・実装する。

そのようにイメージしてみると、組織設計の方針や意図を言語化すべき必要性に気づく。それが無ければ、期待どおりのチームやプロセスが実現されることはないからだ。そうして、アーキテクチャとしての組織設計は脆くも崩れ去っていく。これもまた、ソフトウェアアーキテクチャと同じではないか。

組織のミッションやビジョンとは違い、組織設計については、組織メンバーに向けて詳しく語られる機会は少ない。「繰り返し話さなければ」とよく言われるのは、ミッションやビジョンであり、組織設計ではないことからも明らかだろう。組織設計については、期初に軽く触れられる程度だ。その内容も、組織ツリーについての説明程度だろう。

語られる機会が少なければ、アーキテクトたるマネージャーの思考の言語化率も低くなる。これでは、組織設計に込めた方針や意図が伝わるはずもない。いくら優れたアーキテクチャを練り上げても、想定した組織は生まれないだろう。

そして、組織設計によって作り上げられる組織構造がいびつになれば、ソフトウェアシステムの構造もまた、いびつになってしまう。これは、「コンウェイの法則」という名で誰もが知るところだ。

マネージャーは、組織設計について、組織メンバーにしっかりと伝えていかなければならない。そう感じるところである。

チーム中心の組織作りのための6つのチーム設計原則

近年のソフトウェアプロダクト開発組織の活動単位としてよく言われるのは、「少人数で安定したチーム」であろう。表現は違えど、どの文献でもそのように述べられる。

それでは、「少人数」と「安定」の2つの要件を満たせば高パフォーマンスなチームが設計できるかと言えば、そんなはずもない。他にも要件があるはずだ。

そこで、チームに共通して必要だと考える要件を、設計に関わったこれまでの組織から抽出して言語化し、原則としてまとめてみた。それが、「安定」「アトミック」「非兼務」「少人数」「流動性」「イテレーティブ」の6つだ。

初期に携わった組織には欠けていた要素もあるが、何度も失敗を重ねるうちに見いだしたものだ。組織設計のプラクティスとしてよく聞くものもあるが、いずれも実体験を経て必要だと感じたものばかりである。

なお、本記事で取り上げる6つのチーム設計原則だけでは、組織設計として不十分だ。チームにどういった機能を持たせ、どのように配備(デプロイ)するかについても考えなければならない。しかし、そこまで含めると記事が長くなり過ぎる。そのため、それらは次回の記事にまわすことにした。

1. 安定

「安定」したチームは、プロジェクトチームのような一時的に編成されるチームとは真逆のコンセプトに基づくチームだ。いくつものプロジェクトに渡って存続し続ける。チームの顔ぶれも頻繁に変わるようなことがなく、概ね固定のメンバー編成であることが保証されている。つまり、存続期間が長く、かつ、メンバーがほぼ固定されるというのが「安定」と称する理由だ。

存続期間が長く、メンバーがほぼ固定されている

チームが安定することで、チームワークが安定する。プロジェクトチームと違い、プロジェクトのたびにチームビルディングをいちから始める必要がないからだ。タックマンモデルで言うところの「機能期(Performing)」を維持することも可能である。

機能期を長く維持できる

ジェフ・サザーランド(Jeff Sutherland)の著書『スクラム』に、次のような一文がある。

チームが一つにまとまりシンクロし始めると、魔法にかかったようになる。チームがいる部屋に一歩入ればそれを感じる。チームが仕事に取り掛かると見えてくる。スムーズに流れるような動き。チームが一つになることで、個々の集まりを超えた境地に到達した状態だ。

これこそまさに、機能期のチームだ。私も過去に、このようなチームを体験したことがある。

プロダクト開発はチームプレーだ。機能期にあるチームは、まるでスポーツチームであるかのように、それぞれに受け持つポジションがある。互いに連携し、状況に応じてフォーメーションを変えながら、プロダクト開発ゲームを進める。長く一緒に働いているから、チーム内でのそれぞれの役割(チームロール)が自然と形成され、それが上手く噛み合って機能するのである。互いのパーソナリティだけでなく、ハードスキルやソフトスキルも理解し合っているのだ。

その効果のひとつとして、ソフトウェアの内部品質の劣化を抑制しやすくなる点が挙げられる。チームワークによって、コードレビューやペアプロをはじめとするチームでの協働が機能するからだ。もし、保守性を悪化させてしまったら、そこに変更を加えようとする未来の誰かが苦労する。そのコストが開発時間を長引かせ、市場投入までの時間に悪影響を及ぼす。安定したチームならば、チームワークによってこういった問題を軽減することも可能なのだ。

さらに、安定したチームは、計測したベロシティの信頼性も高い。繰り返されるプロジェクトやイテレーションを通して、チーム編成がほぼ一貫しているからだ。ベロシティの信頼性が高まるということは、プロジェクトの予測可能性も高いということだ。

チームのベロシティの信頼性が高まり、プロジェクトの予測可能性も高まる

チームとしてのパフォーマンスを高めること。プロジェクトの予測可能性を高めること。チームを安定させる狙いはまさにこれである。

安定したチーム

■関連記事

2. アトミック

チームの「アトミック」性とは、組織内でチームを「個」として扱うことを意味する。仕事の割り当て対象が、個人ではなく、チームであるということだ。チームとして仕事を引き受け、チームとしてアウトプットする。チーム内の関係性はフラットだ。チームが引き受けた仕事を、チーム内で「誰が何を、いつ、どのように行うか」はチーム自身で決める。そこに対してチーム外から口出しすることを禁ずる。

チームとして仕事を引き受ける

従来のソフトウェアプロジェクトにおける開発業務は、プロジェクトマネージャー(PM)によるオーケストレーション型で進められる。誰が何を、いつ、どのように行うか、それを計画し、実行を指示し、進捗を管理するのはPMである。極端に言えば「すべてはPMが考え、その通りにチームが動く」ということだ。プロジェクト成否の大部分は、PMの手腕にかかっている。それが、オーケストレーション型のプロジェクトマネジメントである。

PMのスケジューリングにしたがってメンバーが動く

オーケストレーション型では、チームの自律性が育ちにくい。PMの指示に従い、割り当てられたタスクに集中し、期限内に要求通りのアプトプットを出すことができれば、メンバーとしての責任が果たせる。だから、メンバーはそれぞれ、担当タスク以外のことに注意が向きづらくなってしまう。

アトミック性を持つチームは、チームが引き受けた仕事をどうやって進めるかについて、チーム内で話し合う。そうして分解されたアイテムを誰がやるかは、チーム内の自薦や他薦で決める。チームリーダーであっても、あれこれ指示してはいけない。ここでのリーダーの役割は、メンバーらによるチーム運営をサポートすることだ。

こうすることで、メンバーそれぞれが、ミッションを念頭にチーム思考で動けるようになることを期待している。自分のタスクだけに専念するようなことはしないということだ。

たとえば、チームのカンバンボードにコードレビュータスクが溜まっているとしよう。こんな時、チーム思考があれば、誰かがやることを期待して放置したりしない。仕掛中の担当タスクが終わった人が、別の担当タスクを始める前に、溜まったコードレビュータスクに取り掛かるだろう。このように、チームやプロジェクトを俯瞰して「誰が何を、いつ、どのように行うか」を自分たちで適切に意思決定できるようになることを期待しているのだ。いわゆる「自己管理型」である。

人手が足りない他チームの応援をする場合も、アトミックに対応する。従来のやり方ならば、応援を要請しているチームXに対し、チームYがメンバーを貸し出す方法をとる。チームYから貸し出されたメンバーは、一時的にチームXのメンバーになるのだ。だがアトミックなやり方は違う。自チームから人を貸し出したりはしない。チームXの仕事の一部を、チームYが責任を持って引き受けるのだ。これが、チームの「安定」にもつながる。

チームメンバーを貸し出すのではなく、チームとして仕事の一部を引き受ける

この「アトミックチーム(Atomic Teams)」というコンセプトが、私の組織設計の中核になっている。

アトミックチーム

■関連記事

3. 非兼務

非兼務、つまりは1人のメンバーが複数のチームに所属しないということだ。所属できるチームの数は、原則として、1人あたり1つだけに限定する。

兼務はチームの独立性の阻害要因となることが問題なのだ。チーム間で人を共有するということは、チーム間で競合が発生するということだ。その競合を解消するためには、チーム間での調整が必要になる。チーム単独で計画づくりができない。これが、チームの独立性を阻害するということだ。

兼務者を挟んでチーム間に競合が発生することで、チームの独立性が阻害される

たとえば、Aさんが、チームXのメンバーとして3日間かかる仕事を受け持ち、兼務するチームYでも3日間の仕事を受け持っていたとしよう。このどちらを優先すべきか。優先することになった仕事は3日後に完了する。だが、もう一方の仕事は4日めから着手することになるため、完了するのは6日後だ。両方同時に進めたら、ともに6日後以降に完了することになるだろう。いずれにしても、少なくともどちらか一方は、完了日が遅くなる。これをチーム間で話し合うのだ。

仮に、チームXの仕事を優先することになったとする。この仕事の完了が遅延したらどうなるだろう。もちろん、チームYの仕事の着手が遅延し、完了も遅延する。Aさんを接点として、チーム間にクリティカルチェーンクリティカルパス)が形成されたからだ。チーム間の結合度が高い状態だとも言えるだろう。

問題はこれだけではない。兼務によって、Aさんは、チームXのミーティングにも、チームYのミーティングにも参加しなければならなくなる。両チームがスクラム開発を採用しているとしたら、Aさんは、そのどちらのスクラムイベントにも参加することになる。各チーム内外での細かなやり取りも含め、Aのコミュニケーションコストが倍になっている。つまり、開発時間がそれだけ削られるのだ。

この例では、各チームのスクラムイベントも、実施時間を調整することになる点も見落とせない。どちらのチームも朝10時からデイリースクラムをやろうとすると、Aさんはどちらか一方にしか参加できなくなる。チームXは10時から、チームYは10時15分から、といったように調整するしかない。うんざりだ。そもそもAさんにとっても、朝から2つのデイリースクラムに参加するなんて……

チームにとってもメンバーにとっても、非兼務である方がストレスも少なく、パフォーマンスも発揮しやすいということだ。

非兼務

■関連記事

4. 少人数

チームが少人数であるべき理由はいくつもある。主たるものは次の5つだ。

1つめの理由は、一人ひとりに主体性や責任感が生まれやすい点。大人数だとどうしても、一部の少数の人だけが頭を働かせ、残りの人達はそれに従うだけでどこか他人事になってしまいがちだ。人数が少なければ少ないほど、チーム全体で主体的に行動せざるを得なくなる。もちろん、チームメンバー全員がフラットな関係性であることが前提だ。そうして自己管理型のチームに近づいていく。

多人数チームは、一部の人だけが主体的に動きがちになる

自己管理型チームは、そうでないチームよりも、優れたプロダクトを生み出せる。私はそう考えている。ただ言われたことを実行するのではなく、ミッションを念頭に自分たちで意思決定し、行動することになるからだ。

2つめは、コミュニケーションコストが小さくなること。ミッションを共有する1つのチームとして行動するためには、メンバー間の相互コミュニケーションが欠かせない。一方で、コミュニケーションはコストとしての側面も持つ。チーム内での密なコミュニケーションを実現しつつも、そのコストを最小化するためには、少人数であることが適している。人数が少ないほど、コミュニケーションパスの数が減るからだ。

コミュニケーションコストは人数の2乗のオーダーで増加する

3つめは、バッチサイズが小さくなる点。バッチサイズとは、1度の開発におけるスコープの大きさだ。チームが小さければ、スコープも小さくせざるを得ない。大きなスコープに対応しようとすると、市場投入までの時間が長くなり過ぎるからだ。アジャイル開発を採用して、イテレーションを短くすることで、さらにバッチサイズは小さくできる。

バッチサイズが小さければ、早く安全に失敗できる。たとえば、プロダクトに対するアイデアを6か月かけて開発し、リリースしたとしよう。その結果、それがビジネスにとってもユーザーにとっても価値を生まなかったらどうなるだろう。6か月の労力が無駄になってしまう。しかし、小さなアイデアを2週間かけて開発してリリースしたなら、失敗してもダメージは小さい。その失敗から学んだことを、次のイテレーションでまた試せば良い。小さいバッチサイズならば、こういったフィードバックサイクルをまわせるのだ。

バッチサイズが小さければ、早く安全に失敗できる

4つめは、チームの敏捷性が高まる点。変化への適応能力に優れているということだ。これは、上述の3つの理由によって実現されるものだとも言える。

最後の5つめは、マネジメントコストが小さくなることだ。人数が多ければ多いほど、メンバーマネジメントに関するリーダーやマネージャーの負担が大きくなる。その負担が大きければ、マネジメントが行き届かなくなり、チームを崩壊させることにもなりかねない。私が観察してきた限りでは、チームの規模が8名~10名以上になるあたりから、問題が生じやすくなるように感じている。

以上が、少人数チームが優れていると考える主な理由である。

組織をスケールさせるにも、チームの人数を増やすのではなく、このような少人数チームを増やすという考え方が基本だ。チームメンバーを増やすことで組織をスケールさせるアプローチは取りたくない。

私は昔、20名以上のメンバーを抱えるチームを引き継いだことがある。この多人数チームは、正式なチームとしては1つであるが、実態はもっと複雑であった。

まず、数名からなる保守チームというものが内部に構成されていた。この多人数チームで開発したソフトウェアシステムの保守業務のみを担当するチームだ。そして見事に失敗ケース「保守・運用の分離」を踏み抜いていた。彼らは、品質の悪いソフトウェアのおもりにうんざりしながら毎日の業務をこなしていたのだ。当然、保守チームに割り当てられたメンバーのモチベーションは落ちていた。

残りのメンバーはと言うと、開発業務向けの「共有リソースプール」として管理されていた。この多人数チームは常に複数のプロジェクトを抱えていた。その規模も、大小さまざまだ。共有リソースプール化は、この状況に柔軟に対応するための体制だろう。プロジェクトが新しく立ち上がるたびに、そこから数名がプロジェクトにアサインされていた。もちろん、人数面、あるいは能力面で不足するプロジェクトも出てくる。そうなると、プロジェクトの掛け持ちも横行する。

この多人数チームのマネージャーの権限も大きかった。チームメンバーは、マネージャーのコマンド&コントロールで動き、自主性は失われてしまっていた。

このように、多人数チームの実態は、安定もせず、アトミックでもなく、少人数でも非兼務でもないチームだったのだ。人数の多いチームをマネージャーがなんとか機能させようとする中で、このような形になったのだろう。多人数チームを引き継いで私が最初におこなったことが、チームの分割だったことは言うまでもない。

■関連記事

5. 流動性

チームを安定させなければならないと言っても、若干の流動性は必要だ。時々はメンバーを入れ替えなければならない。チームの顔ぶれを何年ものあいだ固定し続けると、十中八九、ひどい属人化に陥るからだ。

流動性がないチームの業務は属人化しやすい

チームにおける属人化の症状は、様々な形であらわれる。例えば、本番稼働で障害が発生した際、緊急対応しているのがいつも同じメンバーであるとか。彼が対応すれば早く解決するから、他の人は遠慮してしまうのだ。そうするうちに、当人と他のメンバーの間の緊急対応に対するスキル差はどんどん広がっていく。

他にも、特定の領域のコードの理解容易性の低下という形であらわれることもある。その領域の変更はいつも同じ人が担当するから、当人だけがコードを理解すれば良く、理解容易性を高める動機がないのだ。そうしてコメントもなく、適切なドキュメントもないコードができあがる。複雑化してしまうこともあるだろう。こうして他のメンバーは、この領域に含まれるコードに手出しができなくなる。

属人化したコードは、理解容易性が低い

属人化は、メンバーそれぞれに得意分野ができはじめることから生じる。同じチームで長く仕事を続けていると、みんな、いずれかの分野が得意になっていく。得意になれば、その分野の仕事は人から頼られるようになるし、自ら引き受けるようになる。得意な人がやった方が短期間で仕事が完了するし、アウトプットの品質も高くなるから当然だ。だが、それが長く続くと属人化されてしまう。

属人化はチームにパフォーマンスをもたらす代償として、バス係数を悪化させてしまう。属人化した業務を担うメンバーが、チームの単一障害点になると言った方が分かりやすいだろうか。そのメンバーが何らかの理由でその業務を遂行できなくなった時に何が起こるかを考えると明らかだろう。当人が不在になると、属人化した業務が滞ってしまうのだ。

チームに若干の流動性を持たせることで、属人化の進行を緩和できる。チームに新メンバーを受け入れることになれば、オンボーディングが必要になる。そのためには、仕事のやり方が可視化され、言語化されていなければならない。また、既存のメンバーが抜けることになったなら、引き継ぎも必要となる。こういったイベントを半年や、長くても1年に1回程度の頻度で発生させれば、冗長化が進むことが期待できる。

流動性によって冗長化が進む

もちろん、流動性を持たせることだけが、属人化に対する唯一の軽減手段ではない。しかし、組織設計としてそういった仕組みを入れておくことも必要だと考えている。

以前は、属人化を許容するスタンスを私はとっていた。個々の得意分野を活かして、存分に能力を発揮して欲しいからだ。冗長化によって組織としての能力を平均化するより、彼らの能力を活かして組織の強みにしようというわけだ。もし、彼らが退職したとしても、その時に対応すれば良いと考えていたし、実際にいつも何とかなった。

しかし困ったことに、これでは人が育たないのだ。得意分野がある人が、毎回その分野の仕事を担うため、それが結果的に他の人の学習機会を奪うことになるからだ。それに、チーム内に属人化した業務を抱えているからといって、当人をずっとチームに固定し続けると、その人の新しいチャレンジの機会を奪うことにもなる。どちらの立場にたっても、人が育たない環境を生み出してしまっているのだ。

そもそもこれでは、「チーム」という単位にこだわって組織づくりを進めているはずの私自身が、パフォーマンス面で個人にばかり目を向けていることになる。これでは一貫性もない。ジェフ・サザーランド(Jeff Sutherland)も書籍『スクラム』で、メンバー個人の力量より、チームの力に目を向けるべきだと述べている。個人のパフォーマンスの違いより、チームのパフォーマンスの違いの方が大きいからだ。

そういうわけで、属人化を許容したパフォーマンスの獲得より、チームパフォーマンスの向上に力を入れたいのである。これは、メンバー個々の得意分野を活かして、存分に能力を発揮することを否定しているわけではない。そうした高い能力を活かしてもらいつつも、他のメンバーにもその能力を継承(スキルトランスファー)し、人を育てられる体制を作りたいのだ。

非属人化が、スキルトランスファーと新しい領域へのチャレンジをうながす

思ったより長い節になってしまったが、チームの流動性には、もう1つ狙いがある。それは、チームに刺激を与えようという意図だ。

チームを長く安定させると、文化や価値観が固定化されてしまう。そうしてコンフォートゾーンに入り込んでしまう。しかし、外部環境も内部環境も常に変動している。新しいことを学び、チャレンジしなければ、優れたプロダクトをユーザーに提供することなどできない。それに、長くコンフォートゾーンに浸かり続けると、仕事に飽きもくる。

新メンバーがチームに入ることで、その停滞した空気に刺激が加わる。新しい文化や価値観が流入するのだ。そうすれば、チームは再びラーニングゾーンに入り、変化に適応することが可能になるだろう。

流動性のあるチーム

■関連記事

6. イテレーティブ

イテレーティブなプロセスは、ソフトウェアプロダクト開発における意思決定を経験主義に基づかせるためには欠かせない。「少人数」の節でも触れたが、これは、早く安全に失敗し、そこから学ぶためのフレームワークなのだ。

我々が身を置くのは、常に不確実性が高く、予測可能性が低い領域だ。時間をかけて深く分析すれば正解が導き出せるなんて、とんだ思い込みであると知るべきだ。そうして進めた結果、あとから「間違っていた」と気づくことが何と多いことか。

それを端的に表す数字が、「アイデアの3分の2は価値がない、あるいは逆に価値を損なわせる」という、マイクロソフトの調査結果だろう。どれだけ自信を持ってリリースした機能であっても、ユーザーから良い反応が得られないことの方が多い。プロダクト開発に携わっていれば、これは誰もが経験することだ。

イデアの2/3が価値がない、あるいは価値を損なわせる結果に

こういった失敗は、なにもプロダクトや機能といったレベルでのみ生じるわけではない。アーキテクチャや内部設計でも起こり得る。

たとえば、素晴らしい出来栄えだと思ったアーキテクチャや内部設計が、ほとんど役に立たなかった経験は誰にでもあるだろう。むしろ、可能性を予測して作り込みすぎたために、使いもしない内部機能が設計を複雑にしてしまったようなケースだ。

ソフトウェアプロダクト開発は、クネビンフレームワーク(Cynefin framework)で言うところの「複雑(Complex)」な状況を扱う領域なのだ。この領域では、時間をかけて状況を分析してみても、そこから正解を導き出すことが難しい。探索することでようやく状況を把握し、正解らしきものを見つけられるのだ。それに合わせて軌道修正すれば良い。これが、スクラムガイドでも3本柱のうちの2つとして挙げられている、経験主義による「検査」と「適応」だ。

イテレーティブなプロセスによる経験主義に基づく検査と適応

スクラムをはじめとするイテレーティブな開発プロセスモデルを採用しているならイメージしやすいだろう。スプリントの成果をスプリントレビューで検査し、そこでのフィードバックを次回以降のスプリントとして適応させることができる。実際にリリースしてユーザーに使ってもらえば、もっと正確なフィードバックが得られるだろう。

スプリントのたびに得られる経験は、プロダクトに関してのみではない。プロジェクトを通じてチーム活動に関する知見も得られる。そうしてスプリントごとの振り返りで、チームの成長について議論できる。これも、経験主義による検査と適応だ。

アーキテクティングや設計も、はじめから大きく作り込みすぎると、大きく失敗しやすい。いわゆる「BDUF(Big Design Up Front)」だ。ある程度はBDUFも必要だと感じるが、「ENUF(ENough design Up Front)」で必要最小限な設計にとどめつつ、開発のたびに少しずつ進化させたい。テスト駆動開発は、コードレベルでそれを実現する。小さなフィードバックサイクルの中で、少しずつ内部品質を高めながら実装を進めるフレームワークだからだ。

「イテレーティブ」であることは、チームとプロダクトに、正しい進化と成長をもたらすということだ。

とは言え、組織設計の中で定義できることは、ソフトウェア開発プロセスモデルをイテレーティブにすることぐらいだ。それより内側のフィードバックサイクルについては、チームに任せるしかない。

■関連記事

つづく

次回の記事では、これらの原則を満たすチームにどのような機能(業務機能)を持たせるべきかを考える。また、それらを組織内にどのように配備するかについても検討する。

mtx2s.hatenablog.com

開発と保守・運用の分業は個別ミッションの遂行手段にコンフリクトを生じさせやすい

ソフトウェアエンジニアリング組織の主たる業務機能は、開発、保守、そして運用の3つだろう。これらをどう組織化するか。それが、生産性にもビジネスにも影響する。私は多くのケースにおいて、この3つの機能をすべて持つ、少人数のプロダクトチームをいくつか組織化する。その理由は、過去の記事で何度か書いたように、開発でのアウトプットに対するフィードバックサイクルをまわせるようになるからだ。それが、技術・サービスの両面を向上させる。

しかし本稿のケースは違う。ここで取り上げるのは、保守・運用が、開発とは分離された構造を持つ組織だ。この体制における課題を明らかにし、そのうえで解決策を探ってみたい。

事象は開発と保守・運用の分離が上手く機能していないこと

実は、先日登壇させていただいたオンラインカンファレンスにて、保守・運用の分離に関して質問を受けたのだ。それを深掘りしようというのが、本稿の動機であり、趣旨である。

具体的にどういった質問を受けたのか、そのテキストが手元にないため記憶に頼ることになるが、概ね次のようなものであったと思う。

  • 組織は、開発と保守に分かれている
  • 開発が速くなっている
  • どうすれば良い関係を築けるか

その場では、想定する前提に基づいて少々抽象度の高い回答になった。ZoomのQ&A機能を使った短いテキスト文での質問であったため、前提に不明な点が多かったことと、回答時間が1分ほどしかなかったからだ。その時は、「開発が速くなっている」という点を「良いこと」と受け止めて答えたのであるが、あとから考えると、それは、保守チームにとって「困りごと」だったのかもしれない。

色々と想像で補うしかないが、とりあえず検討を進めてみようと思う。

ここでは便宜上、保守チームの責務に運用も含まれている前提とする。誤解を招かないよう、保守・運用チームと呼ぶことにした方が良さそうだ。ただし、運用と言っても、ソフトウェアシステムをマネージドなインフラ/プラットフォーム上で本番稼働させている想定だ。また、扱うソフトウェアシステムも、自社プロダクトであるものとする。

問題は開発が保守・運用を阻害すること

まず、開発が速くなった理由であるが、これはちょっと分からない。様々な可能性があるからだ。

「開発が速い」という表現は、開発のリードタイムが短く、リリース頻度が高い状態を表しているのだと考えられる。その頻度が、保守・運用チームの負荷になっていたり、ソフトウェアシステムの信頼性に悪影響を与えているのではないか。そして、保守・運用上におけるこのような状況が続いていることについて、チーム間で建設的に話し合えておらず、問題を取り除くことができないままにあるのではないか。

リリース頻度が高まると、2つの面で、保守・運用業務の負荷が高まりやすくなる。

1つは、引き継ぎが困難になることだ。ソフトウェアシステムに加えられた変更点が何であるか、リリースの度に開発チームから保守・運用チームへの引き継ぎが発生する。この頻度が高いと、保守・運用チームにとってはつらい。

また、あまりにその頻度が高まると、開発チームにとっても引き継ぎ準備がオーバーヘッドとなる。高頻度なリリースの足かせだと感じ始めるのだ。すると、まともな引き継ぎなど行われなくなる。保守・運用チームは、引き継ぎのないまま保守を続けることになるだろう。そもそも、早期のリリースと引き換えに、ソフトウェアの内部品質を犠牲にしている可能性も高い。それが長く続くと、担当するソフトウェアシステムが、保守・運用チームにとって得体のしれないものになっていく。この状況で安定した保守を継続するというのは、なかなかにハードだ。

もう1つは、バグフィックスや緊急対応に追われるようになることだ。バグトラッカーには、リリースする度に、未対応のままの軽微なバグが積まれていく。その増加スピードがあまりに速いと、保守・運用チームの負荷は高まる。それに加え、リリース前に検出されなかったバグが本番環境でトラブルを引き起こし、その緊急対応や、その後の是正対応に追われることもある。リリース頻度が高まれば、こういった対応も増えるかもしれない。

開発チームと保守・運用チームが分離したままであっても、この状況を何とか改善する術はないか。それが、質問者の言いたいことだったのではないだろうか。

課題は個別ミッション遂行におけるコンフリクトを解消すること

この状況はコンフリクトだ。開発チームは、リリース頻度を高めたい。保守・運用チームは、リリース頻度が高すぎることを問題視している。典型的な、devとopsの対立である(保守をopsに含めて良いのかわからないが)。

開発チームは、優れた機能をユーザーに届けるために、開発のリードタイムを縮め、リリース頻度を高めようとする。リードタイムが短ければ、それだけビジネスにも好影響を及ぼす。たとえば1か月で100万円の利益が見込める機能を1か月早くリリースできたなら、利益を100万円多く得られる。もちろん、リリースしたからといって、新機能が思惑どおりの価値を生み出すとは限らない。しかし、リリース頻度が高まれば、それだけフィードバックサイクルが速くなり、新機能をより価値のあるものに近づけやすくなる。

一方の保守・運用チームは、信頼性の高いサービスを提供するために、プロダクト品質やサービスレベルを高めたり、安定させることに努める。品質やサービスレベルが下がると、ユーザーの不満足につながってしまう。だから、それらを日々、監視し、メンテナンスし、守り続けるのが彼らの責務だ。それだけに、プロダクトに変更を加えられるのは、品質やサービスレベルの安定性を崩す要因になりかねない。リリースに対して慎重にならざるを得ないのだ。

このように、チーム間での利害が相反するため、解決は難しいようにも思えるが、本当にそうだろうか。

開発チームであろうが、保守・運用チームであろうが、彼らには共通のミッションがある。それは、プロダクトのユーザー価値を高めて優れたユーザー体験を提供することと、その実現を通してビジネス面で大きな成果を得ることだ。そのミッションを支える戦術の1つが、開発チームの責務である「優れた機能をユーザーに届ける」というミッションであり、また、保守・運用チームの責務である「信頼性の高いサービスを提供する」というミッションだ。

分業によって生じやすい弊害として、各チームが互いに共通のミッションを見ずに、それぞれのチームに割り当てられた個別ミッションの範囲内で活動や思考が閉じてしまう点がある。いわゆる部分最適である。そうすると、チーム間でのコンフリクトが起き始める。この組織の開発チームと保守・運用チームは、この状態に陥っていると考えられる。

したがって、各チームが共通のミッションに立ち戻り、それを踏まえた上で個別のミッションを遂行できれば、コンフリクトを解消・軽減できるはずだ。

対策は共通ミッションに立ち戻ること

チーム間でコンフリクトしている対象が、実はそれぞれの個別ミッションの遂行手段である点に注目すべきだろう。1つしかない共通のミッションがコンフリクトするわけはないし、それぞれの個別ミッションもコンフリクトしない。あくまでも、それらを「どう遂行するか」がコンフリクトしているのだ。これは、自チームのミッションの範囲内だけで遂行手段を考えてしまうからだろう。したがって、それぞれのミッション遂行手段を両チームで話し合って決めれば良いのではないかという考えに行き着く。

たとえば、未解決のバグの数に上限を設けるというルールを設けてはどうだろうか。必ずしもすべてのバグを解決しなければならないわけではないが、解決するバグの数より、リリースの度に追加されるバグの数の方が多いようであれば問題である。それならば、バグの数が上限を超えたら、それらを収束させるまでリリースをストップするのだ。その間、開発チームと保守・運用チームが協力して、バグの解決に取り組む。バグの数でエラーバジェットを設けるようなイメージだ。

この方法の良いところは、バグ増加の抑止力にもなる点だ。リリースを止めたくなければ、開発チームは品質を担保しなければならなくなる。そのために開発速度が多少下がる可能性もあるが、優れた機能をユーザーに提供することも、信頼性の高いサービスを提供することも両立させることができる可能性が高まる。本番稼働後のトラブルの数にエラーバジェットを設けることだってできる。

他にもやり方は考えられる。

たとえば、コード内のコメントや、適切なドキュメントなどが未整備な状態が続いているなら、開発プロセスに、保守・運用チームが関わるのも手だろう。開発チームと協力し、開発を進める中で、並行して、保守・運用チームが必要最小限のドキュメントを整備していく。そのために、保守・運用チームが設計に関わるのも良いだろう。

また、保守・運用メンバーがコードレビューを担当し、変更されたコードを理解しつつ、コメントの不備などを指摘する。ここで、必要なログが出力されていない箇所があれば、それもあわせて指摘しても良いだろう。システム運用には重要なことだ。もっと踏み込んで、開発メンバーと保守・運用メンバーでペアプロをやってみるのも良いだろう。

さらに、開発チーム、保守・運用チームが、互いの課題について共有し合う場を定期的に設けるのも手だ。相互にフィードバックし合うわけだ。そうすることで、開発・保守・運用いずれに対しても改善が進む。

まあ、前提条件や制限事項がない状態での空想なので、これらの対策の実現性やその効果がどれだけであるかは定かではない……

いずれにしても、要は、全体最適になるよう各チームの行動を設計するということだ。チームの個別ミッションだけで思考を閉じてはいけないのだ。開発チームと保守・運用チームで、同じ目標を追いかけてみるのも良いだろう。

結論は両チームをあえて密結合にすること

はっきり言って、例として挙げた対策を実行すると、開発チームと保守・運用チームとの間で、コミュニケーションコストが増大するかもしれない。それが、かえって業務負荷につながる可能性もある。チームの境界を越えるコミュニケーションパスは、少なく、細い方が良いと私は考えている。それは、そういったパスが増えたり太くなるほど、チームの独立性を阻害する要因となるからだ。チーム単独で、業務を計画・遂行できなくなって、リードタイムに悪影響を及ぼすということだ。

ただ今回は、1つのプロダクトに対し、開発と保守・運用でチームを分けてしまっている。それ故、共通の担当プロダクトが結合点となり、両チームを縛る要因になる。チーム境界を越えるコミュニケーション量が増えるのはこのためであり、必然なのだ。

したがって、この組織構造においては、チーム間が疎結合である方がおかしいのだ。積極的にコミュニケーションを取り、協働するのが、開発と保守・運用が分離された組織でのあり方ではないだろうか。

追記

本稿を書き終えてから、質問文を入手できた。それが以下だ。

開発チームで開発したシステムを、開発するたびに保守、運用チームに保守・運用をすべて任せることで、次々と開発スピードが早くなります。早い開発をしたい場合、互いのチームの良い関係性はありますか?

あらためて読んでみて、質問者は開発チームメンバーなのかもしれないとも感じた。開発スピードを速くすることで、両チームの関係性が崩れる。そうならないようにする、あるいはそれを改善するにはどうすれば良いか。そういったところだろうか。

関連記事

mtx2s.hatenablog.com

note.com

mtx2s.hatenablog.com

speakerdeck.com

findy.connpass.com

「アジャイルテストの4象限」はアジャイル開発を補完するソフトウェア開発手法である

従来のプロジェクトにおける「テスト」は、リリースや納品前の最終工程として行われるものだ。多くのケースでそれは、前工程までの遅れと、それでも固定されたままのリリース日に挟まれ、予定された期間を食いつぶされた中で実施される。その上、時間に追われる中で実装されたソフトウェアは、動作確認も十分にされない状態でテストフェーズをむかえることになる。こうして品質の保証は、テスターに丸投げにされるというのが実態ではないだろうか。もちろんここでテスターに丸投げされているのは外部品質、特に機能面での品質の保証のみだ。非機能面での品質の保証は手薄になり、内部品質は顧みられることはない。

これは、ウォーターフォール開発を採用するプロジェクトで私が頻繁に経験した失敗パターンであるが、アジャイル開発でも遭遇する。その理由は、そのままのテストモデルがアジャイル開発の中でも用いられるために、同様の失敗パターンに陥りやすくなるからだろう。ウォーターフォールと比べ、1サイクルあたりの開発期間が短いアジャイル開発ではなおさらではないか。

アジャイル開発において、このような従来から抱える問題を解消するテストプロセスとはどういったものか。その問いの中で思い出したのが「アジャイルテストの4象限」だった。"テスト" の4象限ではなく、"アジャイルテスト" の4象限と呼ばれていることに、より注意を向けて見直してみるべきだと思ったのだ。

そこで、その原典であるブライアン・マリックのシリーズ記事をあらためて読み直してみたのであるが、どうやら本質を理解できていなかったようだ。これまでは、アジャイルテストの4象限を単なる「テストの分類を理解するための図」といった程度でしか見てなかった。しかし、そこに描かれていたのは、アジャイル開発を補完するかのようにデザインされたソフトウェア開発手法だったのである。

本稿は、その深掘りを目的としている。

アジャイルテストの4象限

アジャイルテストの4象限(agile testing quadrants)」は、2003年にブライアン・マリック(Brian Marick)が、シリーズとしてブログ投稿した8つの記事 "Agile Testing Directions" の中に登場する図だ。このシリーズ記事は、アジャイルテストの将来を見据え、その方向性を示すために記された。その中心を構成するのが、テストの役割を4つに分類し、それらを4つのトピックに分けた解説である。2×2のマトリクスで描いたこの4つの分類こそが、「アジャイルテストの4象限」と呼ばれる図だ。ただしこの、"agile testing quadrants" という呼称は、シリーズ記事の中で出現しない。これはあとから名付けられたものだろう。

アジャイルテストの4象限 - 原典の図にテストタイプの記載は無い

4つの象限は、左下をQ1(Quadrant 1, 第1象限)として、そこから時計回りに各順に、Q2, Q3, Q4と呼ぶことが多い。ただし、象限に付けられたこの順序を表す数字は、テストを実施する順序とは関係がない。

アジャイルテストの4象限の上下は、その領域に属すテストタイプが、「ビジネス面(business facing)」のテストを目的としているか、「技術面(technology facing)」のテストを目的としているかで分類されている。

上段に位置する「ビジネス面」のテストとは、顧客やユーザー視点でのテストだと考えると良い。そこで使われる用語は、プロダクトが対象とするドメイン領域で使われる言葉だ。テスト内容も、そこに接している顧客やユーザーが理解できるものであり、機能テストやユーザー受け入れテスト(UAT)といったテストタイプが該当する。

対象的に、下段に位置する「技術面」のテストは、開発者(ソフトウェアエンジニア)視点でのテストだ。ユニットテストや非機能テストなどが該当する。

アジャイルテストの4象限の左右における分類は、テストタイプが「チームを支援する(support team)」ものであるか、「プロダクトを批評する(critique product)」ものであるかを示す。原典の図で左側象限は、「チーム」ではなく「プログラミング」を支援するものとされていたが、シリーズ記事の途中で対象がチームに拡張されている。

左側に位置する「チームを支援する」テストは、機能開発をガイドする目的を持つものだ。基本的に、先にテストが書かれ、そのテストに合格する機能を開発する。TDD(test-driven development, テスト駆動開発)をイメージすると分かりやすいだろう。TDDは、技術面を扱うQ1に位置するユニットテストを先に書く開発手法であるが、ビジネス面を扱うQ2でも先にテストを書くことが想定されている。

右側に位置する「プロダクトを批評する」テストとは、その実施によって、仕様と期待との間のギャップを発見しようとするものだと考えると良い。定義された仕様が、必ずしも顧客やユーザーの期待に沿うものになるとは限らない。そのようなギャップを見つけ出し、それを新たな設計や仕様にフィードバックする役割が、右側に位置するQ3とQ4の役割だ。

この左右の分類こそが、従来のテストとの違いを理解するうえでの肝となるものだと、私は考えている。それが、短いイテレーションで反復的に開発するアジャイルソフトウェア開発プロセスの中でテストが実施されることを念頭に描かれているからだ。そこには大小のフィードバックサイクルが組み込まれている。おそらくこのような前提が、アジャイルテストを特徴づけるものなのだろう。以下でそれを説明する。

左側象限:「チームをサポートする」

左側象限におけるテストは、基本的に、プロダクトバックログアイテム単位や、それをさらに細分化した開発単位、あるいはもっと細かい単位で個別に実施されるものだ。リリースやイテレーションごとに実施する一括テストではない。むしろ後者は、右側象限で主に担うテストであり、それらは従来のプロセスで言うところの「テストフェーズ」以降で実施されるものが主だ。すると前者は、テストフェーズより前に実施されるテストだということだ。これは、品質の保証をテストフェーズに丸投げしていた失敗パターンと対比すれば、テストの「シフトレフト」と言えるだろう。

シフトレフトによって、テストフェーズまでにテストの多くを実施

テストに限らず、シフトレフトがもたらす恩恵の1つは、手戻りコストの低減だ。欠陥を埋め込んでから、それが検出されるまでの時間が短いほど、その欠陥を生じさせている問題が何であるかを特定することが容易になる。欠陥を埋め込んだ本人が、自分がさっき加えた変更に原因があると気づきやすいからだ。最後の最後に位置するテストフェーズになってから欠陥を検出しても、誰のどの変更が原因であるか、解きほぐしていくコストが必要となる。不具合が生じた機能の実装が、必ずしも原因があるとは限らないからだ。

左側象限は、「作る前にテストを書く」というアプローチ、すなわち「テストファースト」という手法をとる。これには主に2つの恩恵がある。

その1つは、「何を作るのか」に対する曖昧さを排除できる点だ。テストを先に書くことによって、仕様を考えるだけでは気づけなかった矛盾点や、未定義のままの詳細などに気づくことができ、より精緻な仕様を定義できるようになる。むしろ、テストを書こうとする中で、仕様を考えるようにもなる。これで、本番稼働後に発生する障害の原因としてよく挙げられる「仕様の考慮漏れ」も生じにくくなるだろう。また、そうして明確に定義された仕様とそのテストがあれば、仕様と実装との間に生じやすいギャップ、すなわち欠陥(バグ)を減らすことも期待できる。もちろんここで言う「仕様」とは、Q2で扱う機能レベルの仕様だけでなく、Q1で扱うコードレベルの仕様も含んでいる。

定義された仕様とその実装の間に生じるギャップが欠陥である

もう1つの恩恵は、早期にフィードバックを得られるという点だ。テストを書くという行為は、想定する仕様を持つ機能やコードを「使用する」行為である。使用することで、使い手にとってそれが良い仕様なのか、悪い仕様なのか、自然に明らかとなる。テストを書きつつ、それが悪い仕様だと感じたならば、その時点で仕様を変更すれば良い。こうして、小さなフィードバックサイクルが形成され、仕様はより洗練されていくことになる。

左のサイクルが、テストファーストによるフィードバックサイクル

これらの恩恵を最大限に享受するためには、仕様を定義する人とテストを書く人が同一人物であるか、あるいは両者が密接に協力する関係が求められる。Q1で用いられるTDDは、まさにこれを前提に置いた開発手法だ。テストコードの作成を他者に委ねることなく、プロダクションコードを書く人が担うことになる。Q2の場合、仕様検討段階から積極的にテスターが関わることになるだろう。「テスターは、テストフェーズだけでなく、プロジェクトの早い段階から関わるべきだ」といった話を聞くことがあるが、その理由はここにもあるのだろう。

このように左側象限は、シフトレフトとテストファーストを通して、仕様の精緻化、洗練化を促し、何を作るべきかを明らかにしていく。これが、「チームを支援する」と呼ぶ理由なのだろう。ブライアン・マリックは、Q1でのTDDになぞらえて、このような開発手法を「例駆動開発(example-driven development, EDD)」と呼んでいる。テストケースやテストシナリオとは、開発対象の使用方法について書かれた「例(example)」であるからだ。

左側象限:イテレーションへの効果

左側象限によるシフトレフトとテストファーストは、開発のあとに開始するテストフェーズの期間を削減する効果をもたらす。テストフェーズに至るまでに一定の品質を保証できるため、テストフェーズで検出される欠陥が減り、欠陥修正に要するコストが小さくなるからだ。また、そもそもテストフェーズまでに終わらせたテストケースは、テストフェーズ内で検証する必要がない。これも、期間の削減につながる。品質の保証を過度にテストフェーズに依存し過ぎてテストフェーズ期間が長くなってしまうこととは対照的である。

短いイテレーションでプロセスをまわすアジャイル開発では、長いテストフェーズは扱いに困る。イテレーション期間に長いテストフェーズを無理に組み込もうとすると、開発期間を圧迫してしまう。仕方なく、テストフェーズを後続のイテレーションに切り出したり、開発した機能のテストをテスターに任せ、エンジニアは新しいイテレーションを開始して次の機能開発に着手したりすることになる。複数のイテレーション分の成果物をまとめてテストするようなやり方もあるだろう。

そういったテストモデルが必ずしも悪いとは思わないが、気になる点もある。後続のイテレーションでテストするということは、欠陥を埋め込んでから、それが検出されるまでの時間を長くする。その時間が長ければ長いほど、検出された症状から原因を特定することが難しくなる。また、欠陥の存在に気づかないまま、その上に積み重ねられてしまう変更の量も、時間の経過とともに大きくなる。それが、修正による手戻りコストを大きくする。テスターにテストを任せて次の機能開発を進めるという方法も、機能開発と並行して欠陥を修正するというマルチタスクを生みやすい。それに、この手法では、次の機能開発のベースとなるコードが欠陥修正前のものとなり、欠陥修正後のコードとのマージがコンフリクト発生の温床となったりもする。スプリント開発であれば、いずれにしても、スプリントレビューをスプリント内に実施することが不可能になるだろう。

しかし、シフトレフトとテストファーストを実現できれば、品質の保証の大部分をイテレーション内の早い段階で完結させられる。テストフェーズを経なくても、多くの欠陥が開発の中で検出され、修正済みとなるからだ。

シフトレフトとテストファーストによって、テストフェーズにおける従来の役割は小さくなる

さらに、テストファーストで書いたテストが自動化されていれば、リグレッションテストに使用することもできる。ウォーターフォール開発プロジェクトに比べ、短いサイクルでのデプロイを繰り返すアジャイル開発プロジェクトでは、リグレッションテストの実施回数がそれだけ多くなる。リグレッションテストも含め、テストフェーズのコストが大きいと、デプロイの頻度を下げようとする意識が働いてしまう。それだけに、高い頻度でのデプロイを繰り返すためには、リグレッションテストの自動化比率を上げ、テストフェーズのコストを下げることが欠かせない。

リサ・クリスピン(Lisa Crispin)とジャネット・グレゴリー(Janet Gregory)は、書籍『実践アジャイルテスト』の中で、左側に位置するQ1とQ2でのテストを特に自動化すべき領域と述べている。

Q1およびQ2が、主なテスト自動化対象となる

こうなるともはや、テストフェーズがイテレーションに組み込まれているか、そうでないかは大きな問題ではなくなる。欠陥を検出し、それを修正するというテストフェーズの役割の比重は小さくなるからだ。それならば、テストフェーズにもっと他の役割を与えることもできる。それが、右側象限の「プロダクトを批評する」ためのテストだ。

右側象限:「プロダクトを批評する」

左側に位置するQ1とQ2のテストで検出される欠陥は、仕様と実装との間に生じうるギャップだ。ギャップがあれば、仕様に合わせる必要がある。これは、あくまでも仕様を正としている。

右側に位置するQ3のテストでは、仕様を正としない。そこで検出される誤りは、優れたユーザー体験と仕様との間に生じうるギャップと言えば良いだろうか。ブライアン・マリックはこれをイシュー(issue)と呼んでいた。従来型のテストモデルで陥りがちな失敗パターンにおけるテストフェーズでは、仕様と実装のギャップの検出とその修正が目的であった。あくまでも仕様を正としたテストが行われていたのだ。この点が大きく違う。

定義された仕様を正としない

ここでのテストは、動くソフトウェアをユーザーが実際に体験することが一番であるが、その代替手段として、テスターによる探索的テストの採用もありえるだろう。これが、テストフェーズの新たな役割となるのではないだろうか。探索的テストであれば、必ずしも開発と同期させてテストする必要はない。非同期でテストすることさえ可能だ。ユーザーによるテストにいたっては、リリース後のA/Bテストといった形での実施もあるだろう。なお、アジャイルテストの4象限の様々なバリエーションの中には、A/BテストをQ2に分類するバリエーションもあるが、Q3の方が合うと私は考えている。

一方で、「プロダクトを批評する」という点では、Q4も位置づけは同じだ。非機能テストにより、プロダクトのパフォーマンスやセキュリティ、堅牢性などを検証することになるからだ。これらのテストのいくつかは、自動化してビルドパイプライン内に組み込んでおくことも可能だろう。

いずれにおいても重要なことは、プロダクトを批評することで発見されるイシューは、その領域がQ3であるかQ4であるかに関わらず、欠陥(バグ)ではないということだ。もちろん、多少の欠陥も検出されるが、発見すべきものはあくまでもイシュー(課題)なのである。それが、左側象限で定義される仕様やテストにフィードバックされる。こうして、フィードバックサイクルが形成されるのだ。とても、アジャイル開発プロセスらしいではないか。私はそう感じた。

イシューとしてフィードバックする

そういえば、最近、noteに書いた記事『ビジネスインパクトのない新機能に費やす時間とコストを低減する』も、これに関連するテーマを扱っている。このnoteの記事ではアジャイルテストの4象限については書いていないが、フィードバックサイクルがもたらす効率化・高品質化について整理している。

note.com

開発者テストとアジャイルテストの4象限の関係

さて、エンジニアリングマネージャーである私としては、アジャイルテストの4象限を、開発者視点でもう少し掘り下げてみたい。

開発者が担うべきテストを指して、「開発者テスト(developer testing)」と呼ぶことがある。私がこの言葉を知ったのは、gihyo.jpに連載された『[動画で解説]和田卓人の“テスト駆動開発”講座』だった。ここでは、開発者テストと並べて、顧客テストとQAテストも紹介されている。

書籍『Developer Testing』の著者であるAlexander Tarlinderは、開発者テストを次のように定義している

Developer testing is the developers’ intentional and systematic employment of testing tools and techniques to create testable and maintainable software with as few defects as possible.

(開発者テストとは、開発者がテストツールやテクニックを意図的、かつ体系的に利用して、可能な限り欠陥が少なく、テスト容易で保守容易なソフトウェアを作成することである)

この定義からは、開発者テストの範囲が、Q1である「チームを支援する技術面のテスト」を中心として広がるものであることが読み取れるだろう。4象限図にその範囲を重ねたものが、次の図となる(Alexander Tarlinderの図をもとに作成)。

開発者テストの範囲は、Q1を中心として、Q2やQ4にも及ぶ

開発者テストの範囲は、Q1に加え、Q2の「チームを支援するビジネス面のテスト」やQ4の「プロダクトを批評する技術面のテスト」にも及んでいることがわかる。

開発者テスト:Q1

まずはQ1の「チームを支援する技術面のテスト」であるが、この象限で扱うテストは、理想的にはすべてが自動化され、もっとも多くのテストケースを有し、それゆえ自動テストの土台となる。テスト自動化ピラミッド(testing automation pyramid)で言えば、最下層に位置する。テストタイプとしては、ユニットテストコンポーネントテストなどが該当し、テストサイズで言えば、部分的にはMediumテストを含みつつも、多くがSmallテストになるだろう。

Q1で扱うテストはピラミッドの最下層に位置する

ここでのテストにTDDが用いられる理由は、それがソフトウェアの内部品質を引き上げて保守性を高めるからであり、また、テスト自動化が促進されて機能面での外部品質を維持するコストを一定にする働きを持つからだ。TDDがもたらすこれらの効果は、ソフトウェアプロダクト開発には欠かせない。プロダクトは、その長いライフタイムの中で機能追加や機能改善を何度も繰り返す。もし保守性が低ければ、簡単な変更に長い時間を要するようになる。また、テストコストを一定に維持する意味は、先にも述べたとおりだ。

このように、TDDがもたらす価値は高いはずであるが、それを十分に実践し、そこから価値を享受しているソフトウェアプロダクト開発組織がどれだけ存在するのだろうか。その背景として、「そこに割く時間が取れない」といった話も聞く。プロダクションコードを書くことに精一杯で、テストコードを書く時間が無い、といった意味での発言である。では時間があれば、TDDを実践し、そこから十分な価値を引き出せるのだろうか。おそらく、そうはならない。問題はテストコードを書く時間が無いことではなく、テストコードを書くことやTDDを実践するための、知識や経験、そしてスキルの不足にあると感じるからだ。

開発者テストの学習のために、組織が時間を割いていないのだ。優れた品質のプロダクションコードを書くことが難しいように、優れた品質のテストコードを書くことも難しい。そして、その両方の能力を求められるTDDで価値を生み出すことは、さらに難しいのではないか。だからこそ実践だけでなく、そのための能力開発も必要なのだ。

Alexander Tarlinderは、開発者テストを実践するには、いくつかのコアコンピテンシーを習得する必要があると述べている。そして、それを次のような図にまとめている。

Alexander Tarlinderによる、開発者テストのコアコンピテンシー構造

これらを体系的に学び、実践を重ねることで、開発者テストの定義である「可能な限り欠陥が少なく、テスト容易で保守容易なソフトウェアを作成すること」が可能になるということだ。

開発者テスト:Q2

ブライアン・マリックによれば、Q1のTDDも含め、左側象限で書かれるテストケースやテストシナリオは、例駆動開発(EDD)における「例(example)」である。その中でも、Q2の「チームを支援するビジネス面のテスト」における例の役割の1つに、「技術のエキスパートとビジネスのエキスパートとの対話の向上(improving conversations between the technology experts and the business experts)」を挙げている。ここで言う技術のエキスパートとは、開発者のことだ。また、ビジネスのエキスパートとは、顧客やそのプロキシを指しており、それはドメインエキスパートのことであるとも言える。

ドメインエキスパートと開発者の対話と言えば、ドメイン駆動設計(DDD, Domain-Driven Design)を思い出す。ブライアン・マリックも、DDDの実践を提案している。Q2で例を書くことでドメイン用語を形成し、その用語がオブジェクトに変換されていく。こうしてドメインエキスパートとの対話を通じて設計とモデリングを進めることが、ここでの開発者の役割なのではないだろうか。

Q2で書かれるテストケースは、テスト自動化ピラミッド内でほとんどが中層に位置し、一部が最上層といったところだろう。テストケース数はQ1のそれより少なく、かつ、実行時間がかかる。主なテストタイプは機能テストであり、テストサイズはMediumからLargeだろう。リサ・クリスピン(Lisa Crispin)らは、書籍『実践アジャイルテスト』の中で、Q2におけるテストの自動化は、可能であればプレゼンテーション層より内側をカバーし、さらに、クライアントアプリケーションがリモートで利用するAPIも範囲であると述べている。

Q2で扱うテストはほとんどがピラミッドの中層に位置し、一部が最上層に

シリーズ記事が書かれた時点ではこの象限におけるEDD実践の事例はあまりなく、どのように例が書かれていくかはまだ探求段階にあったようだ。また、現在においてもEDDの実践について事例をあまり見かけない。私が知らないだけの可能性もあるが、実態としては、それほど普及しなかったのかもしれない。ただし、コンセプトには共感できるところもある。エッセンスを抽出して活用したいところだ。

開発者テスト:Q4

Q4の「プロダクトを批評する技術面のテスト」とは、つまり非機能テストであり、テスト対象となる領域はさまざまである。エンジニアとして真っ先に思い浮かぶのはパフォーマンステストや負荷テストであるが、セキュリティやアクセシビリティなども対象となる。

この象限でのテストを設計し、実施して結果を検証するためには、そのそれぞれの領域において高度な専門的技術が求められる。専用のツールを使いこなすスキルも必要だ。シリーズ記事でブライアンマリックは、アジャイルプロジェクトで求められる人材は、スペシャリストよりジェネラリストだと述べているが、一方でこのQ4についてはスペシャリストが必要となる領域であることも認めている。

エンジニアに限らず、ソフトウェアプロダクト開発組織の中にそのようなスペシャリストが十分に存在するのかと考えると、不足しているというのが実態ではないだろうか。セキュリティについてはツールでカバーできる範囲も広がっていると感じているが、それ以外は人に頼らざるを得ないというのが実感だ。この象限を任せられるスペシャリストは、希少人材なのだろう。

必然的に、この象限のテストは手薄になってしまう。また、ここでのスペシャリストの多くは、テストだけでなく、同領域における設計のスペシャリストでもある。したがって、手薄になるのはテストだけでなく、設計も不十分になるだろう。ソフトウェアシステムに、非機能観点での設計や実装が適切に組み込まれないということだ。

私の実感では、周囲のエンジニアから「優秀なエンジニア」だと認められ、信頼されているエンジニアの多くは、これらの領域を担うスペシャリストだ。逆に言えば、このようなスペシャリストになることは、エンジニアにとって、自身の価値の向上につながる。当たり前ではあるが、エンジニアリング領域を預かるマネージャーは、こういった人材を育て、あるいは獲得することに注力する必要があるのだろう。

なお、ここで扱うテストサイズは当然ながらLargeである。テスト自動化ピラミッドの位置づけは、自動化可能なテストであれば、中層から最上層にあたるだろう。

Q4で扱うテストはピラミッドの中層から最上層に位置する

開発者はQ3にどう関わるのか

開発者テストの範囲に含まれなかったQ3の「プロダクトを批評するビジネス面のテスト」は、開発者には無関係なのだろうか。

Q3のテストでは、ソフトウェアプロダクトを基本的にブラックボックスとして扱うため、その中身を知る開発者が効果的なテストを担えるかは疑問ではある。もちろん、担当外の範囲のテストを担うことで、「中身を知っている」という状況は緩和されるが、やはり中身の推測はできてしまう。

その上、作った本人である開発者が、公平な観点で「プロダクトを批評する」ことができるだろうか。

このように考えると、開発者がこの象限のテストを担うことは適切ではないと感じるのであるが、そうであるからこそ、そこで発見されたイシューは、開発者にとって価値のある情報となる。作り手としての認知の外での気づきとなるからだ。開発者が、このようなフィードバックに注意を傾けることができれば、プロダクトの価値をより高めるヒントを得ることになる。

したがって、Q3における開発者の行動は、テストをよく観察することになるのではないだろうか。例えば探索的テストであれば、テスターとペアを組み、テストの様子を観察しながらそこで発見されたイシューについてテスターと議論する。それは、有意義なインプットとなるだろう。

なお、この象限のテストは自動化対象ではなく、テスト自動化ピラミッドでは、ピラミッドの上にかかる雲のように描かれることが多い。

Q3で扱うテストはピラミッドの上にかかる雲に位置する

現実と現在を見る

開発者テストの実践を浸透させるにあたり、現実問題として、もう1つ大きな障壁がある。プロダクトを新規で開発するケースなら良いのだが、大抵のケースはそうではないだろう。それは、既存のレガシーコードと闘うことになるかもしれないということだ。

マイケル・フェザーズ(Michael Feathers)の定義では、レガシーコードとはテストのないコードだ。既存のプロダクションコードに、あとからテストコードを追加するのは非常に難しい。プロダクションコードのテスト容易性が低いのだ。これは経験者なら誰もが実感するところだろう。この現実が、Q1での開発者テストの実践に立ちはだかる高い壁となる。テストを書くためには、コードを書き換えなければならない。ここに割くためのコストが大きいのだ。

もちろん、テストコードを書く対象に優先順位を付けて、新機能開発などで変更が必要になった箇所に対して優先的にテストを書いたり、読む頻度が高いコードの可読性を上げつつ優先的にテストを書くといった進め方もある。しかし、この程度のテスト自動化では、いつまで経っても自動リグレッションテストとして十分に機能しない。結果、手動でのテストに時間がかかり、相変わらずそれらがテスターに丸投げされることになる。

本稿はテスト自動化をテーマとしていないため、この根深い問題への解決策を探求しないが、テスト自動化ピラミッドで示される理想像を目指しつつ、逆三角形からはじめてみるのも、戦略的に悪くはないだろうと考えている。E2Eテストの自動化から始めることで、リグレッションテストをなるべくカバーするのだ。これまで手動で行われていたリグレッションテストのテストケースを自動化するのだと考えると良い。そして、機能変更などによってE2Eテストが壊れる時が、その範囲の自動テストの階層を下げるタイミングだ。

とは言え、これはこれで、理想的なピラミッドに近づくまでにはやはり時間がかかる。やり遂げるために、根気が試されるだろう(ちなみに、ブライアン・マリックは逆に、ユニットテストなどの自動テストが壊れたら、階層を上にあげることを提案している)。

本稿で取り上げたシリーズ記事が書かれた2003年は、アジャイルソフトウェア開発のまだまだ黎明期だ。アジャイルソフトウェア開発宣言は2001年であり、ケント・ベック(Kent Beck)の『エクストリームプログラミング』の英語版書籍出版が2000年で、『テスト駆動開発』は2001年。ちなみに、エリック・エヴァンス(Eric Evans)の『ドメイン駆動設計』の英語版書籍出版は2003年。そのような時代に書かれた記事であることを念頭に置いて、参考にすべきだろう。