Googleのソフトウェアエンジニアリングを読んだ
メモ書き程度に書いていく。
ch 5¶
リーダーやマネージャーについて書かれた章。
- 権限がなくても広範囲に影響を与えることができる
- マネージャーとメンバーで親子のような関係にならないように気を付ける
- 人の問題を無視してはいけない
ch 8¶
スタイルガイドとルールについて書かれた章
- ほとんどのエンジニアリング組織にはコードベースを管理するルールがある。フォーマットや命名、パターン、例外、スレッドなどに関するルール
- ルールは法律であり厳格で強制的。普遍的に施工可能であり、承認を得た場合を除いてルールを無視できない
- ルールとは別に推奨事項やベストプラクティスを提供するガイダンスを設ける。これに従うことを推奨するが、多少の変更の余地がある
- ルールを設ける理由は良い行動を奨励し、悪い行動を防ぐため
- コードを読む人のために最適化、一貫性を保つ、エラーが起こりやすい構造を割ける、必要に応じて実用性を認める
- 静的チェッカーやフォーマッターを使って機械的にチェックする
ch 9¶
コードレビューについて書かれた章
- readability の確認
- commit 前にレビュー
- code owner を設ける
- 完璧なコードでなくても今のコードより良くなるのであれば、受け入れるという組織での合意
- コードを書く時に本当にその機能が必要か確認する。誰かがすでに同じことをやってるかもしれないし、コードを書かずに解決できる課題かもしれない
- シフトレフトで早めにミスを検知する
- コードは一度書かれると何度も読まれる
- 24(営業)時間内のレビュー
- 200 行以内の変更
- PR の 35%が 1 つのファイルだけの変更
- レビュワーを最小限にする
ch 10¶
ドキュメンテーションについて書かれた章
- 自分のために書くドキュメントも良いが、読む人を意識したドキュメントをこころがけよう
- ドキュメントはすぐにその効果を得られるわけではなく、後からその効果が得られることが多い。組織が拡大した場合など
- ドキュメントにもオーナーが必要
- 読者を特定したうえでドキュメントを書き始める(経験・ドメイン知識・目的を考慮)
- Design Doc はアーキテクチャのトレードオフについて書こう
ch 11 - ch 12¶
テストについて書かれた章
- テストは、エンジニアの信頼によってその価値を発揮するもの
- もしテストが生産性の低下を招き、常に労力と不確実性をもたらすものであれば、エンジニアは信頼を失い、回避策を見つけるようになる
- 開発を円滑に進めたいのであればテストの自動化が must
- 最も重要なことは、プロセスに対する高い信頼性を維持するために、壊れたテストを迅速に修正することに重点を置くこと
- テストのメリット:デバッグの軽減、変化に対する自信の向上。ドキュメントの補足。レビューをシンプルにできる。コードの責務を意識できる。迅速かつ高品質なリリースの実現
- エンジニアは大規模なシステム規模のテストを書くことを好むが、そのテストは小規模なテストよりも遅く、信頼性が低く、デバッグが困難である
- test サイズを意識する
- 何を unit test, integration test と呼ぶかは色々流派があって統一が難しい。単一のプロセスで完結するものを small、単一のマシンで完結するものを medium(Docker compose のようなイメージ)、複数のマシンで完結するものを large と呼ぶことにする。
- テストは small が多く、medium が少なく、large はほとんどないというピラミッド型の関係になるのが理想
- テストが小さくなるほど不確実性が減り、テストの信頼性が高くなる。テストが小さくなるように mock などを活用する
- テストサイズが大きくなると実行時間が長くなったりフレイキーになる
- 既存の社員をいきなり教育するのは難しいので、新しい社員のオンボーディングでテストについて教育し、そのメンバー達からテストに対する文化をひろげた
- 公開されてる API を通じて(ユーザーと同じ方法で)テストする
- プライベートな実装は公開されてる API を通じてテストされる
- ふるまいのテスト
- フレイキーなテストは生産性を下げるので減らす
- テストは DRY ではなく DAMP のほうがいいよ
- テストでは DRY 原則を多少破ってもわかりやすさを重視。ファイルジャンプが多いと理解しづらい
- テストコードは頻繁に読まれるものではないので、メソッド名が長くていい。名前見て何してるか説明的なのが良い
-
テストの中で条件分岐やループのような制御フロー文の使用を強く推奨しない。より複雑なテストフローは、それ自体がバグを含む危険性があり、テスト失敗の原因究明をより困難にする。
- テストにロジックを入れるな。ロジック:演算子、ループ。分岐など
- Google ではなるべく mock を使わず本物を使うらしい
- あるシステムが特定の動作をすることを確信したいのであれば、その動作を確認する唯一の方法は、そのための自動テストを書くこと
- コードと対象のテストを書く間隔が短いほどいい。後回しにしない
- 複数の動作を同時にテストしない
ch 18¶
build system について書かれた章
- 外部の依存関係の更新によってビルドが壊れないようにバージョン管理が不可欠
- 依存関係を自動で推測してビルドしてくれるシステムがあると楽
- Pants Python の依存関係を自動で推測してくれるので好き
- 推移的な依存関係の管理難しそう
- shell でビルドするのメンテナンスが大変
- ビルドシステムの拡張。デプロイ用の goal とか作りたい
- アーティファクトベースのアプローチは再利用と並列的な面でメリットがある
- Google だとバイナリが数万のターゲットに依存されてることもある
- リモートキャッシュと分散ビルドで解決
- リモート実行にすることで各ローカルマシンで毎回ビルドしない
- モジュールの粒度が大きいと並列ビルドができない。毎回大きなビルドが走る
- 各ディレクトリで 1 つのパッケージ、ターゲット、BUILD ファイルにすることで依存を小さくする
- ビルドターゲットを小さくすると、分散ビルドが速くなり、ターゲットの再構築の頻度が減る
- 不必要にモジュールを public にしない
- ほとんどの BUILD ファイルは、public なターゲットを 1 つだけ持つ
- バージョン指定しない latest 依存は事故のもと
- ダイヤモンド依存は避けたい
- コードのサードパーティ製の依存は 1 つのバージョンのみにする
ch 23 - ch 24¶
CI/CD について書かれた章
- システム開発の後ろの工程になるほどバグが見つかる
- カナリアテストで少しずつ変更を試す
- FeatureFlag
- コードが古く、規模が大きいほど CI が必要
- 本番環境相当でベンチマークしないと意味ない
- 利用されないものはリリースしない
- 頻繁に小さな単位でリリース
- リリーストレイン
- CI は製品の安全性を高め、開発者の幸福度を高める
ch 25¶
コンピューティングについて書かれた章
- トイルの削減の手法として自動化と監視、スケジューリングがある
- CPU やメモリといったリソースの見極めは人間がやるのは難しい。機械的にやっていい
- サーバレスは 0 までのスケールインが魅力
- サーバレスは一定の制御が失われる。これはトレードオフでコントロールできる状況であればコントロールしにいかなけれなばいけない
- サーバレスを使う時はステートレスを意識
- バッチはスループット重視で生存時間は比較的短め
- サービングはレイテンシ重視。長期間立ち上がっていることが多く、あらゆる点でバッチより耐障害性が高い
- サービングは大抵オーバープロビジョニングする必要がある
- サービング用にオーバープロビジョニングして過剰リソースにバッチジョブを割り当てられると良い
- サービスの接続をハードコードしている場合はそのインスタンスが交換可能でない。間接的なレイヤーを経由して接続したほうがいい
- Borg は 2003 年からあるプロジェクト
- 共有クラスタは複数のチームで使ってコスト的なメリットがでる