トランクベース開発におけるメリットとデメリット
こんにちは、モバイルエンジニアのころむにーです。
普段、モバイルアプリを通じたユーザーへの価値提供を目指すプロジェクトに、技術リードという立場で参加しています。
この記事では、トランクベース開発を体験してみて感じている私個人の考えを書いてみます。
はじめに
トランクベース開発は、シンプルかつ強力な開発方法です。
上手く運用できれば、開発チームのパフォーマンスを最大限引き出し、爆速の開発を実現できます。
しかし、実際にプロジェクトで運用してみると、メリットが大きいことは間違いないものの、デメリットも一定程度あると感じました。
本記事では、私が実際にトランクベース開発を導入し、運用している中で感じたメリットとデメリットを具体的なシーンを含めて簡単にまとめてみます。
トランクベース開発に関する具体的な戦略に関しては、以前別の記事に書いています。
気になる方は、こちらも参考にしてみてください。
トランクベース開発の概要
トランクベース開発とは、1 つのメインブランチ(トランクブランチ)を中心に開発を進める方法です。
以下のような開発でよくある課題を解決できることが特徴です。
- 長期間生存しているブランチをマージする際、コンフリクトが発生しやすい
- 一部のメンバーだけで修正を長期間管理することで、多くのメンバーからのフィードバックを得られにくい
- マージを止める期間が発生することにより、開発スピードが鈍化する
トランクベース開発では「1 日を超える生存期間を持つブランチを基本許容しない」というようなルールを設けます。
それに伴い、基本的には以下のような開発フローとなります。
- トランクブランチに 1 日未満の作業単位で細かくコミットしたり PR をマージしたりする
- トランクブランチ上でテストを繰り返し、品質を担保する
- トランクブランチ上の最新コミットを、基本そのまま本番デプロイする
機能開発途中のコードも本番デプロイされるのが普通となるので、フィーチャートグルなどを用いてロールアウト制御の仕組みを導入することがほぼ必須です。
導入しているプロジェクト
私が参加していてトランクベース開発を導入しているプロジェクトは、以下のような特徴があります。
- iOS/Android アプリの開発。iOS と Android でそれぞれ独立したリポジトリを持つ。
- iOS と Android でそれぞれエンジニア 4〜5 名ずつ、QA 4〜5 名の計 12〜15 名程度のメンバーで開発とテストを行う。
- 1 ヶ月に 1 回程度、リリースする。
メリット
Git-flow や GitLab-flow、GitHub-flow などのブランチ戦略と比較した、トランクベース開発における実際に感じたメリットを記載していきます。
ブランチ管理が限りなく簡単になり、コストやリスクが低減する
トランクベース開発では、全ての開発用ブランチを 1 日以内にトランクブランチへマージします。
また、本番デプロイのときにはトランクブランチからリリースブランチを切り、数日間保持する場合があります。
つまり、1 日を超えた生存期間を持つブランチは多くてもトランクブランチとリリースブランチの 2 種類になります。
そのため、限りなく簡単なブランチ管理が可能になります。
これにより、以下のようなメリットがあります。
- ブランチ管理のコストがほとんどなくなり、機能開発などの価値提供に使うコストが増える
- マージ時のコンフリクトを解消する機会がほとんどなくなり、解消ミスによるリスクがほとんどなくなる
- ブランチ管理やコンフリクト解消などの難易度の高い作業がほとんどなくなることで、特定の熟練したメンバーだけにコストが集中することを防げる
実際に私が経験しているプロジェクトでは、以下のような定性的な効果がありました。
トランクベース開発の運用フローが安定しているここ半年間くらいは、コンフリクトを解消する機会がほとんどなくなった。
コード修正をどのブランチにマージすればいいかなどの認識合わせが不要になり、ブランチ管理のコストが大幅に削減された。
1 本のブランチ上で開発、テスト、自動チェック(CI)を集中することで、これらのコストパフォーマンスを最大化できる
主要なブランチがトランクブランチのみであるため、1 本のブランチ上で開発、テスト、自動チェック(CI)を高サイクルに回すことが可能になります。
これにより、以下のようなメリットがあります。
- 高頻度で自動・手動リグレッションテストを回すことができ、常に一定の品質を担保しやすくなる
- 開発者が全員で 1 つの状態のコードを触るため、全員の知見が早期に共有されやすくなる
実際のプロジェクトでは、以下のようなシーンがありました。
リグレッションテストにより、開発途中の機能のデグレが早期に検知された。
機能 A のコード修正がトランクブランチにマージされたあと機能 B に関するコード修正のビルドが通らなくなり、機能 B と機能 A の依存関係が新しく発覚した。
デプロイとロールアウトの分離が強制されることで、開発プロセスに柔軟性が生まれる
前述した通り、トランクベース開発では、機能開発のコードがデプロイされたとしても機能のロールアウトを別の仕組みで制御できるようにすることがほぼ必須です。
これにより、副次的にいくつかのメリットが発生します。
- 開発プロセスの早い段階でデプロイのことを考える必要があり、不確実性を早期に減少させられる
- ロールアウトにおけるリスクへの対策の選択肢が増える
- ロールアウトにおけるビジネス的な要求に対して柔軟に対応できる
- 一般ユーザーのベータ機能への早期アクセスなどの仕組みが容易に導入できる
実際のプロジェクトでは、以下のようなシーンがありました。
「機能 A のクライアント側の開発を着手したいんだけど、これってフィーチャートグルつける必要あるかな?」
「これはサーバー側のファイルがデプロイされることで機能が発動するようにできるから、フィーチャートグルは不要だね。」
「OK!ただ、サーバー側のデプロイ状況にロールアウトを依存させるってことは、サーバー側のロールバック時にクライアント側もロールバックされるような挙動になっておかなきゃだね。」
「来週のリリースに含まれる機能 B はデータベースへの書き込みが増加するから負荷が心配だね。もし問題が起きた時は、ロールバックしようか。」
「そうだね。ただリリースに含まれてる他の新機能も一緒にロールバックされるともったいないから、機能 B のフィーチャートグルを OFF にすることで機能 B だけをロールバックしようか。」
「機能 C は来週リリースだったんだけど、機能 D と合わせてリリースしたいから来月に遅らせることできる?」
「その機能はフィーチャートグルを ON にするだけだから問題なくできるよ!」
デメリット
以下では、実際に感じたデメリットを記載していきます。
品質基準やリリース計画とは関係なくまぜこぜに修正が取り込まれていくため、予測可能性が下がる
トランクベース開発では、必要最低限のコードを取捨選択してリリースしてデグレリスクを抑えるような厳格な品質基準を設定しにくくなります。
トランクブランチは機能開発やバグ修正のコードが PR レビュー完了次第マージされていくため、トランクブランチ上で一時的にデグレしている状況が起こりえます。
そして、トランクベース開発ではトランクブランチの最新コミットを元にリリースするため、一時的にデグレしている状況だとそのままリリースされてしまうリスクが高まります。
実際のプロジェクトでは、以下のようなシーンがありました。
開発途中の機能 A の修正により公開済みの機能 B にデグレが発生し、そのままリリースされてしまった。
これを防ぐために、包括的な自動テストや高サイクルなリグレッションテストを高精度で行い、デグレの早期解消を継続的に行うことが重要です。
一方で、重大度に関わらずデグレを流出させることがビジネスとして致命的になる状況では、トランクベース開発は向いていない可能性があります。
また、バグ修正などの種類のコード修正は、リリースタイミングを事前に計画することが難しくなります。
バグ修正は、バグ修正前の期待動作を定義しにくいため、フィーチャートグルでの管理がコスト観点で現実的ではないことが多いです。
そのため、トランクベース開発において、バグ修正におけるロールアウトのタイミングを柔軟にコントロールすることは一般に難しいです。
実際のプロジェクトでは、以下のようなシーンがありました。
バグ修正 A に関して、リリースにおける QA コストの関係でリリースから外すことになった。
この際はやむをえずトランクブランチ上でバグ修正 A のコード修正をリバートし、一般ユーザーに修正がロールアウトされないように対応した。
トランクベース開発では、バグ修正に関しては対応が終わった直後のリリースで順次ロールアウトしていいという取り決めをするのが最もスムーズです。
一方で、バグ修正がユーザーにロールアウトされるタイミングを事前に計画し完全にコントロールすることが必須な場合には、トランクベース開発は向いていない可能性があります。
デプロイとロールアウトの分離が強制されることで、開発プロセスの複雑性が増す
デプロイとロールアウトの分離により、以下のように開発、テスト、運用などのプロセスでそれぞれ行うべきことが増えます。
- コード上でフィーチャートグルを管理し、ON/OFF 時の挙動の分岐を実装する
- フィーチャートグル ON/OFF 両方の状態でテストを行う
- フィーチャートグルが動的に切り替わる(Ops トグル)パターンを想定している場合は、ON と OFF の状態遷移のテストを行う
- フィーチャートグル切り替えを適用する
- 不要になったフィーチャートグルの分岐や定義を削除するメンテナンスを行う
- 監視やログの設計をフィーチャートグルを考慮したものにする
これにより、各プロセスに必要な工数が少しずつ増え、メンバー間のコミュニケーションコストも少しずつ増えていきます。
実際のプロジェクトでは、以下のようなシーンがありました。
「機能 A はフィーチャートグルを使って実装しましょう。フィーチャートグル OFF の場合は、機能 A が表示されないようにしてください。」
「今回のリリースに機能 B の途中までの修正が含まれますが、フィーチャートグル OFF 状態のままとするので、一般ユーザーには機能 B が見えることはありません。」
「今回のリリースには機能 C が含まれます。機能 C はフィーチャートグルを使って実装しているため、リリース時にフィーチャートグルを ON にする必要があります。」
さらに、プロダクトオーナーやビジネスサイドのメンバーにも説明が必要になってきます。
例えば、以下のようなシーンがありました。
「機能 A は来週月曜日のリリースでは、まず一部のユーザーにだけ開放されます。」
「機能 B は来週月曜日に全ユーザーへ公開されます。もし、監視で問題が発生した場合は、すぐに機能 B を無効化します。」
こうしたコミュニケーションは、プロダクトの外部への発信やユーザーへのサポートなどに必要です。
メリットとデメリットの比較
メリットとデメリットに関して、特徴的な部分を抜き出すと以下のようになります。
- 開発者が価値提供に集中でき、平均的には品質を保ちながら高速な開発を行えるメリットがある
- 特定の時点で完璧な品質に仕上げるのはコストがかかり、またリリース時期の予見が一部困難であるというデメリットがある
そのため、高速に開発したい、かつ、品質基準やリリース調整を完璧にはコントロールする必要がないプロジェクトでは、トランクベース開発は非常にマッチした手法と言えます。
私が参加しているプロジェクトは以下のような前提で、マッチしていると考えています。
- 高速に開発したいという要求が強い
- 品質基準は高いものを求められているものの、リリース時にバグがゼロでなければいけないほどの基準ではない
- リリースタイミングは、できたタイミングで順次リリースしていくという方針である程度合意している
実際、導入後に開発スピードは保てていて、メリットを強く感じています。
一方でいま、業務プロセスの関係上リリースタイミングをきちんと予見したいという要求も出てきていて、その部分に対してはデメリットが徐々に大きくなっていると感じています。
プロジェクトの全体的な業務フローを整理して、適切な運用方法を検討中です。
最後に
本記事では、私が実際にトランクベース開発を導入し、運用している中で感じたメリットとデメリットを記載してみました。
トランクベース開発を導入する際には、メリットとデメリットを踏まえて、適切な運用方法を検討してみてください。
Discussion