mtx2s’s blog

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

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

デプロイ頻度とリードタイムは、開発チームが自らのパフォーマンスをモニタリングするうえで欠かせないメトリクスである。それらが、収益性や市場占有率といった組織パフォーマンスに影響を与えるからだ。その調査結果は、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年。そのような時代に書かれた記事であることを念頭に置いて、参考にすべきだろう。

モノリポとマルチリポの比較が浮き彫りにする開発能力を高めるための課題とトレードオフ

ソフトウェアプロダクトに対して求められ、日々繰り返される機能追加は、コードベースを肥大化・複雑化させ続ける。成長する組織では、開発者の増員がそれを更に加速させるだろう。そして、認知負荷の軽減を目的に、いずれはコードベースの分割について考えるようになる。その目指すアーキテクチャがマイクロサービスにせよ、モジュラモノリスにせよ、コンポーネントやモジュール単位でリポジトリを分けるというのが、コードベースのもっとも一般的な管理方法ではないだろうか。

しかし、ここにはもう1つの選択肢がある。「モノリポ(モノレポ)」だ。すべてのコンポーネント、モジュールを1つのリポジトリで管理する。それどころか、社内のあらゆるソフトウェアプロダクトを1つのリポジトリで管理することさえあり得る。

モノリポにはどのような利点や欠点があるのだろうか。私自身、小規模のマルチプロジェクトリポジトリを複数組み合わせて扱うことが多いが、これは後述するマルチリポだと認識している。モノリポがどういうものであるかの知識があまりなく、採用すべき手法であるかどうかの判断ができない。そこで、Googleのモノリポについて書かれた論文 "Advantages and Disadvantages of a Monolithic Codebase" を読むことにしたのだが、そこで得られたのは、組織の開発能力を高めるための知識や課題であった。

本記事では、モノリポと、その対極にあるマルチリポを比較する中で、組織が獲得し得る開発能力を明らかにしたい。

モノリポとは?

ソフトウェアエンジニアリングにおいて、ソースコードは、VCS(Version Control System, バージョン管理システム)内のリポジトリで管理するのが一般的だろう。「モノリポ(monolithic repo, monorepo)」は、複数のプロジェクトのコードを、同じ1つのリポジトリに格納するソフトウェア開発戦略だ。これに対し、複数のリポジトリに分けて管理する戦略を「マルチリポ(multi-repo)」や「メニーリポ(manyrepo)」、あるいは「ポリリポ(polyrepo)」と呼ぶこともある。

それではマルチプロジェクトのリポジトリがすべてモノリポなのかと言うと、そうではないように思う。明確な定義は分からないが、モノリポと呼ばれるリポジトリには、それぞれが完全に独立した複数のプロジェクトがホストされているのではないか。例えば、マイクロサービスアーキテクチャを構成するサービス群のソースコードを1つのリポジトリで管理するような場合だ。それらは更に細かくサブプロジェクトに分割されてホストされているだろう。また、Googleのように、Google検索、GmailGCP関連サービスといった複数プロダクトのホストもあり得る。

このような背景から、モノリポでは、1つのリポジトリを複数のチームで共有することが多いのではないだろうか。それぞれが所有するプロジェクトを共有リポジトリにホストしているのだ。

一方、マルチリポでは、リポジトリ内が複数プロジェクトであっても、それらを1つのチームやコミュニティが所有する。オープンソースプロジェクトのリポジトリは、マルチプロジェクトのものも多いが、今回取り上げる論文内でもマルチリポに分類されていた。

モノリポと言えば、Googleが採用していることで有名だ。2016年の論文 "Why Google Stores Billions of Lines of Code in a Single Repository" によれば、彼らのモノリポは、調査当時で約20億行のコードを含む86TBのデータが含まれ、Googleの95%の開発者によって使用されていると言うから、その規模にはあらためて驚かされる。

調査

論文 "Advantages and Disadvantages of a Monolithic Codebase" での調査は、Googleでモノリポを利用している開発者を対象に行われた。アンケート調査とログ分析が主な手法であり、前者については23,000人からサンプルとして無作為に選んだ1,902人の開発者のうち、46%にあたる869人から回答が得られた。そのうち、379人(44%)が企業でのマルチリポのコードベースの利用経験があり、337人(39%)がオープンソースでのコードベースの利用経験があり、205人(24%)が他社でのモノリシックなコードベースの利用経験があった。

満足度に対する設問(論文内Table 1のQ1.1, Q2.1)では、Googleのモノリポに対する満足度は全体的に高く、マルチリポに対する満足度は意見が分かれている(論文内Figure 3)。86%にあたる326人は、Googleのモノリポをより好んでいるという点も注目だろう(論文内Table 1のQ2.2に対する回答)。

調査結果の観点は、主に3つに分けることができる。「可視性」「依存関係」「開発者ツール」だ。以降でその内容をそれぞれ見ていく。

可視性

モノリポでは複数のプロジェクトの開発者が互いのコードを共有し、それらを自由に検索・閲覧できるという、高い可視性を持つ。マルチリポ経験者に対する設問(論文内Table 1のQ2.1)で、Googleのモノリポをより好むと回答した開発者は、その理由としてこの「コードベースの可視性(Visibility of codebase)」を多く挙げている(論文内Figure 4)。裏を返せば、回答者らのマルチリポでの経験は、担当するプロダクト領域(PA, Product Area)以外のコードへのアクセスが制限されるケースも多かったのだろう。Googleのモノリポを経験した彼らには、過去に関わったマルチリポでのそのような制限が、欠点として感じられたのだ。

