世界を動かす技術を、日本語で。

プルリクエストとコードレビューの舞台

2025年9月25日原文(meks.quest)

概要

  • Goatmire Elixir ConfでのSaša Jurić氏による「Tell Me a Story」講演の要点
  • コードレビューとPull Request(PR)の課題と改善策
  • レビューしやすいPRの作り方とコミットメッセージの重要性
  • クリーンなコミット履歴がもたらす価値
  • コラボレーションを成功に導くための具体的なプラクティス

Goatmire Elixir Conf「Tell Me a Story」講演レポート

  • Goatmire Elixir Conf にてSaša Jurić氏が「Tell Me a Story」を発表
  • 演劇的なストーリーテリング実践的な技術アドバイス の融合
  • 技術的な内容 を物語として展開し、理解しやすさと面白さを両立
  • 講演録画は後日オンライン公開予定、視聴を強く推奨

コードレビューとPull Request(PR)の課題

  • コードレビュー は多くのエンジニアが敬遠しがちな作業
  • PRが 大規模・複雑・理解困難・テスト困難 になりやすい現状
  • 「Looks Good To Me」や表面的な指摘で済ませてしまう傾向
  • git blame で責任を個人に押し付けがちだが、システム全体の責任は全員にある

レビューしやすいPRとは

  • 理解困難なPR は著者に返却することを推奨
  • 「理解できないので承認できない」と伝える勇気の重要性
  • 本当にレビュー可能なPRとは「 5〜10分でレビュー可能」な範囲
  • 中堅〜シニアレベル の開発者が対象、初心者や10xエンジニアではない
  • PRのスコープを縮小 し、1つの機能でも複数PRに分割
  • 目安は 300行以内500行超えはレビュー困難

ストーリー性のあるコミットの作り方

  • コミットは物語を語るもの として設計
  • 変更内容を 段階的かつ論理的 に提示し、レビュアーが思考の流れを追いやすくする
  • 「add dependency」「implement file upload feature」などの 汎用的なコミットメッセージ は避ける
  • 目的や背景、具体的な変更点を明記

デモによる実践例

  • Saša氏は 152行の追加と2行の削除13個のコミット に分割
  • コミットごとのストーリーを追うことで、なぜその変更が必要かが明確に
  • 例:mix.exsへの:runtime_tools追加の理由も、コミットの流れで納得

イテレーティブな開発とコミットの整理

  • fixupコミット を活用し、インタラクティブリベースで履歴をクリーンに保つ
  • autosquash オプションで自動的にfixup対象に統合
  • コンフリクト解決が困難な場合は 新規コミット作成も許容
  • 履歴の一貫性と可読性を重視

クリーンな履歴の価値

  • 全コミットがコンパイル可能・アプリが動作可能 であることを推奨
  • git bisect によるバグ発見効率の向上
  • 大規模コミットやビルド不能コミットは デバッグを困難
  • ストーリー性ある履歴が 回帰調査やコード理解 に役立つ

コラボレーション成功のためのポイント

  • フォーカスしたPRストーリー性あるコミット で早期フィードバック
  • レビュアーが理解しやすく、 質の高いレビュー が得られる
  • 履歴が明快 なため、過去の経緯も追いやすい
  • 次回PR作成時は「 レビュアーがストーリーを追えるか」を意識
  • 小さな改善から始める(例:300行以内、説明的なメッセージ)

参考リソース

  • git blame :各行の最終変更者・リビジョン表示
  • git rebase :コミット履歴の整理
  • git fixup :過去コミットの修正
  • git bisect :バグ導入コミットの特定

Hackerたちの意見

PRレビューって、ちょっとパフォーマンス的なところもあるよね。でも、同僚たちがちゃんとレビューしてくれるって信じてるし、逆に自分のPRを無視してくれるのも全然OK。それがみんなが望んでる形だと思う。特定の変更については、該当の行にコメントでタグ付けして、影響の説明と直接的な質問を添えてレビューをお願いすることが多いんだ。この「コードを壁に投げて解釈してもらう」スタイルのPRは、忙しい人たちにとって優先度が低くなりがちだと思う。コメントにちょっとしたストーリーを加えるのもいいけど、根本的な問題は、変更のブロックをそのまま提示して、全体に対して「OK」の一言を求めるのはコストがかかるってこと。文脈や意図を共有することに代わるものはないし、それはコードの外で伝えるべきだよね。

