mtx2s’s blog

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

コード品質はやはりビジネスに影響を与える

私たちソフトウェアエンジニアは、コード品質についてしばしば論ずるけれども、ではコード品質の良し悪しがどれほどビジネスに影響するのかと問われると、回答に窮する。只々、「コード品質が悪いと変更により多くの時間がかかります」だとか、「欠陥の修正に追われて開発時間が奪われます」だとか、個人の経験やエンジニア的一般論に頼った定性的な説明に終始するしかない。ソフトウェアを繰り返し変更する頻度が高いほど、コード品質が開発時間に影響を与えるのは確かにそのとおりだと思えるが、はたしてそれは、どれほどのインパクトなのだろうか。

2022年の研究論文 "Code Red: The Business Impact of Code Quality – A Quantitative Study of 39 Proprietary Production Codebases" では、コード品質がビジネスに与えるインパクトを「時間」という形で計測している。市場投入までの時間というものが、ビジネス上での競争優位を左右するという考えからだ。

本稿では、前述の論文を中心に、「市場投入までの時間」という観点で、コード品質とビジネスの関係について考える。

市場投入までの時間とコード品質の関係性

「市場投入までの時間というものが、ビジネス上での競争優位を左右する」とは言うが、「市場投入までの時間」と「コード品質」との間には、どのような関係が存在するのだろうか。

マーク・リチャーズ(Mark Richards)らの著書『ソフトウェアアーキテクチャの基礎』では、「市場投入までの時間」を関心事とした時に必要となるアーキテクチャ特性のひとつに「アジリティ(agility)」を挙げている。同書では、ソフトウェア開発におけるアジリティを「変更に迅速に対応する能力」としている。

また、和田卓人による『アジリティを支える品質特性』によれば、アジリティと関係の深い品質特性は「保守性(maintainability)」であり、その品質副特性として「理解容易性(understandability)」「変更容易性(modifiability)」「テスト容易性(testability)」を挙げている。これは、バリー・ベーム(Barry Boehm)らによる保守性の定義によるものだ。

そしてこの保守性とは、コード品質がもたらすものであることから、コード品質が「市場投入までの時間」を決定づける要因であることが分かる。

市場投入までの時間を短縮するには、アジリティと並んで「デプロイ容易性(deployability)」も忘れてはならない。ビジネス上のパフォーマンスを高める上で、テスト容易性と並んでデプロイ容易性が重要である点は、書籍『LeanとDevOpsの科学』でも述べられているところだ。これらのアーキテクチャ特性を高めるためには、疎結合アーキテクチャが求められるという点でコード品質とも関係する特性であると認識すべきだろう。

計測結果とリポジトリマイニング

"Code Red: The Business Impact of Code Quality – A Quantitative Study of 39 Proprietary Production Codebases" では、次の3つの結果を得ている。なかなかの衝撃的な数字だ。

  1. 低品質なコードに含まれる欠陥は、高品質なコードの15倍
  2. 低品質なコードの平均開発時間は、高品質なコードの2倍
  3. 低品質なコードの最大開発時間は、高品質なコードの9倍

具体的な測定結果は、論文内に掲載された次の表のとおりだ。

ここでのコード品質の判定は、コード分析ツールのCodeSceneによって計測されるCode Healthというメトリクスが使われている。このメトリクスは、コード品質を、最も低品質であることを示す1.0から最も高品質である10.0までの数値で表す。これを更に、10.0から8.0の間であれば "Healthy" とし, 8.0から4.0を "Warning", 4.0から1.0を "Alert" として、コードベース内のそれぞれのファイルを3つのカテゴリのいずれかに分類している。上記の「低品質なコード」とは "Alert" とされたファイルであり、「高品質なコード」とは "Healthy" とされたファイルを指す。

開発時間(Time-in-Development)の計測は、JiraとGitのログから得ている。例えば、コミット#1がJiraの課題Xと紐付けられていたら、そのコミットで変更されたファイル1の開発時間は、課題のステータスが "In Progress" となってからコミットされるまでの経過時間となる。次のコミット#2が、同じく課題Xと紐付けられ、ファイル2を変更していた場合、ファイル2の開発時間は、コミット#1からコミット#2までの経過時間となる。さらに、課題Xに紐づくコミット#3がファイル1とファイル2の両方を変更していたら、ファイル1はコミット#1での計測時間に、コミット#2からコミット#3までの経過時間が加えられる。ファイル2も同様に、コミット#2での計測時間に、コミット#2からコミット#3までの経過時間が加えられる。また、課題タイプが「バグ」であるかどうかも見ている。

このようなリポジトリマイニングの対象とされたコードベースの数は、論文タイトルにもあるとおり、39である。

「欠陥が15倍」による影響

欠陥が多いということは、予定外の作業がそれだけ増えるということだ。Jiraで「バグ」に分類された課題の平均数が、"Healthy" と判定されたファイルと "Alert" と判定されたファイルで15倍も違うなら、コード品質の良し悪しは見積り精度に影響を与える

バグ対応に要する時間は、開発計画にどれだけ組み込まれているだろうか。おそらく「バッファ」という形で吸収できるよう、計画に組み込まれているプロジェクトも多いと思うが、あまりにバグが多すぎてバッファを消費しきってしまうことだってあり得る。そのようなプロジェクトは、市場投入を計画通りに進められず、遅延を起こす。それが、ビジネスに悪影響を及ぼす。

さらに、顕在化されたバグがそれだけ多いということは、潜在的なバグが多いであろうことも予想できる。そういったバグが市場投入後に障害を起こす。そうして、開発者は障害対応に追われ、開発時間を失っていく。それが進行中のプロジェクトの計画にも悪影響を及ぼし、遅延に遅延を重ねる結果となる

「開発時間が平均2倍、最大9倍」による影響

品質が悪ければ、開発時間がより長くなるという傾向が、計測結果によって明らかにされた。"Healthy" とされたファイルと "Alert" とされたファイルを比較した場合に、平均開発時間では後者は前者の2倍以上、最大開発時間では9倍近くとなった。

この結果は、単に開発時間が長くなるといういうだけの問題ではない。「見積り」という観点で、予測可能性が著しく下がることも意味する。算出した見積りに対し、結果として、2倍から9倍もの時間がかかってしまうかもしれないということだ。カテゴリごとに見てみると、"Healthy" では平均開発時間に対して最大開発時間が2倍弱、"Alert" だと7倍以上に達する。コード品質が悪いと、開発時間が長くなるだけでなく、ファイルごとの開発時間のばらつきも大きくなるということだろう。

このように、コード品質の良し悪しが、市場投入までの時間を引き伸ばしてしまうだけでなく、計画に対する予測可能性を損なわせる要因になっているのだ。

「予測可能性の低下」という問題

先述した3つの計測結果はまさに、「市場投入までの時間」という関心事に対し、コード品質が影響することを示した。コード品質が低ければ、開発時間をより必要とし、さらに予測可能性の低下がプロジェクトの計画を瓦解させる。そしてこれらは結果として、ビジネスの機会費用や機会損失につながる。

このような状況に陥った開発チームは、見積もり時にバッファを可能な限り大きく積むことで、なるべく確実性の高い市場投入日を計画するようになる。しかし、これでは市場投入までの時間がむやみに引きのばされただけだ。こんなやり方は、プロジェクト関係者の不信感を生む

根本的には、すでに劣悪になってしまった既存コードの品質を改善しなければならない。しかし、コード品質が十分に高くなるまでプロジェクトを不安定な状態で放置するわけにもいかない。プロジェクトの予測可能性を高めるための計画づくりが必要だ。

スクラム開発のようなアジャイル開発手法であれば、それはイテレーションごとにチームのベロシティを見直すことで実現できるかもしれない。直近の数イテレーションでの見積り予実を比較することで、1回のイテレーションでどれぐらいの開発が進められるかを補正できる。これなら、予測可能性を高められる。それに、このようにチームの実績統計に基づいて算出された見積りであれば、プロジェクト関係者も納得するだろう。

これは、「コード品質が悪化すると、チームのベロシティが下がる」という前提に基づいている。ベロシティが下がる要因は、ここまでで見てきた通り、予定外の作業が発生しやすくなることと、1つの変更に対する開発時間が長くなることだ。

しかし、見積りをストーリーポイントで行っているなら注意点がある。コード品質が良い状態でチームが完了したイテレーションのストーリーポイント合計が100ポイントだったとしよう。ベロシティは100となる。では、これとまったく同じ内容の開発を、コード品質が悪い状態で見積もったらどうなるだろうか。100ポイントのままだろうか。100ポイントより大きくなるだろうか。いずれにしても、1回のイテレーションには収まりきらないだろう。したがって、前者の場合はベロシティが下がる。しかし、後者の場合はベロシティが下がらない

もう少し詳しく説明すると、チームはベロシティを100としているので、前者では例えばイテレーション完了時点で100ポイントのうちの67ポイント分だけが完了して、ベロシティが下がる結果になる。しかし後者の場合、見積り時点で150ポイントといった数字になるので、今回のイテレーションでは150ポイントのうちの100ポイントだけを計画に含めることになるだろう。したがって、ベロシティは100のままだ。

どちらの見積り方法が正しいかは知らないが、前者はコード品質の悪化がベロシティに現れ、後者はコード品質の悪化が見積りに現れる。定点観測するなら、前者の方が時系列での変化を追いかけやすい。後者は、何を比較すれば良いのかわからない。それはすなわち、コード品質の悪化を関係者に説明することが難しくなることを意味するのではないだろうか。

ただ実際のところ、コード品質が悪ければ「予定外の作業」が増えるので、どちらの見積り方法であっても結局はベロシティは下がるだろう。それならば、あまり気にする必要はないのかもしれない。ただ、「予定外の作業」も「1つの変更に対する開発時間が長くなること」も、どちらの影響もベロシティに現れた方がシンプルではないかとも思う。

コード品質を誰の目にも明らかにする

Googleが言うように、ソフトウェアエンジニアリングは、たった1度書いて終わりのプログラミングとは違う。「ソフトウェアエンジニアリングとは時間で積分したプログラミングである」という言葉が示すように、何度も繰り返し変更されるソフトウェアを対象としている。そして、少なくともその活動が人間の営みである間は、保守性を高め、維持し続けることだけが、コードベースに変更を繰り返すことを持続可能にする。「ソフトウェアを保守性のある状態に長期間保つということは、不断の闘いにほかならない」ということだ。

Stripe社のレポートによれば、開発者の平均的な1週間の仕事時間41.1時間のうち、42%にあたる17.3時間は、品質の低いコードによって無駄に費やされている。また別の調査では、技術的負債の管理に費やされる開発時間は開発全体の25%であるが、その追跡にツールを利用する組織はわずか26%で、体系的に追跡している組織は7.2%しかなかった。バックログや、静的コード解析ツールなどが活用されていないということだろう。

一方で、コード品質の問題を認識しているのは、開発者やアーキテクト、プログラムマネージャーであり、経営者やビジネスマネージャーはほとんど認識していない(42%)という調査結果もある。そして、コード品質の問題を積極的に管理していると解答したビジネスマネージャーは、わずか10%しかいなかった。

これらの結果からも分かるように、やはり、コード品質の問題が組織の中で可視化されず、エンジニアしか認識できない状態に置かれているのだ。これでは組織としてコード品質の問題に取り組むことなどできるはずもない。だから、コード品質との闘いは、エンジニアだけの活動になるのだ。しかし、ツールを活用してコード品質を積極的に可視化し、追跡可能にできれば、組織内で問題・課題を共有できる。数多くある静的コード解析ツールの中には、コードの問題を特定したり、メトリクス化するだけでなく、その問題を解消するために要するであろう工数の参考値を出してくれるようなものもある(経験的に言って、それらの精度に期待しすぎることはできないのだが)。

