Ken Mazaikaさんの2015年1月31日付のブログ記事、Why I’m betting on Elixir
And why you should too, unless you want to become a maintenance programmer.の翻訳です。
[翻訳] Elixir - 次に来る大物Web言語もそうでしたがなんかRailsのプログラマさんたちがやたらアツく語ってるんですね、Elixirを。
メンテナンスプログラマになりたくなければ1、なんてタイトルからして挑発的です。私の3つ前の仕事はまさにそういう保守系でしたけど。
あんまりアツいんで皆さんとアツさを共有したくて翻訳しました。
なおQiitaのCentOS + Erlang + Elixir + PhoenixのDockerイメージで今日から始めるElixir on Phoenix入門の追記のところでも紹介されていましたので既に読んだよという方も多いかもしれません…。
背景: 私は過去6年間を Ruby と Rails フレームワークでウェブアプリケーションの開発に費やしてきました。新しい言語が出てくるたびにちょっと粉をかけて来たのですが、 Elixir は初めてグッと来た言語でした。
Rubyがぶっ壊した!
Ruby言語とRailsフレームワークはそれまでのウェブアプリケーションの開発手法を完全に変えてしまいました。それはコミュニティが気にかけていたように"価値の宗教"としての始まりでした。そして「プログラマが使うツールは開発者の幸福と生産性に向けて最適化されたものであるべきだ」という思想の嚆矢となりました。
「開発者が彼らのコードが十分にテストされ動作することを確認する」ということを開発者自身の仕事にするということは大きな挑戦でした。他の言語及びフレームワークからはそのやり方は笑いものにされていました…それが成功し始めるまでは。
そしてそういった言語・フレームワークもRubyコミュニティからその原則を取り入れ始めるようになったのです2。
Rubyが人目につかない言語として控えめにスタートを切ったところから始まって最も人気のある言語のひとつになった大きな理由はRailsフレームワークとDHH3、Wycats4、Aaron Patterson、José Valim他の数多くのスーパースターたちによる驚異的なリーダーシップにあります。
でも時折Rubyの控えめな出自の痕跡が現れる
メモリが足りない!
Zed Shawは悪名高い"Railsはゲットーだ"という投稿で、彼は初期のRailsにはガーベージコレクションにひどい問題があってアプリを動かし続けるためには4分に1度プロセスの再起動が必要だった!と喚き散らしています。
現在出ているうちで最も人気のあるrailsサーバーのひとつはUnicornでしょう。私の本番のウェブアプリケーションはRailsアプリケーションで、今までやってきた他のアプリケーションと比較してもまずまず単純です。私はそのアプリケーションをDigitalOceanの512MBのDroplet5に標準的な説明書に従って移行しました。デプロイから数日経つと私のunicornサービスはメモリを食いつぶしアプリケーションは相当遅くなってしまいました。
どうやって解決したかって?Unicorn-worker-killerです。それは以前からある解決策と言えるか微妙なシロモノです。
DigitalOceanのDropletはunicornワーカースレッド2本~これがリソースの大半を食ってましたが~と、Postgresデータベースと他のいくつかのアプリケーションを動かすことができました。要求時間もま、OKなんじゃない?ってことでその仕事は終わりました。
並行性!
何年もRailsアプリケーションを開発してきていますが私は今まで本番のRailsウェブアプリケーションで一度たりとも新しいスレッドを立ち上げたことはありません。Rails自体はスレッドセーフですが、私はJava, C++その他のオブジェクト指向言語で他のスレッドをガンガン使った時に「ここは竜の巣だな…」と気づいていたからです。
実際、mutexやsemaphoreやそういったものについて考えたくないんですよ。ある一つのスレッドを動かしている間に別の一つのスレッドを止めてっていうのはどう見ても本物の並行動作に見えません。加えて、そのコード、絶対にデッドロックを起こさないって言えますか?
テストはRubyコミュニティの中心的な話題ですが、ほとんどのRuby開発者はスレッドが基本的にテスト不可能なもので、再現不能なバグを生み出しやすいためにスレッドを使うのを避けているのです6。
私はと言えば大半の健全なるRuby開発者と同じように並列に処理を実行させるにはsidekiqまたはresqueを使います。Rails 2.2からはスレッドセーフが追加されていますがRails 4.2にはActive Job APIが追加されました。こっちの方が100万倍使い物になります。
しかしバックグラウンドジョブというのは、その名の通りバックグラウンドで実行されるのです。ミッションクリティカルな項目はメインプロセスに残り、結果が失敗した時に反応するようにするか、タスクが終わるまでトランザクションが失敗することなく完了することを保証しなくてはなりません。
スピード!
私はワガママです。自分の時間が貴重です。1秒でももったいない!それが私がテスト実行時間を気にする理由です。真剣に時間をかけてテストスイートのパフォーマンスを最適化しました。アプリケーションの構造を変えることなく、テストによって引き起こされる設計へのダメージなしに、です。
以前仕事していたプロジェクトではユニットテストと機能テストに20分以上!もかかっていました。その時はRailsの分散テストフレームワークとしてhydra7を使っていたのですがテストスイートがパスするまでが大変でした(おそらく不快なほど複雑なコードベース…中にはそれほど出来の良くないコードも含まれてそうな…が原因で)。
テストが開始するまでの時間ですら相当長くかかります。だいたい40秒ぐらい。…で40秒経ったところで"syntax error, unexpected end-of-input, expecting keyword_end"などとメッセージが出て文法にポカミスがあったことがわかる、というわけです。
どうやって解決したかって?Zeusです。Railsアプリ起動時の一般的なあれこれを事前にロードしてくれる素晴らしいgemで、(Githubの記述によれば):
どんなRailsアプリも1秒以内に起動する
とのこと。私はこのgemがお気に入りですしRails開発者ならぜひ使うべきだと思います。
しかしZeusの開発者たちがどうやってこの機能を成し遂げたかというと…コア部分はイケてるGoで書いてあるんだなこれが…。
Scala
この2年ほど、私はScalaを使ってみたくてウズウズしていました。いざ使い始めてみたら…速攻でイヤになってきました。
Scalaには数多くの関数型プログラミング的な考え方が入っています。Akkaフレームワークは非常に並行性が高く耐障害性を持つアプリケーションの作成を可能にします。JVM上で実行されるのでどんなJavaのライブラリでも問題なく使えますし、JVMはパフォーマンスについてとんでもなくカリカリにチューニングされているのです。
Scala言語そのものはなかなか楽しめるもので、私はパターンマッチングが好きですね。じゃ、何が台無しにしたのかというと…JVMでした。JarのパッケージマネジメントはRubygemやBundlerと比べると控えめに言っても冗談抜きでややこしい。
解決法はいろいろとあります。例えばSBT、Maven、Ivyなど8。でもそれらで他の誰かが作ったライブラリをインポートしようとすると萎縮しちゃうんですよね…。多分私はRubyに毒されちゃってるんでしょう。でもRubyのパッケージ管理機構は私の生産性の核なのです。
もうひとつScalaで悩ましかったのは使っていたライブラリの大部分がJavaで書かれており、それらを書いた人のスキルは私のスキルと根本的に違っていたということです。
ScalaでPlay!フレームワークを使ってWebのソリューションを構築するのはJavaでPlay!フレームワークを使ってWebのソリューションを構築するように感じられました。多少マシな文法とパターンマッチングの機能を除いては。Play!はRailsの影響をちょっとだけ受けているようですがその違いは理屈で説明できるようなものじゃないんです。
Elixirのエコシステム
mixによるパッケージ管理
Elixirを使っての「初めての冒険」でMixに出会いました。MixはrubyのBundlerとrakeのハイブリッドみたいなものです。Mixを見てぶっ飛んだのは…Bundlerとrakeに比べて悪くないじゃないかということでした。どっちよりも優れている、とは見えなかったけれどもともとハードルは高いし出会い自体は印象的でした。
Mixは粛々と作業を進めてくれるし、余計なことに口を出さないし、あなたにXMLとの格闘を押し付けたりもしないんです。
Erlang仮想マシン
ElixirはErlang仮想マシン上で走るのでErlangコミュニティのほとんどの優位性を取り込んでいます。ElixirもErlangも耐障害性と高いスケーラビリティを持つ関数型プログラミングがすごい!というところがご自慢です。
ElixirについてYouTubeで見られるトークのほとんどでErlangに関する次のような話が出てくるでしょう。
- Erlangは電話網の50%を動かしています。「この電話はメンテナンスのために計画停止します」なんて聞いたのはいつのことでしたっけね?
- 何億ドルかで買収されたWhatsAppは何百万個ものプロセスを1台のサーバーで走らせ4億5千万ユーザーをサポートしていた。たったの32人のエンジニアで。
この優位性と同じタイプの優位性はElixirコミュニティにも取り込まれています。このため、ElixirのエンジニアがErlangで書かれた管理ツールやcowboy httpサーバーを使っても自分の得意なことを犠牲にしなければならない、とは感じないはずです。
Phoenix Web フレームワーク
Phoenix Web フレームワークは明白にRuby on Railsに強く影響されているしPhoenixウェブアプリケーションを書くのはRailsアプリを書くのとすごく似ていると感じます。私はRailsのルーターが好きです。ActionControllerもActiveRecordもRails Viewもコードの書き方のお作法そのものも。私はRailsアプリケーションの構成も気に入っています。
PhoenixはそういうRailsっぽいソリューションなのでRailsアプリを作ってるような気分になるかもしれません。ただしElixirで動いていてElixirとErlang仮想マシンの利点を全て持っている、という点を除いて。
Phoenixは更にWebSocketもチャンネルを通じて提供しています。これでFirebase9が提供するような使いやすさともっと細かい粒度の制御でWebSocketを使うことができます。
「速い」ということは既にお伝えしましたっけ?Phoenixは電光石火の速さなんです。私の月5ドルのDigitalOcean dropletから拾ったこのログを見てください。シングルコアのマシンでリクエスト応答速度がほんとにマイクロ秒単位なんですよ10。
強力なリーダーシップ
私見ですが、単なるオープンソースとムーブメントの違いはプロジェクトに関与するリーダーシップの周辺にあると思います。本当にデキる人たちが日夜ソフトウェアの改良に勤しまないとダメなんです。
Railsムーブメントは本当にものすごい加速度を持っていました。それはDHH、Aaron Patterson、José Valim、Wycats、その他たくさんの素晴らしい人たちの努力の賜物です。Railsが第一宇宙速度で発射されなかったら、人々はその仕事をするのをやめてしまったでしょう。
それは古き良き、仕事に打ち込む際の心構えですし、同時にコミュニティを作るということは努力を要するのです!11
Elixir言語のコアチームのJosé Valim、Chris McCord他全てのメンバーとPhoenixコアチームはこれまでも、そしてこれからもElixirコミュニティが成長するために不可欠な努力を続けていくでしょう。
ウェブの世界はまさに抜本的な変革を経験しようとしている
その事実に向き合ってください。CRUDなアプリは既にコモディティ化しています。次に来るのは…AirBnBみたいな感じでケチャップを借りるようなサービスというのは生き残れない世界です。
勝つのは技術の変化を受け入れていくような人々です。Phoenix/ElixirのWebSocketやプロセス、及び並行性は開発者の幸福をなんら犠牲にせず簡単に使えるという事実はゲームのルールを完全に変えてしまいます。
私はRuby on Railsが大好きです。Railsは2005年から2014年までの間、人々がウェブアプリケーション開発について思っていたことをすっかり変えてしまいました。
私はElixirとPhoenixが同様の衝撃を2015年から2025年までに与えるのではないかと期待しています。
もし、あなたがPhoenixとElixirによるウェブアプリケーション開発を始めたいと思ったなら私が作ったこのチュートリアルをチェックしてください12
2015/5/29 追記 既にチュートリアルは古いようです。Phoenixの本家サイトを見たほうがいいです。
-
(2006年のblog、The Noble Art of Maintenance Programmingによればメンテナンスプログラマは用務員さんみたいに思われている…と当時から書いてありますね) ↩
-
テストファーストなどの考え方は別にRuby on Railsの専売特許ではないと思うのですが…普及時期はかぶりますし積極的にRailsに仕組みが取り入れられていたのは事実ですけど。 ↩
-
David Heinemeier Hansson。言わずと知れたRailsの原作者。 ↩
-
Yehuda Katz。 RailsだけではなくjQuery, ember.jsなどの開発コアメンバー。 ↩
-
DropletはDegitalOceanの用語でバーチャルマシンのこと。下に月5ドルの、とあるので一番安い、512MBメモリ/2~3GHzの1Core CPU/20GBのSSDのやつでしょう。 ↩
-
さすがにここまで言うか?と思いますが… RubyのThreadクラスなどの低レベルレイヤーを直接呼び出さず次の段落に出てくるgemを利用するという意味でしょう。 ↩
-
同じJVM言語でもClojureのLeiningenはかなりイケてると思います。以前の投稿でも述べましたがElixirのmixと設計思想が似ています。 ↩
-
チャットなどのリアルタイム性の高いアプリ用のバックエンドを提供するサービスで昨年Googleに買収されました。Angular2のng2015用デモ(todos)にも使われていたんですが、あれ、動かしてみてうっかり恥ずかしい内容(心がぴょんぴょんするんじゃあとか)書いちゃった人いませんか?丸見えですからねw ↩
-
確かにMicrosoft AzureのもっとショボイVMでも
[info] Sent 200 in 934µs
とかチラ見えします。サンプルプログラム程度だとブラウザで開いた体感ではピンと来ないというのが正直なところですが。 ↩ -
ここの訳はあんまり自信ありません。リンク先のインスタグラムもなんかよくわかんなかった^_^; ↩
-
で、私は赤いカプセルを飲んでしまったので今読み始めています…なかなか手順が細かく書いてあります。PhoenixってまだPostgresqlしか使えないんですね。あーなんかPostgresqlの設定に失敗したあ…(T_T);お手軽にsqlite3も使えたりしないだろうか…→2015/5/29 追記 現在、MySQLには対応しています。 ↩