Elixir/Phoenixで個人サービスを作ったことの振り返り・本番環境運用

この記事は[Qita Elixir Advent Calendar 2018 - 12/14](https://qiita.com/advent-calendar/2018/elixir)の記事になります。

----

## この記事の趣旨
この記事ではElixir/Phoenixを使用して個人サービスを作ったことで感じた**Elixir/Phoenixメリット・デメリット及び本番環境**について書いていきます。

## サービスについて軽く説明
まずどんなサービスを作ったのか説明がないとイメージがつかみにくいので簡単にサービスの説明をします。
作ったサービスは「[Kururu - テスト管理サービス](https://www.kururu.io/)」になります。テストの継続的な実施及びテストケースの管理を行うサービスになります。
個人サービスでの開発についての記事は[Qita 個人開発 #2 Advent Calendar 2018 - 12/17](https://qiita.com/advent-calendar/2018/private-developmen2)の中で別途書いていきますので良かったらぜひ見に来てください。

## 使用技術
個人サービスを作るのにあたって使用した技術は以下になります。

| 環境 | Tool | Front | その他 |
|:--|:--|:--|:--|
| Elixir 1.7.3<br/>Phoenix 1.4.0<br/>PostgreSQL 10<br/>Docker<br/> | Heroku<br/>CircleCI | TypeScript<br/>React<br/>Redux<br/>RxJS<br/>Ramda<br/>Webpack<br/> | GraphQL |


## なぜElixirを選択したのか
実は今回作ったサービスは`Python/Django`で作ったことがありました。しかし、改めて`Elixir/Phoenix`で今回は作成しました。何故、作り直したのかと言うと要件が大きく変わったのが大きな理由ですが、折角なので関数型言語で挑戦してみたかったのがきっかけになります。
少し脇道に逸れるのですが、個人サービスを完成させる最大の障害はモチベーションでして、今回のサービスのように短期間で作り切ることが難しい場合は技術的な挑戦も含めてカンフル剤を打たないと中々進まないと自分の場合気づきました。

また、バックエンドかつ関数型言語で現実的に選択肢があるのはフレームワークも含めてScala or Elixirと自分で考えました。ただ、仕事でならまだしも個人サービスでScala(JVM)は少し重いなというのもあって試しにElixirを触ってみていけそうだと判断しました。Elixirを実際に触ってみる前はIOをめちゃくちゃ捌くのに適していて敷居が高い言語だと思ったのですが実際に書いてみると非常に感触が良かったです。Phoenix自体も非常によく出来たフレームワークでRailsの後発とあってRailsを改良しており、そういえばRailsのこの部分は使いにくかったんだよなという発見がありました。
印象でいえばRailsとDjangoの良いとこを取り込んだフレームワーク。Rails程ブラックボックス感も無く、かつ高速に開発出来る点です。

後付けの理由ですが、今後Websocketを使った共同編集機能の追加・大量のテストケースがあっても速度を落としたくないというのも理由にはあります。

## メリット・デメリット
### メリット
Elixirの肝はデータの変換で関数に対してのinput・outputを意識することが重要です。これは今までオブジェクト指向言語で書いてきたことからすると結構これは衝撃的で今まではオブジェクト中心で考えてきたからです。実際、Elixirにとってどのmoduleにどの関数が定義されているかはさほど重要ではありません。そのため、関数のinput・outputと関数を純粋・副作用を分けることに注力すれば保守性の高いコードに仕上がります。実際に開発していてわけわからないバグに遭遇したりして開発が進まなくなることはほとんどありませんでした。
その他沢山メリットもありますが自分が一番感じたメリットになります。

### デメリット
デメリットも書かないとこれから使う人にも判断できないので書きます。

- ドキュメントは基本英語
- ブログ記事ではなくて公式ドキュメントから実装を導き出せること
- 中小規模のサービスで使用したという事例が少ない
- 本番環境で運用の記事が少ない

よく言われるライブラリの数が少ないというは十分開発には困らないレベルであるので杞憂かなと思います。自分自身は英語ドキュメントにさほど抵抗はありませんが、苦手な人は大変そうだなと印象です。
公式ドキュメントから実装を導き出せることというのはある意味メリット・デメリットがあって、リファレンスを調べればAPIがどんな挙動をするのか想像がつくのでだいたい実装は出来ます。逆に言えば、チュートリアル通りに書いていれば出来ちゃいますというのが少ないので、ドキュメントをきちんと読むことが重要でした。

## 個人的にどんなサービス・チームに向いているのか
メッセージを大量に送るサービスはErlangの強みが活かせるので向いてますね。
ただ、この印象が強いので大規模サービスでないとメリット享受できないのかという誤解が生じている面はあります。上記に加えて個人的に中規模以上のサービス、クローラーに向いています。
例えばスタートアップのメインサービスと相性が良いんじゃないかと個人的に考えていて、サービス開始から3年以上かつ開発者が6人以上になってもスピードを落とさないまま高速に開発が出来ます。RubyやPHPだとこの辺で一気に開発スピードが落ちていく傾向があるので、開発スピードと保守性を維持が出来るElixir/Phoenixは強いです。また、大量のIOをさばき落ちにくいので社内基盤サービスでも力を発揮出来ると考えてます。

まとめると、個人的な印象ではこんな感じです。

- 2〜3年以上運用する目処がたっている
- 開発者の人数が6人以上になるかも
- ビジネスロジックを集約してモノリシックに構築したい
- 社内基盤サービス

マイクロサービスは向いてないわけじゃないと思いますが、わざわざElixir/Phoenixを使わなくてももっと適切な技術があると考えてます。

## Phoenixの本番環境について
Elixir/Phoenixは入門記事だと日本語の記事も含めて結構見つかるのですが、運用以降になるとガクッと事例が他の言語に比べて少なくなってきます。ただ、最近はDevOpsと切り離して考えることは難しいので自分も出来たら事例を上げていきたいと考えてます。

今回、私が本番環境で運用しているのはHerokuになります。最近ではGigalixirというPaaS環境も出てきているので比較して何故Herokuにしたのかを紹介したいと思います。

### Heroku
- 管理画面が充実している
- addOnが充実していて外部サービスとの連携がスムーズ
- 運用事例の記事が多い
- 開発環境・ステージ環境の構築が簡単
- Gigalixirに比べて**DB料金が安い**

### Gigalixir
- デプロイでダウンタイムが発生しない
- Herokuは一日一回再起動がかかるがGigalixirはかからない
- 新しい技術

### 環境についてのまとめ
以上のように総合力でHerokuにしました。何よりも決め手だったのはHerokuのDBの料金が圧倒的に安かったことです。ただ、Elixirの強みを最大限に活かしたいのならGigalixirの方が良い選択になります。
IaaSに関しては運用していくが大変なので最初から検討はしませんでした。ただ、将来的にはIaaSに上げてそこの知見を公開出来たらなとは考えてます。
Herokuで環境構築した時も色々とつまづきがあったのですが、それは別記事にするので割愛します。

## 終わりに
色々ありましたがElixirを選択してまず間違いなく正解だったと言えます。今まで得意言語はありましたが好きな言語は無かったのでそういう意味でも特別な言語になりました。Elixirが純粋にすごいなと思うのは実際に使ってみて不満を持つ人が少ないということです。
ぜひ試しに使ってみてください。