考えてみれば、プロジェクトやプロダクトの定期報告には、売上やコストといったビジネスメトリクスや、アクティブユーザー数やダウンロード数といったユーザー行動に関するメトリクスは含まれても、コード品質に関する情報は含まれない。報告に含まれるのは、せいぜい、障害発生数や欠陥数ぐらいだろう。コード品質の問題が積もり積もって大きくなり過ぎた時にはじめて、その解消に時間が欲しいとエンジニアが相談を切り出す。これではコミュニケーションが上手くいくはずもない。私たちエンジニアは、こういったコミュニケーションにも、もう少し目を向けるべきではないだろうか。

リリースした新機能や改善の多くに価値がないという調査結果が意味すること

プロダクトに備わる機能の64%がほとんど使われないと言う。あるいは、80%という数字が用いられることもある。これが本当だとすれば、ソフトウェア開発に費やしたコストの多くが無駄だったことになる。ソフトウェア開発は常にスピードが求められるものだが、そもそもこのような無駄がなければ、ユーザーや顧客への価値の提供をもっと速くできたはずだ。

ソフトウェプロダクトをローンチし、それから次々とリリースを繰り返しながら追加されていった変更は、いったいどれだけのものが実際に価値があったのだろうか。本稿では、Standish Groupやマイクロソフトの文献を中心に、ヒントとなる数字をいくつか紹介し、その理解を深める。

64%はめったに、あるいはまったく使われない

まずは「64%」という数字の出典であるが、2002年5月に地中海のサルデーニャ島で開催された "The XP 2002 Conference" にまでさかのぼることになる。Standish Groupの創設者であり会長のジム・ジョンソン(Jim Johnson)による基調講演 "ROI, It's Your Job" の中で紹介されたものだ。この時の様子は、マーティン・ファウラー(Martin Fowler)がレポートしている。

原典となる公演資料が手元にないのだが、ジム・ジョンソンが提示したデータはStandish Groupによる調査で得られた結果であり、次の円グラフにある通りだ。ソフトウェアプロダクトが備える機能それぞれの使用頻度を調査している。ここで、「まったく使わない(Never)」とされた45%の機能と、「めったに使わない(Rarely)」の19%を足し合わせたものが、例の「64%」である。

「いつも使う(Always)」と「よく使う(Often)」を合わせてもたった20%であり、さらに「時々使う(Sometimes)」を合わせても36%だ。ジム・ジョンソンが同講演において合わせて引用したDuPontによる「機能の25%だけが実際に必要」という研究結果をみても、惨憺たるものだ。

マーティン・ファウラーは、提示されたこれらのデータがソフトウェアエンジニアとしての経験と合致すると感じたようだ。それについては、次のように述べられていることから分かる。

This certainly fits the anecdotal evidence of many agilists who feel that traditional approaches to requirements gathering end up gathering way more requirements than are really needed to a usable version of a release.

確かにこれは、要件収集に対する従来のアプローチにおいて、リリースするバージョンに本来必要な要件より多くの要件を集めてしまうと感じている多くのアジリストの事例証拠と一致する。

おそらく、ジム・ジョンソンが公開したStandish Groupの調査結果を知った多くのソフトウェアエンジニアが、マーティン・ファウラーと同様に感じたのではないだろうか。そうであるからこそ、この調査結果は数多くの文書で引用されることとなったのだろう。

しかしながら、Standish Groupによる調査結果を信頼する上で、その調査の詳細がどのようなものであったかが気になるところだ。その答えとなる情報は、私の知る範囲で2つある。

1つめは、書籍『アジャイルな見積りと計画づくり』などの著者であるマイク・コーン(Mike Cohn)による2015年のブログ記事 "Are 64% of Features Really Rarely or Never Used?" だ。彼は、Standish Groupに連絡を取り、この調査が4つの企業の4つの社内アプリケーションを対象にした調査であることを聞き出した。たった4つの、しかも社内での開発プロジェクトのみを扱ったデータであることから、この調査結果は一般化できないというのが、彼の主張だ。

2つめは、Standish Group自身によって2010年頃に公開された "MODERNIZATION - CLEARING A PATHWAY TO SUCCESS" というレポートだ。そこでは、100のカスタム開発アプリケーションを対象とした調査に基づいていると説明されている。1996年に行われたユーザーワークショップによって得られた結果のようだ。

たった4つのアプリケーションなのか、100のアプリケーションなのか。どう解釈すれば良いのか分からないが、後者について書かれたレポート "MODERNIZATION ~" には続きがある。それが「80%」に関する説明だ。

80%は価値が低い、あるいはまったくない

80%」の出典もまたStandish Groupのレポートであり、最近の同社のレポートでは、「64%」ではなく、「80%」が使われるようになっている(私が知る限り、少なくとも2014年のレポートまでは)。

Standish Group research shows that 80% of features and functions have low to no value.

Standish Groupの調査によると、機能やフィーチャの80%は、価値が低い、あるいはまったくないことを示している。

先述した2010年のレポート "MODERNIZATION ~" によると、これは、1996年の調査で64%という結果を得て以降、数年ごとに繰り返し実施された調査で得た結論のようだ。その数年にわたる調査では、ほとんどのメソドロジー(methodology, おそらくソフトウェア開発方法論のこと)において、調査のたびに結果が大きく変動するようなことがなかったと言う。

Using some automated tools and spot checks every couple of years, we found, to no surprise, that the numbers are relatively unchanged for most methodologies.

いくつかの自動ツールを使い、数年ごとにスポットでチェックしたところ、やはり、ほとんどのメソドロジーにおいて、数値が比較的に変化しないことがわかった。

そして、下の円グラフで表される結論に至ったのだ。それが、「めったにない(Hardly Ever)」「まれ(Infrequently)」を合わせて80%という数字だ。

これらのことから、「80%」という数字は、Standish Groupによる「64%」という調査結果を経た上でのより新しい、アップデートされた結論であることが分かる。

それでは「機能やフィーチャの80%は、価値が低い、あるいはまったくない」と言い切ってしまえるかと問われると、少々ためらうところもある。単純に、調査内容について詳細が分からないことが原因だ。それは主に3つある。

1つめは、この調査で扱われたソフトウェアに、商用などの社外向けアプリケーションが含まれていたのかどうかだ。マイク・コーンが言うような、社内アプリケーション向けの社内プロジェクトだけを対象とした調査であるなら、社外向けアプリケーションでの状況は異なるかもしれない。

2つめは、どんな機能を対象とした調査だったかだ。めったに使わない機能であっても、必要なものはある。例えば、ユーザーが自身の登録情報を変更する機能がそれにあたるだろう。こういった機能は、調査でどう扱われたのだろうか。

3つめは、現在も継続して調査が行われているのかどうかだ。ソフトウェアを取り巻く環境は大きく変化し続けている。Standish Groupの結論は、2010年以前に出されたものだ。その後も状況に変化がないのだろうか。

もちろん、Standish Groupの調査についてもう少し調べていけば、これらに関する解答が得られるのかもしれない。しかし、いまのところ、これ以上の情報を見つけられていない。それでも有用なデータだとは思うが、自戒を込めて言えば、共感できる数字だけに、このままでは確証バイアス的に利用してしまいやすい。

そもそも、先ほど2つめの原因として挙げた通り、機能の価値と使用頻度が一致するとは思えない。あるタスクを処理するために、ユーザーが毎日使わなければならない機能と、ほとんど何もしなくても処理してくれる機能では、ユーザーにとってどちらがより価値が高いだろうか。使用頻度は、ソフトウェアに加えた新機能や改善を評価する上であまり意味がないのかもしれない。

そのような理由から、Standish Groupの調査結果は有用なデータのひとつとして参考にしながらも、より「価値」というものに焦点をあてた情報の必要性を私は感じていた。

3分の2は価値がない、あるいは逆に価値を損なわせる

最近、マイクロソフトのオンライン実験に関する論文を2つ読んだ。きっかけは、デイビッド・ファーリー(David Farley)の著書『継続的デリバリのソフトウェア工学』の7章にある次の一文だった。

機能は開発チームが役に立つと考えたから作られているのだが、多くのドメインでほとんどのアイデアが重要指標を改善できていない。Microsoftでテストされたアイデアのうち、改善されたのは1/3だけだった。

ここで注目すべきは、リリースされた機能を「重要指標」で評価しているという点だ。それがビジネス価値を計測する指標であるか、ユーザー価値を計測しようとする指標であるかは場合によるだろうが、「1/3」という数字は、そういった「価値」として定義した指標をもとにアイデアを評価したものである点が良い。

私自身が関わるソフトウェアプロダクト開発でも、リリースされた機能や改善は、すべてではないが、A/Bテストなどを通し、KGI(Key Goal Indicator, 重要目標評価指標)OEC(Overall Evaluation Criterion, 総合評価基準)を構成するKPI(Key Performance Indicator, 重要業績評価指標)に関連付けて評価されている。それらのデータを過去に遡って集計すれば、上述のような統計データも得られるだろう。しかし、こういった手持ちのデータだけを見ていても、自分たちが上手くやれているのかどうなのか分からない。たった1人しか受験しない大学入試模擬試験が役に立たないことと同じだ。自分たち以外のデータもあってこそ、相対的なものさしを手に入れ、改善の要否なども見えてくる。そういった点において、上述のようなマイクロソフトの調査結果があるのはありがたい。

本題に戻るが、『継続的デリバリのソフトウェア工学』での先の引用もととなった参考文献は、マイクロソフトの "Online Controlled Experiments at Large Scale" という2013年の論文だ。内容としては、A/Bテストのような「対照実験(controlled experiment, control experiment)」における実験回数のスケーリングに焦点があてられている。これはこれで興味深い内容だったのだが、本稿とはテーマが異なる。

同論文内で参考文献に挙げられていたマイクロソフトの2009年の論文 "Online Experimentation at Microsoft" に、興味深い統計データがいくつか書かれていた。マイクロソフト社内でのBingなどのプロダクトに関する対照実験のデータだ。先述の「1/3」もここからの引用らしく、この論文内では次のように書かれている。

Evaluating well-designed and executed experiments that were designed to improve a key metric, only about one-third were successful at improving the key metric!

主要な指標を改善するよう適切に設計され、実施された実験を評価すると、それに成功したのはわずか1/3程度だった!

~ ~

Stopping the launch saves the company money and avoids hurting the user experience. As humbling as it may be, this represents about one third of experiments.

ローンチを中止することで経費を節約し、ユーザー体験を損わずに済む。控えめに言っても、これは実験のおよそ1/3に相当する。

~ ~

While it is expensive to experiment, it is more expensive to continue developing and supporting features that are not improving the metrics they were supposed to improve, or hurting them, and at Microsoft, these two cases account for 66% of experiments.

実験にはコストがかかる。しかし、指標を改善しない機能や指標を悪化させる機能を、開発したりサポートしたりし続けるのは、もっとコストがかかる。そしてマイクロソフトでは、これら2つのケースが実験の66%を占めている。

つまり、マイクロソフトの実験では、イデアの1/3は価値があるが、2/3は価値がないか、逆に価値を損なわせると言うのだ。アイデアの良し悪しに対する人間の感覚がどれだけ信用できないものであるかが、この結果からよくわかる。

