Software Engineering at Google 2020年11月に、一人で読んでいる。
arxiv にある同名の文章 Software Engineering at Google by Fergus Henderson とは無関係らしい。
以下、章のタイトルと、おすすめ度。★ なし(つまらない)から★2(必読)。私の感想や、サマリー。
1. What Is Software Engineering?★
プログラミングと、ソフトウェアエンジニアリングの違いは、何十年にも渡って使われ続ける必要のあるものを対象とするかどうかである。後者は、メンテナンスのしやすさが重要となる。
Hyrum’s Law:API の利用者が多くなれば、あなたが公式に約束していることだけでなく、あなたのシステムの振る舞いすべてが、誰かによって依存されている。
2, How to Work Well on Teams
ソフトウェアエンジニアリングはチーム作業だ。
3. Knowledge Sharing
チーム内で教えあって、高め合おう。
グーグルには、経験豊富な一部のエンジニアが、すべてのコードの読みやすさをレビューする制度がある。
4. Engineering for Equity
文化、性別などへのあなた自身のバイアスに注意しよう。
5. How to Lead a Team
チームのリーダー心得。
6. Leading at Scale
経営者の心得。
7. Measuring Engineering Productivity
生産性って、なんだろう。迷わずに行数って答える奴のことは知らん。
8. Style Guides and Rules★ ★
Google Style Guides に、言語別のスタイルガイドがある。重要なのは、かっこの位置はどれがいいか、でなくて、 社内の全部のソースが同じスタイルであること。規則を決めたら、ツールでそれが守られているかを判断できること。あるいは、無条件にそのとおりにフォーマットすること。google-java-format, clang-format, gofmt, yapf
スタイルガイドは、かっこの位置ばかりにこだわっているのでなく、使うべきあるいは避けるべき言語機能やイディオム、常識やベストプラクティスも紹介していて、勉強になる。
abseil は、グーグル社内向けC++ ライブラリ。標準ライブラリに無いものを提供したり、誤りを正しているらしい。boost は使っているのだろうか。21 章、Dependency Management を読んだら、それは実験的だと書いてあったから使ってないのだろう。python にも同名のライブラリがある。アップザイレンは、登山用語で、懸垂下降。なんで?
9. Code Review★
スタイルは、前項のツールで確認済み。変更は小さく。お互いに敬意を持って。
ソースコードには、必ず、オーナーが決まっている。OWNERS ファイルに、書いてある。そのファイルやディレクトリを所有する。
10. Documentation
良い設計文書やチュートリアルの書き方。
11. Testing Overview★
Testing on the Toilet という、トイレに貼られたメモを使った、テスト文化を広める試み。
テストは、3種類に分ける。1プロセスで全部動くテスト、1マシンで動くテスト、複数マシンで、ネットワークやディスクI/O を伴うテスト。
単体テスト、統合テスト、とは別の軸らしい。
テストピラミッド。単体テストが80%のテストケース。統合テストが15%、end to end が5%。これをめざす。
コードカバレッジだけを、テストが十分であることのメトリックとしてはいけない。
私の経験では、後述するモックをあまり使わない単体テストだと、カバレッジを上げるのはむつかしい。単体テストをたくさん書くと、こわれやすい。そのへん、どうなのだろう。単体の定義が違うのかも。
なあんだ。60%で、OK なのだ。https://testing.googleblog.com/2020/08/code-coverage-best-practices.html
そうだよな。むりむり、100%をめざすやつは#$%@だとも書いてある。
12. Unit Testing★★
こわれやすいテストは最悪。と、までは、本には書いてない。
https://testing.googleblog.com/2015/01/testing-on-toilet-change-detector-tests.html ここに書いてあった。製品コードがどんなサブルーチンをどの順番で呼んだかを調べるテストは、本当に #@%& だ。
実装をテストするな。外部から見える状態をテストしろ。
13. Test Doubles★★
ダブルとは、いわゆるモック。モックの作り過ぎは良くない。できるだけ、本物のコード同士で動かせ。フェイクとモックは違う意味で使っている。
14. Larger Testing
Larger Test にも、オーナーを決めて、きちんとメンテナンスすること。
15. Deprecation
API の廃止は、難しいね。
16. Version Control and Branch Management★★
git などは使ってない。インハウスの、集中型バージョンコントロールソフトウェアを使っている。
ブランチは1つだけにしろ。long lived developer branch がたくさんあるのは最悪。
トランクに開発中コードをチェックインしてもいいけど、動かないようにしておけ。
トランクに開発ブランチをマージするのは、恐ろしい。バグが混入する。だから、先延ばしにするのでなくて、こまめに、頻繁にマージして、テストで担保しろ。
リリースブランチはあってもいい。出荷済み製品に対して、最小限のバグ修正を入れる。いずれはブランチごと捨てる。トランクへのマージなどは起きないので問題ない。
17. Code Search
グーグル社内のソースコード検索ツール。
既存のソースコードを読んで理解するのは、開発者の重要な仕事で、多くの時間を占めるので、それをサポートするツールは重要。
Kythe は、クロスレファレンスとsemantic indexing ツール。
18. Build Systems and Build Philosophy ★
Blaze という、インハウスのビルドツールをオープンソースにしたのが、 Bazel.
task ベースのビルドツールでなく、 artifact ベースがいい。前者は、開発者が、コンパイラ呼び出しなどを記述する。後者は、ソースコードとバイナリ生成物の関係だけを記述する。後者は分散並列ビルドにも適する。
19. Critique: Google’s Code Review Tool
Critique は、インハウスの、コードレビュー支援ツール。
gerrit は、それとは別の、オープンソースのツール。 Android, Chrome など、社外のオープンソース開発者とやりとりが必要なチームが使っている。
20. Static Analysis ★
Tricoder は、インハウスの、静的解析フレームワーク。30以上の言語をサポートする。ユーザが、解析やチェックを追加できる。開発者の幸せが、最も重要。誤った指摘で時間を奪ってはいけない。 false positive は、5%以内。
Java 用の ErrorProne, C++ 用の clang-tidy も使われる。
具体的なツールや、どうやって、どういうバグを見つけるか、という話は無かった。
参照されている、CACM の記事は、そのへんのことも書いてあって、面白かった。
Lessons from Building Static Analysis Tools at Google ★★
Java の静的解析ツール Error Prone は、FindBugs の失敗から学んだ。
警告を表示しても誰も見ない。コンパイルエラーにして、開発者のワークフローの一部とすることが必要。開発者に嫌われてはいけない。フィードバックが重要。開発者がチェックを contribute できることが重要。
どれだけの指摘を出したかをメトリックとしない。実際に開発者がどれだけのコード修正をしたかが重要。具体的なアクションのできない指摘、理論的にはバグだが現実的な影響のない指摘はごみ以下。と、までは記事は言ってない。
可能なら、自動でコードを修正する。
びみょうな修正は、コードレビューのプロセスの中で、人が判断できるようにサポートする。
ビルドを止めてはいけない。既存の全てのコードが、チェックを通るように直した後、それをコンパイルエラーにする。こうして、コード全体が、レベルアップする。
コードレビューが終わり、チェックインされ、本番稼働しているプログラムに、指摘を上げてもそれに従って直す人はいない。ワークフローの早い時期にやらないと意味がない。
21. Dependency Management★★
怖い章だ。
世の中では、 SemVer といって、major, minor, patch バージョンの3つの数字を使う方式が一般的。 major バージョンの変更は、外部 API の変更を伴い、危険、など。しかし、実はあてにならない。
大規模ソフトウエアでは、依存関係のネットワークが大変。Live at Head は、とにかく最新版を使うポリシー。逆に、依存の満たされる最も古いものにしがみつく戦略もある。解は無い。テストで担保するしかない。
コントロールできない、OSS プロジェクトに依存するときは、よくよく考えろ。10年後にもあるか、互換性を大切にするプロジェクトか。テストはあるか。
gflags の失敗:C++ コマンドラインを処理するライブラリを、2006年ころにグーグルはオープンソースにした。しかし、社内版と OSS版は乖離し、社外で使われる多様なプラットフォームとツールチェーン全てに対するテスト環境をグーグルは持たず、オリジナル開発者は社を去り、プロジェクトは社内の誰も面倒を見るものが無くなった。教訓。「長い期間サポートする計画と権限が無いなら、何かをリリースするな。」
AppEngine の失敗:2014年に、AppEngine は、 python バージョンを上げ、32ビットから64ビットになった。一部の重要顧客はバージョンアップできず、結局、グーグルは3年ほど、両方のシステムを維持することになった。
22. Large-Scale Changes★
Large Scale Change の例:グーグルは、 C++ 標準 unique_ptr ができる前、自前の、 scoped_ptr を使っていた。すべてのソースで、この移行をする必要が生じた。変更して、テスト、を繰り返した。
Rosie は、large scale changes のための、レビューとテストツール。
ソースの変更はツールで自動でできるのがよいが、人が見ないといけないこともある。
ソースコードのスタイルが統一されていることは、ツールによるソース変更にとっても重要。
23. Continuous Integration★
TAP: Test Automation Platform は、グーグルの、 Continuous Build システム。
こわれやすいテストは困る。pre submit テストは最小限に、数分で終わるものに限る。開発者の手を止めてはいけない。post submit テストで発見されるテスト失敗もある。多くの場合、変更はロールバックされる。しかし、変更は複数をまとめてバッチ実行されるので、誰の変更がテストをこわしたのか調べるのが大変。
24. Continuous Delivery
小さい変更、こまめの統合。
25. Compute as a Service★★
Borg が解決したかった課題。スケールと自動化。その進化、設計上のトレードオフ。
stateless は、ほぼ、絵空事。普通の業務には persistent storage が必要。では、 storage server は、 pet かな、 cattle かな?
26. Conclusion
2020年5月に読んだので、忘れてしまった。思い出したら、書く。これもいい本だった。
Building Secure & Reliable Systems これは、無償で公開されている。