それではコードベースの可視性の高さは、具体的にどのように役立つのだろうか。調査では、コードの「閲覧」と「編集」の2種類に分けてログを分析し、その用途について触れていた。

まず、「コードの閲覧」についての調査結果では、開発者の半数が、閲覧回数の28%以上を担当外のPAにあるファイルに対して行っている(論文内Table 2)。アンケート設問の結果を見ると、その目的が、「コードの再利用(Code Reuse)」や「利用例(Usage Examples)」にあろうことが見て取れる(論文内Figure 4, 5)。「利用例」とは、例えばあるAPIをはじめて利用する時に、既にそれを利用している他のプロジェクト内のコードを見つけ出し、それを参考にして自身のコードを書く、といったことを指している。開発の速さやコードの品質の高さに関する設問(論文内Table 1のQ1.2, Q1.3)でも、多くの開発者が、PAを横断したコードの検索が重要だと回答している点も注目すべきだろう(Figure 1, 2)。

次に、「コードの編集」についての調査結果では、開発者が10%程度が、60%以上のコードのコミットを担当外のPAに対して行っていることがわかる(論文内Table 2)。これは、自身が開発を担当するAPIに変更を加えた時などに、それを利用する他プロジェクトのコードを最新バージョンに対応させる(Easy Update)ために行われているようだ(論文内Figure 4, 5)。

このようなコードの閲覧および編集の自由度がコードの保守性に良い影響を与えることは、DORAのドキュメントでも言及されている。次の引用は、保守性を高める3つの要因のうちの1つとして挙げられていた一文だ。

It’s easy for the team to find examples in the codebase, reuse other people’s code, and change code maintained by other teams if necessary.

(チームにとって、コードベース内から例を探したり、他人のコードを再利用したり、必要に応じて他チームが保守するコードを変更するのが簡単である)

一方で、マルチリポの利点としても「開発の速さ」が挙げられている点が興味深い。しかし、その理由がモノリポとは違った。

マルチリポの利点とする開発の速さには、コードの「サイズの小ささ(Small Size)」や「ビルド時間(Build Time)」の短さが挙げられている(論文内Figure 6)。コードのサイズが小さければ、開発者にとって認知負荷が低い。加えて、ワークスペースへのコードのコピーが短時間で済むし、ビルド時間も短く済む。また、既にビルドされてバイナリ化された依存プロジェクトを取り込めるから、その分、ビルド時間は更に短くなる。

このような、ビルド時間の短縮は、高品質なコードを作り出すためにとても重要な役割を果たす。それは、継続的インテグレーションの文脈で明らかだ。自動テストも含めたビルドパイプラインの実行に一晩かかるのと、数分で終わるのとでは、ビルド失敗時の解決コストの大きさが違うことは、開発者なら理解できるだろう。

また、マルチリポであっても、モノリポのような可視性を実現することが不可能なわけではない。ただし、そこには課題もある。例えば、リポジトリごとの設定によって、コードベースの可視性は簡単に制限されてしまう。そもそも、組織のガバナンスとして不可視に設定しているケースもあるだろう。

逆に、モノリポの実現にも課題はある。特に、コード編集時のコミット権限だ。以前投稿した記事『マイクロソフトの調査にみるコードのオーナーシップと品質の関係』にもあるように、コードの所有権を明確にすることが、品質の高さにつながる。所有者のレビューを経なければ、変更がコードベースに反映されないようにする必要があるということだ。マルチリポであれば、リポジトリごとに所有権を設定しやすいのだが、モノリポではコードベース内のディレクトリごとに所有権を管理するなどの手段が必要となる。組織が採用する開発プラットフォームがそのような権限管理に対応していなければ、実現手段に悩まされることになるだろう。

mtx2s.hatenablog.com

依存関係

Googleのモノリポでは、「トランクベース開発(trunc-based development)」が採用されている。その運用方法として、ブランチは、リリースのために使われるが、ほとんどのケースで開発ブランチを持たない。そのため、開発者によって変更されたコードは、リポジトリのヘッドにコミットされる。

リポジトリ内の依存関係にはバージョンがなく、プロジェクトはリポジトリのヘッドにある依存関係のバージョンを使用する。Googleには、「単一バージョンルール(One-Version Rule)」というものがある。その定義は次のとおりだ(書籍『Googleのソフトウェアエンジニアリング』から引用)。

開発者には、「このコンポーネントのどのバージョンに依存すべきか」についての選択の余地が絶対にあってはならない。

これがダイヤモンド依存関係に対する悩みから開発者を解放する。Googleのモノリポをより好む理由に、この点(Dependency Mgmt)を挙げる開発者も多い(論文内Figure4, 5)。

「ダイヤモンド依存関係(diamond dependency)」とは、プロジェクトが依存するソフトウェアのバージョンが衝突する状況を言う。例えば、プロジェクトがAとBの2つに依存しており、AとBが共にCに依存していたとする。しかし、Aが依存するCのバージョンと、Bが依存するCのバージョンが異なると問題が起きる。これが、ビルドを失敗させたり、実行時エラーを引き起こしたりするからだ。