もちろんこの数字も、同社のプロダクトに対する数多くの変更を母集団と考えた場合に、実験対象となった変更の集合に標本として偏りがあるかもしれない。実施された対照実験の多くが、実験しやすい変更に対するものだったかもしれないからだ。それに、これはマイクロソフトに閉じた結果でもある。発表されたのも2009年であり、同社の2013年の論文でも引用されているとは言え、やはり少々古い。

しかし、アイデアの価値を対照実験を通して評価するという点で言えば、私が関わるプロダクト開発でも条件は同じだ。その点で、このマイクロソフトの数字は、自分たちの現状と比較するデータとして参考にできそうだ。

「勝利宣言」からの脱却

先のマイクロソフトの論文では、同社以外の数字についても紹介されている。例えば、Netflixでは、自分たちのイデアの90%が間違っていると考えているようだ。Amazonでは、すべての新機能を評価することが当たり前であり、その成功率は50%を下回っているとされている。また、ソフトウェア産業におけるアイデア成功率は、対照実験によって科学的に評価した場合、50%以下であるという報告で溢れていると言う。

これらのことから、人間は基本的に、成功するアイデアと失敗するアイデアを見分けることが得意ではないということがよくわかる。長年、ソフトウェアプロダクト開発に携わっていれば、これに頷ける。プロダクトのアップデートを何度繰り返しても重要指標が一向に改善されないことや、自信を持ってローンチした新機能がほとんど使われないといった経験を重ねてきただろう。だからこそ、Standish Groupのデータにも共感するのだ。

優れていると信じるアイデアをローンチできただけで、ユーザーやビジネスに価値を付加できたと確信してしまっていないだろうか。ジョナサン・ラスムッソンの著書『ユニコーン企業のひみつ』では、これを否定的に「勝利宣言」と呼んだ。そのアイデアが成功を導くと信じ込んでしまい、実際に価値を提供できたのかどうかを検証せず、フィードバックによる学習を放棄しているからだ。

勝利宣言するタイプの開発組織では、成功を信じるあまり、ひとつのアイデアに対する開発規模が大きくなる傾向があるのではないだろうか。確実に勝利を手にするために、時間をかけて分析し、必要な機能を網羅しようとするからだ。無駄になるかもしれないという考えがそこにはない。

ティーブ・マコネル(Steve McConnell)によれば、要求の間違いをリリース後に修正するコストは、要求段階で修正することに比べ10倍から100倍かかると言う。そうであるなら、成功するか失敗するかを見分けられないはずのアイデアの開発規模を、はじめから大きくしてしまうことは無駄だとわかる。

ソフトウェアプロダクト開発は、クネビンフレームワークで言うところの「複雑(Complex)」な領域にマッピングされるものだ。予測可能性が低く、 分析だけで正しい答えを得ることはできない。探索が必要なのだ。だからこそ実験する。すなわち、仮説と検証を繰り返す。解決すべきは不確実性であり、それが、フィードバックループを形成するインクリメンタルな開発の意義なのだろう - Experiment or Die!

「機敏なユーザー体験」を実現するUIに求められる応答時間

機敏(snappy)なユーザー体験は、魅力的(glamorous)なユーザー体験に優る」とは、ヤコブ・ニールセン(Jakob Nielsen)の言葉だ。瞬時に起動し(あるいは表示され)、インタラクションに遅延を感じさせないアプリケーションは、いちユーザーとして使っていて本当に気持ちが良い。逆に、何をするにも「遅い」と感じさせるものもある。そのようなアプリケーションは、使うたびにうんざりするし、特別な理由がない限り使いたくないものだ。

そうであればこそ、ソフトウェアエンジニアはユーザインタフェース(UI)の応答時間に注意を払うべきだろう。それは、優れた体験を生み出してユーザーの離脱や離反を防止する効果が得られるだけではない。ビジネス価値向上に対し、エンジニアがイニシアチブを取れる数少ない対象の1つでもあるのだ。それに加え、そもそもエンジニアにとってパフォーマンスチューニングというものは、何であれ成功すれば達成感が得られるものだ。つまりUIの応答時間改善とは、ユーザー、ビジネス、エンジニアのいずれにとっても価値ある取り組みと言えるだろう。

では、「機敏(snappy)」と呼べる応答時間とは、どのように定義できるのだろうか。これが、本記事のテーマだ。

3つの時間制限

ヤコブ・ニールセンは、アプリケーションのパフォーマンスについて、0.1秒1.0秒10秒という3つの時間制限を用いて説明している。

0.1秒以内のフィードバックは、UIオブジェクトに対するユーザーの直接的な操作への応答としての限界点となる。これを超えると、ユーザーが遅延を感じるようになるからだ。

しかし、1.0秒以内であればまだ許容範囲だ。ユーザーは遅延を感じるものの、待たされているとまでは感じない。これが1.0秒を超えると、ユーザーは待たされていると感じるようになる。

それでも10秒以内であれば、ユーザーは引き続きタスクに注意を向け続けるが、10秒を超えても応答が無ければ、その注意も別のことに向け始めてしまう。最終的には、ユーザーは待つことをあきらめ、離脱してしまうかもしれないというのだ。

UIの遅延を感じさせない応答時間

まず0.1秒という時間制限であるが、wev.devの記事では、アルベール・ミショット(Albert Michotte)の研究に触れている。そこでの実験では、スクリーンに映し出された物体Aが移動し、静止している別の物体Bに接触した時、Bが0.1秒以内に動き出せば、実験の被験者は、Aの衝突がBの動作を引き起こしたという印象を受けるという結果になった。この遅延が0.2秒以内であれば、そのような印象を持つ被験者はまだ存在する。しかし、遅延が0.2秒を超えると、Bの動作はAによって引き起こされたという印象を持たないようだ。スチュアート・カード(Stuart K. Card)らによる "The information visualizer, an information workspace" でも、知覚処理(perceptual processing)を0.1秒と定義しているが、おそらくアルベール・ミショットの実験結果を参考にしたものだろう。

ロバート・ミラー(Robert B. Miller)の "Response time in man-computer conversational transactions" では、「キーの押下」や「文字の選択」といったユーザーの直接的な制御操作に対する反応時間の制限を0.1秒以内、あるいは0.1秒から0.2秒以下としている。その上で、ユーザーの熟練度によっては、この0.1秒から0.2秒の遅延を「遅い」と感じる可能性にも触れている。その例として挙げられているのは、機械式パイプオルガン奏者の訓練だ。彼らは、打鍵から音が鳴るまでの0.1秒から0.2秒の遅延に適応して演奏できるよう学ぶそうだ。

GoogleによるCore Web Vitals(CWV)の定義で該当するのはFID(First Input Delay)だろう。FIDとは、「ユーザーが最初にページを操作したとき (リンクをクリックしたり、ボタンをタップしたり、JavaScript を使用して実装されたカスタム コントロールを使用したりしたとき) から、その操作に応じてブラウザーが実際にイベント ハンドラーの処理を開始するまでの時間」のことだ。CWVでは、75パーセンタイルの応答時間0.1秒以下のページを "GOOD" とし、0.1秒から0.2秒のページを "NEEDS IMPROVEMENT" としている。ここでの0.1秒という閾値は、Google Chromeの匿名化された集計結果に基づいて定義されている。Chrome UX Report(CrUX)に貯められたそれらのデータの75パーセンタイル以上のオリジンが、0.1秒以内で応答していたのだ(スマートホン:78%, デスクトップ:99%超)。

これらを踏まえると、UIオブジェクトの直接的な操作に対する応答時間としては、0.1秒以下という制限が妥当そうだ。0.2秒以下であっても許容範囲であるが、人によっては遅延を感じる可能性を考慮すべきだろう。

「待たされている」と感じさせない応答時間

次に、1.0秒以内という時間制限についてみてみると、上述したスチュアート・カードらの文献では、即時反応(immediate response)を1秒と定義している。この時間を超えてあまりに長くなると、ユーザーは応答を待つのに飽きてしまうとされている。この定義はアレン・ニューウェル(Allen Newell)の書籍 "Unified theories of cognition(認知の統一理論)" からの引用だ。web.devの記事によると、そこでの定義は即時反応を0.3秒から3秒としている。

ロバート・ミラーは先の文献で、「人間がマシンコミュニケーションで行える(あるいは行おうとする)タスクは、応答遅延が2秒を超え、さらに1秒程度延長される可能性があると、その性格を大きく変えてしまう」と述べている。

CWVでの定義はどうなっているかと言えば、LCP(Largest Contentful Paint)2.5秒以下を "GOOD" とし、2.5秒から4.0秒を "NEEDS IMPROVEMENT" としている。これもFIDと同様、CrUXのデータに基づいて定義されている。ちなみにLCPとは、「ビューポート内に表示される最も大きい画像またはテキストブロックのレンダリング時間」としている。

ヤコブ・ニールセンの定義から分かるように、ここでは人間がコンピュータに「待たされている」と感じるか否かを分ける応答時間の境界が焦点となる。ここでの参考文献を総合すると、1秒以内であれば十分で、2秒から3秒だと、待たされていると感じる可能性が高くなるということだろう。

ユーザーがタスクを成功させる応答時間

最後に、10秒以内という時間制限についてだが、スチュアート・カードはこれを単位タスク(unit task)の要件としている。ユーザーによる何らかの簡単なタスク行為を10秒以内に完了させられることを目指すという目標値だ。ヤコブ・ニールセンによれば、これは、タスク行為中の人間の短期記憶に保存された情報の減衰と関連している。10秒よりさらに時間を要してようやくシステムから応答が返されても、ユーザーは、中断していたタスクを再開することが困難になり、タスクを成功させる可能性が低下する。それどころか、多くの場合、10秒の遅延はユーザーを離脱させてしまうと言うのだ。CWVの背景にある調査でも、3秒間隔で様々な遅延をテストした結果には、9秒から12秒の遅延で満足度が低下し、12秒の遅延で戻る意思が低下したとある。

ロバート・ミラーは、複雑な問い合わせに対する図やグラフでの応答を、2秒以内に開始して10秒以内に完了する必要性を述べている。ただし、同様の複雑な問い合わせであっても、表形式での応答であれば4秒以内としているため、この制限時間内に行われると想定される処理の多くは描画によるものと考えられる。当該文献が公開された当時と比べ、現在のコンピュータは遥かに性能が向上しているので、この閾値はそのまま採用すべきでないだろう。しかし、これはユーザーによる思考の連続性を維持することを目的に定義された時間制限とされているため、本質はそこにあると捉えておけば良さそうだ。

機敏(snappy)なユーザー体験とは

以上を踏まえた上で、「機敏(snappy)なユーザー体験」と呼べる応答時間について自組織に向けて定義してみるなら次のようになるだろうか。なお、私自身の理解度がまだ十分ではないためか、多少違和感は残る。

  • UIオブジェクトの応答時間:0.1秒から0.2秒以内 - フロントエンドのみで処理できるような、UIオブジェクトの操作に対する反応。許容範囲は0.2秒だが、それでは「遅い」と感じるユーザーも存在するため、0.1秒以内が望ましい。
  • 画面表示の切り替え:1秒から2秒以内 - ネットワークを介したバックエンドとの通信も必要とするような画面の切り替え。2.5秒以内でも良い。ユーザーやコンテキストによっては、3秒だと「遅い」と感じさせてしまうこともある。10秒を超えるとユーザーが離脱する可能性がある。
  • 処理コストの高い問い合わせへの応答:2秒から10秒以内 - ビジネス向けの分析機能や、複雑な条件を組み合わせた問い合わせへの応答など。10秒を超える応答時間は、調査や分析を目的としたユーザーのタスク遂行の阻害となる。

