モノレポでJavaのFWを開発していることに気付いたので運用を考える。

# はじめに
本記事は、JavaのFWを開発するプロジェクトにおいて、モノレポ開発のメリットを享受する為のリポジトリ運用について考える記事です。

# モノレポとは
端的にいって、モジュールを横断してコードを一つのリポジトリで管理しようというリポジトリの運用戦略です。モノレポの考え方として下記の2つがありますが、本記事では**後者**について考えます。

1. 企業のコード全てを1つのリポジトリで管理しようとする考え方
2. プロジェクトのモジュール全てのコードを1つのリポジトリで管理しようとする考え方

# これってモノレポでは？
私の所属するチームでは、JavaのFWを開発しています。FWはいくつかのモジュールから構成されており、それらのモジュールは1つのGitリポジトリで開発されていました。何故こういったリポジトリ構成になったのか、チームに経緯を確認した所、製品として品質保証したい範囲でリポジトリを作成した為とのことでした。
当時、Gitの経験が浅かった私は違和感を抱かなかったのですが、どうやらこういったリポジトリの運用をモノレポと言うらしいので、モノレポ運用のメリットを活かせている運用か調べてみることにします。

# モノレポのメリット
モノレポ開発の為のツールセットである[Nx](https://nx.dev/angular)のドキュメントを参考にすると、モノレポ運用をすることのメリットとして挙げられるのは下記の4点です。

1. コードが全て同じリポジトリにあり、互いに参照できるため、コードの再利用がしやすい。
2. モジュール変更の影響が同じリポジトリ内で完結し、1PRで解決できる。
3. 異なるツールや技術を利用したモジュール群のビルドやテスト手順を一貫したものにできる。
3. モジュール毎の依存を単一のセットに固定でき、後になって依存関係の競合に悩まされない。

## チームのJavaリポジトリを顧みる
下記の2点から、リポジトリはモノレポのメリットを享受できていると言えそうです。実際のところ、機能の開発・修正に伴って、あちこちのリポジトリにPRを投げるようなことはないですし、連結テストになって依存関係に悩まされることもありません。

### 1. 製品を構成するモジュールが同一リポジトリで管理
モジュール群はテストコードを含め、同一のリポジトリで開発されており、互いに参照されるとともに、変更の影響を確認できます（※画像の構成はイメージ）。[GitLab CI/CD](https://docs.gitlab.com/ee/ci/)のように、リポジトリにパイプラインジョブを定義するファイル（.gitlab-ci.yml）が含まれる場合、パイプラインジョブの再利用がしやすいこともメリットとして挙げられますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686574/2add6380-7e4b-6ccb-b664-9c3b48228062.png)

### 2. 依存関係はgradleファイルで一意に管理されている
製品の依存関係は単一のgradleファイルで管理されています。

```groovy
dependencies {
	implementation("org.aspectj:aspectjrt:1.9.4")
	implementation("org.aspectj:aspectjweaver:1.9.4")
	implementation("com.fasterxml:classmate:1.4.0")
	implementation("commons-beanutils:commons-beanutils:1.9.3")
	implementation("commons-betwixt:commons-betwixt:0.8") {
		exclude module: "commons-beanutils-core"
	}
    // 中略
}
```

# モノレポの運用
上述の通り、チームはモノレポのメリットを受けられていることを確認できました。
次はモノレポのメリットを最大化し、モノレポの運用課題に対処するために、モノレポ運用の検討事項について考えてみます。
こちらは参考文献を基に記載しています。参考文献については、本記事の末尾に記載しているので、こちらもご参照ください。

**1. 物理的なリポジトリサイズの増加にどう対処するか**
全てのコードが単一のリポジトリで管理される都合上、リポジトリが肥大化します。サイズはもちろんのこと、ビルドやテストにかかる時間の増加への対処を検討する必要があります。一般的に、影響範囲のみのビルドやテストを実施するよう制御します。

**2. いじられたくないモジュールをどう守るか**
全てのモジュールが単一のリポジトリに格納されると、別チームにモジュールを破壊される可能性があります。モジュールに対してチーム毎に制御を設けることなどが検討されます。

**3. 各モジュールに対して単一の規格をどれだけ浸透させられるか**
モジュール毎にコーディングスタイルや品質の管理基準、依存セットが異なっていると、モノレポのメリットは失われ、管理が煩雑になります。対処方法としてデファクトスタンダードの規格をモジュールに強制するアプローチなどが取られます。

**4. モジュールの変更を素早くリポジトリ全体に浸透させられるか**
モノレポ運用のメリットは、全てのモジュールの最新コードを全ての開発者が参照できることに依る所が大きいです。したがって、リポジトリの運用として、CI/CDを前提としたトランクベース開発が好ましいと考えられます。

## チームのJavaリポジトリ運用を顧みる

モノレポの運用と比較して、チームのリポジトリ運用の評価は下記の通りです。

1. リポジトリと開発チームは巨大ではない。
2. プロジェクトの性質として、多数のチームが参加して開発するものではない。
2. 製品として**重厚な品質管理**が規定、一定の規格がモジュール間で統一されている。
3. featureブランチによる開発。

チームでは、品質管理のCI/CD化を進めることでコードの変更反映を速めています。加えて、少数チームでの開発で、開発者がリポジトリ全体を掌握しきれている為、リポジトリサイズや開発規模に起因する課題は生じていないという状況だといえるでしょう。

# まとめ
モノレポで開発することのメリットと運用方法について説明し、チームのモノレポとその運用について確認しました。結論として、チームのリポジトリは、モノレポ運用に関して大きな課題はなく、メリットを受けつつ開発を進められているという結論でした。
少数チームで開発するリポジトリにおいては、モノレポにすることで生じる課題はあまりないと言えるのではないでしょうか。

余談ですが、レポジトリとリポジトリが並ぶと少々違和感がありますね。

# 参考文献
モノレポに関して、下記の参考文献をもとにメリットや運用の検討について述べています。

- Nxのドキュメント：https://nx.dev/angular/getting-started/why-nx
- Misconceptions about Monorepos: Monorepo != Monolith：https://blog.nrwl.io/misconceptions-about-monorepos-monorepo-monolith-df1250d4b03c
    - 翻訳：https://www.graat.co.jp/blogs/ck1099bcoeud60830rf0ej0ix
- Monolith→MultiRepo→MonoRepoでの
リポジトリ戦略：https://slides.com/kotamat/repository-strategy