逆に自分のPRを無視してくれるのも全然OK。PRはオプションであるべきだと思う。すべての変更がピアレビューを必要とするわけじゃないし、同僚を信頼するなら、パフォーマンス的なPRに時間を無駄にせずに、自分のブランチをマージできるようにすべきだよ。

それはコードの外で伝えるべきだよね。理想的にはそうだね。ゼロ金利政策の下で10年近く過ごした後、多くの労働者は、自分の意図を文脈の中で意識し続けるインセンティブがなかったように思える。私が一緒に働いた人の半分は、前の文の苦々しさではなく、その長さに気分を害するだろう。実際に機能することと、期待されることの間にはインピーダンスミスマッチがある。これは、文脈や意図を明確にするよりも、むしろ痛々しいシンタックスエラーを引き起こすことが多い。そうなると、コードベースはすべての貢献者の文脈と意図の標準的な表現となり、彼らが最善を尽くしていないときでも、正直なところ、それが悪いことなのか?もしかしたら、コードの中で伝える方が劣った体験になるかもしれない。でも、コードの外でのコミュニケーションが確立できないとき、他に何ができる?こういうコミュニケーションをコードを通じて促進するツールがあれば嬉しいな。例えばGitHubは、そういうことをするのに完璧な位置にいるのに、やってないよね。Git + PR + プロジェクトは、情報の流れが逆になっていて、最近ではその失敗モードについて全体のカンファレンスで話されることもある。

これ、めっちゃ気になるんだよね。仕事では、結構多くの貢献があるコードベースの専門家なんだけど、同僚から「承認して!」みたいなプライベートIMがたくさん来る。100行以上のコードが送られてきて、その中で私に関係あるのは10行くらい(私が専門としているファイルや挙動だから、承認が必要なんだ)。最低限、変更の背景や、なぜこの部分のコードベースに変更が必要だったのか、その考え方を知りたい。たまに、でもあまり頻繁ではないけど、レビューを返してこの情報を求めることもある。私の意見では、多くのソフトウェア開発者は、書くのが速くないから、自分の変更に対する説明を提供するのが大変なんだと思う。あるいは、AIやIDEに従って作業しているだけで、説明を提供できるほどの理解がないこともある。人々が時間をかけないのが、レビューを形式的にしてしまう原因だと思う。

何行かの変更があるPRについて、開発者が自己レビューをしていなかったら、私は全くレビューしない。代わりに、自己レビューをして、文脈を追加してから再レビューをリクエストするようにお願いしてる。さらに、「これらの洞察の中で、コードに直接コメントとして追加する価値があるものはある?」って質問することが多い。9割の確率で、彼らが書いた文脈はコード内の良いコメントになるはず。人々は時々、意図せずにすごく怠けることがある。私たちは、モンキーブレインがより良く機能するためのリントツールが必要だ。gitプラットフォームがこの種のコンプライアンスを強制するためのUXフレンドリーな方法をもっと提供してくれたらいいのに。CI/CDでそれをある程度偽装できるけど、私の意見ではそれだけじゃ不十分だね。

そうそう、コードや変更について考えてもらいたいなら、必要なコンテキストを提供できるようにしないとね。もしそれが分からないなら、自分のコードがみんなが待ってたギフトだと思わないでほしい。自分はそう思ってるかもしれないけど、他の人には何をしたのか分からないから、誰かがその作業をしてくれるまで待つことになる。要するに、追加したコードは作業を生むってこと。だから、せめてその作業を減らすために、自分のコードが何で何じゃないのかを分かりやすくする努力をしよう。どんな変更をしたのか(機能的に)、なぜそれをしたのか、どんな選択をしたのか(あれば)とその理由、PRのコードの状態について自分の意見をまとめてみて。必要な理由や、将来のメンテナンスがどうなるか(理想は低い)についても考えてみて。要するに、誰かがドアをノックして、自分のプロジェクト用のパッチが入ったUSBを渡してきたときに、何を知りたいか自問自答して、その知識を加えてみて。大きな機能については早めにドラフトPRを作成することも考えてみて。そうすれば、誰も望んでいないものをプログラミングしたり、他の誰かがすでに作業していることを避けられるし、メンテナが方向性を示したり、作業を始める前に断ることができる。

