SIerが実践する分散開発とバージョンコントロール

# このページについて
SIerが実践するシステム開発プロセスの中の、
分散開発とバージョンコントロールについて書きます。

文中で出てくるツールは、Javaを使った場合のツールなので、
日々使用している言語に合わせたツールに読み替えていただければと思います。

# 対象読者
* SVNで消耗している人たち
* 構成管理でラクしたい人たち

# システム開発の構成
書き出す前に、システム開発の構成の定義と従来型のやり方を書いてみます。

## 場所
以下の３カ所でそれぞれ開発するものとします。

| 場所 | 作るもの |
|:-----------------:|:------------------:|
| 社内 | オレオレライブラリ |
| オフショアA | 日常業務で使うWEB |
| オフショアB | 夜間バッチ |
オフショアA、Bとしましたが、同じ会社の別部署など、
とにかく別ロケーションで開発する場合を想定しています。

## ソースの構成
おそらく、以下のように１つのJavaプロジェクト内にすべて書くのではないでしょうか？
![従来型.png](https://qiita-image-store.s3.amazonaws.com/0/56851/6616e9f6-5ffe-1053-0b31-67611ee4601b.png)

### デメリット
 * バッチを書いている人が、オレオレライブラリやWEBのソースを改変する可能性がある。（オレオレライブラリ、WEBも然り）
 * プロジェクトが太って行った時に、コンパイルなどに時間がものすごくかかる。（5000以上のJavaファイルが配置されているものを見たことがある）

それぞれのソースでプロジェクトを分けているものも書こうかと思いましたが、
その場合は、システムでスタックをちゃんと組んでるかな、と思ったので省略。

## リポジトリのモデル
従来型の場合は、以下のパターンのどちらかではないでしょうか？
### リポジトリは分けている
![従来型（リポジトリ分ける）.png](https://qiita-image-store.s3.amazonaws.com/0/56851/06a92b7f-bca4-1460-2680-9fb2f863102d.png)

最終的に社内のSVNリポジトリにオフショアA、Bのソースをマージすることを想定しています。
#### デメリット
* オフショアA、Bのマージが大変
* オレオレライブラリの追加モジュールや修正版をオフショアに配る時に、オフショアA、Bへのマージが大変（考えただけで頭痛のしそうなシチュエーション。。。）

### リポジトリは同じ
![従来型（リポジトリ同じ）.png](https://qiita-image-store.s3.amazonaws.com/0/56851/23862bd6-bce2-12f9-d11d-4198e8ddf239.png)

リポジトリが１つだから最後にマージする必要がないヤツですが、
契約にも問題がありそうなモデルです。（こんなリスクの高い構成とってるプロジェクトがあるのかって感じのレベルですね。）
#### デメリット
* 別ロケーションからのコミットで、他ロケーションの人間が迷惑被る可能性がある。<BR>自社なら、ごめんなさいで済むかもしれないけど、他の会社どうしだったら、誰が責任取るんでしょうね？
* オフショア側からしても、オレオレライブラリのインタフェースがよく変わったり、内部の振る舞いが変わったとしたら、最終成果物として何を担保すれば良いのかも分からないですね。

# 従来型のよくある課題
* オレオレライブラリにあまり左右されずにオフショアに開発してもらいたいけど難しい
* マージが大変

上記は、過去携わったPJで一旦クリア済みなので、その方法を提供します。

# 改善した際の構成
## ソースの構成
JAR、WAR化する単位ごとにJavaのプロジェクトを分ける
![ソースわける型.png](https://qiita-image-store.s3.amazonaws.com/0/56851/f29f5ec1-8388-a076-1b94-b46104e92408.png)

アプリケーションのスタックを積むと以下のような感じです。
![stack.png](https://qiita-image-store.s3.amazonaws.com/0/56851/90b96039-8f65-26ce-fb8f-ce6c0c2dc94b.png)

WEBもバッチもオレオレライブラリに依存します。

### メリット　
* バッチから、WEBとオレオレライブラリのソースを編集できなくなる
* JARを取り込まない限りは、他ロケーションに迷惑はかからない
* プロジェクトが太った場合に、太らせる度合いが最小限になる

### デメリット
* JARを配るタイミングが難しい

このデメリットを消すために、バージョンコントロールをします。
# バージョンコントロール
プロジェクトにおけるバージョンコントロールとは、
不具合の修正などを行ったライブラリを、入れたいタイミングで適応することです。

## どうやるのか
Mavenとライブラリ管理を組み合わせます。

### Maven
ライブラリの依存関係を自動解決してコンパイルが行えるツールです。
また、JARファイルなどを生成して、Mavenリポジトリに保存できます。

Maven、または類似のツールを使っことがある人は知っていると思いますが、
例えばSpring-Coreを使いたいという場合に、pomに

```xml:pom.xml
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>4.3.4.RELEASE</version>
</dependency>
```
を書くと思います。
こうすると、spring-coreのversion 4.3.4.RELEASEが参照しているその他のJARファイルも落ちてきて嬉しいですよね。
ただ、このページでは依存関係の自動解決つえ〜〜！ではなく、
指定したバージョンが落ちてくる、ということについて、注目します。

例中は、spring-coreを取ってきてきますが、
これが、自分たちのプロジェクトで作ったライブラリ（文中のオレオレライブラリ）でも良いですよね。
オレオレライブラリのバージョンを書き換えるだけで、そのバージョンのJARに差し代わるなら、
オフショア側の良きタイミングで、取り込んでもらえますよね。
ライブラリを取り込みたいタイミングで取り込める、バージョンコントロールの一丁上がりです。
とはいえ、SIerのプロジェクトの場合、インターネット上のサービスなんて使えないことが殆どなので、
ライブラリ管理を自前でします。

### ライブラリ管理
概要は以前、以下に書いたので見てみてください。
[ライブラリ管理のススメ](http://qiita.com/sh-ogawa/items/26bd4edb2eff5787ca75)

上記記事中に出てくる、社内環境のMavenリポジトリに、MavenでオレオレライブラリJARをアップロードすることで、SIerでもバージョンコントロールを可能にします。
図にすると以下です。
![リポジトリ.png](https://qiita-image-store.s3.amazonaws.com/0/56851/f3a1ba6d-00c3-e4bf-f6e7-bebc0e3acc92.png)
※図は、[ここ](http://szk-takanori.hatenablog.com/entry/20071019/1192800438)から拝借させていただきました。

# 分散開発
Gitを使ってください、といういつもの回答ですが、お付き合いくださいw
分散開発に限らず、複数バージョン（バグフィックスや次期バージョン、２期先のバージョン開発の同時実行くらいは、よくある）の並行開発にも役に立つのがGitです。
SVN使ってるプロジェクトはGitに移行するといいぞ的な内容のものは去年書いているので、そちらを参照してください。
[Subversionを使用し続けているプロジェクトがGitに移行することを考えてみた](http://qiita.com/sh-ogawa/items/0bac2516d85e3db4dfd8)

リポジトリの構成は以下とすることが個人的には推奨ですが、
プロジェクトの規模感や、メンバーのGit習熟度で柔軟にやってもらえれば良いです。
(明日面白いものを書いてくれる@syobochimさんに「重厚すぎる」って言われたのも、実はちょっと引きずってます（嘘）)

![分散リポジトリ.png](https://qiita-image-store.s3.amazonaws.com/0/56851/1e7349d3-555c-a984-e730-50d70b3764ae.png)

masterブランチへの直接pushをできない設定もありますが、リポジトリを分けるのが、管理する側からすると安心安全だと当時は思ったので、この構成にしています。 

Gitとバージョンコントロールをセットとしたのは、相性が良いからです。
なぜなら、Git上でブランチを切ったその上で、バージョンを上げたライブラリの動作確認ができるからです。
※オレオレライブラリのダメだった箇所を修正・仮リリース（Mavenリポジトリにアップロードする）して、使う側に試してもらう、といった具合で進めます。

また、ライブラリ管理をしていないと、Gitで自分の使っているブランチ上にオレオレライブラリのJARをファイルサーバから取ってマージする、という手間が発生したり、そうでなくても何れかの手間が発生しますが、ライブラリ管理していれば、pom.xmlのバージョンを書き換えさせすれば試せます。
開発として、どちらが手っ取り早いかは言うまでもないですよね？

# 最後に
分散開発で書きましたが、これは並行開発でも使える手法です。
むしろ並行開発の方が受ける恩恵が大きいと思います。
ここに書いた内容をやるって決めさえして本腰を入れれば、難しい話ではないです。

こんな施策で疲弊する人が減ったり、リリースまでのリードタイムが短縮できるのであれば、ここで価格を下げるのは微妙な感じもしますが、取り組む価値は大いにあるはずなので、今のやり方に課題は感じているけど、何も動けていないプロジェクトは、こういう方法もあるってことで検討してみてください。