こういった問題を解決するためには、依存するCのバージョンを統一し、Cの呼び出し元となるAやBのコードをすべて修正することになるが、修正対象がそれぞれ異なるリポジトリにホストされていると、修正の網羅性を担保することが難しくなる。もちろん、リポジトリが分かれているために、1度のコミットですべての変更をコミットすることも不可能だ。

モノリポであれば、コードベース全体の高い可視性によって修正箇所を見つけ出し、すべての変更をアトミックにコミットすることも可能になる。これは、可視性で Easy Update として挙げられた利点でもある。そして、この利点は、モノリポによるコミット範囲の柔軟性によってもたらされることにも気づく。上述した通り、変更が複数のリポジトリに分散すると、それらを1つのコミットにまとめることができない。しかし、モノリポであれば、そのような境界はなくなるのだ。これは、分散システムにおけるトランザクション境界の話にも似ている。このようなコミット範囲の柔軟性も、モノリポの魅力のひとつだろう。

さらに言えば、Easy Update による恩恵は、コミュニケーションコストにも及ぶ。自身が担当するプロジェクトのAPIに変更を加えたとしよう。マルチリポであれば、このAPIに依存するプロジェクトの所有者それぞれに、APIの新バージョンへの対応を促すことになる。しかし、モノリポであれば、APIの変更と同時に、それに依存する他のプロジェクトのコードをすべて修正することも可能になる。これによって、プロジェクト間でのコミュニケーションコストが不要、あるいは最小限にできるという効率性も得られるのだ。

前述したもうひとつの論文 "Why Google Stores Billions of Lines of Code in a Single Repository" でも述べられているように、依存関係の更新は、開発者にとって苦痛でコストの高い作業だ。そのために、更新が後まわしにされ続け、気付けばその対応コストもリスクも高い状況に陥りやすい。Googleのモノリポのように、APIの更新と共に、影響を受けるすべての依存元コードを同時に更新することは、まさに合理的なのだ。

依存関係に関するマルチリポの利点としては、バージョン管理された「安定した依存関係(Stable Dependencies)」が挙げられている(論文内Figure 6)。つまり、バージョン指定による依存関係のセットを持ち、それを組み込んだプロジェクトをビルド、テストすることで、期待通りに動作することを保証する安定したバージョンのプロジェクトを提供できるということだ。これも、裏を返せば、モノリポによる Easy Update は、依存関係を壊す原因にもなり得るということだろう。

依存関係については、モノリポとマルチリポの間にある利点と欠点はトレードオフの関係にあるようだ。

開発者ツール

オープンソースのコードベース経験者を対象とした設問(論文内Table 1のQ3.1~Q3.3)では、Googleのモノリポとオープンソースコードベースが共に、「利用可能な開発者ツール(Available Developer Tools)」を最大の利点としている(Figure 8, 9)。しかし、その意味合いは異なる。むしろ、両者の利点もまたトレードオフの関係にあるようだ。

オープンソースプロジェクトでは、ツールやスタイル、プログラミング言語などの選択が自由だ。DORAによる研究では、このような「チームへのツール選択権限の付与」が、ソフトウェアデリバリのパフォーマンスを高めるケイパビリティの1つとして特定されている。プロジェクトの課題や特性を把握しているのはチーム自身である。そして、その解決にもっとも適したツールを選択できるのもチーム自身だろう。この観点から、ツール選択の自由は、Available Developer Tools として利点に挙げられたことに納得できる。

しかしその自由度は、欠点にもなり得る。

ツール選択の基準が、テクノロジーに対する興味や目新しさにばかり焦点があてられてしまうと、その選択は、後から大きなコストとなって跳ね返る可能性がある。また、プロジェクトの課題や特性をチームが正しく定義できなかったり、適したソリューションを選択できなくても同様だ。「チームへのツール選択権限の付与」が機能するのは、あくまでも、チームに自律性とスキルが備わっていること、あるいはそうなろうと試行錯誤しているチームであることが前提になるのではないだろうか。

もう1つ考えられる欠点としては、一貫性の欠如につながるという点だ。プロジェクトやチームごとにツールセットが不統一だと、他人が書いたコードのデバッグや実行が困難になる場合も多い。加えて、開発者のチーム異動にともなう学習コストも高くなる。

Googleのモノリポでの開発は、これらの欠点が補われている。彼らは、巨大なコードベースを扱いやすくするために、多くのツールが自社開発されており、開発者らはそれを利用している。この標準化によって、Googleのモノリポ上での開発が高効率性を獲得していることは、調査の中で報告されている。加えて、標準化による「一貫性のあるスタイル(Consistent Style)」も、数は少ないが利点に挙げられており(論文内Figure 4, 5)、これが、高品質のコードに繋がっていると考える開発者が多いことも指摘されている。

Googleのような標準化は、開発者にとってのツール選択の制限となり、DORAの定義するケイパビリティの欠如に見えてしまうが、実態はそうではないのだ。結局は、ツールの選択権の自由度云々よりも、ツールがどれだけ開発者に有用であるかがポイントであるとも考えられる。

まとめ