ソフトウェアプロダクトにとって、「魅力的(glamorous)なユーザー体験」の実現が重要な課題であることは間違いない。一方で「機敏なユーザー体験」は、「魅力的なユーザー体験」と違い、その実現に求められるものが何であるかが明らかである。それはスピードだ。やるべきことは、迅速に応答を返すことでしかない。その実現難易度が高くとも、迷わず進めることが可能であるからこそ、継続的に取り組みたい重要な課題に位置づけられるだろう。そして、その価値がユーザーのみならずビジネスに及ぶことは、CWVのケーススタディからも期待が持てる。何より、エンジニアにとっても達成感が得られる取り組みになるのではないだろうか。

9つのチームロールでチームワークを強化する / ベルビンチームロール

ティーブ・マコネル(Steve McConnell)の著書『More Effective Agile』の第6章で、「ベルビンのチームロール理論」なるものが紹介されている。そこに、「Plant」や「Shaper」「Resource Investigator」など、聞き慣れない9つのロール名が並ぶ。チーム内でこれらのロールのバランスが取れていることと、チームのパフォーマンスの間には、高い相関があるそうだ。

そう言われると興味を持つ。ベルビンチームロールとはどのようなものだろうか。しかし残念なことに、同書からはほとんど情報を得られない。書かれているのは、先の9つのロールそれぞれに関する短い説明文と、次の引用にある記述ぐらいだ。

この理論では、チームにおいて人々がどのように行動するか、人々がどれくらい協力して作業を行うと考えられるか、そして各役割の候補者をどのように選択するかを評価する。

2020年に日本語版が発売された同書を読んでから気になりつつも、調べることを後回しにしているうちにすっかり忘れてしまっていた。それが最近、「チームワーク」について色々と調べているうちに再びこのキーワードに出会い、思い出した。

ベルビンチームロール(Belbin Team Roles)は、チーム内での個人の行動特性をクラスタリングしたものだ。その9つのクラスターを、チームのパフォーマンスに効果的に貢献する「チームロール」として定義している。ソフトウェアプロダクトの開発チームで私たちが普段扱うロールと言えば、「スクラムマスター」や「テックリード」「アーキテクト」のように、チーム内での機能によるものだろう。ベルビンチームロールはそれとは違うようだ。

優れたチームワークを実現するには、チームメンバーそれぞれのソフトスキルやパーソナリティを活かした貢献も評価すべきだと、私は常々考えていた。それは実体験からだ。ソフトウェアプロダクトの開発と運用を小さな安定したチームで継続し続けていて気づいたことが、「チームが機能するかどうかは、メンバー個々の技術スキルの高さだけが決定要因ではない」ということだった。メンバーが互いを補い合っていると言えば良いのだろうか。それぞれの個性を活かしてチームに貢献していた。

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

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

私が体験したことはまさにこれだった。このような高いチームワークに再現性を持たせるためにベルビンチームロールは使えるかもしれない。本稿では、ベルビンチームロールを中心に、チームワークについて考えてみたい。

天才神話

チームワークについて考える前に、まず個人に焦点を当ててみる。

先述の書籍『スクラム』では、エール大学のプログラミング授業で出された課題に関する統計について記載がある。そのクラスを取っていたジョエル・スポルスキ(Joel Spolsky)による調査結果では、もっとも速く課題を仕上げた学生は、一番長く時間をかけた学生の10分の1の時間で終わらせていた。これは確か、ジョエル・スポルスキ自身の著書にも書かれていたように記憶している(現在、手元に本が無いので確認できないが)。

書籍『ピープルウエア』には、著者のトム・デマルコ(Tom DeMarco)らが1984年から1986年にかけて行ったプログラミングコンテストに関する記述がある。92社、のべ600人以上が参加したこのコンテストのデータを分析することで、プログラマの生産性にはバラツキがあることが明らかとなった。「コンパイル時のエラーを消し、デバッグに入れる状態までの所要時間」について、ある年のデータを見ると、最優秀者は平均より2.1倍速く、また中央値を挟んで上位半分は下位半分より1.9倍優れていた。他の年でも傾向は同様だったようだ。

トム・デマルコはまた、3つの文献(実際には4つのようだが)の調査結果を分析した結果として、次の3つの経験則を得ている。上記の調査結果は、これに見事に当てはまっている。

  • 最優秀者の測定値は、最低者の約10倍である。
  • 最優秀者の測定値は、平均的プログラマーの約2.5倍である。
  • 上位半分の平均測定値は、下位半分の平均の2倍以上である。

ソフトウェアエンジニアである私たちも、このような個人差は調査に基づかなくとも経験的に知っている。そのため、優れたソフトウェアシステムを生み出しているのは優れたソフトウェアエンジニアだ、と信じてしまいがちだ。書籍『Googleのソフトウェアエンジニアリング』では、これを「天才神話」と呼んでいる。

天才神話は、人間としての我々が、チームの成功を単独の人物/リーダーに帰せずずにはいられないという性向なのである。

身近に優秀なエンジニアがいれば分かると思う。「困難な障害が起きても迅速にシステムを復旧させ、根本的な原因を特定してしまう」「誰も解決できなかったシステムのパフォーマンス問題を粘り強く調査と実験を繰り返して解決してしまう」「皆に先行して設計と実装を進め、どのように開発すれば良いかチームを導く」「技術的な疑問に何だって答えてくれる」など。しかも、これは色んなタイプの天才ではなく、たった1人でこれだけの活躍をしてしまったりするのだ。そんなスーパーエンジニアがチームにいれば、そのたった1人がチームを成功に導いているような錯覚にチームメンバーは陥ってしまうのも仕方がない。

だが違う。同書の言葉を借りれば、「ソフトウェアエンジニアリングとはチームによる取り組み」なのだ。書籍『スクラム』によれば、約3,800のプロジェクトを分析した調査で、1番能力の高いチームが1週間でできた仕事を、1番能力の低いチームは2,000週間かかったと言う。つまりチームのパフォーマンスに2,000倍の開きがあったと言う。この結果はさすがに大きな外れ値に起因するのではないかと感じてしまうが、個人間でのパフォーマンス差の大きさより、チーム間でのパフォーマンス差の方がより大きく、そこにこそ注目すべきだとジェフ・サザーランドは言っているのだ。

※蛇足だが、ソフトウェアエンジニアリングにおける個人の能力は、単純にプログラミングの速さや欠陥の少なさだけでは計測できないと、私は考えている。これについては『Googleのソフトウェアエンジニアリング』でも言及されている「プログラミングとソフトウェアエンジニアリングの3つの違い」と同じ話である。例えばその1つである「時間」としては、「ソフトウェアを保守性のある状態に長期間保つ」という観点となる。書籍『Clean Architecture』でロバート・マーチン(Robert C. Martin)の言うところの「ソフトウェアをソフトに保つ」ということだ。プログラミングコンテストやプログラミング課題に関する調査結果では、この点は評価されていない。

アポロシンドローム

それでは、「天才的な人材ばかりを集めてチームを組めば成功が約束されるのだろうか」という疑問が湧く。ベルビンチームロールの生みの親であるメルディス・ベルビン(R. Merdith Belbin)は、まさにそれを実験していた。参加者が複数のチームに別れて経営手腕を競い合うゲームを実施するにあたり、そのうち1チームは、事前に行われた個人向けの知能テストで高得点であったメンバーのみで構成するようにしたのだ。そして、このチームを「アポロ」と命名した。

もちろん、アポロチームが好成績を収めることが予想されたわけだが、そうはならなかった。最下位となったのだ。その後、数年に渡り同様の実験が繰り返されたが、いずれのアポロチームも結果は散々だった。アポロとして編成された25のチームのうち、優勝したのは3チームのみで、8位以下がほとんどだった。この様子は、メルディス・ベルビンの著書『Management Teams』の2章に詳しく書かれている。

アポロチームの問題は、基本的にチームワークの悪さだ。本来、優秀であるはずの彼らの強みである競争心の強さや、クリティカルシンキングによる分析力・反証力の高さが裏目に出て、チームとしての協働を阻害してしまうのだ。これを「アポロシンドロームApollo syndrome)」と呼ぶ。

メルディス・ベルビンは、責任ある立場に知能面での優秀さが特に求められる産業領域として、コンピュータの応用分野と研究開発分野を挙げている。顧客企業にコンピュータシステムをインストールするチームを対象にした調査では、大半が高いクリティカルシンカーであることが分かった。特に、チームの中で最も賢く創造的なメンバーがプロジェクトマネージャーであった場合に、プロジェクトは最も失敗しやすくなるようだ。しかし、よりマネジメント能力に優れ、創造性に劣るメンバーがプロジェクトのリーダーを務めるようにしたところ、チームの技術力や想像力を損なわずに、有効性を高められた。

つまり、個人の優秀さのみにフォーカスした編成では、チームが上手く機能しないということだろう。

ベルビンチームロール

ソフトウェアプロダクト開発に関する書籍で、チーム編成に関する記述を読んでいて感じるのは、チーム内での役割が、プロセスに直接関連するような機能のみに焦点があてられて定義されていることだ。確かに、開発プロセスやプロジェクトを遂行するという観点ではそういった話題は必要だ。だが、成功するチームを作り上げるには、個々のパーソナリティやソフトスキルから生じる行動特性にも目を向ける必要がある。

メルディス・ベルビンによって定義された9つのチームロールを簡単にまとめたものが次のリストとなる。パーソナリティやソフトスキルに基づいた分類であることがよく分かる。

  • Plant(PL) - 非常に創造的であり、斬新なアイデアで問題を解決することを得意とする。
  • Monitor Evaluator(ME) - 偏見を持たず、ものごとを論理的に観察・判断することに長けているため、あらゆる選択肢を公平に評価できる。
  • Specialist(SP) - 特定の領域・分野に関する深い知識や高いスキルでチームに貢献する。
  • Shaper(SH) - 目標達成に向けて精力的に突き進む。チームが常に動き続け、集中力や勢いを失わないようにするための原動力となる。
  • Implementer(IMP) - アイデアを実行可能で効率的な計画に落とし込み、行動に移す。
  • Completer Finisher(CF) - 間違いが無いかをチェックし、納得がいくまで仕上げようとする完璧主義者であり、高品質を追求する。
  • Co-ordinator(CO) - 多くの場合でチームリーダーであり、目標を明確化してチームをその達成に集中させる。
  • Teamworker(TW) - チームの潤滑油的存在であり、外向的で、メンバーが互いに理解し合えるようサポートすることに長けている。
  • Resource Investigator(RI) - 外交的で好奇心旺盛であり、外部から情報を収集し、チームにアイデアを持ち帰る。

1人のチームメンバーが、このどれか1つのチームロールのみに該当するということではない。多くの場合、支配的なチームロールを1つ持ち、副次的なチームロールを2つから3つほど持っている。前者を特に「プライマリチームロール(primary Team Role)」と呼び、後者を「バックアップチームロール(back-up Team Role)」と呼ぶ。メンバーがどのチームロールに該当するかを判別するには専用の質問に回答する必要があるが、自身も含めチームの誰がどれに当てはまりそうか、何となくイメージはできるだろう。

エンジニアになる学生を対象とした調査

『More Effective Agile』内で、ベルビンチームロールに関して参考文献として挙げられているのは、"Optimal selection of team members according to Belbin’s theory" という論文だ。この論文はメルディス・ベルビン本人によるものではないが、エンジニアになる学生を対象とした調査である点が良い。

調査対象となった学生24名は、AからFまでの6つのプロジェクトチームに4名ずつが所属していた。アンケート回答をもとにした彼らの判定結果は次の表の通りとなる(論文中のTable 3を加工)。チームロールの略称が前述のものとは少々異なる。これについては後述する。

