『Googleのソフトウェアエンジニアリング』読書メモ・感想

先日、『Googleのソフトウェアエンジニアリング』を読みました。

www.oreilly.co.jp

各章ごとに、気になったトピックなど踏まえながらつらつら感想を書いていきます。

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

「プログラミング」と「ソフトウェアエンジニアリング」という言葉の違いにきちんと言及している書籍を初めて見た気がする。
今まで自分は「プログラマー」なのか、「ソフトウェアエンジニア」なのかよくわからないなと思っていたが、この書籍の定義でいえば、「ソフトウェアエンジニア」となるし、そうでなければいけないと感じた。
つまり、技術スタックや開発チームの長期的な保守性やスケーラビリティが確保されている状態にする仕事を負っている。
特に今は仕事で新しいサービスの開発を行っているので、この点を意識し続ける必要がある。

また、Hyrumの法則(APIを作成すると、あらゆる挙動に依存するユーザーが現れる)は印象に残った。
Rubyで言えばprivateメソッドにしていても使おうと思えば使えてしまうし、インスタンス変数も直接参照することだってできる。(自分もたまにどうしてもgemをカスタムしたいときにやってしまうこともある)

Beyonceルールにも共感した。
少し書籍に書かれている事例とは違うが、とある修正をした結果、CIが通った上で他の機能に障害やバグが起きてしまったのなら、それはその原因を混入したコード(開発者)に責任があるのではなく、その機能のテストをきちんと書けていなかったことが問題という考え方をした方が良さそう。

直前に読んだ『ソフトウェアアーキテクチャの基礎』と同様に、この書籍からも(「はじめに」も含めて、)、「意思決定に絶対的な決定はなく、常にトレードオフがあって、間違える可能性もあるからなるべく早く間違いに気づいて修正できるようにしよう」というメッセージが受け取れた。

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

とにかく全体的に、エンジニアは隠れていないで(一人で閉じこもらないで)、どんどんチームに相談して、失敗を早期に発見して無駄なことに時間を使わず、開発力を上げていけ、ということを言っている章。

「こいつ馬鹿だって思われるんじゃないか」という気持ちで完成前に誰かに見られるのを不安に思う気持ちとか、身に覚えがありすぎて、グサグサ刺さって、時折笑ってしまった。
ただ、Googleに勤めているような人でもこの気持ちになりながら仕事をしていると思うと、おそらく全員のエンジニアが思っているんだなという気持ちになって少し気が楽になったような感じがした。

ジャグリングの例はなるほどなと思った。(ジャグリングの技術を教えられても、自分自身を否定されたようには思わないだろう。コードへの指摘も同じであるはずだ。)
「相手が自分を攻撃するかもしれない」というのは相手を十分に信頼できていないということでもある。

自分は特にチームでの開発で成果を出していきたいと考えている人間なので、この章の書いてあることには強く共感した。
ぜひまた都度読み返したいと思う章だった。

3章「知識共有」

「ずっとアーカイブされることを恐れて質問をしたくない」は、あまり言われないがあると思う。
例えばいつでもslackのチャンネルで質問しても良いよと言われても、後々自分の質問が残っていくことを考えると、質問しづらいと思ったことが自分もある。
そんなケースを救ってくれるのが1対1のメンターをはじめ、口頭で気軽に質問できる場を用意することだなと思った。(あるいは質問を匿名でできる場を用意するのはどうだろう?と思った)

心理的安全性の確立をするには、「なんでも聞いてください!」というだけでなく、自分もその手本となることが必要だと思った。
「リーダーこそ自分のわかっていないことを表明したり素直に質問をすることが肝心で、その方がむしろ尊敬を集める」という記載はとても共感した。

ドキュメント化は、必要だと頭ではわかっていながら、どうしてもコードを書く方に戻りたくなったりして、書かずに置いてしまう心当たりがあったが、これほどまでに必要性を説明されたら、さすがににもう少し書くか…という気持ちになった。 それに関して、URLを技術名にするのはいいアイデアだと思ったし、できるなら試してみたくなった。(keycloakについてのドキュメントはxxx/keycloakなど)