以上が、モノリポとマルチリポの比較の結果であるが、注目すべきはその比較として抽出された数々の開発能力だろう。普段はマルチリポのみを使っていたとしても、こうやって比較することで、あたり前に得ていた便益や損失を見出すことができる。それを知るだけでも価値がある。

コードベースの広範な可視性は、Code Reuse, Usage Example によって、開発速度に良い影響を与える。そこに、コミット範囲の柔軟性が加わると、さらに、Easy Update が可能になる。小規模なコードベースは、開発者の認知負荷を下げるとともに、ビルド速度を高めてくれる。単一バージョンルールが導入できれば、ダイヤモンド依存関係の煩わしさから開発者を解放するが、バージョン指定での依存関係であれば、依存関係を安定させることができる。チームへのツール選択権限の付与は、チームのパフォーマンスを高めるが、リポジトリ間でのスタイルの一貫性の欠如を招く。標準化によって一貫性は保てるが、ツールの有用性が担保されなければチームのパフォーマンスを落としかねない。

組織がこれらの開発能力の何を特に必要とするか。それを評価することがまず先だ。その上で、選択した開発能力の獲得を見据え、適したプラットフォームや言語・フレームワーク、ツール、テクニックを組み合わせる。その中に、モノリポやマルチリポといった開発戦略が含まれる。どちらを選択することになるにせよ、そこに含まれる欠点を補う方法があることも忘れてはならない。

既存のコードベースに対するリポジトリ戦略や依存関係管理手法の切り替えは、コストが高い。だからといって、あまりにも限定的な導入では、モノリポにせよ、マルチリポにせよ、その便益はほとんど得られないのではないか。ハイブリッドでの導入が現実的であるようにも思うが、最大の効果を発揮できるような境界を見つけ出す必要がある。慎重に判断したいところだ。

ソフトウェア開発上の問題や課題をビジネスリーダーや経営者らの関心事とするために

ビジネスリーダーをはじめ、ソフトウェアプロジェクトの関係者にとって、ソフトウェア開発上の関心事は、開発の進捗とシステムトラブルだ。ソフトウェアの内部品質や開発プロセス上の問題や課題なんて、開発者以外に興味を示す人などほとんどいない。だから、関係者ばかりか開発者自身も、開発の進捗とシステムトラブルにばかり注意を向ける。

そのような状況に、一部の優秀な開発者は我慢ならない。憂いている。「このままではまずい、積み上がった問題に取り組むために時間が欲しい」「まとまった時間でなくても、継続的に取り組むための少しの割り当てでも構わない」と。そんな願いも虚しく、使える時間はすべて、担当する開発を進捗させることにのみ費やすことを強いられる。

私たちエンジニアリングマネージャーやテックリードは、このような状況を見て見ぬふりをしていないだろうか。開発の進捗やシステムトラブル以外にも注意を向けるべき対象がある。それを関係者らに伝えられているだろうか。説明責任を果たし、ソフトウェアの内部品質や開発プロセス上の課題を組織の課題としてプロジェクトで認識を共有することができているだろうか。

本記事では、ソフトウェア開発における関心事を組織の関心事にまで押し上げ、その問題や課題に取り組むための方法について考えていく。

情報の分断が組織を分断する

スクラムに代表されるモダンなソフトウェア開発手法では、誰が、何を、いつ、どのように行うかを決める主体はチーム自身だ。そのような自己管理型、自己組織化がチームのあり方とされる。

しかし、それを実践できる組織がどれだけあるのだろうか。現実の現場で「チーム」と呼ばれるものは、ソフトウェアエンジニアだけで構成され、その活動は、内部設計や実装からリリースまで、そして本番運用に限定されていることも多い。何を作るか、それをいつリリースするかは、企画を含むビジネス担当者らが中心となって決める。経営者が関与することもあるだろう。そして、その強い意向によって、チームがその意思決定に関与する余地は、見積りを提示してリリース日やスコープをわずかに調整する程度となるのだ。

このように、ビジネスと開発が分断した組織構造は、それぞれが有する情報や関心事の共通範囲が狭く、相互理解が乏しい。その状況でビジネスリーダーが意思決定を行うとしたら、ソフトウェア開発上の関心事が意思決定に及ぼす影響は必然的に小さくなる。

しかしもし情報の分断がなく、ビジネスの課題もソフトウェア開発の課題も互いに理解し合えていたとしたら、そもそも組織も分断していないのかもしれない。ビジネス上の関心事とソフトウェア開発上の関心事の両方を総合して下す意思決定が、組織を一体化するのだ。その先にあるのが、機能横断型で自己管理型のチームというわけだ。

そう考えてみると、問題の根底にあるのは、情報の流通にあるとは言えないだろうか。ソフトウェア開発上の関心事は専門性が高く、その理解に知識や経験を要するため、ソフトウェアエンジニア以外がそれを理解することが難しい。このことが障壁となって、開発からビジネスへ情報が流通しにくくなっているのだ。また、ビジネス上の関心事は比較的理解しやすいのであるが、そこに興味を持つエンジニアが少ない。これらの事情ゆえにビジネスと開発はそれぞれが自分たちの領域にとどまって活動する。これが、組織の分断の実体ではないだろうか。

