見出し画像

[書評] Googleのソフトウェアエンジニアリング ~持続可能なプログラミングを支える技術、文化、プロセス

Google流ソフトウェア開発の実践術
この本では、Googleにおけるソフトウェア開発の実践が詳細に解説されています。

具体的には、エンジニア文化の醸成、アジャイル開発手法の適用、静的コード解析ツールの利用など、Googleならではのソフトウェアエンジニアリングの考え方と手法が紹介されています。

巨大なソフトウェアシステムを開発・運用するうえでの知見が豊富に盛り込まれているため、読者のソフトウェア開発力向上に役立つ内容となっています。

高品質なソフトウェア構築の実践的なガイドブックとして、3,872円の価値は十分にある良書です。ぜひ参考にしてください。
目次及び章節のタイトルについては、「Googleのソフトウェアエンジニアリング」からの引用となります。

購入先: O'Reilly Japan - Googleのソフトウェアエンジニアリング
原書: Software Engineering at Google
著者名: Titus Winters、Tom Manshreck、Hyrum Wright 編、竹辺 靖昭 監訳、久富木 隆一 訳
出版日: 2021年11月
価格: Ebook 3,872円



1章 ソフトウェアエンジニアリングとは何か

ソフトウェアエンジニアリングとプログラミングの違いについて説明しています。ソフトウェアエンジニアリングは時間と変化を考慮し、スケールと効率を重視する点でプログラミングと異なります。

重要なポイント

  • ソフトウェアエンジニアリングは時間と変化を考慮する

  • コードの想定稼働期間が長いほど、外部要因の変化への対応が重要になる

  • Hyrumsの法則:APIのユーザーはその挙動に依存するため、APIの変更は困難

  • 組織が拡大するにつれ、ソフトウェア開発のプロセスもスケールする必要があります

  • 短期間で開発・使用されるソフトウェアには時間と変化を重視する必要がない場合もある

  • 小規模な組織では、スケールするプロセスよりもスケールしないプロセスの方が適切な場合もある

ソフトウェアエンジニアリングの特徴として、時間と変化、スケールと効率、そしてそれらのトレードオフを取り扱うことをあげています。これらの観点を意識することで、長期にわたって価値を提供し続けるソフトウェアの構築を目指すことができます。


2章 チームでうまく仕事をするには

ソフトウェア開発を成功させるために必要な文化的側面について説明しています。ソフトウェア開発は個人的な取り組みではなく、チームによって進められるものであるという考え方が重要です。また、謙虚、尊敬、信頼という3本柱が健全なチームを形成する基盤となることが強調されています。

重要なポイント

  • ソフトウェア開発はチームによる取り組みである

  • 謙虚、尊敬、信頼の3本柱が健全なチームを形成する基盤となる

  • 早期発見、高いバス係数、迅速な進捗の面で共同作業が有利

  • 心理的安全性が学びを促進する重要な要素である

チームプレイの重要性が説かれていますが、個人の才能や状況によっては単独での開発も可能です。チームワークのあり方には個人差もあり、具体化が難しい側面もあります。



3章 知識共有

組織内での知識共有の重要性と方法について説明しています。組織の成功には専門家の育成と知識の共有が欠かせません。心理的安全性のある環境づくりが重要で、ドキュメント作成やメンタリング、共有掲示板の活用などの実践が推奨されています。

重要なポイント

  • 専門家の知識を組織内で共有することが成功の鍵

  • 心理的安全性のある環境が知識共有を促進する

  • メンター制度や共有掲示板が知識共有に効果的

  • ドキュメント化も重要だが、人的交流の代わりにはならない

  • 組織の発展段階に応じ、知識共有のバランスを調整する必要がある

知識は人にあると同時にドキュメントにもあるべきで、状況に応じた適切なバランスが求められます。心理的安全性が前提となり、メンタリングやドキュメント作成、共有掲示板の活用などが知識共有力の向上につながります。


4章 公正のためのエンジニアリング

ソフトウェアエンジニアリングにおけるダイバーシティ、エクイティ、インクルージョンの重要性が説明されています。ソフトウェアは社会に広範な影響を及ぼす可能性があるため、公正さを実現する責任があるとしています。

