プロダクションコードででElixirを採用した話
はじめに
- 今回は表題の通りなんでElixirをプロダクションコードとして採用した話をします
- もともと、プロダクトチームではElixirの採用実績はあったが、BFFとかではなく定期実行などで叩かれるAPIなどに止まっていました
背景
- 弊社Uzabaseでは下記のようなプロダクトを作っていて、プロジェクトごとに技術選定をエンジニアが自由に行っています
- そんなこともあって採用実績のある言語はこんな感じになっているのですが、
Kotlin, Clojure, Dart, Rust, Elixir, Scala, Go, Java 8, TypeScript, JavaScript, Python
割と、BFFは動的型付け言語、APIは静的型付け言語みたいな感じで言語選定を行っていて、 Kotlin - PythonとかGo - Clojureみたいな組み合わせが多いです。
今回
BFFでElixir を採用した理由
- ここについては、BFFは動的型付け言語を選択するという考えのもと(BFFの責務的にBFFで静的型付け言語を採用するメリットがあまりない)3つの言語(Clojure, Python, Elixir)を候補にしました
- その中でElixirを採用した理由は、ClojureはBFFとして採用実績があり、チーム内にも書ける人間が多くあまりチャレンジ要素がなかった(技術選定の際にチャレンジ要素を求める文化が前提としてあります)
- PythonもBFFとして採用実績があり、書いたことがある人がいるということからElixirの採用がすんなり決まりました
- また、後付けの理由にはなりますが、並行処理や軽量なプロセスによる処理で負荷耐性が期待できるなど、今回僕たちのプロジェクトが作るケースにマッチするような言語特性を有していたので、そのような観点からElixirを採用しました
APIで採用した理由
- BFFでElixirを採用することは特に問題なかったのですが、一方でBFFのみでしか使わないことには別の問題が生じます
- それは、言語の特徴を生かした実装をする機会があまりないということです。
- 具体的には、Elixirではパターンマッチやパイプライン演算子など有名なものがいくつかありますが、BFFに限ると出番が少ないというのが実情です。
- というのも、BFFはデータを受け流すだけという責務に留まることが多く、パターンマッチも下記のようなエラーハンドリングをする程度で終わってしまいます(パイプライン演算子なんてほとんど出番がない)
def hogeGateway do case fugaDriver.get do {:ok, response} -> response :error -> :error end end
- また、データの複雑な処理は基本的にAPIで行うこと、BFFは実装が終わるとあまり手が入ることが少ないこと、などを考えるとAPIでもElixirを採用した方がElixirのことをもっと知ることができるのではないかという思いからElixirをAPIでも採用することになりました。
実装するまでにやったこと
- 基本的にElixir Schoolを1周して、あとはPhoenixでAPIを何本か実装してみたという感じです
- エディタはVS Codeを使ってみて、ElixirのPluginが結構用意されてたので実装に困ることはありませんでした
技術スタック
- Elixir周辺でしようしたものを書き残します
- Phoenix(ElixirのWebフレームワーク)。Elixirでフレームワークはこれ1強らしいのでこいつを採用しました。ただ、フロントエンドは別のマイクロサービスで実装したので、実際に必要だったのはcowboyだけでした
- mixプロジェクト(buildツール的なもの)これを使うことで複数の.ex ファイルを1つのディレクトリに束ねて、コンパイル・実行することが可能になる
- umbrellaプロジェクト(mixプロジェクトを束ねるパッケージマネージャーのようなもの)ディレクトリ構造を管理するのに非常に役立つ。依存関係を制限することが可能なので、依存性逆転などを制御することも可能になる
- mox(elixirのモックライブラリ)弊社では非常に厳密にTDDを行っているので、これを結構使いました
やってみた感想
- Elixirはとっつきやすい(私はJava, Kotlinなど静的型付け言語を書いてきた期間がエンジニア人生の大半を占めており、パラダイムの違う言語を書くのはほぼ初めてでしたが、かなりわくわくした。特にパターンマッチ)
- 学習コストはそこまで高くない。Clojureと比べたときに個人的にはElixirの方が書きやすいなという印象を持ちました
- Elixir Schoolが結構充実している
- 最初、docker imageを作ってデプロイするときにハマった(これは単純に公式ドキュメントをきちんと読んでなかっただけでした)
- 静的型づけ言語から来るとクラスが恋しくなる。これは、個人的に思ったのですが、DDDとかやるときにdefstructで独自のstructを作れるけど、structであってクラスではないなという当たり前の感想を持ちました。ドメインクラス擬にプロパティを追加した際に、テストコードが型が違うとJavaとかKotlinとかだと怒ってくれますが、Elixirはそこまで怒ってくれないので、動的型付け言語も一長一短だなという感想を持ちました。
- とはいえ、パターンマッチとかパイプライン演算子とかイケてるなという感じの実装もあるので多くあるので、決してネガティブな印象を持ったわけではないです
最後に
- 簡単ではありますが、僕たちのチームがプロダクションコードでElixirを採用した背景から感想までを書いてみました。
- 個人的に関数型言語の入りとしてはとても良い言語だなと思いましたし、書いてみたいと思ってる人とか新しい言語を身に付けたいと思っている人は書いてみる価値があるのではないかと思いました。
- 次回は、Kotlinとか他の言語と比較しようかなと思っています。