このような分断を解消することは、テックリードやエンジニアリングマネージャーの責務だと考えている。互いの情報を流通させ、組織を一体化させていくのだ。少なくとも、自社ソフトウェアプロダクトの内製組織では、ビジネスも開発も利害は一致する。プロダクトのユーザー価値およびビジネス価値を高め続けることがミッションであるからだ。遂行するミッションが同じならば、情報や組織の分断を解決することも可能なはずだ。対立しているのはミッション遂行の手段の優先順位付けであり、その対立は低い相互理解によって生じているだけである。

この対立解消に向け、ソフトウェア開発上の関心事を伝える方法を以降で考えていく。ビジネス上の関心事を開発者らに伝える方法についての検討は、本記事では対象外とする。

問題や課題の存在に同意を得る

取り組むべき問題や課題の存在を意思決定者が認識していなければ、そこに時間をかける意思決定がなされるはずもない。意思決定者がビジネスリーダーであってもチーム自身であってもそれは同じだ。まずやるべきことは、ソフトウェア開発上の関心事の認知をチーム内外に浸透させることだろう。

「ソフトウェア開発上の関心事」と言ってしまうと、その影響が開発者らだけに閉じているように聞こえてしまうが、もちろん実際はそうではない。組織全体のミッション遂行に必ず影響する。それを切り口としてソフトウェア開発上の関心事を伝えなければ、開発者の話がビジネス担当者らに響くことはないだろう。つまり、ソフトウェア開発における関心事は、ビジネスにおける関心事でもあるということに同意を得るのだ。

組織全体のミッションは、ビジネス目標として表現される。それは、ビジネス価値やユーザー価値で計測される。そのいずれであっても、価値の総量の変化は、ソフトウェア開発によって駆動されることを前提としている。マーケティングや営業努力だけでは継続可能性が低い。ソフトウェア開発なしには、中長期での目標の達成はありえず、ミッションは失敗に終わる。だから、ソフトウェア開発における関心事は、ビジネスにおける関心事と言えるのだ。

このことは、組織がミッションとして扱う領域を「価値」と「価値を提供する組織の能力」に分けるとより理解が深まる。私は以前の記事でこれらの探求を「プロダクトの差異化」と「組織としてのプロダクト開発能力の差異化」と呼んだ。また、Scrum.orgのエビデンスマネジメントガイド(Evidence-Based Management Guide)ではこれらをそれぞれ「市場価値(market value)」「組織的な能力(organizationl capability)」という言葉で表現している。この表現がしっくりくる。市場価値とは、例えば市場占有率顧客満足度、アクティブユーザー数などが挙げられる。組織的な能力は、DORAのFour Key Metrics(変更のリードタイム、デプロイの頻度、サービス復旧時間、変更失敗率)や、ソフトウェアの内部品質などだ。

ビジネス目標は「市場価値」を問うものだ。開発者は、同じミッションを遂行する組織の一員として「市場価値」を探求することはもちろんであるが、ソフトウェア開発においては「組織的な能力」を探求することになる。そして、ソフトウェア開発上の関心事に問題や課題があるなら、組織的な能力が不足した状態になる。市場価値を高める可能性が下がり、価値を届けるまでの時間が長くなり、価値の継続的な提供を困難にする。それゆえ、ソフトウェア開発における関心事は、ビジネスにおける関心事と言えるのだ。

リーンと同様、トヨタ生産方式に起源を持つTOCでも、思考プロセスにおいてまず最初にやるべきは、問題や課題の存在について同意を得ることだ。認識しない問題や課題に取り組む判断などあり得ない。ソフトウェア開発上の関心事に対し、ビジネス担当者らからの同意を得る必要性はそこにあるのだ。

メトリクス化により関心事を評価する尺度を揃える

ソフトウェア開発上の関心事は質的な情報を多く扱う。それらを説明するのはとても難しい。説明する側とされる側、互いの語彙や知識、経験が揃っていなければ、それがさらに障壁となって伝わらない。エンジニアとビジネス担当者とのコミュニケーションがまさにその典型だ。それは、ソフトウェアの内部品質を話題にするシーンを思い浮かべると明らかであり、エンジニアの多くが経験するところだろう。

しかし、概念は伝えられる。伝えるための工夫や努力は必要であるし、相手も理解しようとする姿勢が必要であるが、それらが揃えば、内部品質が何であるか、それがどう問題なのか、理解を得られるだろう。

問題となるのは、概念の理解ではなく、ビジネスリーダーがその「程度」を推し量ることができないことだ。概念を理解できても、ビジネスリーダーは、対象そのものを見て、それを評価する術を持ち合わせていない。評価ができなければ、判断ができない。問題があるのかどうか。問題があるなら、それは大きいのか小さいのか。

そのもので推し量れないなら、推し量れる別のものを見て判断するものだ。「いま現時点でプロジェクトは順調に進んでいる」と、少なくともビジネスリーダーにはそう見える。だから、「おそらく問題はない、あるいは小さいのだろう」という評価にいたってしまう。技術的な問題への対処に時間を割かないという判断になる。この結論が、エンジニアの判断と合わないのだ。プロジェクトが順調に進んでいるように見えるのは、「自分たちが苦労して何とかカバーしているに過ぎない、いずれ破綻する」と認識しているからだ。

ここで、量的な情報が必要になる。「コードの保守性が低すぎて開発時間がかかるから、早急にリファクタリングが必要だ」と言ったところで判断できない。保守性がどのくらい低いのか。開発時間がどのくらい余分にかかるのか。それらを評価するために、客観的に定量化した数字が必要なのだ。