重要なポイント

  • バイアスはデフォルトの状態であるため認識が必要

  • ダイバーシティの必要性を理解し多文化理解能力を高める

  • 一本槍のアプローチは危険で確立されたプロセスにも注意

  • 価値観ではなく結果を重視する

  • 好奇心を持って新しい視点に挑戦することが重要

ソフトウェアが社会に広範な影響を及ぼし得ることから、公正さへの配慮が欠かせないと説いています。社会的影響を考慮し、多様な視点を取り入れることの重要性が述べられています。



5章 チームリーダー入門

ソフトウェアエンジニアリングチームのリーダーとして必要な資質と心構えについて解説されています。チームリーダーにはマネージャーとテクニカルリーダーの役割があり、移行期の苦労とアンチパターン、建設的なリーダーシップの態度が例示されています。

重要なポイント

  • マネージャーは組織面、テクリードは技術面を担当

  • リーダー移行期は困難だが克服は可能

  • アンチパターンを認識し、建設的パターンを実践する

  • 謙虚さ、相手の立場に立つ思考が重要

  • 満足度調査でフィードバックを得る

  • 信頼と自主性が能力を引き出す

チームリーダーには様々な課題が待ち受けますが、アンチパターンを認識し建設的な態度を心がけることで、信頼され尊敬されるリーダーとなることができます。謙虚な学びの姿勢が不可欠です。


6章 スケールするリーダー

組織のスケールに合わせてリーダーシップをスケールさせる方法について解説されています。意思決定の迅速さ、他者への任せ方、自身のリソースの保護が重要だとしています。

重要なポイント

  • 決定はできる限り早く下す

  • 任せるべきことは任せる

  • 自分の時間と精力は大切にする

  • 問題空間の分割が効果的

  • 成功と失敗のサイクルを利用する

  • 重要なことと緊急なことを区別する

スケールする組織のリーダーにとって、迅速な意思決定、適切な任せ方、自身のリソースの適切な配分が鍵となります。これらを意識的に実践することで、スケールに合わせたリーダーシップを発揮することができます。



7章 エンジニアリング生産性の計測

ソフトウェアエンジニアリングにおける生産性の計測とその意義について解説されています。ゴールの設定、適切な指標の選定、データに基づく検証が生産性向上に効果的だとしています。

重要なポイント

  • 生産性の計測はコストと価値のバランスが大切

  • ゴールの設定が先決

  • 指標はゴール達成を反映するものを選ぶ

  • データに基づき指標の妥当性を検証

  • 計測結果を行動変容につなげることが重要

生産性の計測は適切に行わないと逆効果になります。ゴール達成に資する指標を設定し、データに基づいて検証することで、生産性向上に寄与する計測が可能となります。


8章 スタイルガイドとルール

ソフトウェア開発におけるコーディングスタイルのルール設定とその意義について解説されています。ルールの設定と運用、適用の在り方がコードの品質向上と開発効率の改善につながるとしています。

重要なポイント

  • 一貫性のあるコーディングスタイルがコードの可読性を高める

  • ルール変更のプロセスを明確化する

  • 自動チェックツールを活用する

  • コードフォーマッターでの自動整形が効果的

  • ルールは柔軟に、状況に応じて運用する

適切なルール設定と自動チェックツールの活用で、コードの品質と開発効率が向上します。ただし、状況に応じた柔軟な運用が必要です。ルールは開発を支援する手段であって目的ではありません。


9章 コードレビュー

ソフトウェア開発におけるコードレビューの意義と方法について解説されています。レビュープロセスと効果的な実践がコードの品質向上につながると説明しています。

重要なポイント

  • コードレビューは品質向上、知識共有、心理面で有益

  • 小さな変更単位、適切な説明が効果的

  • 礼儀正しく建設的なフィードバックを心がける

  • レビュワーは最小限にとどめる

  • 状況に応じたレビューの形式を使い分ける

適切なプロセスと実践により、コードレビューは品質向上と知識共有に大いに貢献します。コードへの思い入れを排し、建設的な議論を心がけることが重要です。


10章 ドキュメンテーション

ソフトウェア開発におけるドキュメンテーションの意義と方法について解説されています。ドキュメンテーションはコードと同様に扱うべきで、ターゲットと内容を明確化することが重要だと説明しています。

