Money Forward Developers Blog

株式会社マネーフォワード公式開発者向けブログです。技術や開発手法、イベント登壇などを発信します。サービスに関するご質問は、各サービス窓口までご連絡ください。

20230215130734

小さいプルリクエストを作る技術

この記事は、Money Forward Engineering 1 Advent Calendar 2023の18日目の記事です。

15日目はSammyさんの"マネーフォワード SDETインターンの魅力とは?"でした。

初めに

こんにちは、Taskと申します。 普段はマネーフォワードクラウド連結会計のバックエンドエンジニアとして、大阪開発拠点にて勤務しています。

今年の7月にマネフォに転職してきたのですが、開発生産性を上げる仕組み、特に小さいプルリクエスト(PR)を作り、頻繁にmainブランチに取り込むための取り組みがおもしろいなと感じたので紹介させていただきます。

なぜPRを小さくする必要があるのか

まず、PRを小さくすべき理由をいくつか紹介します。

コードレビューを簡単にするため

大きいPR(=大量の変更が含まれているPR)は一度に確認しないといけない範囲が大きくなるため、レビューに時間がかかります。 また、複数の変更点の依存関係を脳内に留めながらレビューする必要があるので、難易度も上がります。 PRを小さく分割することで、レビューが必要な変更範囲を狭められるため、迅速かつ容易にコードレビューを行えるようになります。

コンフリクトを最小限にするため

大きいPRは変更範囲が広いため、複数の開発者で並行して開発を行っていると、それぞれの変更がコンフリクトしやすくなります。 PRを小さくすることで変更範囲を狭めコンフリクトを最小限にできます。

頻繁にリリースするため

現代のソフトウェア開発(DevOps)において、コードの修正からリリースまでのリードタイムは重要な指標として扱われています1。 このような状況において、小さい変更を頻繁にリリースすることの重要性は至るところで説明されています。 大きいPRは前述の通りコードレビューに時間がかかるためリードタイムが延びるほか、そもそもコードを修正してPRを作成するまでにも時間がかかるため、マージしてリリースする、という作業を容易に行えなくなります。

ほかにも、今回は割愛しますが、PRを小さくすべき理由はたくさんあります。 一方で、いくつかの理由から、それが困難な場合があります。

なぜPRを小さくできないのか(物理編)

物理、つまりコードベースに起因する理由として、以下が挙げられます。

機能が中途半端な状態でリリースされてしまうから

PRを小さくするためには、一つの機能のためのコード修正を複数のPRで行う必要があります。 そのため、実装途中の状態でPRがmainブランチにマージされ、その結果デグレードを引き起こす可能性があります。

モジュールが大きく、PRを分割する単位を見つけにくいから

Fat Controllerのように、メソッドやクラスといった一つのモジュールに複数の責務が詰め込まれている場合、同じモジュールに対して複数回の修正を加えるより、一度で全ての修正を加えることを選択する心理が働くことがあります。

また、物理的な問題のほかに、開発者の心理的な問題も存在すると思います。

なぜPRを小さくできないのか(心理編)

コードベース以外の原因として、開発者側が複数の小さなPRよりも一つの大きなPRを望むことがあります。

そうなる大きな理由としては、一つの機能が一つのPRに集約されることで、変更内容や依存関係を把握するコストが下がるからです。 一つの機能が複数のPRに分割されていた場合、どのPRにどの変更が含まれているかを把握するコストが発生します。 また、レビューする際も複数のPRの依存関係を考える必要があります。

まとめると、レビュアーがPRがどのように分割されるかを事前に理解しておかないと、小さなPRのレビューの難易度がかえって上がってしまう、という問題点があります。

どうすればPRを小さくできるのか

このような問題に対して、僕たちのチームが実際にどのような対策を取っているか紹介します。

機能が中途半端な状態でリリースされてしまう問題

僕たちのチームでは、フィーチャーフラグを活用して、実装、修正中の機能がユーザーに公開されないように管理しています。 フィーチャーフラグとは、ソースコードに修正前のコードと修正後のコードの両方を残し、プロダクトの実行中に動的に実行対象のコードを切り替える仕組みを指します。 フィーチャーフラグを用いることで、開発中のコードはユーザからのアクセス時には実行されないようにできるため、デグレードを防げます。

マネーフォワードでは多くのチームがフィーチャーフラグを用いた開発生産性向上に取り組んでいます。 興味があれば過去の記事もご参照ください。

moneyforward-dev.jp

PRを分割する単位の問題

僕たちのチームではクリーンアーキテクチャ2を採用しており、各レイヤーごとにPRを作成しています。 これはクリーンアーキテクチャに限った話ではないのですが、レイヤードアーキテクチャを採用することで、モジュールの境界がPRの分割の単位として設定しやすくなります。 また、レビューする側としても、層ごとにPRが送られてくることで、コードが、それが置かれている層の責務を満たしているかを意識しながらレビューできます。

レビュアーがPRの分割単位を把握できない問題

僕たちのチームでは、プランニング時に全員でタスク分割を行います。 これによって、開発者全員が一機能の概要を把握しやすくなるとともに、各タスク、各PRでどのようなコード変更がされるかを事前に想像、共有しやすくなります。 コードレビュー時には、自分がイメージしていたものと実際のコードを比較する作業になるため、レビューが効率的になります。

僕はこれまで、一つの機能ごとに一人の開発者がアサインされ、個人でプランニングを行う、という開発方式しか体験したことがありませんでした。 PRの分割を提案したこともありましたが、議論の末、主に上述の「なぜPRを小さくできないのか(心理編)」の理由で機能ごとのPRを作成するという意思決定がなされました。 ですので、僕が全員でのプランニングを初めて体験したのはマネーフォワードに入社してからでした。

やってみたところ、PR分割だけでなく様々なメリットがあることが分かったので、今では好きなイベントの一つとなっています。 僕自身、世間の開発事情にあまり詳しくないので、世間一般ではこれは当たり前のことかも知れませんが、実際に体験してみて、全員でのプランニングはとても大事なことだと感じました(これがこのアドカレで一番伝えたいことです)。

最後に

ここまで読んでいただきありがとうございました。 PRを小さくすることに悩んでいる方の参考になれば幸いです。

また、マネーフォワードでは一緒に働くメンバーを募集しています。 小さいPRや開発生産性に興味がある方は、ぜひカジュアル面談から応募していただければ幸いです。

hrmos.co