とは言え、それらを正確に定量化することは難しい。完璧なメトリクスを作ることは諦め、代替メトリクスを使った方が早い。保守性に関係するメトリクスであれば、静的コード解析ツールから得るのが簡単だろう。ツールが提供するメトリクスは、状態を正確に表したものにはならないが、まったくの的外れな数値でもない。例えば静的コード解析ツールのSonarQubeであれば、テストカバレッジやコードの重複、複雑性、保守性などを計測して数値やランク(rating)で表現する。一部ではあるが、問題の改修にかかる時間の見積りも提供される。こういったものを活用すると良いだろう。

チーム内の開発者らへのアンケートなどを通してスコアリングしても良い。客観性は失われるが、これを見ることで、ビジネスリーダーも課題の大きさを実感することができる。

メトリクスの検討は、書籍『アジャイルメトリクス』が参考になるだろう。

なお、メトリクス化すると言っても、ソフトウェア開発の関心事を、ビジネス上のKGIに連なるKPIツリーに変換する必要性を説いているわけではない。先に述べた通り、ビジネスとソフトウェア開発では、責務とする領域が異なる。市場価値を扱うビジネス系のメトリクスに対し、組織の能力を扱うソフトウェア開発系のメトリクスが及ぼす影響は間接的だ。無理に関連付けようとすると、その効果の判断で悩むことになるだろう。

良し悪しの判断基準を統一する

メトリクス化しただけでは、それが良い状態を表しているのか悪い状態を表しているのかの基準が組織内で揃わない。計測されたメトリクスを見て、ビジネスリーダーは「問題なさそうだから機能開発に専念すべきだ」と言うかもしれない。一方で開発者は「悪い状態だから今すぐ問題に取り組むべきだ」と言うかもしれない。これは、ビジネスと開発の間で評価が分かれるだけでなく、開発者間でも評価が分かれる可能性もある。そもそも、メトリクスの良し悪しが判断できない場合だってある。

良し悪しの境界となる何らかの基準が欲しいところだ。そうすれば、その基準を上まわっているなら良く、下回っているなら悪いという判断が統一できる。

システムパフォーマンスをはじめとする外部品質と呼ばれるソフトウェア品質は、その基準策定に合意を取りやすい。ユーザーが見て、触れて、感じられる品質は、ユーザー体験に影響するため、ビジネス上の関心事として扱われることも多い対象だからだ。そもそも、外部品質の良し悪しは、ビジネス担当者自身も体感できる。このようなメトリクスは、ビジネス上の関心事として扱われることも多い対象であり、非機能要件として従来どおりに定義すれば良いだけだ。

一方で、内部品質やチームパフォーマンスについては合意が難しい。内部品質はどれぐらいが妥当であるか誰にも判断がつかない。チームパフォーマンスは、妥当なラインについて、開発者とビジネス担当者との間で意見が対立したりする。

このような合意が難しいケースでは、組織の内外から比較対象を見つけると良いだろう。内部品質であれば、社内の他のソフトウェアの測定値と比較してみることもできる。比較対象とできるソフトウェアが無いのであれば、OSSの内部品質を計測してみて比較する手も使えるかもしれない。チームパフォーマンスであれば、DORAやpuppetのState of DevOps Reportで公開されているクラスタ毎のパフォーマンス値を参照しても良いだろう。

もしそういった比較対象を見つけられないなら、自己参照してみるのも良い。チーム内の意見を聞き、過去の経験を踏まえて良かった時期、悪かった時期がどうだったのかで基準を決めるのだ。ベロシティのように、他チームと比較することに意味がないメトリクスはこの方法で定義することもできる。

ただし、ベロシティがそうであるように、メトリクスによっては、基準ラインを決めることが「メトリクスの自己目的化」という別の問題を生じさせることもある。これについては後述するが、そういう場合は良し悪しの判断基準を決めず、「時系列の変化」を追うだけでも良いだろう。

時系列変化の可視化で一体感を醸成する

ソフトウェア開発上の関心事に対するこういった取り組みは、ビジネスリーダーらから理解を得られても、組織内では他人事になりがちだ。賢明に取り組んでいるのは開発者だけで、その外側にいる人たちは関心を持たないばかりか、取り組みの存在自体を知らないことも多い。「自分たちにできることは何もない」という意識もあるからだろう。これはちょうど、ビジネスに関心を持たない開発者と同じ構図だ。その上、取り組みへの同意を得たはずのビジネスリーダーらの関心も長続きはしない。

メトリクスの時系列での変化を組織全体に可視化すれば、この残念な状況を多少改善できるだろう。ここで言う可視化とは、変化を定期的に報告するということだ。組織やプロジェクトの週次報告に記載しても良いし、組織全体への月例会で報告しても良い。とにかく、メトリクスが取り組み開始時や前回報告時と比較して改善しているのか悪化しているのか、時系列での変化を能動的に発信するのだ。