重要なポイント

  • ドキュメンテーションはコードと同様に扱う

  • 対象読者を意識したドキュメントを作成する

  • リファレンス、チュートリアル、概念ドキュメント等を作成

  • ドキュメントもレビューする

  • 始め方・構成・要点を明確化する

  • 不要になったドキュメントは廃止する

ドキュメンテーションの効果を最大化するには、読者と目的を明確化し、適切に構成することが重要です。作成だけでなくレビューや廃止も意識する必要があります。


11章 テスト概観

ソフトウェアテストの意義とアプローチの基本について解説されています。テストの目的はコードの正しさを担保しリグレッションを防ぐことであり、網羅的なテストスイートの構築が重要だとしています。

重要なポイント

  • テストの目的はコードの正しさとリグレッション防止

  • 高速なフィードバックループが重要

  • テストスイートは網羅的であるべき

  • ユニットテスト、統合テスト、エンドツーエンドテストを行う

  • テスト可能な設計、コードカバレッジ等にも注意

  • テストの文化とプロセスがテスト力を左右する

コードの正しさを担保するには、網羅的なテストスイートと迅速なフィードバックループが必要不可欠です。またテストを支えるプロセスと文化的な要因も重要です。


12章 ユニットテスト

ソフトウェア開発におけるユニットテストの意義と方法について解説されています。保守性の高いテストコードの書き方と、テストと本番コードの適切な関係付けが重要だと説明しています。

