ある機能追加のプルリクエスト(PR)を開いたら、ロジックの変更だけでなく、全く関係のないファイルのリファクタリングや、コードフォーマッターによる大量のスタイル修正まで含まれていて、レビューにうんざりした経験はありませんか?
このような、複数の目的が混在した「巨大なPR」は、レビューの質を低下させ、バグを見逃す原因となり、チームの開発速度を著しく妨げます。
優れたPRの原則は、ソフトウェア設計の**「単一責任の原則(Single Responsibility Principle)」と同じです。すなわち、「1つのPRは、1つの関心事にのみ責任を持つべき」**ということです。今回は、なぜPRを小さく、目的に集中させることが重要なのかを解説します。
アンチパターン:「ついで修正」が詰め込まれたPR
例えば、あなたのタスクが**「商品の割引価格を計算する関数を追加する」**ことだったとします。作業中に、あなたは別のファイルにある古いコードや、プロジェクト全体のコーディングスタイルの乱れに気づきました。そして、「ついでに」それらも修正して、一つのPRにまとめてしまいました。
悪いPRの例:3つの異なる関心事が混在
PRタイトル: 新機能追加と全体的なクリーンアップ
--- a/products/services.py (本来の目的:機能追加) --- + def apply_discount(price, discount_rate): + """割引後の価格を計算する""" + return price * (1 - discount_rate)
— a/users/models.py (無関係なリファクタリング) —
- def get_full_name(self):
return self.first_name + ' ' + self.last_name
- @property
- def full_name(self):
return f'{self.first_name} {self.last_name}'
— a/settings.py (無関係なフォーマット修正) —
- INSTALLED_APPS=[
'app1',
- ]
- INSTALLED_APPS = [
"app1",
- ]
このようなPRは、レビュアーにとって悪夢です。
- 認知負荷の増大: レビュアーは、①新機能のロジック、②ユーザーモデルのリファクタリング、③設定ファイルのスタイル修正という、全く異なる3つの文脈を頭の中で切り替えながらレビューしなければなりません。
- 重要な変更が埋もれる: 最もレビューしてほしいはずの
apply_discount
関数のロジックが、大量の「ノイズ」に埋もれてしまい、バグが見逃されるリスクが高まります。 - 承認・却下の判断が困難: もし、割引ロジックは完璧でも、
User
モデルのリファクタリングにバグがあった場合、このPR全体を差し戻すしかありません。問題のない変更まで、ブロックされてしまいます。
解決策:関心事ごとにPRを分割する
上記の「悪いPR」は、以下のように3つの独立したPRに分割するべきでした。
PR①:フォーマット修正 (粒度:極小)
タイトル:
STYLE: settings.py にコードフォーマッタを適用
内容: 機械的な修正であり、レビュー負荷はほぼゼロ。すぐにマージできます。
PR②:リファクタリング (粒度:小)
タイトル:
REFACTOR: Userモデルのget_full_nameをプロパティに修正
内容: 既存の振る舞いを変更しない、安全なリファクタリングであることをレビュアーはすぐに確認できます。
PR③:機能追加 (粒度:小)
タイトル:
FEAT: 商品の割引価格を計算するサービス関数を追加
内容: レビュアーはこのPRの核心である、新しいビジネスロジックのレビューに100%集中できます。
このようにPRを分割することで、一つ一つのレビューは数分で完了し、それぞれが安全かつ迅速にマージされていきます。
集中したPRを作成するための実践的ガイドライン
- PRの目的は一つに絞る: 機能追加、バグ修正、リファクタリング、スタイル修正、ドキュメント更新など、PRの目的を明確に一つに定めましょう。
- リファクタリングと機能追加を分離する: 新機能を追加するために既存コードのリファクタリングが必要になった場合、まずリファクタリングだけのPRを作成し、先にマージさせましょう。クリーンな土台ができた後で、本命の機能追加PRを作成すれば、差分は本当に新しいコードだけになり、レビューが非常に容易になります。
- コミット前に差分を確認する:
git commit
を実行する前に、git diff --staged
やIDEの差分表示機能を使い、意図しない変更(デバッグ用のprint
文、自動フォーマットによる不要な差分など)が含まれていないかを確認する習慣をつけましょう。 - PRの粒度を小さく保つ: もし一つの機能が大きすぎるなら、前の記事で解説したように、それを複数の小さなステップに分割し、それぞれを別のPRとしてマージしていくことを検討しましょう。
まとめ
プルリクエストは、レビューというコミュニケーションのための単位です。そして、効果的なコミュニケーションの鍵は、一度に一つのテーマに集中することです。
PRに「ついで修正」を混ぜないことは、単なる作法ではありません。それは、レビュアーへの敬意の現れであり、チーム全体の開発サイクルを高速化し、コードの品質を向上させるための、極めて合理的な戦略なのです。