時系列での変化を報告すると言っても、ただ「上がった」「下がった」だけを伝えても意味がない。なぜ上がったのか、なぜ下がったのかを分析し、それを踏まえて次にどのようなアクションを取るべきかも伝える。時系列の変化を見ることで、現在と過去の比較だけでなく、そこから未来を予測することもできる。過去から現在までが悪化傾向ならば、現在から未来も悪化傾向である可能性が高い。この観点も踏まえた上でアクションを立案し、報告に含めると良いだろう。また、これらの変化がビジネスにどう影響し得るかについて、定性的にでも伝えたいところだ。

これを続けることで、ソフトウェア開発上の関心事への取り組みに対し組織内での認知が進み、一体感がわずかでも醸成される。それは、組織内の誰かとのちょっとした会話の時にあらわれる。開発者以外から、取り組みに対する感想が聞けたりするようになるからだ。こういった声が、チームのモチベーションにつながるだろう。

コントロールからチームを守る

定期報告の存在は、「管理されている」という感覚を開発者に植え付けかねない。特に、報告を受けたビジネスリーダーが報告内容に対して否定的な意見を述べ、アクションを指示したりといったことが繰り返されたときだ。これは、報告相手となるビジネスリーダーが報告者より立場が上の場合に起こりやすい。「管理されている」という感覚は、開発者らの主体性を奪う要因になり得る。自己管理型チームから遠のいてしまう。

報告相手のこのような振る舞いは、性格によるところもあるが、開発者らに対する不信感から発せられることも多い。開発者との信頼関係が構築できていない状況は、分断された組織であるならなおさらだろう。この報告相手にとっては、開発者らが適切に問題や課題をとらえ、それに対する正しいアクションを取れるとは信じられないのだ。だから自ら指示を出し、開発者らをコントロールしようとする。

この問題への対策としては、まず、ソフトウェア開発上の問題や課題を開発者らが正しく認識しており、正しい対策を取ろうとしていることを報告相手にはっきり示すことだ。その上で報告相手が意見を述べ、それが妥当でないと思うなら、その場で議論すべきだろう。報告を受ける側と報告を行う側には、前者が上の立場、後者が下の立場といった上下関係が、自然と意識下に形成されやすいように思うが、「両者は対等である」というスタンスで議論したいところだ。そういう意味で、こういった役割はテックリードやエンジニアリングマネージャーが良いだろう。

他に考えられる対策としては、例えば組織やプロジェクトに関わる全員が参加するような、できる限り多くの人が集まるオープンな場で報告を行うことだ。人目が多ければ、報告者に対してコントロール的な発言をしがちなビジネスリーダーも、そういった発言を控えるだろう。

逆に、できる限りクローズドな場で報告する方法もある。テックリードやエンジニアリングマネージャーだけがそこに参加する。議論結果は、場に参加したテックリードやエンジニアリングマネージャーが翻訳し、フィルタを通して、第三者の建設的な意見として開発者らにフィードバックする。そうすることで、報告相手のコントロールからチームを引き離す。取り組みの主体はあくまでもチームにあるという意識を守るのだ。

このようなクローズドな報告による解決手法は、組織の分断を解消する時間を長引かせるため、おすすめできない。しかし、どうにもアンコントローラブルなプロジェクト関係者が存在する組織では有効な手段となり得る。とにかく、このクローズドな議論の中で、1日でも早く信頼関係を築くよう努力を続けるしかない。

ここで注意したいのは、あいだに入ったテックリードやエンジニアリングマネージャーに蓄積されるストレスだ。本音を話せる同僚がいれば、そのストレスもいくぶん軽減できる。特に、その同僚が、同じような立場、同じような経験を持つ人ならなお良い。社内に見つからないなら社外でも構わない。社外秘情報は話せないが、利害関係がない分、正直な話ができる。画期的な解決法でもなんでもないが、そういった仲間を作っておくことも、思ったより助けになるものだ。

目標設定で期待値を合わせる

いつまでに、どのレベルまでメトリクスを高められるか。例えば、現時点では基準ラインを下回っているメトリクスが、3か月後に基準ラインに到達できると開発者らは考えているとしよう。3か月後というのは早いのだろうか、遅いのだろうか。開発者とビジネス担当者で意見が分かれる可能性がある。そしてそれは、開発者よりビジネス担当者の方が楽観的な期待を持っていることが多いだろう。その認識のズレに気付くのが遅ければ遅いほど、現実を知った時のビジネス担当者の落胆は大きくなる。それがしこりとなって、互いの信頼関係を壊す結果を招くことになるかもしれない。

取り組みを始める前に、目標を定めてビジネス担当者らと合意しておくことは、彼らの期待値をコントロールする手段となる。いつまでに、どのレベルまでメトリクスを高められるかの認識のズレに、早期に気付いてそのギャップを調整できるからだ。

さらに、目標を時系列方向に細分化して、月次やイテレーション(スプリント)単位の計画に分解しておく。そうすれば、計画と実績の予実差異を知ることができる。前節で述べた定期報告には、計画と実績、そしてその予実差異を含める。これらの情報を定期報告に記載することで、ビジネス担当者らは現実を正しくとらえることができるようになる。

予実差異は、未来を予測するセンサーのようなものだ。実績が計画を下回っているなら、それは期日までに目標を達成できない可能性を知らせている。こうして事前に遅れを検知できるので、開発者は、早期に適切なリカバリアクションを取れるようになる。期日ギリギリになって慌てふためくようなことを予防できるということだ。予実差異によるこのようなメカニズムは、適応度関数として捉えることもできるということだ。