列Membersの MF は、男性か女性かを表している。

列CWからCOまではチームロールを表しているが、ここでは9つではなく8つしかない。それは、学生らがそもそもSpecialistに該当する人物像であったためで、これを除く8つのチームロールのみを扱ったようだ。CWとはCompany Workerであるが、これは上述のImplementer(IMP)のことであり、またCHはChairmanで、これはCo-ordinator(CO)の旧名だ。最後のCOは、Completer Finisher(CF)を指す。この8つのチームロールごとに数値が記載されており、数値が大きいほどそのチームロールに対する強度が高いことを表している。

また、チームロール強度は Very high から Very low まで5段階で評価されており、表内ではそれぞれ次のように表現されている。チームロール強度の値がどのランクに該当するかは、チームロールや性別によって異なる(論文内のTable 2を参照)。

  • Very high - 太字/下線/白背景
  • High - 太字/白背景
  • Medium - 白背景
  • Low - 薄い灰色背景
  • Very low - 濃い灰色背景

列Gradeは、プロジェクトに対する最終評価結果を表す。3.0未満は、ネガティブな評価である。

注目すべきは、2.0 という最低のGradeとなったチームBだろう。全チームで唯一、ネガティブな評価となっている。彼らには、最高強度が Low となったチームロールがあるうえに、最高強度が Very high となったチームロールがひとつも無い。それに対して、他のチームはいずれも全てのチームロールが Medium 以上であり、Very high と評価されたチームロールを2つ以上含んでいる。

もう少し詳細に見ると、チームBで Low だったチームロールは、Completer Finisherだ。書籍『Management Teams』によれば、Completer Finisherの欠如は、「目標に手が届きそうなのに、最後の最後で挫折してしまう原因」となる。チームBには「やり抜く力」や「細部へのこだわり」が弱かったのだ。

それに加え、チームBは、Very high の強度を持つCo-ordinatorがいない唯一のチームでもあった。そのために、チーム内でのリーダーシップが弱く、「目標を明確化してチームをその達成に集中させる」ことができなかったのだと考えられる。逆に、High のCo-ordinatorが3名も存在したことによって、チームとして目指すべき方向が統一できなかったのかもしれない。

チームビルディング

ベルビンチームロールの特徴は、なんと言ってもチームに焦点をあてているという点だろう。個人のみに焦点をあてた自己分析・他己分析ツールとはそこが違う。チームにおいて個人がどう効果的に貢献するのかをロールが表現している。したがって、メンバーのチームロールを診断しても、それをチーム設計やチームビルディングに役立てなければ意味がない。

メルディス・ベルビンは成功するチームとして4つのタイプを挙げている。その中でも実験を通じて最も成功したタイプが「混合チーム(classic mixed team)」だと述べている。特定のチームロールに偏った編成ではなく、チームが多くのロールをカバーし、それぞれのロールが明確に区別され、メンバー間でのロールの重複が少ないチームのことだ。

チームワークとチームパフォーマンスを高めるなら、混合チームの実現を念頭にチームを編成するのが良さそうだ。しかし多くの場合において、必要なチームロールを初めからすべて揃えられるほど人材は潤沢ではないだろう。その制約を受け入れた上で、バランスの取れたチームを作り上げていくしかない。

チームビルディングのプロセスは、概ね次のような流れになるだろう。前提として、新規で編成するチームではなく、既存のチームを想定したものとなっている。

(1) チームの現状を把握する - チームメンバー全員が診断を受け、一人ひとりのプライマリチームロールとバックアップチームロールが何であるかを明らかにする。それらをチーム全体で表にまとめ、チームにどのようなチームロールが揃っているのか、何が欠けているのかを可視化し、チームで共有する。

(2) チームをデザインする - チームによって、より優先的に求められる特性が異なる。クリエイティブなことが求められるチームなのか、より正確性や安全性が求められるチームなのか。そういった特性によって、優先的に必要となるチームロールやその強度も異なり、チームロールのバランスも変わるだろう。チームロールをできるだけ広くカバーすることを意識しつつ、チームが担うプロダクトやプロジェクトの特性に合わせてバランスの取れたチームをデザインする。

(3) チームを実装する - (2)でデザインしたチームのあるべき姿と、(1)で明らかにしたチームの現状を比較する。そのうえで、チームデザイン上必要とされたチームロールそれぞれに対し、メンバーのプライマリロールを参考にひとりずつアサインする。ひとつのチームロールに対し、それをプライマリチームロールに持つメンバーが複数人存在する場合、誰がそのチームロールを担うのかを取り決めることで重複を排除する。逆に、必要なチームロールであるが、それをプライマリチームロールに持つメンバーが存在しない場合、各メンバーのバックアップロールを用いてバランスを試みる。1人が複数のチームロールを担うことは問題ない。このように一人ひとりのメンバーが、チームにとっていずれのチームロールとしての行動が求められているのかを明確にしておく。それがピグマリオン効果(ローゼンタール効果)を生み、自らがアサインされたチームロールに対し、よりふさわしい振る舞いを取るようになることが期待できる。なお、ここで決めたチーム編成は、図や表に記録しておく。

(4) チームを稼働させる - (3)で決定したチーム編成を前提に、チームとしてソフトウェアプロダクト開発を続ける。

(5) チームを評価する - 数イテレーション、あるいは数か月ごとに、チームでの振り返りを行う。(3)での実装はうまく機能したか、(2)のデザインは正しかったのかを評価し、問題や課題を明らかにする。そのうえで、(2)あるいは(3)に戻る。

このように、(2)から(5)を繰り返すことで、フィードバックサイクルを回しながらチームのパフォーマンスを高めていくことになるだろう。もちろん、定期的に(1)に立ち戻るのも良い。チームでの経験を積んでいくことで、メンバーそれぞれのプライマリチームロール/バックアップチームロールの組み合わせに変化が起きることもあり得るからだ。

先の論文 "Optimal selection of team members according to Belbin’s theory" 内で、混合チームとしてのスコアを算出する方法が提案されている。ごくシンプルなものであり、カバーするチームロールの数とその強さの加重合計となっている。チームAからFまでのスコアとGradeとの相関も0.87と高い。まだまだ検証が不十分な算出法であると思うが、これを利用してみるのも良いだろう。なお、論文内の実験で考慮されていないSpecialistの扱いをどうするかの検討が必要となる。

選択的同質性からの脱却

マネージャーや企業には、同質性の高い組織を形成しようとする傾向があるのではないだろうか。自身と似た人材や、既存の組織文化との親和性の高い人材を採用し、育てようとする傾向があるということだ。メルディス・ベルビンはこれを「選択的同質性の原則(principle of elective homogeneity)」や「クローン文化」と呼んでいる。それが必ずしも悪いとは言わないが、そのように形成された組織には問題もある。過度な同質性は、選択可能なチームロールを偏らせてしまうからだ。あまりに均一で同質性の高い組織では、最も成功率が高いとされる混合チームのようなチーム編成の実現が難しくなってしまう。

ソフトウェアエンジニアリングは、チームによる取り組みだ。たった1人の突出した能力だけで大きな成功を得ることは難しい。チームによる成功の大きさは個人による成功に勝る。開発チームが高いチームワークをもって、より優れたパフォーマンスを発揮するためには、チームに多様な個性を混合させる必要がある。スーパーエンジニアが目立ってしまいがちでも、実際のところその貢献は、多様な個性によって補い合うチームワークによってもたらされている。

無論、チームであっても、ハードスキルの高さはエンジニアの能力に最も重要な要素のひとつであることに変わりがない。しかし、チームをよく観察すると、ハードスキルが並程度であってもその人の振る舞いがチームを上手くまわす潤滑油になっている人がいたりする。チームロールで言えば、Teamworkerがそれにあたる。

こういったエンジニアは、評価されずに埋もれがちになる。チームの中での彼らの行動は、明確に定義されたものではないため、周囲に意識されないのだ。「名もなき家事」という言葉にかけて「名もなきエンジニアリング」とでも言えば良いだろうか。

チームロールは、そこに名前を付けたのだと考えると良い。デザインパターンやプラクティスと同様に、名前が付けば語彙として共有でき、その行動を誰もが認識できるようになる。チームロールによって、エンジニアをハードスキル以外でも評価することが可能になるのだ。そうすれば、同質性の高い組織から脱却しやすくなる。ある意味で多様性のある組織に変貌することにも繋がるのだろう。

"Products not Projects"で比較される2つのモデルが開発チームを特徴づける

"Products not Projects" は、効果的なソフトウェアプロダクト組織を設計する重要なコンセプトだ。このコンセプトは、James LewisとMartin Fowlerによって2014年3月に公開された記事 "Microservices" の中で、マイクロサービスアーキテクチャスタイルに共通してみられる9つの特徴の1つとして抽出された。

martinfowler.com

その中心にあるのは、開発チームの組織化に関する2つのモデルの対比だ。すなわち、プロダクトに対してチームを組織化するか、プロジェクトに対して組織化するかという選択肢にある。その選択が、サービス品質チームの思考に大きな違いを生み出す。そして、"Products not Projects" という名の通り、プロダクトモデルがより優れた解なのだと説く。

このコンセプトが適用可能な対象は、マイクロサービスアーキテクチャに限定されるものではないと考えている。ソフトウェアプロダクトをビジネスの中核として展開する組織であれば、アーキテクチャに関わらず試す価値のあるものだろう。

本稿ではこのような前提に基づき、"Products not Projects" について掘り下げてみようと思う。

Model - プロジェクトモデルとプロダクトモデル

プロダクトライフタイムに対するチームのカバレッジとの関係性

原文中に1度だけ出現する "lifetime" という単語。これこそ "Products not Projects" を紐解く鍵となる。プロジェクトモデル(project model)プロダクトモデル(product model)では、ソフトウェアプロダクトのライフタイムに対するカバレッジに大きな違いがある。それぞれのモデルを特徴づける最大の要因こそ、そのカバレッジなのだ。

ソフトウェアプロダクトのライフタイムは、並走する2つの活動によって形作られ持続していく。その2つの活動こそが、開発運用だ。2つのモデルのいずれにしても、開発されたソフトウェアプロダクトは、リリースと共に運用に移る。そしてまた次の開発が始まり、新しいバージョンが完成したらリリースされて運用に移行する。これが何度も繰り返されていく。

[Projects] 短命な開発体制

(前略) the aim is to deliver some piece of software which is then considered to be completed.

目的は、完成したとみなされるいくつかのソフトウェアをデリバリすることである。

プロジェクトモデルでは、1度の開発からリリースまでをプロジェクトと呼び、その遂行に対してチームが組織化される。開発が終えるか、リリースが終えればプロジェクトは終了し、チームは解散する。これが、ソフトウェアプロダクトのライフタイムに対するプロジェクトモデルのカバー範囲だ。1つのプロジェクトを、フェーズと呼ばれるいくつかのリリースに分けることもあるが、終わりがある組織であることには変わりはない。このような体制を「プロジェクトチーム(project team)」と呼ぶ。

プロジェクトの成果物であるソフトウェアプロダクトは、リリースと共に運用組織に引き継がれる。いわゆるdevopsが分離している組織構造だ。運用フェーズに移ったソフトウェアプロダクトに対する小さな変更や不具合対応、緊急対応などのソフトウェア保守業務は、専任の保守メンバーが担うことになる。本番環境にアクセスできるのは、保守メンバーを含めた運用組織だけだ。

