GunosyでのGoパッケージ構成の歴史

この記事は[Gunosy Advent Calendar 2015](http://qiita.com/advent-calendar/2015/gunosy)の16日目の記事です。

先日の[eureka.go](http://eure.connpass.com/event/22873/)でも話があったように、弊社でもGoでAPIサーバーを作るときのパッケージ構成とリポジトリ構成が未だにしっくりこない現状です。。。

# 弊社のパッケージ管理方針（現時点）

- vendoringはしない（最悪の場合、forkする）
- gopkg.inを考慮しているライブラリは積極的にgopkg.inを使う

# 歴史

長い歴史がある・・・ 

## 歴史1: mainパッケージのみ

APIの本数が少ないうちはこれが一番管理も見通しも良いです。
modelsというパッケージ下にすべてMVCのモデルっぽいものがつめ込まれていた。

```
└── github.com
    └── gunosy
        └── hoge-api
            ├── main.go
            ├── models
            │   ├── xxxx.go
            │   └── yyyy.go
            ├── xxxx.go
            └── yyyy.go
```

## 歴史2: 機能毎にパッケージを用意

aaaaとbbbb機能が増え、以前の `models/aaaa.go` に該当するものも一緒のパッケージいれるという形。
古いmainパッケージ時代のモノは、legacyというパッケージに押し込んで、リファクタしていくという流れ。

```
└── github.com
    └── gunosy
        └── hoge-api
            ├── aaaa
            │   └── aaaa.go
            ├── bbbb
            │   └── bbbb.go
            ├── legacy
            │   ├── legacy_main.go
            │   ├── models
            │   │   ├── xxxx.go
            │   │   └── yyyy.go
            │   ├── xxxx.go
            │   └── yyyy.go
            └── main.go
```

aaaaとbbbbくらいならいいけど、これが10パッケージくらいになると相互依存するものが出てきて循環参照してしまうことが多々あった。

## 歴史3: gunosy/goという別リポジトリに共通ライブラリをまとめてgo getする

よく使う機能bbbbを `gunosy/go` に移動した。dbとかairbrakeなど汎用ライブラリのラッパーも `gunosy/go` 側に作った。

```
└── github.com
    └── gunosy
        ├── go
        │   ├── airbrake
        │   │   └── airbrake.go
        │   ├── bbbb
        │   │   └── bbbb.go
        │   ├── db
        │   │   └── db.go
        │   └── logger
        │       └── logger.go
        └── hoge-api
            ├── aaaa
            │   └── aaaa.go
            ├── cccc
            │   └── cccc.go
            ├── legacy
            │   ├── legacy_main.go
            │   ├── models
            │   │   ├── xxxx.go
            │   │   └── yyyy.go
            │   ├── xxxx.go
            │   └── yyyy.go
            └── main.go
```

`gunosy/go/bbbb`パッケージだけ改修してリリースするケースが起こったりしていた。

vendoringしてないので、下位互換を意識して常にmasterを最新にしておかないといけないという点も結構な負担になっていた。

## 歴史4: gunosy/goの一部でAPI依存しているものをinternal下にもっていく

**現在の形**。aaaa、bbbb、ccccのようなhoge-apiに依存しているようなパッケージはinternal下に移動した。

残っているlegacyはリファクタリングして、いずれinternal下に移動する予定。

```
└── github.com
    └── gunosy
        ├── go
        │   ├── airbrake
        │   │   └── airbrake.go
        │   ├── db
        │   │   └── db.go
        │   └── logger
        │       └── logger.go
        └── hoge-api
            ├── internal
            │   ├── aaaa
            │   │   └── aaaa.go
            │   ├── bbbb
            │   │   └── bbbb.go
            │   └── cccc
            │       └── cccc.go
            ├── legacy
            │   ├── legacy_main.go
            │   ├── models
            │   │   ├── xxxx.go
            │   │   └── yyyy.go
            │   ├── xxxx.go
            │   └── yyyy.go
            └── main.go
```

# 未来: 理想形？（まだ見つかってはいない・・・）

gunosyというOrganizationだとgo getの仕組み上どうしても開発しにくい。。。

プロジェクト単位でOrganizationを作成してその中に持たせるようにすれば、もっと開発しやすくなるのでは・・・と想像している。

```
└── gunosy.github.com
    ├── go
    │   ├── airbrake
    │   │   └── airbrake.go
    │   ├── db
    │   │   └── db.go
    │   └── logger
    │       └── logger.go
    ├── hoge-project
    │   └── api
    │       └── internal
    │           ├── aaaa
    │           │   └── aaaa.go
    │           ├── bbbb
    │           │   └── bbbb.go
    │           └── cccc
    │               └── cccc.go
    ├── xxxx
    │   └── xxxx.go
    └── yyyy
        └── yyyy.go
```

※このリポジトリ構成にするために、まずGHEとかGitLabとかを使う必要性がある・・・（ :money_with_wings: :money_with_wings:  :money_with_wings: ）

# バージョン管理

vendoringする必要はないけど、メジャーバージョンの管理はしたいので、gopkg.inを社内環境のみ見れる場所に立ててメジャーバージョンアップ等にも対応できるようにすることも必要かなと思っている。

gopkg.inは、仕組みは簡単なので以下のリポジトリをgo getしてすぐにローカル環境に構築することはできるが、しかしCircleCIの連携やGitHub.comのPrivateリポジトリを使っている場合に考えなければいけないことが多いので現状弊社では使えていない・・・

https://github.com/niemeyer/gopkg

※このgopkg.inローカル環境構築はCircleCIをやめてjenkinsとかCircleCI Enterprise使う等の方向にしていけば、解決するのかなと思っている・・・（ :money_with_wings: :money_with_wings: :money_with_wings: ）

# おわり

冒頭にも書きましたが歴史の話メインで結論も無い内容となってしまいましたが、良い感じの構成があるという方がいましたら是非知見を共有していただけると嬉しいです。