ただし、計画はあくまで計画。固執しすぎることは良くない。計画どおりに進めることが、必ずしも目的を果たすことにつながるとは限らない。目標や計画が間違っていると気づいたなら、見直せば良い。ここを間違うと、チームの中でメトリクスが自己目的化してしまう。

メトリクスの自己目的化を回避する

ソフトウェア開発上の関心事をメトリクス化し、目標や基準を定めることにはリスクを伴う。メトリクスが自己目的化しやすいからだ。開発者らが本来の目的を見失い、目標や基準ばかりを追い求める状況に陥ると、目的に対して意味のない手段でメトリクスを向上させる行動が目につくようになる。

こうならないためにも、あるいはこうなってしまった時も、開発者らが目的と照らし合わせて手段を選択するよう、テックリードやエンジニアリングマネージャーが常に彼らをサポートしたい。メトリクスとは、目的を果たせた時に目標や基準に達しているものだ。逆に、メトリクスが目標や基準に達したからといって、目的が果たせたとは限らない。ここを間違えないよう、チームが常に自らの行動を律する状態を作り出したいところだ。

興味深いことに、ビジネス担当者もソフトウェア開発のメトリクスを自己目的化する罠にかかりやすい。むしろ彼らの方が、開発者よりその傾向が強いようにも思える。その背景は、ビジネス担当者らが、自らの目標に対し特に強くコミットする職種であることに起因するのだろう。ソフトウェア開発が扱う目標と比べるとビジネス目標は、目的に、より近いものだからだ。ユーザー価値は別としても、ビジネス価値を高めるという目的とビジネスメトリクスを高めることはほぼ同義だ。目標を達すれば、目的を果たせる。その思考が染み付いているからこそ、ソフトウェア開発が扱う目標や基準においても、開発者に同レベルのコミットを求め過ぎてしまう。

もしビジネスリーダーらがそのような習性に基づいて、目標に達するためだけの不合理なアクションを求めてきたら "NO" と言おう。それを実行することが目的にとって意味がないなら、ビジネスリーダーらにそれを説明することは、我々の責務である。そうしなければ、チームが無駄なアクションに貴重な時間を浪費することになる。

自己目的化による問題は、目的に対してメトリクスが間接的であるほど起こりやすいのではないか。上述の通り、ビジネス目標で扱う売上や顧客単価といったビジネスメトリクスは、ビジネス価値を上げるという目的とほぼ一致するものだ。だから自己目的化による問題が起こりにくい。一方で、ソフトウェア開発のメトリクスは、目的を完全に説明することができないことが多い。不明瞭なのだ。だからこそ、目的を見失ってメトリクスを上げていくことが、必ずしも目的を果たす結果につながるとは限らない。目的を見据えてメトリクスを改善する手段を選択し、実行する。そしてその効果を検証し、次の手を導き出す。このフィードバックサイクルが必要なのだ。

実は、ビジネス系メトリクスでも自己目的化は起こり得る。ビジネス目標の達成はたしかにビジネス価値を高めるのだが、手段を間違えるとユーザー価値を損なうからだ。ビジネス価値ばかりを追い求め、ユーザー価値を犠牲にするなら、それはビジネス、ひいては企業として問題だ。企業やビジネスが掲げるミッションやビジョンに背いた行為だと言える。だからこそビジネス価値とともにユーザー価値も問わなければならない。ビジネス価値を計測するメトリクスばかりでなく、ユーザー価値を計測するメトリクスもサブメトリクスとしてモニタするのだ。

同様にソフトウェア開発におけるメトリクスも、サブメトリクスで補強することで、それが自己目的化のセンサーとなる。例えば、「変更のリードタイム」の短縮に力を注いでスピードを追い求めたばかりに、本番でのシステムトラブルが増えるのは問題だ。それを検知するために、「変更失敗率」をサブメトリクスとするのも良いだろう。

それでも自己目的化のリスクが高い場合は、それを回避するために、目標や基準を作らないことも1つの選択肢となる。自己目的化とは、メトリクスを向上させようとする意識が強くなり過ぎた状態だ。チームの思考を「どうやってメトリクスを向上するか」ではなく、「何がメトリクスを悪化させているか」に置き、その障害を取り除くことに注力すべきだろう。

最後に

私が知る限り、ビジネスリーダーたちにのし掛かるプレッシャーはいつだって大きい。短期、あるいは中長期で達成しなければならないKGIに全力を注いでいる。ビジネスやユーザーの価値を計測するそれらのメトリクスは、思い通りに動いてはくれないから、限られた経営資源を使い、考えつく限りの施策を打つ。そうやって、小さな成果を一つひとつ積み重ねながら、実績値を目標に近づけていく。

それゆえに、彼らには余裕がない。ソフトウェア開発上の関心事の話など、開発者らの子供じみた言い分にしか聞こえない。そんなことに、貴重な経営資源を費やすわけにはいかない。

そこに割って入るためには、私たちも彼ら同様に真剣であることを示すしかない。ともに担うミッションの遂行と目標の達成のために、ソフトウェア開発上の関心事に取り組む重要性を説くのだ。その継続が、互いの信頼関係を築き上げていき、分断した組織は、やがて1つに統合されるのだろう。