また、Googleのリーダビリティの制度はさすがGoogleだし、改めてすごい世界だ…という感想。

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

基本的に日本で国内向けにアプリケーションを開発しているとなかなか考えない視点の話で興味深かった。
特に、低代表の人にさらに害を与えてしまう可能性の話については、誰かに利益があるようにする裏には、誰かに不利益となるかもしれない、ということだと感じた。
そこで公正ではないことが行われるのであれば、エンジニアとしてストップをする勇気を持ちたい。

5章「チームリーダー入門」

リーダー(マネージャー)の役職に興味がないわけではない自分にとっては参考になる話がとても多かった。
PRなどで目にみえる形で進捗がある開発メンバーに比べ、マネジメントをするようになると「今日は何もしなかった」と思いやすいというのは想像に容易いし、辛い気持ちになりそう。
実際にはマネジメント業務のあれやこれやをしているわけなので、タスクをチケットに切って見える化しておくのも良さそう。

また、マネージャーは管理職と呼ばれたりするが、「管理」という言葉を言葉通り捉えるとマイクロマネジメントに陥るというのは罠すぎると思った。
その中で、「やる方法を気にするのではなく、やり遂げられるかを気にするべき」という箇所は印象に残った。
自分も以前小さいチームのリード的な役割をしていた時を思い返すと、やる方法を気にしていた場面があったような、、と反省した。

自分はマネージャーという役職に興味がないわけではない一方で、なかなかそちらの世界に踏み込めていない一因として、自分はリーダーとして相応しい知識や経験が全く足りないのではないか、というのがある。
ただ、本章を読んで、(もちろん足りない部分があるのは事実だが、)それのみを以て自分には資格がないと思うのは違うか、と考えられるようになった。
自分が勝手に想像するリーダーというのはどんな質問や障害に対しても常に一定の回答と対応ができるような人間で、自分はまだそうなれない、、と思っていたが、思い返せば、多分それができる人はほぼいないし、自分もそんなリーダーを求めているわけでもない(本章にあるとおり、わからないことをわからないと表明してくれるリーダーは良いリーダーだと感じる)ので、前向きな気持ちになった。

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

ここでも『ソフトウェアアーキテクチャの基礎』で何度も出てきた「永久的な正解はなくトレードオフがあるだけなので高速で失敗してイテレーションを回せ」という趣旨の話が出てきた。

本書で出てくる「自動運転チームを構築する」というのは、良い指針だと思った。
リーダーの仕事はもっぱら組織・戦略づくりと方向づけであって、組織に何か課題が発生した時に、しばらく放っておいても自律的にその課題を解消することができるようなイメージだと理解した。(自動運転=リーダーは何もしない、のではなく、自動運転ができる状態を常にメンテナンスするイメージかなと思った)

また、緊急な仕事と重要な仕事の章は印象に残った。
以前公務員として緊急な仕事ばかりしていたときのことを思うと、(中には緊急で重要な仕事もあったけど、)確かに自分が思っているよりは重要な仕事は少なかったかも。
そのため、自分が持っているうちの「自分にしかできない決定的な重要なもの」以外の80%は投げ捨てるべきらしい。(もし投げ捨てたうちに重要なものがあればまた戻ってくる。)
些細な例だが、確かに普段電話があって取れなかった時に「もし大切な連絡ならまたかかってくるでしょ」と思って全部の電話にかけ直したりしないことをしているが、考え方としては近いのかなと思ったりした。

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

計測する価値があるかどうかの判断基準の話が面白かった。
計測した結果が良い結果だったり悪い結果だったりした時に、それぞれきちんと行動がとられなければ意味ない、というのは言われれば当然だが抜けてしまうこともあるのでは、と思った。
良い結果が出ても現状維持だし、悪い結果が出てもなんだかんだ色々理由をつけて維持されることが予想されるようなものに対して計測を行う意味はない。