重要なポイント

  • テストコードの保守性が重要

  • 公開API経由でのテストが望ましい

  • 状態をテストすることが望ましい

  • 一つの検証につき一つのアサーション

  • テストと実装コードは分離する

  • 過剰なDRY(Don't Repeat Yourself)は避ける

  • テストデータと仕組みの共有化でDRY

ユニットテストの効果を最大化するには、テストコード自体の保守性に注意し、適切に実装コードと関係付けることがポイントです。テストコードは実装コードとは異なる設計思想が必要です。


13章 テストダブル

テストでのテストダブル技法について解説されています。テスト対象システムの依存部分を置換することで、テストを隔離し保守性を高められると説明しています。

重要なポイント

  • テストダブルは依存部分の置換技法

  • フェイク、スタブ、モックなどの手法がある

  • 過剰なスタブはテストを脆弱化するリスクあり

  • 状態のテストが望ましい

  • テストダブルもテスト対象とする

  • 適材適所でテストダブル技法を使い分ける

テストダブルは過剰使用に注意が必要ですが、適切に用いることでテストの保守性と隔離性を高めることができます。状態のテストに重点を置くことが大切です。



14章 大規模テスト

ソフトウェア開発における大規模テストについて解説されています。大規模テストはシステムレベルでの動作を確認するもので、網羅性と検証が重要だとしています。

重要なポイント

  • 大規模テストはシステムレベルでの動作確認

  • 実運用に近い設定でテストすることが重要

  • 網羅的なテストデータと検証が必要

  • 機能テスト、性能テスト、設定テスト等を行う

  • テスト結果は開発プロセスに組み込む

  • 大規模テストにはコストがかかるため吟味が必要

大規模テストは実施コストが高いため、網羅性と効率性に注意が必要です。テスト結果を迅速に開発プロセスにフィードバックすることが重要です。


15章 ソフトウェアと機能の廃止

ソフトウェアや特定の機能の廃止について解説しています。廃止は適切に管理され、前もって計画されるべき重要なプロセスです。廃止はしばしば難しく、考慮すべき要素が多いため、それに対応するためのツールや手法が必要です。

重要なポイント

  • ソフトウェアや機能の膨張を防ぐために廃止が必要

  • 廃止は難しいプロセスであり、適切な計画と管理が必要

  • 廃止の方式には、勧告的廃止と強制的廃止の2つがある

  • 廃止プロセスの管理は非常に重要で、一貫性と明確性が求められる

  • 廃止に向けてのツールや支援を用意することが望ましい

ソフトウェアや機能の廃止は、コードや機能の膨張を防ぐために重要なプロセスです。しかし、これは難しく、十分な計画と管理が必要です。また、適切なツールや支援を用意することで、このプロセスを効果的に管理することが可能です。


16章 バージョンコントロールとブランチ戦略

ソフトウェア開発におけるバージョンコントロールの重要性と、ブランチ戦略の異なる手法について解説しています。バージョンコントロールはコードの変更履歴を記録し追跡するための重要なツールであり、ブランチは並行作業を可能にするもので、その適切な管理と使用が開発効率に大きく影響します。

重要なポイント

  • バージョンコントロールはコードの変更履歴の記録と追跡を可能にする

  • バージョンコントロールの方式には分散型と集中型の2つが存在する

  • ブランチは並行作業を可能にするためのコードの分岐である

  • 一般的には開発ブランチとリリースブランチが使われる

  • ブランチは管理が容易になるように必要最小限に保つべき

  • ある状況下では、単一ブランチが最適な場合もある

  • モノリシックリポジトリの利用も一つの考慮点となる

バージョンコントロールとブランチ戦略は、複数人でのソフトウェア開発において重要な役割を果たします。変更履歴の適切な記録と追跡、並行作業の効率化、そしてコードの保守性を保つためにこれらは必要不可欠です。


17章 Code Search

17章では、ソースコード検索ツールの一つであるCode Searchについて詳細に説明しています。Code Searchはソースコードを検索するためのツールで、これを使うことでコードの再利用性と可読性を高めることが可能となります。

重要なポイント

  • Code Searchはソースコードを効率的に検索するためのツールである

  • コードの再利用性と可読性を向上させる役割を持つ

  • 専用のウェブツールとして実装されることが多い

  • 検索速度とインデックス作成速度はその性能を評価する重要な指標である

  • 検索インデックスとランキングアルゴリズムがその核心機能を構成する

  • 完全性と表現力の間にはトレードオフが存在する

  • 開発ツールとの統合が開発者の生産性を高める

Code Searchは大規模なコードベースを効率的に検索するための重要なツールとして位置付けられています。高速な検索と適切なランキングが求められ、他の開発ツールとの統合により開発者の生産性を一層向上させることが可能となります。


18章 ビルドシステムとビルド哲学

18章では、ソフトウェア開発におけるビルドシステムとその設計思想について詳しく説明しています。ビルドシステムはソースコードから実行可能なファイルを生成する工程を管理し、その過程での依存関係管理が重要な課題となります。

重要なポイント

  • ビルドシステムはソースコードから実行ファイルを生成する役割を持つ

  • 依存関係の管理はその成功にとって不可欠である

  • ビルド手法は大きくタスクベースとアーティファクトベースの2つに分類できる

  • 分散ビルドはスケーラブルなビルドシステムのための一つの解決策である

  • モジュール設計と依存関係管理がビルドシステムの設計において重要な観点である

  • 時間、スケール、トレードオフを考慮した設計が求められる

ビルドシステムの設計には、依存関係、分散処理、モジュール分割といった要素を総合的に考慮する必要があります。特に、スケーラビリティと信頼性を確保するためには、これらの要素をバランス良く設計することが重要となります。


19章 GoogleのコードレビューツールCritique

19章では、Googleが開発したコードレビューツールであるCritiqueについて詳しく説明しています。Critiqueはコードレビューを効率的に行うためのツールであり、コード変更の作成、レビュー依頼、コメント付加といったプロセスを支援します。

重要なポイント

  • Critiqueはコードレビューを支援するためのツールである

  • コード変更の作成、レビュー依頼、コメント付加など、コードレビューのプロセス全般を支援する

  • ディファレンシャル表示を用いて変更箇所を強調する

  • 静的解析の結果を活用してコードの問題点を提示する

  • スコアリングによりレビュー完了の判断を行う

  • 他の開発ツールとの緊密な連携が求められる

Critiqueはコードレビューという重要な開発プロセスを効率的かつ効果的に行うためのツールです。変更内容の可視化や静的解析結果の活用、そして他の開発ツールとのシームレスな統合がその成功の鍵となります。


20章 静的解析

20章では、ソースコードの静的解析について説明しています。静的解析はコードを実行せずにその構造や内容を解析し、バグや品質の問題を早期に発見する手法です。

重要なポイント

  • 静的解析はソースコードを実行せずにその構造や内容を解析する手法である

  • バグや品質の問題を早期に発見するために利用される

  • スケーラビリティとユーザビリティはその性能を評価する重要な指標である

  • 開発プロセスに深く統合されることで最大の効果を発揮する

  • ユーザーが自身のニーズに合わせてカスタマイズできることが求められる

  • Googleが開発した静的解析ツールであるTricorderが紹介されている

  • コンパイラーとの連携もその有効性を高める

静的解析はコードの品質を向上させるための重要なツールであり、使いやすさと大規模なコードベースへの対応能力が求められます。また、コンパイラーとの連携もその有効性を高めます。


21章 依存関係管理

21章では、ソフトウェア開発における依存関係の管理について詳しく説明しています。依存関係管理は外部ライブラリなどのバージョン管理を行うもので、競合する要件の調整が難しい一方で、開発において避けて通れない課題となります。

重要なポイント

  • 依存関係管理は外部ライブラリなどのバージョン管理を行うものである

  • 競合する要件の調整が難しく、セマンティックバージョニングが一般的に用いられる

  • 最小バージョン選択、バンドリングなどの戦略が存在する

  • 依存関係のエクスポートも重要な考慮事項である

  • 時間、ス

ケール、トレードオフを考慮した設計が求められる

依存関係の管理は、時に困難な課題を伴いますが、適切に管理することで開発の効率性と安定性を高めることが可能となります。バージョン競合の解決や、依存関係のエクスポートなど、柔軟な対応が求められます。


22章 大規模変更

22章では、大規模変更(Large-Scale Changes, LSC)について解説しています。LSCは、広範囲にわたるコードベースに影響を及ぼす変更を指します。その規模と影響から、これらの変更を適切に管理し実行するためには、通常の開発プロセスでは対応できない特殊な手法やツールが必要となります。

重要なポイント

  • LSCは広範囲のコードベースに影響を及ぼす変更であり、その管理と実行は通常の開発プロセスでは対応できない

  • LSCを成功させるためには、専用のプロセスとインフラが必要です

  • LSCは、シャード(管理可能な単位)に分割され、各シャードは領域ごとのオーナーによって管理されます

  • 大規模な変更を適切に行うためには、大規模テストが必要不可欠であり、これにより予期しない問題を早期に検出できます

  • LSCにおけるコードレビューは並列化され、時間を効率的に使うことができます

  • 言語に対する支援やコード移行ツールの利用も重要で、これによりLSCの効率と効果が向上します

大規模変更は複雑であり、その成功は十分な計画と準備、適切なツールとプロセスの適用に依存します。その影響範囲を適切に管理し、変更を管理可能な単位に分割し、テストとレビューを通じて問題を早期に発見することが重要です。


23章 継続的インテグレーション

ソフトウェア開発プラクティスの一つである継続的インテグレーション(Continuous Integration, CI)について解説しています。CIは、開発者が作業を頻繁にマージし、そのたびに自動的にビルドとテストを行うというプラクティスです。

重要なポイント

  • CIは、開発者が頻繁に自分の作業をマージし、それに続いて自動的にビルドとテストを行うというプラクティスです。

  • CIの目的は、フィードバックループを短縮し、問題を早期に発見・修正することです。

  • テストの自動化は、CIの中核的な部分であり、各マージに続くテストを自動化することで、問題を即座に検出することが可能となります。

  • CIを実施するには専用のCIサーバーやその他のインフラが必要となります。これらはCIプロセスの一部となり、コードがマージされるたびにビルドとテストが行われることを保証します。

  • CIはただのツールセットではなく、組織全体でのプロセスの変革を必要とするため、その導入と実施は慎重に計画され、徐々に行うべきです。

CIは開発の効率と品質を向上させる強力なツールですが、その成功は自動化の程度と、組織全体でのプロセス変革に大いに依存します。


24章 継続的デリバリー

ソフトウェア開発プラクティスの一つである継続的デリバリー(Continuous Delivery, CD)について詳述しています。CDは、ソフトウェアのリリースプロセスを自動化し、頻繁にかつ一貫性を持ってリリースを行うプラクティスです。

重要なポイント

  • CDは、ソフトウェアのリリースプロセスを自動化し、小規模かつ頻繁なリリースを可能にするプラクティスです。

  • CDの中心的な考え方は、完全なリリースを待つのではなく、リリース可能な最小単位を頻繁に繰り返しリリースすることです。

  • リリースプロセスの自動化は、CDの重要な部分であり、すべてのリリースが一貫性を持ち、かつリリースを行った後に問題が発生した場合には迅速にロールバックできるようにします。

  • リリースのスケジューリングと管理には「リリーストレイン」のような手法が必要となります。

  • データを活用した意思決定が、リリースのタイミングや頻度、またその他の関連事項についての決定には重要となります。

  • CDはただのツールセットではなく、組織全体のプロセスと文化の変革を必要とします。そのため、CDの導入と実施は段階的に行うべきです。

CDはソフトウェア開発の効率と品質を向上させる強力なツールですが、その成功は自動化の程度と組織全体のプロセス変革に大いに依存します。


25章 サービスとしてのコンピュート

サービスとしてのコンピュート(Compute as a Service: CaaS)について詳しく説明しています。CaaSは、ユーザーがサーバーやインフラストラクチャを直接管理する代わりに、クラウドプロバイダーがそれを提供し管理するサービスを指します。

重要なポイント

  • CaaSは、クラウドプロバイダーが提供・管理するコンピュートサービスである

  • インフラの自動化とコンテナ化がその基盤であり、アプリケーションのスケーリングや運用を容易にする

  • ステートレスなデザインやバッチ処理といった用途に特に適している

  • サービスを抽象化し均一化することで長期的なスケーリングと維持が可能となる

  • マネージドサービスの利用は、メリットとともにトレードオフも存在する。例えば、コストやセキュリティ、カスタマイズ性など

  • パブリッククラウドとオンプレミスとの比較検討が必要で、使用するアプリケーションの要件により最適な選択が変わる

CaaSは、インフラの管理をクラウドプロバイダーに委ねることで、アプリケーションの開発や運用に集中できるというメリットがあります。しかし、どのタイプのインフラストラクチャを選択するかは、アプリケーションの要件やコスト、セキュリティなどの要素を総合的に考慮する必要があります。パブリッククラウドとオンプレミスのそれぞれのメリットとトレードオフを理解し、適切に評価することが重要です。


おわりに

"Googleのソフトウェアエンジニアリング"は、Googleがどのように大規模なソフトウェア開発と保守を行っているかを理解するための必読書です。特に、組織全体が持続可能に協力し、調整を進めるための手法に焦点を当てています。

本書の主な対象はソフトウェア組織のポリシーメーカーや意思決定者、また学生たちです。Googleがどのようにベストプラクティスを形成し、どのような理由でそのようなアプローチを取るのか理解することができます。

本書ではソフトウェアエンジニアリングを「多人数による多バージョンのプログラムの開発」と定義し、それが時間を経ても持続可能な方法で問題を解決するためにどのようにチームと協力するかに焦点を当てています。

チームの創造性、信頼、謙虚さ、互いの尊重を育むことの重要性を強調しています。心理的安全性と失敗の受け入れが学習の鍵となります。

また、Googleが多文化的な能力を育むためのさまざまな取り組みをどのように行っているかを紹介していますが、平等と多様性に関する課題はまだ残っていると認めています。

Googleのコードレビューは、欠陥の検出よりもむしろ教育や共有理解のためのものであり、レビュワーとレビュイーの双方に学習の機会を提供します。

静的解析により、バグを早期に見つけて修正することが可能です。これにより一部のバグをより効率的に特定できます。

Googleは基本的に「ブランチなし」の戦略を採用しており、全員が同一のコードベースを操作し、分岐を避けて変更をインクリメンタルに行います。

外部の依存関係の管理は制御が難しく、互換性の問題が発生しやすいです。そのため、Googleでは外部依存性を最小限に抑え、依存性のバージョン数を制限するようにしています。

効率性を追求するには選択肢が敵であることが多いため、Googleはバージョン管理や依存関係管理においてエンジニアから選択肢を取り除く方針を採用しています。選択肢がなければ、問題もないというわけです。

参考文献

Titus Winters、Tom Manshreck、Hyrum Wright 編、竹辺 靖昭 監訳、久富木 隆一 訳 (2021) 「O'Reilly Japan - Googleのソフトウェアエンジニアリング

この記事が気に入ったらサポートをしてみませんか?