次のバージョンに向けた大きな開発は、新たなプロジェクトとしてプロジェクトチームが編成される。つまり、dev自体もプロジェクトごとに顔ぶれが変わるのだ。それは、プロジェクトごとにその性質に適した人材配置が行われることによるものだと言いたいところだが、実態はそうでもない。組織内では常に複数のプロジェクトが並走しているのが通常だろうから、「適した人材」のリソースが空いていることなど奇跡だ。だから、人的なリソース計画の都合によって、プロジェクトへのアサインが決定する。

チームのメンバー数も、プロジェクトの規模に応じて様々だ。

[Products] 安定した開発体制

それに対し、プロダクトモデルとはどのようなものなのか。次の引用文は、原文中でプロダクトモデルに関して述べられている箇所だ。

Microservice proponents tend to avoid this model, preferring instead the notion that a team should own a product over its full lifetime.

マイクロサービス推進者たちはこのモデル(=プロジェクトモデル)を避ける傾向にあり、プロダクトのライフタイムすべてに渡ってチームがプロダクトを所有する考え方を好む。

これが、ソフトウェアプロダクトのライフタイムに対するプロダクトモデルのカバー範囲だ。

プロダクトモデルでは、ソフトウェアプロダクトのライフサイクル全てを通し、一貫してチームが責任を負う。チームはソフトウェアプロダクト自体が終わりを迎えることが無い限り解散することがなく、存続し続けることになる。このような体制を「プロダクトチーム(product team)」と呼ぶ。

プロダクトチームは、開発だけでなく運用も担う。devとopsが分離していない。もちろん、より低レイヤーに位置するインフラに関することは、専任のインフラ運用組織が担当する。しかし、本番環境上でソフトウェアプロダクトを動作させ、安定稼働させるのは、プロダクトチームの役割だ。そのために、インフラ運用組織が提供するセルフサービス化されたプラットフォームを活用し、リリースに必要な環境の構築、そこへのアプリケーションのデプロイをはじめ、運用、保守のすべてを行う。

このような運用・保守業務と並行し、プロダクトチームは次のバージョンのリリースに向けた開発も進める。そこで活躍するのはもちろん前回の開発と同じメンバーだ。ソフトウェアプロダクトの長いライフタイムの中でプロダクトチーム内の顔ぶれも少しずつかわっていくかもしれないが、基本的にメンバー構成が一度に大きく変わるようなことはなく、安定している。

その人数も、人が親密な関係を築ける認知的な上限であるダンバー数から、7人前後程度の少人数が良いとされている。この数字は、Jeff Bezosの「2枚のピザ」ルールにも当てはまる。

Knowledges & Skills - ドメイン知識と技術スキルの方向性の違い

フィードバックループとの関係性

"Products not Projects" というコンセプトは、Amazonの "you build, you run it" という考え方をヒントにしたものだ。それは、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は違う。開発した人たちが運用も行う。この考えにより開発者は、ソフトウェアの日々の運用に接することになる。顧客とのこのフィードバックループはサービス品質の改善に不可欠だ。

Vogelsが「フィードバックループはサービス品質の改善に不可欠」と話しているように、本番環境で稼働し、顧客に使われるソフトウェアプロダクトからのフィードバックは、サービス品質と強く関係している。チームの実践的な技術スキルを高め、ビジネス、ユーザーに関するドメイン知識を深めさせるからだ。

[Projects] 様々なドメインに対する広い知識と技術面での即応性

Vogelsに対するインタビュー記事からの引用文にある「従来のモデル(traditional model)」とは、プロジェクトモデルのことだ。このモデルでは、本番稼働するソフトウェアプロダクトに対する顧客や保守・運用面からのフィードバックをチームが直接受け取ることができない。リリースすれば、プロジェクトチームは解散してしまうからだ。

プロジェクトモデルであっても、顧客やビジネス担当からの要求などで断続的に新たなプロジェクトが立ち上がる。それらが技術面での改善に向けられたものであることは稀だ。多くは、機能面での追加や改善だ。これによって顧客面でのサービス品質は断続的に改善されていくことになるが、それを実行するチームは要望に応えているだけだ。

その顔ぶれも毎回異なる。例え同じメンバーであったとしても、彼らはプロジェクトとプロジェクトの合間に他のソフトウェア開発プロジェクトに従事している。関わるソフトウェアシステムはそれぞれドメインも違えば抱える課題も異なる。そこで使われる技術も異なるだろう。プロジェクトチームに携わる開発者に求められるのは、様々なドメインに対する広い知識や、技術面での即応性だろう。

[Products] 担当するドメインに対する深い知識と実践的な技術スキル

プロダクトモデルはまさに「開発した人たちが運用も行う(You build it, you run it)」の実践に他ならない。安定したプロダクトチームが開発も運用も担うため、本番稼働するソフトウェアプロダクトからのフィードバックループを形成できる。そこで得られた知識をもってサービス品質を継続的に改善することが可能なのだ。

よく言われるように、開発者が自分たちで保守を担わなければ、その成果物たるソフトウェアに優れた保守性(maintainability)を期待することはできない。開発者は、理解容易性(understandability)変更容易性(modifiability)の低いコードで苦しんでこそ保守性の高いコードを書こうとするようになり、そういうコードを書けるようになる。これもフィードバックループだ。

運用におけるログの大切さもそうだ。適切なログが吐かれていないばかりに緊急対応で苦労してこそ、ログ設計について考えるようになる。そして、システムを安定稼働させるにはどうすれば良いか、問題発生時にシステムを素早く復旧させるにはどうすれば良いか悩み、日々の運用の中で実践を続ける。

これらはいずれも技術面でのフィードバックによって積み重ねた知識と、身につけた実践的技術スキルによって改善されていくサービス品質である。一方でビジネスやユーザー体験に関するサービス品質の向上については、顧客からのフィードバックが重要であることは明らかだ。

ビジネス向け、コンシューマ向けのいずれであるかに関わらず、ソフトウェアプロダクトとは顧客課題、つまりはビジネスやユーザーが抱える何らかの課題に対するソリューションとして作りだされる。ソリューション足り得るかどうかは、実際に顧客がそれらを採用し、利用してくれるかどうか、その結果がどうであったかをみなければ分からない。そこから得られた顧客の声やアクセスログ等は、サービス品質向上に欠かせないフィードバックとなる。

ビジネスやユーザー、技術のいずれであれ、プロダクトモデルであればそれらのフィードバックをチームが受け止めることができる。そこから得た知識や経験が、プロセスやソフトウェアプロダクトの改善につながる。そしてまたフィードバックを得る。このように、プロダクトモデルは強力なフィードバックループを形成でき、プロダクトチームの実践的な技術スキルを高め、担当ドメインの知識を徐々に深めながら、ソフトウェアプロダクトを継続的に改善していくモデルなのだ。

Team Mentality - プロジェクト思考とプロダクト思考

[Projects] 納期・予算・要件の厳守

プロジェクトモデルのゴールは、約束した期日までに、約束した予算で、約束したソフトウェアをリリースすることだ。リリースされたアウトプットが顧客課題のソリューション足り得るかどうかは、最初に決めることであり、ソフトウェアが完成してから変更するものではない。約束通りに作り上げたソフトウェアが結果として十分なソリューションとならず、ビジネスやユーザーにとっての価値を生まなくても、それは必ずしもプロジェクトの責任とは言い切れない。彼らがコミットするのはあくまでも「約束した期日までに、約束した予算で、約束したソフトウェアをリリースする」ことだ。これを「プロジェクト思考(project mentality)」と言う。

もちろん、プロジェクトモデルであっても顧客課題のソリューション足り得ることを目指す。プロジェクトの初期段階において、分析と設計に時間をかけて要件を決めることでそれを担保するのだ。しかし、そうして机上で定義された要件に基づいて完成したソフトウェアプロダクトが、顧客が真に求めるものとなるかは怪しいところだ。Chaos Report 2015によれば、「納期、予算、要件(OnTime, OnBudget, and OnTarget)」という解像度で「成功(successful)」と判断されたプロジェクトは36%であるが、「納期、予算、満足(OnTime, OnBudget, with a satisfactory result)」だと7ポイント低下して29%となっている。

また、分析と設計に多大な時間をかけることは、リリースまでのリードタイムが長くなることも意味する。それに、このアプローチは網羅的な要件と仕様を生み出しやすく、開発スコープを肥大化させるのではないだろうか。プロジェクトサイズが大きいほどプロジェクトの成功率が下がることを、Chaos Reportの調査結果が示している点も見逃せない。サイズがSmallだと「成功(successful)」が61%であることに対し、Grandだと6%しかない。

多くのソフトウェアプロダクト開発が扱う問題領域は、クネビンフレームワーク(Cynefin framework)で言うところの「探索 - 把握 - 対応(probe - sense - respond)」の繰り返しを必要とする複雑(Complex)な領域に位置するのではないだろうか。プロジェクトモデルでのアプローチでは、この問題領域を「把握 - 分析 - 対応(sense - analyze - respond)」で解決する煩雑(Complicated)な領域として扱っている。ソフトウェアプロダクト開発というものを、不確実性は高いが、予測可能性が高く、分析によって問題や解決策が明らかになるものだと想定しているのかもしれない。

mtx2s.hatenablog.com

[Products] 継続的なソリューションの提供

プロダクトモデルは、チームの責任範囲がソフトウェアプロダクトのライフタイム全てに及ぶ。プロダクトチームは、その長い時間の流れの中で、日々の運用や保守を続けなければならない。その間、彼らは顧客や技術面でのフィードバックにさらされ続けることになる。継続的に顧客課題や技術面での問題に直面し、それらを解決するために開発を繰り返す。ソフトウェアプロダクトをより良いものへと漸進的に進化させ続けるのだ。プロダクトモデルにおけるチームは、ビジネスやユーザーにとっての価値に対してコミットしているということだ。これこそが「プロダクト思考(product mentality)」であり、それは次の引用に集約されている。

The product mentality, ties in with the linkage to business capabilities. Rather than looking at the software as a set of functionality to be completed, there is an on-going relationship where the question is how can software assist its users to enhance the business capability.

プロダクト思考は、ビジネス能力との結びつきに紐づく。作り上げようとする機能の集まりとしてソフトウェアを見るのではなく、ユーザーのビジネス能力を向上させるためにソフトウェアがどのように支援できるかという問題に対して、継続的な関係が存在する。

プロダクトモデルでは、プロジェクトモデルのように分析と設計に多くの時間をかけて網羅的な要件と仕様を定義する必要がない。それよりも、実際にリリースしてみる方が効率が良い。リリース後のフィードバックを経て更に改善することを前提に開発できるからだ。ソフトウェアプロダクト開発というものを、不確実性が高いだけでなく、予測可能性が低い対象としてみなしているのだ。つまり、そこで扱われる問題領域を複雑(Complex)な領域と位置づけ、反復的な「探索 - 把握 - 対応(probe - sense - respond)」というやり方を実践している。

このような開発スタイルであるから、プロダクトモデルでの1度の開発規模はプロジェクトモデルに比べて相対的に小さく、リリース頻度も高い。先述したChaos Reportの調査結果にあるように、開発規模が小さい(small)なら、高い成功率も期待できるのではないだろうか。

プロダクトモデル実践における落とし穴

このようにして2つのモデルを比較してみると、プロダクトモデルのより優れた面が理解できる。プロダクトモデルを実践すれば、頭を悩ます様々な問題が解決し、成功に向けてものごとが上手く動き出すように感じてしまうかもしれない。そうしてプロダクトモデルを始めてみると、しばらくして現実はそう甘くないと痛感することになるだろう。そこには様々な落とし穴があるからだ。