また、計測するのは必ずしも定量的なメトリクスに限らないというのも参考になった。
どうも定性的な指標は嫌がられるきらいがある気がする(それが正しい場面も多い)が、例えばエンジニアへのアンケートでしか得られない情報も多いのも確かだなと思った。

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

コーディングガイドラインのルールを作る時は「まず組織が何に価値を置くかを認識しなければならない」し、ルールを定義する場合は「どんなゴールを前進させようとしているのか」の質問をするべき、というのはなるほどと思った。
確かにこの観点が抜けるとルールの一貫性がなくなるし、好みの問題じゃんという議論が多くなってしまう気がする。

本題とは関係ないが、Googleは「20億行以上のコードが入ったコードベースに向けて、約6万回のコード提出が毎日行われている」らしく、改めてとんでもない規模だなという感想。

「コードは書かれるより読まれることの方が圧倒的に多い」
これは何度も肝に銘じたい。

「ルールを決定するに背景の根拠をドキュメント化しておくと、変更するときにその根拠を前提に判断できる」
変更するときに効いてくるというのは新しい視点だった。

9章「コードレビュー」

「コードとは債務である」 変更が難しいクラスなど、いわゆる技術的負債のみを債務と考えがちだが、コードを書けば必ず保守が発生する。

コードレビューがもたらす影響についての記載も面白かった。 - エンジニアにコードが「自分個人のもの」ではなく、集合的な事業の一部であるという認識を強化させる - 批判にさらされることを受け入れやすくする - コード提出前の最後の一確認をするようになる

など、心理的な好影響については考えたことがなかった。

以下は、自分の組織だと行なっていないが、導入を検討・提案する余地がありそうと思った。 - レビューコメントに対する修正を行いさえすれば、再レビューを経なくて良いというもの(尊敬と信頼) - 大半のコードレビューはレビュアー1名。複数人に見てもらう場合でも別々の側面に専念するべき。

レビュー時には以下に気をつけることを改めて意識する(今でも自分としてはできているとは思うけど) - コード作成やのアプローチが間違っていると決めてかかる前に、なぜそのようなアプローチが取られたのかについて質問する

また、Googleでのコード変更の約35%というのは、想像よりもかなり高い割合で驚いた。
Webアプリケーションで全く同じようにはできないと思うが、このくらい変更が少ない単位で高速にレビューを回すというのは自分としては良い方法だと思う。

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

「ドキュメンテーションをコードのように扱う」は参考にしたい考え方だと思った。
やはり別物と考えてしまうために、保守のことを想定しなかったりして廃れていってしまう気がする。

ドキュメントを書く人と読む人が別になるのは結構罠で、意識しないとズレていく原因になるので意識したい。

Googleの取り組みで、自分の組織にも取り入れたいと思ったのは「鮮度日付」の仕組み。
今働いている会社にはせっかく頑張って作成したドキュメント集があるが、鮮度を保つ仕組みがないので、それこそリマインダーなど、何かしらやってみたい。

11章「テスト概観」

概ね、うんうんそうだよね、という話だった。(単体テストの比率の話など)

一方で、「テストは本番環境向けコード同様に扱うべき」というのはちょっとできていないところがあると思った。
レビューでも割と開発者任せにしてしまっているところがある。
ただ最近は、RSpecのうちsystem specには、重要かつsystem specでしか書けないテストだけ書く、くらいは意識しているつもり。

新人エンジニアにテストを書くのが当たり前という講習を受けさせて文化を変えていった話は、組織文化の変容のさせ方として非常に面白かった。
思想は強制するのではなく、「成功する思想は広まるものである」というのも納得の考え方。

12章「ユニットテスト」

こちらも今まで勉強してきたことや先輩に教えてもらった内容通りだなと思って読んでいた。