全体的な意見には賛成だけど、 > 「良い目安は300行のコード変更。500行を超えると、レビューできない領域に入る」っていうのには反対かな。提案されたようにコミットを分けると、行数はあまり関係ないことがわかったよ。重要なのは、変更がどれだけ物議を醸すかってこと。理想的には、PRには多くの議論を生む部分が一つだけあればいいと思う。そういうPRは、できるだけ少ないコミット数(単独では意味がないものだけ)を持つべきだね。もちろん、これは一般的な経験とレビュー担当者との経験に依存するから、行数のカウントみたいな指標が役立つこともあるよ。

よく機能している環境では、逆の相関関係があることが多いよ。物議を醸す変更やバグ修正は小さくてターゲットが明確で、意図しない副作用について深くレビューされる一方で、大きな変更セットは、事前に話し合われた新しい作業で、確立されたパターンに従ってスルーされることが多い。

90%の開発者にこのレベルの履歴手術をやらせるのは難しいよ(ハハ)。実際にできる人(典型的なエンジニアの中のごく一部)でも、正しくやるための忍耐を持っているのはさらに少ないと思う。開発者にこういうことをやらせようとすると、理解できないから目が glazed over したり、余計な作業にイライラしたり、頷いても無関心になるだけ。トップエンジニアの一人がやっても、他の組織がちゃんとしたコミットの衛生を守らないことにフラストレーションを感じるだろうね。自動化で簡単に強制できるものではないから、基本的には達成不可能だと思う。Netflixみたいにトップパフォーマーだけを雇っているなら別だけど、あなたはNetflixじゃないから。

業界の一部では、CRの数やCRごとの修正回数をパフォーマンス指標として追跡してるんだよね。多くの人がこれを利用して、自分の「数字」を良く見せようとする。つまり、CRの数を増やして、CRごとの修正回数を減らすってこと。

コードレビューの目的によって、かなり変わるよね。目的はコードベースの異なる部分で違うかもしれないし。 - もし複数の人間がそのコードを見たことを確認したいなら、10分でPRを読んで「LGTM」か丁寧な「WTF」で返事するだけでもいいかも。チームにセンスがあって、クリーンに分離されたモジュールが明確なAPIを実装しているなら、これでうまくいくよ。最悪のダメージは、一つのモジュールが時々少し微妙になることだけど、大きなプロジェクトではそれも許容できるトレードオフかもしれない。 - すべての変更を徹底的に議論する必要があるなら、事前のデザインディスカッションやペアリング、図解したデザインドキュメント、非常に詳細なレビュー(差分だけでなく、変更を文脈に入れてモジュール全体を再レビューすること)が必要かも。PRの著者に自分のコードを発表して、他の人と一緒に進めるのもいいかもしれない。これはシステムの「コア」に該当する重要な部分に適しているかも。 - あなたのコードの半分が、全体像を理解していないAIによって書かれていて、大規模なメンテナンス性を理解していなくて、手を抜いて、あなたの書いたポリシーやベストプラクティスを_意図的に_破っているなら、正直言って、あなたのチームがAIをしっかり監視しない限り、テクニカルデット地獄にまっしぐらだと思う。一人でも無知な人がAIに微妙に壊れたコードを出させると、どれだけのレビュアーがいても簡単には元に戻せない混乱を生む可能性がある。そうなると、うーん、5,000行未満に抑えて、定期的に全部燃やすとか、そういう感じかな?

コードレビューの議論でよく混乱を招くもう一つの要因は、オープンソースプロジェクトと内部コードベースが一般的にかなり異なる状況にあることだと思う。内部コードベースは、比較的小さな経験豊富なグループによって作業されることが多く、彼らはPRを作成し、レビューも行っている。だから、 - 「この人が何をしているか知っていると仮定してもいいのか?」というベースラインが高い - レビューを早くするために「PRを作成する」プロセスに時間がかかるのは、チーム内の時間のトレードオフに過ぎない - コミットされたコードに問題があれば、そのコードを書いた人がそれを修正するために周りにいる でも、オープンソースプロジェクトでは、「コア」の長期的な開発チームの外からの貢献が多いから、 - 貢献者がコードベースに精通していると仮定できないので、余分な注意が必要 - 変更を提出する人よりもコードレビューを行う人が少ないことが多いので、提出者がレビューアの仕事を楽にするために余分な努力をするプロセスが理にかなっている - コードに問題があれば、提出者がアップストリームに行った後に修正するために利用可能または興味がある保証はないので、微妙な問題を事前にキャッチすることがより重要で、これによりコードレビューのプロセスは「レビューアを楽にするために、たとえそれが提出者にとって余分な作業を必要とする場合でも」という方向に傾くことが多い。

Hacker Newsで議論の続きを見る