まず、チームが運用を担うということは、運用負荷が高いほど開発時間が削られてしまうということでもある。運用負荷を下げるためには、それを実現するための仕組みが必要であり、運用の自動化に向けた開発といった取り組みを進めなければならない。

構築やデプロイの自動化をはじめ、ビルドパイプラインの整備、データなどのバックアップ処理、ログ収集・可視化の仕組み、モニタリング環境の整備など、運用負荷を下げるためにやるべきことは、これらも含めて他にも色々と存在する。プロダクトチームは、専任のインフラ運用組織とも協力(DevOps)して仕組みを作り上げ、維持することになるだろう。

しかしプロダクトチームは、短期間で繰り返されるリリースの中で、開発業務に追われ、運用負荷を下げるためのタスクに取り組むことがなかなかできずにいることが多い。そのために、運用業務にも時間が取られ、開発業務に必要な時間がますます逼迫して、運用負荷を下げる試みに手が出ないという悪循環に陥ってしまう。時間の無い中での開発は、プロダクトコードの品質にも悪影響があるだろう。

プロダクトモデルはサービス品質を高めるはずだが、このような状況は逆にサービス品質の低下を招きかねない。すると、ソフトウェアシステムが頻繁にトラブルを起こし、その緊急対応に追われるようになる。開発者はその都度、仕掛中の開発の手を止めることになり、開発時間が削られるだけでなく、開発に集中することすらままならなくなる。

こういった事態を回避するヒントは、SRE(Site Reliability Engineering)の「50%ルール」だろう。運用業務に費やす時間を業務時間全体の50%以下にし、それを超過した場合は運用負荷を下げるタスクに費やすというものだ。プロダクトモデルにおけるチームでも、運用業務に費やす時間を計測し、20%といった閾値を設けると良いのではないだろうか。

プロダクトモデルを実践する上での落とし穴は他にもまだまだ存在する。その代表的な例を挙げる。

  • 属人化による業務負荷の偏り:トラブル対応や問い合わせ対応といった運用業務は、特定個人に集中しやすい。それが、チーム内の業務負荷を偏らせる。さらに、この状況が長く続くと属人化を生み、業務負荷の平準化を困難にするとともにリスクにもなる。退職などでチームがその個人に頼ることができない状況に陥ると、途端に業務がまわらなくなるからだ。
  • 価値観の固定化:流動性の低い安定したチームは、チーム内での価値観が固定化しやすく、新しい価値を生み出しにくくなる体制でもある。チームがそのような状態にあると、ソフトウェアプロダクトもチーム自身も進化の歩みが鈍化し、イノベーションを期待することなどできなくなる。安定したチームが良いと言っても、ある程度の流動性は必要だろう。
  • 悪いコンフォートゾーン:長いあいだ同じ顔ぶれで仕事を続けると、相互信頼の醸成と共に、チーム内に甘えや妥協がはびこるようになる。私はこれを「悪いコンフォートゾーン」や「勘違いの心理的安全性」と呼んでいる。チームが成長するためには、コンフォートゾーンから抜け出し、勇気を持ってラーニングゾーンで挑戦を続けなければならない。
  • プロダクト思考への不達:開発業務に追われている限り、チームがプロダクト思考を獲得することはない。約束した期日までに、約束した予算で、約束したソフトウェアをリリースすることにコミットするプロジェクト思考にとどまってしまう。なんとかリリースしたらそこで終わり。そのアウトプットのことは忘れ、次のリリースに集中する。だからフィードバックループが形成されないのだ。この状態に陥ることを回避することや、既に陥ってしまったチームの問題を解決することは最も難しい。

まとめ

プロダクトモデルは、ソフトウェアプロダクトのライフサイクル全てを通し、一貫してチームが責任を負う。その長い期間の中で、少人数で安定したプロダクトチームがその運用と繰り返される開発を担う。その体制とプロセスがフィードバックループを形成し、チームのドメイン知識を深め、実践的な技術スキルを高めながら、サービス品質の継続的な改善を可能にする。チームはソフトウェアプロダクト開発が扱う問題領域を複雑な領域と位置付け、不確実性が高いだけでなく、予測可能性が低い対象としてみなしている。これら全てがチームをプロダクト思考に導いていき、チームとソフトウェアプロダクトを、改善を超えた進化へと突き進める。これが "Products not Projects" というコンセプトだ。

このコンセプトにおけるプロダクトモデルは、プロダクト思考を伴ってこそビジネスの成功を引き寄せる。体制やプロセスを真似たところで、チームがプロダクト思考を獲得するわけではない。そこには様々な落とし穴がある。プロダクトモデルを真に実践するためには、チーム自身や彼らをサポートするマネージャーが強い意思を持ってプロダクト思考に近づけようとする努力が必要なのだ。その難易度は高いが、到達したその見返りは想像以上に大きいだろう。

mtx2s.hatenablog.com

note.com

コンウェイの法則と、そこで提示された2つの組織課題

