Monorepo vs Polyrepo ~それぞれ経験してみての所感~
こんにちは,KDDIアジャイル開発センター(KAG)のまさのです.monorepo派とpolyrepo派の意見をまとめたOSSコミッターのJoel Parker Henderson氏による興味深いドキュメントを見つけました.本記事ではドキュメントを読みながら,MonorepoとPolyrepoそれぞけ経験してみての所感を述べてみたいと思います.
本記事は,Qiitaの「KDDIアジャイル開発センター(KAG)Advent Calender 2024」 18 日目の記事です.こちらも是非よろしくお願いします.
Monorepoについて
アプリケーションやサービスを単一のリポジトリで管理するパターンです.一般的にはコンポーネントごとにサブフォルダに分割して管理します.GoogleやAmazonといった巨大テックカンパニーが採用しているとされ,注目されています.
- メリット
- 他のコードを参考にしやすい
- コードを共通化し,重複を排除しやすい
- チーム間のサイロ化を抑止しやすい
- ツールを標準化しやすい
- リリース管理が容易
- リファクタなど横串活動がやりやすい
- デメリット
- リポジトリの巨大化
- テストやビルドなどの分離の考慮
- 修正に対するリポジトリ内の影響の考慮
- ツール(LernaやNxなど)の選定し上手く活用できればいいが,ハードルも
- Workspaceなど導入することによる,その他技術的問題のリスク
Polyrepoについて
アプリケーションやサービスを別々のリポジトリで管理するパターンです.マイクロサービスごとに管理したり,フロントとバックエンドで分けるパターンがあります.
- メリット
- サービスやアプリケーションの切れ目がはっきりする
- リポジトリを軽量に維持できる
- リポジトリ内の影響は把握しやすい
- リポジトリ単体で見れば,仕組みをシンプルに維持できる
- 機動性を確保しやすい
- デメリット
- リポジトリが増えると管理が大変
- リポジトリの区切りを適切に考える必要
- コードの重複は生まれやすい
Monorepo派とPolyrepo派それぞれの意見
引用に関しては,機械翻訳しています.原文は元ドキュメントをご確認ください.
Polyrepo派
規模が大きくなると、モノレポはポリレポが解決しなければならないあらゆる問題を解決しなければならず、その結果、密結合が助長され、さらにVCSのスケーラビリティに取り組むという途方もない努力が必要になるからです。 したがって、中長期的に見れば、モノレポは組織としてのメリットはゼロであり、組織の優秀なエンジニアの何人かをPTSDに陥れてしまうことは避けられません。
Monorepoの問題として,主にスケーリングと密結合の問題について指摘されています.
モノレポのスケーリングの問題
- モノレポのスケーリングは、最終的にはスペースの点で非現実的になる。モノレポが大きくなって開発者のラップトップに収まるより多くのデータを持つようになると、開発者はモノレポをフェッチできなくなり、より多くのストレージ・スペースを得ることは非現実的になるかもしれない。
- モノレポが大きくなると、完全なファイル転送に時間がかかり、実際にはgitのブランチ操作やrepackingなど、他の作業にも時間がかかります。
- モノレポは、あまりにも多くのプロジェクトを含むため、検索、編集、変更の切り分けなど、プロジェクトをまたいで作業するには精神的な労力がかかりすぎる。
スケーリングに関して課題があるのは同意します.ツールを使った緩和策も述べられていますが,実際はハードルはある印象です.sparse-checkoutという手もありますが,他のコードを参照しやすいというmonorepoのメリットを活かしきれないと思います.
- 10-100 developers writing code full time.
- 10-100 projects in progress at the same time.
- 10-100 packaging processes during the same time period, such as a daily release.
- 1K-10K versioned dependencies, such as Node modules, Python packages, Ruby gems, etc.
- 1M-10M lines of code
monorepoのスケールが問題になる目安も示されています.
規模がそこまで大きくない状態であれば,monorepoでも十分に機能すると言えそうです.
無関係なプロジェクト間の結合
無関係な製品間のモノレポ結合について心配しています。これはおそらく私のより自由主義的な世界観から来ている部分もあると認めますが、ある製品に合わせて調整されたサーバー アップグレード スケジュールのような基本的なことが、別の製品の開発に深刻な悪影響を及ぼし、開発が数か月間停止するところまで至った例を私は見てきました。新しい機能や依存関係からの大きな修正が必要なのに、会社全体がアップグレードの準備ができていないために行き詰まるなんて想像もできません。
これについては,一部疑問が残ります.リポジトリを分離したからといって密結合が解消されるかというと,そうとも限らないと考えています.実際にリポジトリが分かれていながら依存関係にあるパターンに遭遇しましたが,リリース管理や開発の影響の考慮に苦労しました.依存関係にあるものが分かれるリスクの方が恐ろしい印象を持っています.
一方で,本来は依存関係のないもの同士を「とりあえず」でまとめて管理してしまって,機能改修を重ねる中でそれらの連携が必要になった際に,必要以上に密結合させてしまう懸念についても,思い当たる節はあります.
目に見える組織
コードベースをリポジトリに目に見える形で整理すると、インターフェースと実装の分割と同じようにコードの再利用が容易になり、どの部分がドメイン固有で、どの部分が再利用可能なライブラリであるかが明確になる、と私は主張します。
「直接関係はないが、一緒にバージョン管理されている」ことと「別々にバージョン管理できるほど分離されている」ことを表現できることは、ツールボックスにあると非常に価値のある区別です。
これはPolyrepoの大きな利点だと実感しています.再利用すべきライブラリをMonorepoで管理した場合,Monorepo内の別々のアプリケーションから同一ライブラリの違うバージョンを参照する際の考慮が必要になる可能性があります.
ただし,Polyrepoのライブラリをどのように公開するかの考慮は必要です.git submoduleで公開した際には,導入方法の面倒さや認証の問題もあり,ベストという感触はありませんでした.
また,再利用するライブラリを誰が管理するのか,或いは共同管理するのかのポリシを明確化しないと,管理されないライブラリとなってしまうと思います.
Monorepo派
コンポーネントを一緒にリリースする必要がある場合は、モノレポを使用します
コンポーネントを一緒にリリースする必要があると思われる場合は、それらを同じリポジトリに配置する必要があります。これは、実際に必要な場合は、同じリポジトリから異なるリリース スケジュールを持つプロジェクトを非常に簡単に管理できるためです。
一方、異なるリポジトリに多数のコンポーネントがあり、それらを一緒にリリースする必要がある場合、それは突然本当に面倒になります。
同意です.
コンポーネントが共通のコードを共有する必要がある場合は、モノレポを使用します。
一緒にリリースする必要のないコンポーネントがある場合は、もちろんそれらを別のリポジトリに保存できます。ただし、これを行う場合、リポジトリ間で共通のコードを共有するには、何らかの堅牢なバージョン管理システムを使用してそのコードを管理する必要がありますが、堅牢なバージョン管理システムは困難です。オーバーヘッドを正当化するほどの価値がある場合のみ、そのようなことを行ってください。スタートアップの場合、価値が十分に高くない可能性が非常に高くなります。
これはPolyrepoのメリットとしても触れましたが,一長一短の話だと思います.別のリポジトリで管理するほどの「しっかりした」ライブラリであるケースは結構少ない印象もあり,気軽に共通化するうえではMonorepoに分があるとも思います.
共通の使命
会社を、共通の使命に従事する人々の集団として考えると分かりやすいと思います。会社は複数のサブプロジェクトを通じて使命を追求し、下されるすべての決定と導入されるすべてのコード変更は、会社の主要目標への一歩です。コード ベースは、会社の包括的な目標とその目的を達成するための手段に関する組織的知識の塊です。
この観点から見ると、モノレポは、すべてのチーム メンバーが単一の、しかし多面的な事業に携わっているという事実を最も自然に表現したものと見ることができます。
事業内容や組織・チームの連携具合にもよるとは思いますが,考え方としては好きです.
1つのリポジトリを分割する方が、複数のリポジトリを結合するよりも簡単です。
大きなリポジトリを小さなリポジトリに分割するのは非常に簡単です (少なくとも Git では)。これを 1 回だけ行う必要がある場合は、subtree で十分です。必要に応じてすべての履歴を保持することもできます。分割する別の方法として、リポジトリを複製し、通常のコミットで各複製からツリーをプルすることもできます。
しかし、小さなリポジトリをまとめて大きなリポジトリにするのは非常に困難です。
まずはモノレポから始めましょう。
モノレポを複数の小さなリポジトリに分割するのは、それが本当に意味があることが明らかな場合のみにしてください。
まずはMonorepoから始めることに関しては同意です.実際,細かすぎるPolyrepoをまとめていく活動を計画した際は,頓挫しました.
分割が細かすぎるかもしれない
ポリレポに関する私の問題は、組織が物事を細かく分割しすぎることが多く、変更が複数のリポジトリにまたがって保存される必要があるため、機能を導入するために単一のコミットを行うことができないことです。
これも思い当たる節があります.「1つのリポジトリを分割するのは楽」ということに通ずる部分がありますが,「とりあえず分ける」というのは楽なので,不必要に分けすぎてしまうのではと仮説を立てています.
中立的な意見
どちらも、実際には作業量が減ったり、エクスペリエンスが向上したりするわけではないようです。しかし、選択によって解決しなければならない問題の種類が決まるだけだと分かりました。
モノレポには、主に単一のレポで組織を拡張することに関する課題が伴います。
ポリレポでは、主に調整に関する課題が伴います。
どちらが優れているかではなく,組織やプロダクトの状況をみて判断が必要そうです.
全体的な所感と結論
Polyrepo派とMonorepo派のそれぞれの意見に,身に覚えや納得する点はありました.一方で,それは各々の良し悪しというより,組織やプロダクトのフェーズ・規模に合った方法を採用しているか,あるいはサービスの境界を適切に見極められているかの問題だと感じています.
実際にはmonorepoから始めてみることが無難であると思います.理由としては,下記が挙げられます.
- プロダクト初期はそこまで規模が大きくなくMonorepoのスケーリングの問題が発生しない
- Polyrepoを結合するより,Monorepoを分割する方が楽
- Polyrepoに分割するにしても,その境界を適正化する必要があるが,最初から考慮することの難しさ
一方で,プロダクトのスケーリングの問題が発生した際にはPolyrepo化を検討しても良いが,過剰に分けすぎないことが大切と言えます.
参考
宣伝
2024年は,Qiita上にmonorepoに関する記事を2つ書きました.こちらも参考にしてみてください.
Discussion