13章「テストダブル」

  • Googleではなるべく現実的なテストを書くことを優先してモッキングフレームワークの利用は避けている、とのこと
  • 先日も仕事でモックを使ったテストコードがあって、よく見たらテストしたいことがテストできていない、ということに気づいたことがあったので、モックは本当に必要な場面で最低限で使うのがいいのかなというのが自分の感想でもある
  • 依存関係が増えて機能修正などでテストが落ちる量が増えるかもしれないが、むしろそれは望ましく、バグ混入するリスクを減らすという大きなメリットを取った結果の仕方ないトレードオフなのかなと思っている
  • ただし、一方で、超大規模コードなどでそうも言ってられないこともあるのだろうなとも思ったりもした。
  • 「フェイキング」という言葉に馴染みがなかったが、外部APIとの接続機能を作る上で実際のAPIをローカルから叩けないときにダミーのリクエスト先を作っておくことをやるような話のテスト版だなという理解をした
  • 「フェイキング」「スタビング」「インタラクションテスト」など色々用語が出てきた。普段使い分けをあまり意識できていなかったが、それぞれ「あの時やったのは"インタラクションテスト"だったな」などという気持ちで読めて面白かった

15章「廃止」

  • 改めて、コードは債務であり資産ではない。価値があるのはコードが提供する機能。
  • ここでもHyrumの法則が関係してくる。ユーザーが提供側が思わぬところに依存していることがある。
    • 以前読んだ『Web API: The Good Parts』でもいかに破壊的変更が難しいか、という話があった
  • 以下は今まであまり考えたことがなかったが、なるほどと思った点
    • 最初から廃止することを念頭に設計すること。
      • 実際、先日外部APIの移行をした際、移行前のサービス名が入ったカラムやクラスがあって若干面倒な作業が増えたなと思ったので、実体験としても確かに大切だと感じた。
      • 若干話は違うけど、よく言う「失敗しても後戻りできるならどんどんしよう」みたいな話の具体的な方法論としても使える考え方だなと思った
    • 期限を定めない廃止勧告が意味はあまりない
    • 廃止作業をする際に専門で人員をつけないと、ユーザーからはケチだと思われる(自分達の要望が後回しにされていると感じる)
    • 廃止の警告をする際は、「行動可能性(エンジニアが何をしたら良いかわかること)」と「関連性があること(ユーザーが実際に使おうとした際に警告が出るなど)」が必要。
    • 廃止の計測的なマイルストーンは完全の撤去ではなく、インクリメンタル(段階的)なものにしておくべき

16章「バージョンコントロールとブランチ管理」

  • Googleのソースコードの大部分は単一のリポジトリーで管理されている(!)
  • Piperという社内用バージョンコントロールシステムを作って使っている

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

  • LGTMを与える場合は、指摘内容の対応は依頼するものの、再レビューは必要としないもので、タイムゾーンが異なる場合などの時間節約につながっている
    • 「信頼を公然と示すこともまた、信頼を築きチームを強化する優れた方法だ」の考え方は取り入れていきたいと思った。

20章「静的解析」

「ユーザーにコントリビュートする権限を与えよ」については、流石にGoogleのように独自の静的解析ツールを作成するのは大変すぎるが、Rubocopなら適用したいor適用したくないcopを開発メンバーが意見できる仕組みを作るのがこの考え方に倣うことになるかなと思った。

24章「継続的デリバリー」

  • 組織の長期的成功への鍵は常に速度
    • 「より速い方が安全」は良い標語だと思った
    • 1章の感想にも書いたが、この、失敗までを早くする、というのは最近読む本には本当にどこにも書かれているなという印象
  • 利用されるもののみをリリースすべき
    • Googleのように事前に大規模のA/Bテストはなかなかできなくても、リリース済みの機能を監視して使われていなければ削除していく、というのは「コードは資産ではなく負債で、資産は機能」という考え方に立つと非常に腹落ちする話だなと思った
  • 障害を恐れてリリース頻度が下がると逆にもっと開発者が辛いよね、という話は、基本的なことだがやはり大切