ソフトウェアエンジニアリング関連の書籍を読んでいると、「コンウェイの法則(Conway's law)」によく出会う。その引用元は、1968年4月に発表されたメルヴィン・コンウェイ(Melvin E. Conway)の論文 "How do committees invent?" で、例の有名な一文は結論(conclusion)に書かれている。

(前略) organizations which design systems (in the broad sense used here) are constrained to produce designs which are copies of the communication structures of these organizations.

(広義での)システムを設計する組織は、自らのコミュニケーション構造を真似た設計を生み出すという制約を受ける。

論文の内容はこの一文に集約されるのであるが、それに付随して2つの重要な組織課題を提示している。それは、「コミュニケーションの効率化」と「生産性向上を人数規模に頼らないマネジメント哲学の構築」だ。本稿ではこの2つの課題を中心に、コンウェイの法則について深堀りする。

コンウェイの法則とは

まず、先述した2つの課題の根幹にあるのは、システムが、それを設計する組織の準同型写像(homomorphism)であるという点だ。これこそコンウェイの法則そのものだ。課題について考察する前に、この点について理解を深めておきたい。

システムは、基本的に構造化されているものだ。それは、相互に接続されたより小さな要素からなり、その要素もまた、さらに小さな要素から構成されている。ソフトウェアシステムで言えば、この要素とは、サービスやコンポーネント、モジュールであり、最終的にはクラスやメソッドといったレベルの詳細度で構成される。これらはインタフェースを介して接続されている。

そのようなシステムを設計する組織もまた、構造化されている。組織は複数のグループに分かれており、グループは更に小さなグループや、さらには複数のメンバーで構成されている。ここではグループのことをチームと呼ぼう。システムでは要素がインタフェースで接続されていたわけであるが、このチーム間、あるいはチーム内を接続するのは、コミュニケーションパスである。

コンウェイの論文では、システムと組織が持つこのような構造が一致することを指摘している。

システム構造内で互いに接続された要素xとyがあれば、組織構造内にもそれを設計した要素XとYがインタフェース仕様を合意しているはずだ。そこにはコミュニケーションパスが存在する。逆に、システム要素xとyの間に通信が無いならば、組織要素XとYの間にもコミュニケーションパスが存在しない。

ここで、組織要素がそれぞれ複数のシステム要素を設計したなら、組織構造は、システム構造を折りたたんだものになる。このような関係を、準同型写像と呼ぶ。下図は、その説明に使われた論文内のものだ。

さて、人数規模にもよるが、組織内のそれぞれのチームやメンバーが、他の全てのチームやメンバーに対して偏りなくコミュニケーションパスを持つことはまず不可能だろう。コミュニケーションパスが存在しなければ、互いが担当するシステム要素を接続することはできない(あるいは、積極的には接続しようとはしないかもしれない)。したがって、組織構造によって、採用できない設計があり得ることになる。論文内で結論(conclusion)に記載されたコンウェイの法則と呼ばれる一文に、"constrain" という単語が用いられているのは、設計において選択可能な選択肢に対するこのような「制約」が存在するからではないだろうか。

課題1:コミュニケーションの効率化

論文内の印象的な提言として、次の一文がある。

Even in a moderately small organization it becomes necessary to restrict communication in order that people can get some "work" done.

適度に小規模な組織であっても、人々が仕事をやり遂げるには、コミュニケーションを制限する必要がある。

これは、どういうことだろうか。

よく言われるように、コミュニケーションコストは、人数に対する2乗のオーダーで増加する。n人の組織では、1人あたり最大 n-1 個のコミュニケーションパスを持つことになる。自分以外の全員とパスを持つという前提だ。そうすると、組織全体のパス総数の最大は、n*(n-1)/2 となる。2で割っているのは、パスが重複するからだ。

一方で、人数に対する組織の純粋な処理能力の伸びは線形だ。グラフで描くと分かるように、人数が増えるにつれ線形に伸びる処理能力に対し、コミュニケーションコストは放物線を描く。

組織の処理能力の一部は、このコミュニケーションコストによって消費されることを忘れてはいけない。2つの線に挟まれた距離が、組織の実質的な処理能力なのだ。したがって、増員による組織の処理能力向上という目論見はどこかの時点で破綻してしまう。コミュニケーションを制限する必要性は、このようなコミュニケーションコストを抑制する目的によって生じるのだ。

これらのことから、コミュニケーション効率を踏まえた上での組織設計が重要なのは明らかだ。下記は、その点について論文内で言及された箇所の引用だ。

Research which leads to techniques permitting more efficient communication among designers will play an extremely important role in the technology of system management.

設計者間のコミュニケーションをより効率的にする技術を研究することは、システムマネジメント技術において、非常に重要な役割を果たす。

コミュニケーションが非効率であるほどコスト放物線が描くカーブは極端になる。それは、組織の人数規模に対し、コミュニケーション構造の崩壊をより早めることを示している。そして、組織のこのようなコミュニケーション構造の崩壊は、システム構造の崩壊につながるのだ。

課題2:生産性向上を人数規模に頼らないマネジメント哲学の構築

コンウェイの論文は、半世紀以上も前に発表されたものだ。前提などに古さを感じる箇所もあるが、それでも今なお引用され続けることからも分かる通り、価値ある文書だ。そこでは、マネジメントの問題についても触れられている。それは現在でも見かける問題ではないか。

その問題とは、プロジェクトにおいて、可能な限りすべての人的リソースを投入することなくスケジュールに間に合わなかった場合、マネジメント上の問題としてマネージャーが非難を受ける可能性があるというものだ。プロジェクトの人的規模を拡大することが適切な解決策ではないとしても、そのような不合理にさらされたくないと願うマネージャーは、人をより多く投入するという選択を行ってしまう。扱うシステムの規模が大きいほど、発生しやすい問題だと言える。

このような不合理が生じる背景は、まさに『人月の神話』にあるのだろう。5人で10か月かけて完成させる仕事を、20人で2.5か月に圧縮して完成させようと考えてしまう罠だ。コストという観点では、どちらもともに50人月だ。しかし、人と月とは交換可能ではない。設計における個々のタスクは独立しておらず、多くのタスクが互いに従属関係を持つ。それらがスケジュール上にクリティカルパスを形成する。クリティカルパスは、人を増やしても短くならない。単純に人数を増やしたところで仕事が早く終わるわけではないのだ。

そして、この設計労力に対する人的リソースの過大配分には、「パーキンソンの法則(Parkinson’s law)」も関係している。利用可能な人的リソースを使い切るまでプロジェクトの人数規模は膨張する傾向があるのだ。プロジェクトに投入可能な人員を多く抱えるマネージャーほど、この罠に陥りやすい。

そもそも、労働力として同じ50人月の価値の組織であっても、そこから生み出されるシステムの価値は同一とはならない。コミュニケーション構造が違えば、生み出されるシステム構造は準同型写像によって違いが生じるからだ。そして、無理に人手を増やしすぎた結果は、課題1で述べた通りだ。

このような問題に対し、論文では組織のスリム化と柔軟性の重要性を説いた上で、次のように述べている。

There is need for a philosophy of system design management which is not based on the assumption that adding manpower simply adds to productivity.

「人手を増やせば単純に生産性が上がる」という思い込みに基づかないシステム設計マネジメントの哲学が必要だ。

適切なシステム構造は価値である

コンウェイの法則が、これほどまでに様々な書籍やドキュメントで引用される背景には、システムの構造というものに関心を持つ人や組織が多いからではないだろうか。システムを扱う組織にとって、適切なシステム構造は価値あるものなのだ。フィリップ・クルーシュテン(Philippe Kruchten)は、それを「見えない(invisible)が、ポジティブな価値(positive valueがあるもの」と呼んだ。そしてその逆となるものを「技術的負債(technical debt)」として仕分けした。

技術的負債となるシステム構造の崩壊は、変更容易性を悪化し、ソフトウェアに対して顧客に要求される変更を実現困難にする。つまり、左象限の「見える価値(visible value」を受け付けなくなる。そうなったソフトウェアは、もはや "ソフト" ではない。変更できないソフトウェアは、ソフトウェアとしての価値、存在意義が失われてしまっている。

システム構造は、組織のコミュニケーション構造に強い影響を受ける。忘れてはならないのは、ソフトウェアプロダクト開発組織におけるコミュニケーションパスの有無やそのパスの太さは、それぞれが担当するコンポーネントの依存関係に強く影響されるということだ。つまり、アーキテクチャを想定せずに設計された組織のコミュニケーション構造は、不適切で非効率なものとなる。そうであるならば、効率的なコミュニケーション構造の追求のために、組織設計者にはアーキテクトとしての素養が不可欠だと言えるのではないだろうか。

マイクロソフトの調査にみるコードのオーナーシップと品質の関係

ひとつのソフトウェアコンポーネントが多くの開発者によって変更されると、品質に悪い影響を与えると経験的に感じている。設計に一貫性が失われることや、知識の浅い状態で変更することによるバグ混入の可能性が高まるからだ。

2011年9月に公開されたマイクロソフト社の調査結果、"Don’t Touch My Code! Examining the Effects of Ownership on Software Quality" は、この「コードのオーナーシップはソフトウェアの品質を左右する」という経験則を裏付けるものだった。全体のコミット数のうち5%未満の貢献にとどまる開発者が多いコンポーネントは、リリース前後における故障が増加するというものだ。

本稿では、このマイクロソフトによる調査結果を紹介し、それを踏まえた上で、ソフトウェアプロダクトの品質悪化を抑えるための組織やプロセス、アーキテクチャについて簡単に考えてみる。

用語:コンポーネントのコントリビューターとオーナーシップ

さきに用語についてであるが、特に重要なものは次の4つだ。

  • コントリビューター(Contributor)
  • オーナーシップ率(Proportion of Ownership)
  • メジャーコントリビューター(Major Contributor)
  • マイナーコントリビューター(Minor Contributor)

この調査では、コンポーネントを変更/コミットした人を、そのコンポーネントに対する「コントリビューター」と呼んでいる。

コンポーネントXに対するコントリビューターAのコミット数が、X全体のコミット数の何パーセントにあたるかを表すメトリクスは、「オーナーシップ率」あるいは単に「オーナーシップ(ownership)」と呼ぶ。

オーナーシップが5%以上のコントリビューターを特に「メジャーコントリビューター」と呼び、5%未満では「マイナーコントリビューター」と呼んで区別している。

結果:マイナーコントリビューター数が故障数に大きな影響を与える

調査では、Windows VistaWindows 7という、2つの大規模ソフトウェアプロジェクトを対象としている。下の表は、それらのリリース前後の故障と各メトリクスとの相関分析結果となる。表内の数値が相関係数で、1に近いほど両者の間に強い正の相関があり、一方が大きくなると、もう一方も大きくなる関係を表す。また、-1に近いほど強い負の相関があり、一方が大きくなると、もう一方は小さくなる。

Ownership Metrics に分類されている TOTAL, MINOR, MAJOR, OWNERSHIP はそれぞれ、コントリビューター数、マイナーコントリビューター数、メジャーコントリビューター数、オーナーシップのことだ。OWNERSHIP には、それぞれのコンポーネントの最大コミット数を持つコントリビューターのオーナーシップが使われている。Classic Metrics に分類されている Size, Churn, Complexity は、静的コード解析でおなじみのコード品質に関するメトリクスだ。

Windows Vistaの結果を見ると、Ownership Metrics のうち、MAJOR を除いたいずれのメトリクスも、リリース前後の故障と強い相関関係がある。トータルのコントリビューター数やマイナーコントリビューター数が多いコンポーネントは故障が多く、オーナーシップが高いコンポーネントは故障が少ない傾向が強い。これは、概ね期待通りの結果だろう。Windows 7のリリース前も同様の傾向だ(リリース後の相関係数が小さくなっているのは、この時点ではリリース後の故障に関する報告が集まってなかったからのようだ)。

ただし、この結果だけで結論は出せない。コード品質との間でも強い相関を示しているからだ。例えば、Windows Vistaでは、TOTAL とリリース前の故障との相関係数が 0.84 となっているが、Size の相関係数も 0.75 と高い。コントリビューター数とサイズの間には関係があるだろうことは想像がつく。つまり、Ownership Metrics の各相関係数は、Classic Metrics に影響を受けた可能性があるということだ。

そこで、故障を目的変数とする多重線形回帰分析を行い、Classic Metrics のみを説明変数に含むモデルと、そこに Ownership Metrics の各種メトリクスを順に加えていったモデルを比較した結果が次の表となる。表内の数値は、故障数の分散のどの程度がメトリクスによって説明されるかを示している。

Base が、Classic Metrics のみを含むモデルだ。このモデルでは、Windows Vistaのリリース前の故障を 26% 説明できる。Base+TOTAL は、Base に対してコントリビューター数を説明変数に加えたモデルで、Windows Vistaのリリース前が 40% となり、Base と比較して 14% 改善していることが分かる。同様に、Base+MINOR のリリース前を見ると 46% であり、Base より 20% 改善し、Base+TOTAL より 6% 高い。つまり、コード品質を考慮してもなお、マイナーコントリビューター数がWindows Vistaのリリース前故障数に強い影響を与えていることが分かる。その影響の度合いは、トータルのコントリビューター数を使った故障数の予測より 6% 高い。

MAJOR や OWNERSHIP を追加したモデルも、Base+MINOR よりわずかな改善を示している。しかし表には記載されていないが、Base+MAJOR や、Base+OWNERSHIP に対して MINOR を追加したモデルは、追加前のモデルより大きな効果を示したようだ。つまり、メジャーコントリビューター数やオーナーシップより、マイナーコントリビューター数の方が、Windows Vistaのリリース前の故障数をより説明できるということだろう。

これらの傾向は、Windows 7のリリース後の故障を除けば、いずれもWindows Vistaのリリース前の故障と同じような傾向を示している。

以上のことから、マイナーコントリビューター数やトータルのコントリビューター数は、リリース前後の故障数に大きな影響を与えると言える。メジャーコントリビューター数や、オーナーシップもリリース前後の故障に影響を与えるが、その度合はマイナーコントリビューターやトータルと比べるとかなり小さい。

故障数を抑えるために何ができるのか?

どうすれば、マイナーコントリビューター数やトータルのコントリビューター数を低く抑えられるだろうか。

まず考えられるのは、ひとつひとつのコンポーネントのサイズを小さくしておくことだろう。サイズが大きいと、コードの変更に関わる開発者の人数も増える。そもそも、サイズが大きいという点からも品質が悪化する恐れがある。

コンポーネント同士の結合度を下げることも必要だ。マイクロソフトの調査結果では、あるコンポーネントのメジャーコントリビューターが、そのコンポーネントと依存関係にある別のコンポーネントのマイナーコントリビューターになることも明らかにしている。結合度を下げることができれば、コンポーネントをまたいだ変更の必要性も下げられるということだ。

また、結合度の強いコンポーネント同士については、同一の開発者がオーナーとなるよう組み合わせるのも良いだろう。そうすれば、オーナーとなった開発者は、どちらのコンポーネントにおいてもメジャーコントリビューターになるはずだ。

チームによるコンポーネントのオーナーシップ

このように整理していくと、安定した少人数の開発チームが特定のコンポーネントを所有するやり方が合理的であることがよく分かる。そうすれば、コンポーネントの変更に関わる開発者の人数も少なくなり、その顔ぶれも基本的に限定される。担当するコンポーネントに関する知識も深まるだろう。マーティン・ファウラー(Martin Fowler)の言葉を借りると、チーム内のメンバー同士は「コードの共同所有(collective code ownership)」であり、それぞれのチームとしては「強いコードの所有(strong code ownership)」だと言える。前者はエクストリーム・プログラミングのプラクティス「コードの共有(shared code)」の実践でもある。

フィーチャー開発において同時に変更されることが多いコンポーネントは、なるべく一括して同じチームが所有する。これなら、依存関係によって発生するようなコンポーネントをまたいだ変更も、チーム内で行える。アーキテクチャによっては、コンポーネントテストやデプロイの容易性が高まり、チーム間でのデリバリー衝突も避けやすくなるだろう。

こうしてひとつのチームに集められた複数のコンポーネントは、ビジネス機能を境界としたコンテキストを形成するはずだ。あるいは、コンテキストは異なっていても、ドメイン間の結合度が高いコンポーネントが集まる。サム・ニューマン(Sam Newman)も言うように、機能の変更とは、ビジネス機能の変更を指すからだ。もし、ビジネス機能ではなく、技術視点でコンポーネントを集めてしまうと、チームの所有権をまたいだコードの変更が頻発するようになる。これは、コストがかかる上にマイナーコントリビューターを生み出しやすい構造だ。

しかし時には、チームが抱えるバックログの実現のために、自チームが所有するコンポーネントのみならず、他チームが所有するコンポーネントを変更するケースも発生し得る。他チームのコンポーネントを変更する開発者は、マイナーコントリビューターだ。こういった場合、コンポーネントを所有する側のチームが、マイナーコントリビューターによって変更されたコードをしっかりとレビューする必要がある。これについての詳細は、過去の記事『開発組織を分散モノリスにしないチーム分割と協働のデザイン - mtx2s’s blog』の中で、「コントリビューター/コミッターモデルでのフィーチャー開発と協働」として書いた。

mtx2s.hatenablog.com

あまりにコンポーネントの数が多いと、どうしてもオーナーシップが低くなってしまうコンポーネントもでてくる。調査結果でも提言があるように、そういったコンポーネントを変更するときは、QAによる検証の優先度を上げるといった工夫も必要になるだろう。

最後に

はっきり言って、この調査で得られた結論に大きな意外性はなかった。しかし、経験的に理解していたことが、統計的に明らかになったという点は大きいと言えるだろう。

マイクロソフトの調査は、多くの企業の多くのソフトウェアプロジェクトを対象としたものではなく、Windos VistaWindows 7という、自社のソフトウェアプロジェクトに限定されていた。したがって、調査結果をそのまま様々なプロジェクトに一般化できるとは限らないだろう。しかし少なくとも、比較的多くの人が関わるソフトウェアプロダクト開発を抱える組織では、この結果を上手く活用できると考えている。