読書メモ。
- Google のソフトウェアエンジニアリング
- https://www.oreilly.co.jp/books/9784873119656/
Google の現役ソフトウェアエンジニアたちが、超大規模ソフトウェアの開発と保守を長期的に支えてきた Google 社内の多様なベストプラクティスを、文化、プロセス、ツールの側面からこの一冊に凝縮。時間と変化、規模と成長、トレードオフとコストという 3 つの基本原理に沿って、コードを持続可能にする方法論を紐解きます。「謙虚、尊敬、信頼」、心理的安全性、ダイバーシティとインクルージョンなど公正を重んじる文化から、コードレビューやテスト構成法など人間の行動を規定するプロセス、継続的インテグレーションや大規模変更システムなど変化への対応を支援する自動化ツールの基盤技術まで、Google が試行錯誤を経て獲得した教訓を余すところなく紹介しています。経済学、心理学、マネジメント論などを背景にした人間への深い洞察をふまえ、データ駆動かつトレードオフから導かれる、定量的かつ定性的な決定プロセスも解説。Google の成長力の源泉を理解でき、得られる知見は、学生から組織の意思決定者、小規模スタートアップからデジタルトランスフォーメーション(DX)を目指す大企業まで、幅広く活用できます。
目次 #
- 第 1 部:主題
- 1 章:ソフトウェアエンジニアリングとは何か
- 第 2 部:文化
- 2 章:チームでうまく仕事をするには
- 3 章:知識共有
- 4 章:公正のためのエンジニアリング
- 5 章:チームリーダー入門
- 6 章:スケールするリーダー
- 7 章:エンジニアリング生産性の計測
- 第 3 部:プロセス
- 8 章:スタイルガイドとルール
- 9 章:コードレビュー
- 10 章:ドキュメンテーション
- 11 章:テスト概観
- 12 章:ユニットテスト
- 13 章:テストダブル
- 14 章:大規模テスト
- 15 章:廃止
- 第 4 部:ツール
- 16 章:バージョンコントロールとブランチ管理
- 17 章:Code Search
- 18 章:ビルドシステムとビルド哲学
- 19 章:Google のコードレビューツール Critique
- 20 章:静的解析
- 21 章:依存関係管理
- 22 章:大規模変更
- 23 章:継続的インテグレーション
- 24 章:継続的デリバリー
- 25 章:サービスとしてのコンピュート
- 第 5 部:結論
1 章:ソフトウェアエンジニアリングとは何か #
我々の見るところ、プログラミングとソフトウェアエンジニアリングの決定的な違いは3つある。時間、スケール、そして作用しているトレードオフだ。ソフトウェアエンジニアリングのプロジェクトにおいてエンジニアは、時間の経過と、結果的に出てくる変更の必要性に、より配慮しなければならない。ソフトウェアエンジニアリング組織内では、生産するソフトウェアと、ソフトウェアを生産する組織、それら両方のスケールと効率に関してより配慮しなければならない。最後に、ソフトウェアエンジニアとして我々は、時間と発展に対する不正確な見積もりに多くの場合基づき、比較的大きな利害の関係する結果を伴う、より複雑な決定の実行を求められる。
Google 社内でときに言われるのは、「ソフトウェアエンジニアリングとは時間で積分したプログラミングである」ということだ。時間を加えることで、プログラミングに新しい重要な次元が加わる。立方体は正方形ではなく、距離は速度ではない。ソフトウェアエンジニアリングはプログラミングではない。利用期間が1時間にすぎないプログラムのために、土台となるライブラリ、オペレーティングシステム、ハードウェアそれぞれの新しいバージョンもしくは言語バージョンへの適応が必要となることはありえない。そのような短命なシステムは実質上「単なる」プログラミング上の問題である。10 年あるいはそれ以上の期間であれば、暗黙的であれ明示的であれ、ほとんどのプログラムの依存関係はおそらく変化するだろう。この認識こそが、Google でのソフトウェアエンジニアリングとプログラミングの間の区別の根本にある。この区別は、我々がソフトウェアのための持続可能性(sustainability)と呼ぶものの核心に位置している。ソフトウェアの想定稼働期間中に、どのような変更が技術的もしくはビジネス上の理由で到来しようとも反応できるようであれば、そのプロジェクトは持続可能(sustainable)である。
スケールを考慮する必要もある。どれだけの人員が関与するのか。時間が経過する中での開発と保守において、その人員はどんな役割を果たすのか。プログラミングのタスクは個人的な想像の行為であることが多いが、ソフトウェアエンジニアリングのタスクはチームの努力の成果である。チームによる共同作業は、新たな問題を提起する一方で、価値あるシステムを生産する潜在力を、どんなプログラマー個人よりも多く提供する。ソフトウェアプロジェクトの、チーム組織、プロジェクト構成、そしてポリシーとプラクティス、それら全てが、ソフトウェアエンジニアリングの複雑性が持つスケールの側面を左右する。
また、行わなければいけない決定とそれに依存する利害の複雑性の点で、ソフトウェアエンジニアリングはプログラミングと異なるともいえる。ソフトウェアエンジニアリングでは、ときに大きな利害が関係し、また多くの場合不完全な価値のメトリクスしかない状態で、今後の方針数個の間でのトレードオフを評価することを定期的に強いられる。
ソフトウェアエンジニアリングにおいてどんなサイズにも適した万能の解があることは稀で、本書にもそれは当てはまる。Google の経験が読者の経験とぴったり一致することはおそらくないだろう。本書が目指すのは、Google で、何万人ものエンジニアと世界中に広がるコンピュートリソースとを用いて、何十年も存続する見込みのソフトウェアの構築と保守を行う際に、効果があると突き止められたものを公開することだ。Google のスケールで必要になることが判明するプラクティスの大半は、より小規模な試みでもうまく機能する。本書を、読者のスケールが拡大していくにつれ役立つ可能性があると我々が考える、あるエンジニアリングのエコシステムについての報告とみなしてほしい。
1.1: 時間と変化 #
初心者がプログラミングを学習する場合、できあがるコードの寿命はせいぜい何時間、何日といった単位で測られるのが通常である。こうしたことは教育の場では驚くべきことではない。
短命なコード開発は、ソフトウェア業界の一般的な場面でも見られる。モバイルアプリの寿命はかなり短いことが多く、また良くも悪くも完全な書き直しが比較的普通のことだ。初期段階のスタートアップ企業にいるエンジニアは、長期投資より即時的なゴールを重視することを、正当な理由のもとに選択している。見返りが効いてくるのが遅いインフラストラクチャー投資の恩恵を受けられるほど長く会社が存続している保証もないからだ。連続してスタートアップに参加している開発者は、10 年間の開発経験があるにもかかわらず、1年か2年以上存続することが想定されているようないかなるソフトウェアの保守経験もないに等しいという話が、合理的な理由によってありうる。
もう一方の端には、成功しているプロジェクトで事実上無限の稼働期間を持つものがある。Google 検索、Linux カーネル、Apache HTTP サーバプロジェクトの終着点を合理的に予測することはできない。つまり、いつ依存関係やプログラミング言語のバージョン等をアップグレードしないでよくなるのか、予測できない。こうした長命なプロジェクトは、プロジェクトの稼働期間が延びるにつれ、プログラミングの宿題やスタートアップ開発とは異なる雰囲気をまとうようになる。
時間と変化への反応の必要性をめぐる議論で暗黙の前提となっているのは、変化は必要なものだろうという点だ。
変化が必要かどうかは場合による。「大半のプロジェクトは、プロジェクトが十分に長期にわたる場合、基盤となっているもの全てを変更しなければならない可能性がある」という点に異存はないだろう。プロジェクトが依存する全ての技術が、致命的バグとセキュリティ脆弱性を含んでいる可能性があるというリスクを抱えている。または、かつてもっともなベストプラクティスの設計に従っていたかもしれないが、それでも時間の経過によって変更が価値あるものとなることもある。
これらの懸念点こそが、なぜ持続可能性に投資していない長期プロジェクトには大きなリスクがあるのかという問いへの答えである。変化の能力は備えていなければならない。
1.2: スケールと効率 #
サイトリライアビリティエンジニアリング(SRE)本(https://www.oreilly.co.jp/books/9784873117911/)で触れられているように、Google の本番環境システムの全体像は、人類によって造られた最も複雑な機械に数えられる。そのような機械を構築し、円滑に運用し続けるには、組織全体の、世界中にいる専門家たちによる数え切れない時間の思索、議論、再設計を要した。つまり、SRE 本として、そのスケールの機械を稼働させ続けることの複雑性に関する書籍を Google は既に書いたことがあるというわけだ。
本書の大部分が対象とするのは、そうした機械を生産する組織のスケールの複雑性と、その機械を時間の経過とともに稼働させ続ける際に我々が用いているプロセスである。コードベースの持続可能性の概念について再度考えてみよう。「変更すべき全てのものを安全に変更可能で、かつコードベースの存続期間を通してそれが可能であるとき、組織のコードベースは持続可能である」。この可能かどうかの議論の中に隠れているものも、コストの一種だ。すなわち、何かを変更するコストが法外な場合、変更はおそらく延期される。コストが時間の経過とともに超線形に増大するならば、その業務は明らかにスケーラブルではない。いずれ時間が優勢となり、絶対に変更しなければならない何かが不意に発生する。プロジェクトのスコープが2倍になってからそのタスクを再度やらなければならない場合、そのタスクが要する労働力は2倍だろうか。次回、その問題への対処に必要な人的リソースをそもそも持ち合わせているだろうか。
組織がコードを生産し保守する際に依存する全てのものは、全体のコストとリソース消費の点でスケーラブルであるべきだ。特に、組織が繰り返し実行しなければならないものは全て、人的労力の点でスケーラブルであるべきだ。この意味で、一般的なポリシーの多くはスケーラブルであるようには思えない。
スケールしないポリシー #
少し練習すれば、スケーリングについて難のある属性を持つポリシーを容易に見つけられるようになる。通常、そうしたポリシーを特定するには、エンジニア1人に課される作業を考えたうえで、組織が 10 倍か 100 倍スケールアップする場合を想像してみればよい。
廃止に対する伝統的なアプローチについて考えてみよう。廃止に対する一般的なアプローチは、スケーリングに関する問題の好例としての役目を果たす。新しいウィジェットが開発されたとしよう。全員が新しいウィジェットを使い、古いウィジェットの利用をやめる決定がなされる。この決定に従うことを促すために、プロジェクトのリーダーが「8 月 15 日に古いウィジェットを削除するので、必ず新しいウィジェットに移行しておくように」と言う。
この種のアプローチは小さなソフトウェアを開発する場面では機能するかもしれないが、依存関係の深さと幅の両方が増加するに従ってすぐに失敗する。スケーラブルな方法でこれらの問題を解くには、廃止を実行する方法を変えることになる。顧客に移行作業を押し付ける代わりに、チームがその作業を内部化できれば、その作業がもたらす規模の経済の恩恵全てを受けられるようになるのだ。
2012 年に、我々はチャーン(churn: 内部の生クリームを激しくかき回してバターを作る撹拌機から転じて、集団内のメンバー入れ替わりを意味する。ここではアップデートへの追随が難しいインフラストラクチャー移行を指す。)を防ぐルールによりこの問題に終止符を打つことを試みた。インフラストラクチャーのチームは、自身が抱える内部ユーザーを自身で新バージョンに移行させるか、あるいはシステムを稼働させたままでアップデートを後方互換性のある形で行わなければならないというルールだ。我々がこの「チャーンルール」と呼んだポリシーは、以前よりよくスケールする。依存しているプロジェクトで、アップデートに追随していくためだけに費やす労力がだんだん増えるということがなくなったのだ。我々はまた、ユーザー全員に保守のための追加的な骨折りを求めるより、専任の専門家グループに変更を実行させるほうがよくスケールすることを学んだ。専門家は時間をかけて問題の全体を深く学び、それからその専門知識を全ての部分問題に当てはめていくからだ。チャーンへの反応をユーザー側に強制するということは、影響を受ける全チームが、インフラストラクチャーの新バージョンに対応する各々のシステムの立ち上げ業務を拙いやり方で行い、当面の問題を解決したら不要になった知識は投げ捨てられてしまうことを意味する。
よくスケールするポリシー #
組織が発展するのに伴ってコスト改善につながるのは、どんな種類のポリシーだろうか。あるいは、欲を言えば、組織の発展に伴い超線形な価値をもたらすポリシーとして施行できるのは、どんな種類のポリシーだろうか。
我々が気に入っているポリシーに、インフラストラクチャーチームの強い味方で、インフラストラクチャーの変更を安全に行う能力を保証してくれるものがある。「製品が、インフラストラクチャーの変更の結果として障害や他の問題に陥った場合、問題が継続的インテグレーション(CI)システムでのテストで表面化していなかったならば、インフラストラクチャーの変更に落ち度はない」というポリシーだ。よりくだけた言い方をするならば、「そんなに好きならそいつに CI テスト付けときゃよかったのに」となり、これは我々が「Beyonce ルール(ビヨンセルール)」と呼ぶものである。スケーリングの観点からは、社内の共通 CI システムから呼び出されない複雑な使い捨ての特製テストはテストに入らない、ということを Beyonce ルールは暗示している。このルールがなければ、インフラストラクチャーチームのエンジニアはおそらく、影響するコードがある全チームを追いかけて、そのチームのテストを実行する方法を聞いて回らなければならなくなる。エンジニアが 100 人ならばそれも可能だろう。だが、今では、そんなことをやっている余裕は絶対にない。
我々は、組織がスケールする際に、専門知識と共有コミュニケーション掲示板が大きな価値を提供することを発見した。エンジニアたちが共有掲示板で問題を論じ答えていくにつれて、知識が広まっていく傾向がある。新たな専門家も育つ。100 人の Java を書くエンジニアがいたとして、1人の面倒見の良い Java 専門家が質問に回答するのをいとわないならば、より良い Java コードを書くエンジニアを 100 人すぐに生み出せる。知識にはウイルスのような拡散性があり、専門家は媒介者である。
シフトレフト、左への移動 #
一般的に正しいと言われることのうち、我々も正しいとわかったことに、たいていの場合は開発者のワークフロー中で問題を早期発見するとコストが下がる、という考え方がある。問題発見をタイムライン上の早期であるところの「左」へと移動させることで、後で行う場合より低いコストで問題を修正できる。
「左」という語は、セキュリティの検討は開発プロセスの終わりまで先延ばしにしてはならないという、「セキュリティのことなら左へ移せ(shift left on security)」とのセキュリティの格言に由来するようだ。
開発プロセスの早期に、品質、信頼性、セキュリティを強調するツールとプラクティスとを提供することこそが、Google のインフラストラクチャーチームの大多数にとって共通ゴールである。左側でできるだけ多くの欠陥を発見することが期待される多層防御のアプローチを取れるため、プロセスやツールのどれ1つとして完璧である必要はない。
1.3: トレードオフとコスト #
プログラムの方法、保守するソフトウェアの稼働期間、新機能を生産し保守するエンジニアが増え組織がスケールアップする際にソフトウェアを保守する方法、以上を理解しているならば、残っているのは良い決定を行うことだけである。これは当たり前のようにも思える。Google 内では、「私がそう言うのだから(間違いない)」のような説明に対しては強い嫌悪感がある。どんなトピックであれ決定者がいて、決定が誤っていると思われる場合には明確なエスカレーション経路があることが重要だ。だがゴールは合意であって、全員一致で異議がない状態ではない。「あなたのメトリクス/価値評価には同意しないが、あなたがどうやってその結論に至ったかはわかる」という事例にいくつか遭遇することは、何も問題がなく、予期されることだ。こうしたこと全てに内在しているのは、全てに理由が存在しなければならないという思想である。「ただ何となく」「私がそう言うのだから」「他の皆がこうしているから」といった説明には悪しき決定が潜む。
最終的に、エンジニアリング集団内での決定というものは、非常に少数の物事に帰着する。
- これをやらなければならないのでやっている(法的要件、顧客の要件)
- 現在のエビデンスに基づき、現時点でわかっている中で、これが最良の選択であるのでやっている
我々は、データが決定に裏づけ情報を与えていることを強く信じているが、時間の経過に応じてデータが変化し、新しいデータが現れるかもしれないことも認識している。このことが内在的に意味するのは、当該システムの稼働期間中、折りに触れて決定を再考する必要があるだろうということだ。存続期間の長いプロジェクトでは、最初の決定が行われた後に方針を変更する能力があることが不可欠である場合が多い。そして、重要なのは、それが、決定者が間違いを認める権利を有していなければならないのを意味することだ。間違いを認めるリーダーというものは尊敬を勝ち取りこそすれ、尊敬を失うようなことはない。
1.4: ソフトウェアエンジニアリング対プログラミング #
我々のソフトウェアエンジニアリングとプログラミングの区別を示された際に、内在的な価値判断が作用していないか気になった読者がいたかもしれない。プログラミングがソフトウェアエンジニアリングに比べて何らかの形で劣っているということはあるのだろうか。何百人ものチームで 10 年存続することが予期されるプロジェクトは、2人で作る1ヶ月だけ有効なプロジェクトより、内在的に価値が高いのだろうか。
もちろんそんなことはない。我々は、ソフトウェアエンジニアリングが上位にあるということではなく、それらが全く異なる制約、価値、ベストプラクティスを持つ2つの異なる問題領域を表象していると考えている。むしろ、2つの領域の差異を指摘することの価値は、一方の領域では素晴らしいが別の領域ではそうでもないツールがあると認識することから得られる。数日しか存続しないプロジェクトでは、インテグレーションテストと継続的デプロイのプラクティスに頼る必要はおそらくないだろう。
我々は、関連しているが別の用語である「プログラミング」と「ソフトウェアエンジニアリング」の間の差異を認めることが重要であると信じている。その差異の大部分が生ずる原因となっているのは、時間の経過に応じたコードの管理、時間がスケールに及ぼす影響、それらの概念に直面しつつ行う意思決定だ。プログラミングとは、コードを生産する即時的行動である。ソフトウェアエンジニアリングとは、コードを利用しなければならない期間中に有用に保つのに必要であり、またチームを横断した共同作業を可能とする、ポリシー、プラクティス、ツールのセットである。
1.5: 結論 #
本書は以下全てのトピックについて議論している。それらのトピックとは、組織についてのポリシーとプログラマー個人にとってのポリシー、ベストプラクティスを評価し洗練する方法、そして保守性のあるソフトウェアに投入されるツールと技術である。Google は、持続可能なコードベースと文化とを備えるべく奮闘してきた。我々のアプローチが物事を行うための唯一の真の方法であるとは必ずしも考えないが、本書は、そのアプローチが可能であることを、我々の先例によって、実際に証明している。本書が、想定稼働期間を通じてどのようにコードを保守すればよいかという一般的な問題について考えるための、有用なフレームワークを提供できれば幸いである。
2 章:チームでうまく仕事をするには #
2.4: Google 的であること #
Google 文化の初期の頃から、ある行為を指して「Google 的(Googley)である」または「Google 的でない」と呼ぶことがよくあった。この言葉は当初は明示的に定義されたためしがなかったが、最終的に Google は「Google 的であること(Googleyness)」という用語によって我々が意味するものに向けた基準を明示的に定義した。この基準は、強力なリーダーシップを表象し、「謙虚、尊敬、信頼」を体現するものとして我々が求める、属性と品行のセットである。
- 曖昧さの中にあっても成功する
- 環境が絶えず変動している最中であっても、互いに競合する複数のメッセージや複数の方針に対処でき、合意を形成でき、問題に対して進捗を遂げることができる
- フィードバックを尊重する
- フィードバックを率直に受け、かつ与えるという両方を行える謙虚さを持ち、フィードバックが個人の(ならびにチームの)成長にとってどれだけ有益か理解している。
- 現状に立ち向かう
- 他者からの抵抗や惰性があろうとも、野心的なゴールを設定し追求することができる
- ユーザーを第一に置く
- Google 製品のユーザーへの共感と尊敬とを持ち、ユーザーの利益を第一に考えた行動を追求する。
- チームを思いやる
- 同僚に共感と尊敬とを抱き、頼まれなくても積極的に手伝うように動くことで、チームの団結を強める。
- 正義を為す
- 行うことすべてについて強い倫理的感覚を持つ。チームと製品の誠実さを守るためなら、困難で不都合な決断を行うこともいとわない。
こうしたベストプラクティスとなる振る舞いが、より明確に定義されたので、我々は「Google 的」という用語の利用は避けるようになった。期待されることというものは、いつでも具体的であるほうがよい!
2.5: 結論 #
ほとんどのソフトウェアの取り組みにおいて、規模にほぼ関係なくその基盤となるのは、よく機能するチームである。単独のソフトウェア開発者による天才神話はいまだに生き残っているが、誰も本当に独力で作業しているわけではないというのが真実だ。ソフトウェア組織が時の試練に耐えるには、個人というよりむしろチームをめぐって、謙虚と信頼と尊敬に根ざした健全な文化を備えていなければならない。さらに、ソフトウェア開発が備える創造的性質により、リスクを取ってときには失敗もすることが必須となる。人々がそうした失敗を受け入れるには、健全なチーム環境が存在しなければならない。
3 章:知識共有 #
3.9: 結論 #
知識は、いくつかの面でソフトウェアエンジニアリング組織の(触れることはかなわないにせよ)最重要資本であり、そのような知識の共有は、変化にさらされていても組織が強靭で冗長化された状態であるために、決定的に重要である。開かれた率直な知識共有を奨励する文化は、そのような知識を組織の至る所へ効率的に行き渡らせ、その組織が時間の経過とともにスケールできるようにする。ほとんどの場合、知識共有を簡単にするために行う投資は、その企業が存在する限り何倍もの見返りをもたらしてくれる。
3.10: 要約 #
- 心理的安全性は、知識共有の環境を育む際の基盤である。
- 小さなことから始めよ。つまり、質問をすること、物事を書き留めることだ。
- 人間の専門家とドキュメント化されたリファレンスの双方から、必要な助けを簡単に得られるようにすべきである。
- 自身のみならず所属チームや所属組織を超えて専門知識を教え広めていくのに時間を割くものは、制度的なレベルで奨励し報奨を与えよ。
- 銀の弾丸はない。知識共有の文化を振興するには複数の戦略の組み合わせが必要であり、どのような特定の配合が組織にとってもっともうまく機能するかは、おそらく時間の経過に伴って変化するだろう。
4 章:公正のためのエンジニアリング #
4.9: 結論 #
ソフトウェア開発、そしてソフトウェア組織の開発は、チームによる取り組みである。ソフトウェア組織はスケールするにつれて、自身のユーザーベースに向けて反応し十分な設計を行わなければならない。今日の相互接続されたコンピューティングの世界では、ユーザーベースはローカルならびに世界中のあらゆる者を意味する。ソフトウェアを設計する開発チームと、開発チームが生産する製品の双方が、そのような多様かつ包括的なユーザー集団の価値観を反映するものとなるよう、さらなる努力を要する。そして、エンジニアリング組織がスケールすることを望むなら、低代表グループを無視することはできない。低代表グループに属するエンジニアは組織自体を強化するだけでなく、世界全体にとって真に有用なソフトウェアの設計と実装のための、そのグループ特有で、かつ、なくてはならない観点を提供する。
4.10: 要約 #
- バイアスこそがデフォルト状態である。
- 包括的なユーザーベースを対象として適切に設計を行うには、多様性が必要である。
- 低代表グループ向けの採用経路の改善のみならず、全ての人々にとって真に支えとなる労働環境の提供に、インクルーシブであることが決定的に重要である。
- 製品の開発速度は、全ユーザーにとって真に有用な製品を提供できているかどうかに照らし合わせて評価しなければならない。一部のユーザーに害を引き起こしかねない製品をリリースするくらいなら、歩みを緩めた方が良い。
5 章:チームリーダー入門 #
どんなチームもリーダーなくしてはうまく機能できない。エンジニアリングがほぼ例外なくチームによる取り組みである Google においては特にそうだ。Google では、2種の異なるリーダーシップ役職が認知されている。マネージャーは人員のリーダーであり、他方でテックリードは技術的取り組みを主導する。これら2つの役職は、職責は相当異なるが、非常に似たスキルを要する。
本章はピープルマネジメントと技術的リーダーシップに関するものだが、たとえ読者が IC(individual contributor: 管理職以外の、部下を持たずに個人としてチームに貢献する社員)であったとしても、おそらく自身のリーダーについての理解が多少なりとも進むであろう点において、依然として読む価値はある。
5.1: マネージャーとテックリード #
チームの初期段階では、両方の役職がテックリードマネージャー(TLM)という同一人物によって務められることもあるだろう。大きなチームだと、経験豊富なピープルマネージャーが管理職を担う立場で参加し、幅広い経験を持つシニアエンジニアがテックリードの役職で参加することになる。マネージャーとテックリードは、各々がエンジニアリングチームの成長と生産性において重要な役割を果たしてはいるが、各役職で成功するために求められるスキルは甚だしく異なっている。
エンジニアリングマネージャー #
多数の企業が、自社のエンジニアリングチームの運営のために、ソフトウェアエンジニアリングについてはほとんどもしくは何も知らないとしても、ピープルマネージャーとしては熟練したものを招集している。しかし Google は早い段階で、自社のソフトウェアエンジニアリングマネージャーはエンジニアリングの経歴を持っているべきであると決めた。このことは、経験を積んだマネージャーでかつてソフトウェアエンジニアだった者を採用すること、またはソフトウェアエンジニアを訓練してマネージャーとすることを意味した。
最もハイレベルなところでは、エンジニアリングマネージャーは、チームが担当する製品がビジネス要件を満たすことを保証しつつ、その上でテックリードを含むチーム内のすべての人員の成績、生産性、満足度について責任を持つ。ビジネス要件と個々のチームメンバーの要求とは必ずしも相容れないため、このことがマネージャーを難しい立場に置く可能性がある場合が多い。
テックリード(TL) #
チームのテックリードは、チームのマネージャーの部下である場合も多いが、製品の技術的側面を担当し、担当業務は技術的な決定と選択、アーキテクチャー、優先度、開発速度、プロジェクト管理一般を含む。通常 TL は、チームに十分な人員がいてエンジニアが自分たちのスキルセットやスキルレベルに最も適切に見合ったタスクに取り掛かれるよう保証するべく、エンジニアリングマネージャーと二人三脚で仕事をすることになる。大半の TL は IC でもあるので、自身で何かを手っ取り早くやってしまうか、それをチームメンバーに任せて(場合によっては)より時間をかけて行わせるかのどちらかの選択を強いられる。チームの規模と力量が増大するにつれ、ほとんどの場合に後者が TL にとっての正しい選択となる。
テックリードマネージャー(TLM) #
初期段階にある小規模チームでは、TLM がいるのがデフォルトである場合が多い。TLM とは、チームでの人員面と技術面の両方に対処できる1人の人物である。比較的シニアな者が TLM であることもあるが、通常は、最近まで IC だった者がこの役職を務めている。
Google では、比較的大規模でしっかり確立したチームでは、1組のリーダー、つまり1人の TL と1人のエンジニアリングマネージャーが、パートナーとして連携して仕事をしているのが通例である。その理屈は、完全に燃え尽きることなく両方の業務を同時に(うまく)こなすのは本当に難しいので、2人のスペシャリストが専任で各々の役目を攻略していくほうがよいというものだ。
5.2: IC 役職からリーダーシップ役職への異動 #
「マネージャー」という言葉を聞くとほとんどの者が感じる一般的なうんざりする気持ちの他にも、大多数の者がマネージャーになりたがらない理由は複数ある。ソフトウェア開発の世界で聞くであろう最大の理由は、コードを書くのに費やす時間がかなり減る、というものだ。TL になろうが、エンジニアリングマネージャーになろうが、この点は当てはまる。
自分のキャリアの大半をコードを書くことに費やしてきたなら、1日を終えたとき、コードであれ、デザインドキュメントであれ、クローズしたバグの山であれ、指し示して「これが今日やったことだ」と言えるものが存在しているのが普通だ。しかし、「マネジメント(管理業務)」の忙しい1日の終りには、たいてい自分が「今日は全く何もやらなかったな」と思っているのに気づくだろう。これは、毎日収穫した林檎の数を数えるのに何年も費やしてから、バナナを育てる仕事へ転職することに相当する。結果として自分の側に生い茂っているバナナの木をおめでたくも無視しつつ「林檎を全然収穫しなかった」と毎日の終わりに自分に告げていると言うだけの話だ。マネジメントの仕事の定量化は、作ったウィジェットの数を数えるより難しい。だが自分のチームが満足かつ生産的でいられるようにすることは、マネジメントの仕事の重要な尺度である。バナナを育てているのに林檎を数える罠に落ちてはならない。(他の差異で慣れを要するのは、マネージャーとして行うことは基本的により長い時間軸で結実するということだ。)
5.3: 今日のエンジニアリングマネージャー #
「マネージャー」という肩書は往々にして時代錯誤であるという事実があるにもかかわらず、大半の人々は相変わらずその肩書を使用している。「マネージする(管理する)者 = マネージャー」としてのその肩書自体が、部下を「管理」することを新人マネージャーに奨励している。マネージャーは親のように振る舞う羽目になることがあり、その結果、従業員は子どものように反応する。マネージャーが部下を信頼していることを明らかにするならば、その部下はマネージャーの信頼に応えるべく前向きなプレッシャーを感じる。それくらい単純なことだ。
伝統的なマネージャーは物事をやり遂げる方法を気にする一方で、優れたマネージャーはどんな物事がやり遂げられるのかを気にする(そして、やる方法を見つけるのはチームに任せる)。
仕事に対する部下への興味が非常に薄いために、部下を納得させて働かせるのに伝統的マネージャーのベビーシッター業務が実際に必要なら、それこそが本当の問題である。
5.4: アンチパターン #
マネージャーとして成功を望むものが従うべきではないパターンを集めてみよう。
押しに弱い者を採用する #
あなたがマネージャーで、自身の職務に関して自信がないなら、誰からも自分の権限に異議を唱えられたり職を脅かされたりしない状態を保証する方法として、言いなりにできる者を採用する、というものがある。自分ほど賢明または野心的ではない者か、単に自信が自分より無い者を採用すれば、その状態を達成できる。それでチームリーダーや意思決定者としての自分の立場は確立されるだろうが、そのことは自分の仕事がかなり増えることを意味する。紐に繋がれた犬のように、引っ張るものなしでは動けないチームとなるだろう。
そんなことをするのではなく、あなたより賢くて交代できる者を採用するよう努めるべきである。これはあなたにとって手強い状況となる場合がある。あなたが採用したその人物が、定期的に楯突いてくるからだ(加えて、あなたが間違ったときはそのことを指摘してくる)。終始あなたを唸らせ素晴らしい物事を実現させるのもまた、同じ人物だろう。そのような人物は、かなりの部分まで自主的に方向を定めて動くことができる。またチームを率いたいと熱望するものもいることだろう。それを、あなたの権力を乗っ取る試みとみなすべきではない。むしろ、あなた自身がさらに他のチームを追加で率いたり、新しい機会を調べてみたり、もしくはチームが仕事をこなしているか確かめるために毎日行う進捗確認の心配をせず休暇すら取るためのきっかけとして見ると良い。
それは学びと成長のための素晴らしいチャンスでもある。自分より賢い人々に囲まれていると、専門知識を広げるのがかなり容易になるからだ。
成績の悪いものを無視する #
Google のサイトリライアビリティエンジニアリング(SRE)チームには「希望は戦略ではない」という標語がある。そして、成績の悪いものを扱う場合以上に、希望が戦略として濫用される場所も他にない。大多数のチームリーダーは歯を食いしばり、目を背け、そして成績の悪いものが魔法のように成績を改善するか立ち去るかのどちらかを、ただ希望するのだ。しかし、その者がいずれかを実行することは、極めて稀である。
リーダーが希望を持ち続け、成績の悪いものが成績を改善しない(もしくは去らない)間に、チームで成績の良いものは成績の悪いものを引っ張るのに貴重な時間を浪費し、チームの士気は空中に漏れ出て消えてしまう。たとえ成績の悪いものがそこにいないかのようにあなたが振る舞っているとしても、成績の悪いものがチーム内に存在することをチームのメンバーは知っていると考えて間違いない。実のところ、チームのメンバーは誰の成績が悪いのかを痛切に認識している。チームには、成績の悪いものを支える必要があるからだ。
成績の悪いものの無視は、成績の良い者が新しくチームに参加するのを妨げる行いであるだけでなく、現在いる成績の良い者にチームを去るよう促す行いでもある。最終的には全員成績が悪いチームになるのが落ちで、それは自分の意志でチームを去ることができないのは成績の悪いものだけだからだ。
最後に、成績の悪いものをチームにとどめておくことは、何の思いやりにすらなっていない。あなたのチームでうまくやれていない者が他のどこかで大きな影響力を実際に発揮する可能性が、往々にしてあるのだ。成績の悪いものに直ちに対処すれば、成績の悪い者は生産性が高まった状態へ移っていくために激励や方向付けを多少必要としているにすぎないことがわかる場合が多いはずだ。
成績の悪いものを効果的に指導するにはどうすればよいか。最適な類推は、足を引きずっている者が再び歩き、そしてゆっくり走り、それからチームの他の者に伴走していくのを学ぶ過程を手伝っているところを想像するというものだ。この指導は、一時的にはマイクロマネジメントを要することがほぼ常である。だがそれでもやはり必要なのは、相当な量の謙虚、尊敬、信頼、特にその中でも尊敬だ。特定の期間(たとえば2ヶ月)と、成績の悪いものがその期間内に達成を期待される何らかの非常に具体的なゴールを設定するとよい。小さな成功の機会が多くあるように、ゴールは小さく、インクリメンタルで、計測可能なものにすべきだ。毎週そのチームメンバーと会って進捗確認し、また成功か失敗かを測るのが簡単なように、今後の各マイルストーンでの極めて明示的な期待要件を必ず設定すべきである。その成績の悪いものがついていけないならば、そのプロセスの早い段階であなたとその者の双方にとって、ついていく能力がないということが明らかになることだろう。その時点で、その者は物事がうまく行っていないのを認め、辞めることを決断する場合が多い。また別の場合では、決意が効果を表してきて、成績の悪いものが期待に沿うようになるだろう。いずれにせよ、成績の悪いものと直接に仕事をすることで、あなたは重要かつ必要な変化の触媒となるのだ。
人間的問題を無視する #
マネージャーには、チームのための2つの主要な関心領域があり、それは社会的なものと技術的なものである。Google ではマネージャーがどちらかといえば技術面に比較的強いのが一般的で、マネージャーの大半は技術職から昇進しているので、人間的問題を無視する傾向を見せる場合がある。それは IC として自分の時間の大半を技術的問題の解決に費やしてきたからにほかならない。学生だったときは、仕事の技術的な詳細について学ぶことが授業の全てだった。しかし、マネージャーとなった今、チームの人間的要素を無視するのは、自殺行為にほかならない。
全員の友人になる #
はじめてのリーダーシップへの進出で大半の者が経験するのは、自分が以前メンバーだったチームのマネージャーや TL になる場合である。多くのリーダーは自分のチームのメンバーたちとの間に育んだ友情を失いたくないので、チームのリーダーになってから、メンバーとの友情を維持するべく特に熱心に努めることがある。友情を、人当たりよくチームを率いることと混同してはならない。あなたが誰かのキャリアに関する権限を有する場合、あなたの友好的な素振りに対して相手は、不自然ながらそれに答えざるをえないプレッシャーを感じているかもしれない。
自分のチームと親しい友人関係にならずとも、チームを率いて合意形成ができるということを、覚えておいてほしい。同様に、既存の友情を投げ捨てなくても強靭なリーダーにはなれる。自分のチームと昼食をとるのは、チームメンバーを居心地の悪い状態に置かずにチームと社交上つながった状態でいるために効果的な方法であることがわかっている。昼食は、通常の仕事環境の外で堅苦しくない会話を行うチャンスとなる。
5.5: 建設的パターン #
ここまでアンチパターンを扱ってきたところで、成功を収めるリーダーシップとマネジメントのための、建設的パターンに目を向けてみよう。Google での経験、他の成功しているリーダーの観察、そしてとりわけ社内のリーダーシップ面でのメンターから我々が学んできたパターンだ。
エゴを捨てよ #
チームリーダーが持つエゴは厄介だ。代わりに、集団的なチームとしてのエゴと主体性を育成し強化するよう努めるべきだ。
信用は、「エゴを捨てること」の一環であり、自分のチームを信用しなければならない。これは、新入りのメンバーであれ、その能力ならびにチームに入る以前の功績に敬意を払うということでもある。
禅の老師となれ #
質問を尋ねることだ。チームのメンバーがアドバイスを求めてくる場合、ついに何かを直すチャンスが来たということで非常に興奮するのが一般的である。それがまさに、リーダーシップの職位に就く前に何年もやってきたことなので、小躍りして問題解決モードに飛び込んで行くのが普通というものだが、それは赴くべきでないところの筆頭だ。アドバイスを求めている者としては、通常は、「あなたに」問題を解決してほしいわけではなく、むしろ解決を手伝ってほしいのだ。そしてそれを行うのに最も簡単な方法は、あなたがその者に質問を尋ねることである。
アドバイスを求めてきた者に問題の精緻化と探求を行うよう努めさせることで、その者が問題を自身で解決する手伝いができる。これにより、通常はその者は答えに導かれ、その答えはその者自身の答えである。そのことは、オーナーシップと責任につながってくる。あなたが答えを知っていようがいまいが、このテクニックを使えばほぼ常に、あなたが答えを知っていたという印象をその者に残すことになる。なんとも巧妙ではないか。
明確なゴールを設定せよ #
明白なように見えて、これは途方もない数のリーダーによってこぞって無視されているパターンの1つである。チームをある方向へ急速に向かわせようとするなら、その方向がどちらであるか全チームメンバーが理解し合意していることを確実にしなければならない。
明確なゴールを持つことになるなら、明確な優先度を設定する必要がある。またトレードオフが必要になったときにチームがトレードオフをどのように行うべきか、決めるのを手伝わなければならない。
明確なゴールを設定し、チームに製品を同じ方向へ引っ張っていくようにさせる一番簡単な方法は、チーム用の簡潔なミッションステートメント(組織の存在意義や目的を短い文章で表すもの)を作ることである。チームが自身の向かう方向とゴールとを定義する手助けをしたら、全員が依然として正しい道を進んでいるか念の為定期的に進捗確認しつつ、自分は一歩引いてチームにさらに自主性を与えることができる。
正直であれ #
チームに何か言えないことがある立場、あるいはもっと悪いことに誰も聴きたくないことを全員に告げなければならない立場に自分がいるのに気づくという事態が、いずれ起きる不可避なものである。
我々の知るあるマネージャーは、チームの新しいメンバーに「君に対して嘘をつくことはないだろう、しかし君に何か言えないことがあるか、単にわからないときは、君にそう言うだろう」と告げる。
もしあなたが情報共有できないことについてチームメンバーがあなたに話しかけてきたら、答えは知っているが何も言うわけにはいかないとただ告げればよい。さらにもっとよくあるのは、あなたが答えを知らないことについてチームメンバーが尋ねてくる場合で、その人物には知らないと告げてよい。
厳しいフィードバックを与えるのは …… まあ、厳しい。部下が間違いをおかしたとか期待通りに仕事をこなさなかったとかいったことを部下に初めて告げなければならないときというのは、信じられないほど精神的に疲れるかもしれない。マネジメントの教科書のほとんどは、厳しいフィードバックを伝える場合は打撃を緩和するために「褒め言葉のサンドイッチ」を使えとアドバイスしている。
「君はチームの信頼できるメンバーで、エンジニアの中で最も賢い部類だ。その上でなんだけど、君のコードはややこしくてチームの誰にとってもほとんど理解不能なんだ。でも君はすごく見込みがあるし、めちゃくちゃイケてる T シャツのコレクションを持ってるね。」
確かに、これで打撃は緩和されるが、この種の遠回しに言うやり方では、ほとんどの者は「やった!自分の T シャツってイケてる!」としか思わずにその場を後にするだろう。
我々は褒め言葉のサンドイッチは使わないよう「強く」アドバイスする。それはいたずらに非情または辛辣な態度をとるべきと我々が思っているからではなく、ほとんどの者が決定的に重要なメッセージを聴かないことになるからである。そのメッセージとは、何かが変わらなければならないということだ。褒め言葉のサンドイッチに頼ることなく、建設的批判を伝える際に思いやりと共感を持つようにするのだ。
「君はわかってないと我々は確信しているが、君のチームとの関わり方は不和を生み反感を買う類のものだ。もし君が役に立ちたいなら、コミュニケーションのスキルを磨かないといけないし、君がスキルを磨く手助けに我々はコミットするよ。」
5.7: 移譲する、しかし手は動かす #
IC の役職からリーダーシップの役職へ異動すると、バランスを取ることが最も難しい類のものになる。当初は、自身で仕事を全部やる気があるものも、リーダーシップの役職に長期間従事した後は、自身では全然仕事しないという習慣に陥りやすい。
ある程度の期間にわたり複数のチームを率いてきたか、新しいチームを率いる事になった場合に、チームの尊敬を得つつチームの皆の仕事内容を把握して追いつくための方法として一番簡単なのは、自分の手を動かすことである。たいていそれは、他の誰もやりたがらないきついタスクを引き受けることによる。あなたには1マイルもの長大なレジュメと実績とがあるかもしれないが、途中から入って何らかのきつい仕事を実際にやってみせることほど、あなたにスキルがあり献身的であることをチームにわからせるものは他にない。
5.9: 結論 #
チームを率いるのは、ソフトウェアエンジニアであることとは異なるタスクである。結果として、優れたソフトウェアエンジニアは必ずしも優れたマネージャーとはならず、それで問題ない。効果的に機能している組織は、IC とピープルマネージャーの双方に生産的なキャリアパスを用意している。Google は、ソフトウェアエンジニアリングの経験自体はマネージャーにとって非常に価値のあるものとみなしてきているが、効果を発揮するマネージャーが貢献できる最も重要なスキルは社交的なものである。優れたマネージャーは、チームがうまく働けるように手伝い、チームが適正なゴールに集中し続けられるようにし、チーム外の問題からチームを隔離することによって、エンジニアリングチームが仕事をできるようにしている。そのようなマネージャーはずっと「謙虚、信頼、尊敬」の三本柱に従っているのだ。
5.10: 要約 #
- 伝統的な意味での「管理」は行うな。リーダーシップ、影響力、チームに仕えることに集中せよ。
- 可能な場合は移譲せよ。DIY(Do It Yourself:自前作業)は行うな。
- チームの着眼点、方向、速度に特に注意を払え。
6 章:スケールするリーダー #
1つのチームを率いるところから、一連のチーム群を率いるところへ移るのは、自然な進展である。解くことになる問題の範囲はさらに大きくなり、より抽象的なものとなる。次第に「よりハイレベル」になることを強いられるのだ。それは、物事の技術的または工学的な詳細に入り込んでいける度合いがどんどん低下し、「深く」というより「広く」事を進めるように追い込まれるということである。
6.1: いつでも決定せよ #
最もハイレベルなところにあるリーダーとしての仕事は、チーム1つだけのリーダーであろうがより大規模な組織のリーダーであろうが、難解で曖昧な問題の解決へと人々を導くことである。曖昧という語で我々が意味するのは、問題に明白な解法がなく、解決不能なことすらあるかもしれないということだ。
コードを書くことが樹木の伐採に類似しているとすれば、リーダーとしての仕事は、「木を見て(森を見ず、ではなく)森を見ること」、エンジニアを重要な木々の方向へ導きつつ、森の中を通る通行可能な道を見つけ出すことに類似している。このプロセスには3つの主なステップがある。まず、「目隠しを特定」しなければならない。次に、「トレードオフを特定」しなければならない。それから、「決定」を行う。
- 目隠しを特定:現状を批判的に検討する。現場のメンバーは長い間同一業務に浸っていると自然のうちに物事の見方が偏ってしまい森が見えなくなる。リーダーは無垢な眼差しで現状を見つめ、彼らの目隠しを特定する。
- トレードオフを特定:ほとんどの場合「銀の弾丸」としての解法はない。現時点での最良の答えのみが存在し、それにはほぼ確実にトレードオフが伴う。トレードオフを皆に説明して、どのようにそれらのバランスを取るかという決定を補助するのがあなたの務めである。
- 決定:トレードオフの情報を用いて最良の決定を下す。定期的に、それらのトレードオフ群を再評価し、バランスを再調整しなければならないかもしれない。決定は反復的プロセスである。
6.2: いつでも立ち去れ #
単に曖昧な問題を解くことだけが仕事なわけではなく、自分が居合わせなかったとしても組織自体がその問題を解けるようにすることも、自分の仕事であるということだ。それができれば、あなたは手が空いて新たな問題(もしくは新たな組織)へと向かうことができ、あなたの進む足跡に自給自足的な成功が残されていくことになる。
もちろんここでのアンチパターンは、自分を単一障害点に仕立て上げてしまうことだ。グーグラーはそのことを表現する用語を持っており、プロジェクトを完全に破綻へと追い込むのに要する、プロジェクト内でバスに轢かれる者の人数である、バス係数がそれにあたる。
問題空間の分割 #
解決困難な問題というものは通常、複数の難しい部分的問題から成る。もし複数チームをまとめて率いているなら、1つのチームにいくつかの部分的問題を担当させるのが自明な選択である。しかし、リスクとしては、そのような部分的問題は時間の経過とともに変化する可能性があり、チーム間の境界が厳格だと、変化の事実に気づいたり適応したりしにくいというものがある。可能ならば、より緩い組織構造を検討すべきだ。つまりその内部では、部分チームが規模を変更可能で、個人が部分チーム間を移動でき、部分チームに割り当てられた問題が時間の経過に応じて変更可能であるような組織構造だ。このために必要となるのは「厳格すぎる」と「曖昧すぎる」の間の紙一重のバランスを取ることである。
6.4: 結論 #
成功しているリーダーは、進むにつれて引き受ける責務が自然に増える(そしてそれは良いことであり自然なことである)。すばやく適切に決定するためのテクニックを案出し、必要な移譲をし、増大する責務を管理するという活動を効果的に行わない限り、忙殺され押しつぶされるように感じる羽目になるかもしれない。期待に応える能力を実際に発揮するリーダーであるためには、完璧な決定をしたり自身で何でも行ったり2倍働いたりしなければならないわけではない。むしろ、いつでも決定し、いつでも立ち去り、いつでもスケールするよう努力するべきだ。
7 章:エンジニアリング生産性の計測 #
(省略)
8 章〜10 章 #
(省略。今日では他の書籍でも扱われているようなプラクティスが記載されている。)
11 章:テスト概観 #
11.2: Beyonce ルール #
新入社員を指導する際によく尋ねられるのは、実際にテストが要る挙動もしくは属性はどれかという点だ。単刀直入な答えは、破綻してほしくないもの全部をテストせよというものである。換言すれば、システムが特定の挙動を示すことについて確信を持ちたいなら、それを確実にする唯一の方法は、そのために自動テストを書くことである。これには、パフォーマンス、挙動の正しさ、アクセシビリティ、セキュリティそれぞれのテストといったお馴染みの面々がすべて含まれる。またシステムが障害をどう処理するかテストするといった、それほど明白でない属性も含まれる。
この一般的な哲学には名前があり、我々は Beyonce ルールと呼んでいる。この哲学は簡潔に、以下の形で述べることができる。「そんなに好きならそいつにテスト付けときゃよかったのに」。Beyonce ルールは、全コードベースにわたる変更の実施を担当するインフラストラクチャーチームにより発動されることが多い。無関係なインフラストラクチャーの変更が、自分のテスト全部に合格するにもかかわらず自分のチームの製品を破綻させる場合、自分で破綻箇所を修正してその部分用のテストを付け足さなければならない立場に追い込まれるというわけだ。
12 章〜14 章 #
(省略。今日では他の書籍でも扱われているようなプラクティスが記載されている。)
15 章:廃止 #
全てのシステムは古くなっていく。ソフトウェアはデジタル資産であり、ハードウェア内のビット自体は劣化しないにせよ、新しい技術、ライブラリー、テクニック、言語、その他の環境的な変化により、時間の経過とともに既存システムは旧式になってしまう。古いシステムには継続的な保守や秘技めいた専門知識が必要で、また周りのエコシステムから外れていくにつれて一般的には必要な作業が増える。旧式のシステムは、それを置き換えるシステムと並列させた状態で無期限にぎこちない稼働を続けさせておくよりは、停止に向けて労力を費やす方がましなことが多い。しかし相変わらず稼働中である旧式システムの数が、実際問題としてそれらのシステムの停止が一筋縄では行かないことを示唆している。旧システムから脱する系統的な移行と、旧システムの最終的な撤去からなるプロセスは、廃止(deprecation)と呼ばれる。
15.1: 何故廃止するのか #
廃止についての我々の議論は「コードは債務であり資産ではない」という基本的前提から始まる。つまるところ、コードが資産であるならば、何故わざわざ時間を費やし旧式システムを止めて撤去しようとするのか。コードにはコストがあり、コストの一部はシステムを作成する過程で負担される。だが他の多くのコストは、システムの存続期間全体にわたってシステムが保守される際に負担される。こうした継続的なコスト、つまりシステムの稼働を保つために必要な運用リソースや、周りのエコシステムが発展するにつれて継続的にそのシステムのコードベースを更新する取り組みといったコストの存在は、古くなっていくシステムの稼働を保つのか、それともそのシステムの停止に取り組むのか、それぞれの行動の間のトレードオフが評価に値することを意味する。
15.2: 何故廃止はこれほど難しいのか #
システムのユーザが多数になればなるほど、システムの設計者が予期も予見もしていない方法でユーザーがそのシステムを使っている確率は高くなり、そのようなシステムは廃止して撤去することが難しくなるだろう(Hyrum の法則)。
より新しいシステムが同じ(または優れた!)機能を提供する状態で利用できるようになるまで、旧システムの廃止は通常は選択肢とならないことが、物事をさらに複雑化させている。新システムは優れているかもしれないが、旧システムと違うところもある。いずれにせよ、新システムが旧システムと全く同じなら、移行するユーザーに何の利点ももたらさないだろう(新システムを運用するチームには利益があるかもしれないが)。こうした機能上の差異があるために、旧システムと新システム間で、一対一で機能が一致することは稀であり、旧システムの利用方法は全て新システムの文脈で評価されなければならないことになる。
廃止の実行について気が進まなくさせる意外な要因としては他に、旧システム、中でも廃止を行うべき者が作成に手を貸したシステムへの、感情的な愛着がある。変化に対するこのような忌避の事例は、Google では古いコードを組織的に削除する際に起こる。我々はときどき、「私はこのコードが好きだ!」という形で現れてくる抵抗に遭遇してきた。自分たちが何年も費やして開発してきたものを解体するようエンジニアたちに納得させるのは難しい場合がある。これは理解できる反応だが、究極的には自滅を招く。この懸念に対する我々の対処法の1つは、ソースコードリポジトリーがトランクのみならず履歴からも検索可能であるよう保証することだ。削除済みコードすらも再発見できる。
旧式のソフトウェアシステムを廃止し撤去する際の困難を考慮すると、ユーザーにとっては、あるシステムを別のシステムで完全に置き換えるより、システムをその場で稼働中のまま発展させるほうが容易なことが多い。インクリメンタルに廃止を行うことで、廃止のプロセスが完全に回避されるわけではない。だが廃止のプロセスが、インクリメンタルな利益を生み出すことのできる、より小さく管理可能なチャンク群へと分割されるのは確かだ。Google 社内で観察されたこととして、全く新しいシステムへの移行は極めてコストが高く、そのコストは実際のコストより往々にして低く見積もられる。その場で稼働中のままでリファクタリングにより達成されるインクリメンタルな廃止の取り組みは、ユーザーに価値を提供しやすい状態で既存システムを稼働させておける。
設計中の廃止 #
多くのエンジニアリング活動同様、ソフトウェアシステムの廃止は、システムが最初に構築される際に計画しておくことができる。プログラミング言語の選択、ソフトウェアアーキテクチャー、チーム構成、そして企業のポリシーと文化でさえ、それら全てが、システムが有用である期間の終わりに達した後にそのシステムを最終的に撤去する際の容易さに影響する。
システムを最終的に廃止できるように設計するという発想は、ソフトウェアエンジニアリングにおいては過激かもしれないが、他のエンジニアリング専門分野ではありふれたものだ。原子力発電所の例を考えてみよう。原子力発電所は、極めて複雑なエンジニアリングによる産物の一例である。原子力発電所の設計の一環として、発電サービスの稼働期間後に結果として起こる閉鎖を閉鎖という目的のための予算確保にさえ至るまで考慮しておかなければならない。原子力発電所が最終的に閉鎖されなければならないことをエンジニアが承知していることで、建設に際する設計上の選択の多くが影響を受けている。
ソフトウェアシステムが原子力発電所ほどに思慮深く設計されることは稀だ。多くのソフトウェアエンジニアが惹かれるのは、新規システムを開発しローンチするタスクであって、既存システムの保守のタスクではない。Google を含む多くの会社の企業文化は、新製品を迅速に開発し出荷することを強調している。そのような企業文化が、最初から廃止を念頭に置いた設計を抑止する逆のインセンティブをもたらしてしまっていることが多い。それでは、将来においてより容易に廃止可能なシステムを設計する際に考慮すべき検討事項には、どんな種類があるだろうか。以下は、我々が Google のエンジニアリングチームに尋ねるよう奨励している2つの質問だ。
- 自分の製品の消費者が、自分の製品から、置き換え先になりうるものへ移行する際の容易さは、どの程度だろうか。
- どうすれば自分のシステムを部分的にインクリメンタルに置き換えられるか。
15.3: 廃止の類型 #
廃止は単一種類のプロセスではなく、「いつの日かこれを停止したいと思っている」から「このシステムは明日消え去る」までのプロセス群の連続体である。大まかに言って、勧告的廃止と強制的廃止だ。
勧告的廃止 #
勧告的廃止とは、締切がなく、組織にとっての優先度が高くない廃止である。こうした廃止は、願望的廃止として分類することもできる。すなわち、チームは旧システムに取って代わる新システムができたことを知っており、顧客が最終的に新システムへ移行することを望んではいるものの、顧客の移行を手伝うために支援を提供したり旧システムを抹消したりといったことを行う差し迫った計画は持ち合わせていない。顧客が移動するよう希望はするが、強制はできないというわけだ。
勧告的廃止は、新システムの存在を宣伝し、アーリーアダプター的ユーザーに新システムの試用を開始するよう促すには良いツールである。そのような新システムは、ベータ期間内にあるとみなすべきではない。新システムは、本番環境での利用と負荷に耐える準備ができているべきで、また新しいユーザーを無期限にサポートする用意ができているべきだ。
勧告的廃止によりシステムの作者は、作者が望む方向へ向かうようユーザーに促せるが、ユーザーが移行作業の大部分を実行するのを当てにするべきではない。
強制的廃止 #
この種の廃止は、通常、旧システムの撤去についての締切を伴う。
直感に反し、強制的廃止の取り組みをスケールさせるのに最良の方法は、単一の専門家チーム内、通常は旧システムを完全撤去するチーム内に、ユーザー移行の専門知識を局限しておくことである。このチームには、他者を旧システムから移行させるのを支援するインセンティブがある。またこのチームは経験を積むことができ、後で組織全体が使えるツールを開発できる。
強制的廃止が実際に機能するには、そのスケジュールが強制メカニズムを備えていなければならない。廃止プロセス実行チームにこの権限がなければ、廃止されるシステムの顧客であるチームが、廃止されるシステムの機能または他のより差し迫った作業を優先して、廃止作業を無視することが容易となってしまう。
15.5: 結論 #
廃止は、サーカスのパレードが街を通り過ぎた後に街路を掃除する汚れ仕事のように感じられることがある。だがこうした取り組みは、保守のオーバーヘッドとエンジニアの抱える認知負担を軽減することで、ソフトウェアエコシステム全体を改善する。複雑なソフトウェアシステムの長期的でスケーラブルな保守は、ソフトウェアの単なる開発と運用にとどまらない。開発と運用に加え、旧式となっているか、旧式でなくとも利用されていないシステムの撤去が可能でなければならないのだ。
廃止は、組織にとって利益の源としては見落とされがちだが、組織の長期的持続可能性にとっては必須である。
16 章:バージョンコントロールとブランチ管理 #
16.3: Google でのバージョンコントロール #
Google の主要リポジトリーは、Piper と呼ばれる内製の中央集権的 VCS(Version Control System)で管理されている。外部のもっと標準的な選択肢を統合し、社内のエンジニアたちが外部での展開から期待するようになってきているワークフローに合わせようとする試みは、定期的に起こる。残念ながら、Git のようなより一般的な VCS に移行する試みは、コードベースとユーザーベースの圧倒的な規模のせいで妨げられてきた。これらは驚くようなことではない。5 万人のエンジニアがいて何千万ものコミットがあるとうまくスケールしない(*)。履歴とメタデータの送信が頻繁に起こる Git のような DVCS(Distributed Version Control System)モデルでは、作業用リポジトリーの作成開始に大量のデータを要する。
*リポジトリーには大体 86TB のデータがあった。それもリリースブランチを除いてだ。それを開発者のワークステーション上に直接納めるというのは …… 厳しいというほかないだろう。
我々のワークフロー内では、コードベースについての中央集権制とクラウド内ストレージが、スケーリングにとって決定的に重要であると思われる。DVCS モデルは全コードベースをダウンロードし、ローカルでアクセスできるようにしておくという考え方の周りに構築されている。組織がスケールアップするにつれて、どの開発者も、リポジトリー内の相対的に小さな割合のファイルとそれらのファイルのほんの少数のバージョン上で作業することになる。ファイル個数とエンジニア人数が増加するにつれて、全コードベースのデータをいちいち伝送すると、ほぼまるごと無駄になる。
16.4: モノリポ #
2016 年に、我々は Google のモノリポというアプローチについての(多数引用され、大いに議論された)論文を発表した(https://research.google/pubs/why-google-stores-billions-of-lines-of-code-in-a-single-repository/)。モノリポのアプローチには利点がいくつかある。モノリポでは、何かのどのバージョンが正式なものか決めたり、どのリポジトリーが重要か見つけたりするというプロセスが存在しないのだ。ビルドの状態を理解するためのツールを開発する場合も同様に、重要なリポジトリーがどこに存在するか探さないで済む。エンジニアは他の皆がやっていることを見ることができ、自分のやっていることが他者から見えることを利用して、コードとシステムの設計における自分自身の選択を他者に知らせることができる。これらは非常に良いことずくめだ。
モノリポの利点を公に語っている組織は Google だけではない。Microsoft、Netflix、Uber も、モノリポのアプローチへの信頼について公言している。DORA はモノリポ関連で相当な量の発表を行ってきた。
モノリポこそが「たった1つの真のやり方」なのかという質問が出るのも無理はない。比較として、オープンソースのコミュニティは、一見したところ数限りないプロジェクトのリポジトリー群の上に成り立つ「メニーリポ」アプローチを取りつつも特に問題なく機能しているように見える。
答えを短く言うと否である。モノリポのアプローチが、万人にとって完璧な答えであるとは、我々は考えていない。重要なのはモノリポを重視するかどうかではない。重要なのは、既に組織内で利用されている何らかのライブラリーへの依存関係を開発者が追加する場合に、どれだけ無駄な労力なくそれを行えるかということである。
OSS の世界でのプラクティスの多くは、自由の優先、協調の欠如、計算リソースの欠如に由来している。OSS の世界の別々のプロジェクトは、実際には、お互いのコードをたまたま見ることができるだけの別々の組織である。1つの組織の内部では、もっと多くの前提条件を設けることができる。コンピュートリソースの可用性を前提条件にでき、協調を前提条件にでき、ある程度の量の中央集権的な権力が存在することを前提条件にできる。
モノリポへの反対論のほとんどは、単一の大きなリポジトリを持つことの技術的制約を主に指摘している。リポジトリーのクローン処理に開発者の時間が何時間も無駄にかかるなら、組織がそのようなものを敬遠する理由は容易に理解できる。我々は大規模にスケールする内製 VCS を提供することでこの罠を回避した。
過去数年の Git への主要な改善点を眺めると、より大規模にリポジトリーをサポートするために多くの作業が行われているのが明らかである。すなわち、シャロークローン、スパースブランチなどだ。我々は、こうした改善作業が続き、「だがリポジトリーは小さく保たなければならない」という話の重要性が減少していくことを期待している。
また粒度の細かいリポジトリーとモノリポをスマートな形で混合するメカニズムを提供することが増えている。Git サブモジュールは、現代的な開発者が、モノリポのコストと欠点なしに、モノリポの挙動の弱近似となるものを合成して作れるようにしている。粒度の細かいリポジトリーは、スケール(Git は、数百万回のコミット後にパフォーマンスの問題が出ることが多く、またリポジトリーが大きなバイナリアーティファクトを含むとクローン処理が遅くなる傾向がある)の点で扱いやすい。バーチャルモノリポ(virtual-monorepo / VMR)スタイルのリポジトリー内に粒度の細かいリポジトリーを設けることで、共通ユーティリティへのアクセスを許容しつつも、実験的なプロジェクトや極秘のプロジェクトを容易に分離することができる。
モノリポのアプローチに対する真っ当な懸念点は、組織がスケールアップするにつれて、全コードが、法律、コンプライアンス、規制、機密、プライバシーの全てについて全く同じ要件に服している見込みがだんだん減る点だ。メニーリポのアプローチに固有の有利な点は、別々のリポジトリーが、権限のある開発者、可視性、パーミッション等のセットを個別に持つことが、当然ながら可能であることだ。この特徴をモノリポに継ぎ足すことは可能だが、カスタマイズと保守の面での、多少の継続的な維持コストを伴う。
換言すると、組織内の全プロジェクトに同じ機密、法律、プライバシー、セキュリティの要件があるなら、真のモノリポは進むべき道として申し分ない。そうでない場合、モノリポの機能性は目指すものの、モノリポの体験を別の様式で実装するという柔軟性を提供すべきだ。
近い将来、VCS は大規模リポジトリーでより優れたパフォーマンスを可能とすることと、プロジェクトの境界を超えてリポジトリー群を縫合するための VMR としてのより優れたメカニズムを提供する方向に進化していくことを我々は予期している。
17 章〜25 章 #
(省略)
その他 #
本書の著者たちが応じたインタビューが以下に掲載されている。
- Software Engineering at Google: Practices, Tools, Values, and Culture
- https://www.infoq.com/articles/software-engineering-google/