言語
それでは、初めに述べた言語たちを分析することにしましょう。
Rubyはオブジェクト指向プログラミング言語として優れています。(私見では)Rubyは優れたOOPエクスペリエンスと開発者の幸せを主要な目標に置いています。しかしコードの実行速度は主要な目標ではありません。
訳注: ご存知のとおり、現在のRubyは「Ruby 3x3」の旗のもとでコードの実行速度改善の優先順位を以前よりも上げています。
Ruby on Railsは、Ruby言語上で構築されたWebフレームワークであり、生産性と開発者の幸せを主要な目標に置いています。コードの実行速度や、癒着のないOOPエクスペリエンスはRailsの主要な目標ではありません。ソケット接続はまあまあですが、優秀というほどでもありません。
Elixirは関数型プログラミング言語として優れています。(私見では)Elixirはマルチコア処理(コードの実行速度)とソケット接続のサポートを主要な目標に置きつつ、開発者の幸せや十分な生産性にも配慮しています。
ElixirにはPhoenixというWebフレームワークもあり、Phoenixについて知れば知るほど、PhoenixがElixirと同じ目標を目指してElixirと連携するライブラリの集合体であることが理解できます。
つまり対決の図式は、Elixir vs Ruby vs Ruby on Railsということになります😄。
私の説明はどの言語でも似たり寄ったりに見えますが、「魔は細部に宿る」ものです。
Ruby
オブジェクト指向プログラミングの概念(SOLID原則やオブジェクトのコンポジション、DCI、オブジェクト指向解体設計(OODD)、シンプルデザイン、境界コンテキスト、DDD、BDD、TDDなどなど)の理解が深まれば深まるほど、Rubyがこうした概念と見事に調和していることに気付かされます。
私見では、Rubyは「開発者自身を記述するのに最適な言語」です。一部の開発者もおおむねこの点を支持していますが、このことにはそれ以上に重要な点があります。皆さんの職歴のほとんどはチーム作業で占められているのですから、自分や同僚がコードに込めた意図が相手に伝わることが重要です(それこそが言語というものですから)。
よくある誤解のひとつに、Railsを使わないとまともなRuby Webアプリは書けないというものがあります。実際にはHanamiやSinatraなどさまざまな選択肢があります。
RubyはWeb開発に特化した言語ではなく、汎用的なプログラミング言語であることを思い出しましょう。私はこの9年間で、純粋なRuby CLIツールを何十個も個人用や職場向けに作成しています。Google SketchupのようなRubyを実行できるアプリもありますし(訳注: 現在はGoogleの所有ではありません)、Rubyは日本ではかなり人気の高い言語です。
「Rubyは死んだ」記事はいくらでも見かけますが、裏付けを示している記事はめったにありません。たいていはグローバルなデータに立脚していない、開発者の個人的な見解や経験をぶちまけた記事です。どこかの会社が別の技術に乗り換えたぐらいで言語全体が死ぬということにはなりません。
Rubyは今日も元気いっぱいに溌剌と生きています。
Rubyは決して大メジャーではありませんが、それがマイナス要因になっていません。コミュニティのところで説明したように、実際にはこの方がむしろ望ましい状態かもしれません。
Rubyはかれこれ25年も長らえています。Rubyがそう簡単に消えてなくなることはないでしょう。
本記事を多面的に捉える裏付けのひとつとして、Railsが縮小しつつある場面をこちらの記事でご覧ください。最近のコーディングブートキャンプの科目ではRailsが他のものに置き換えられつつあります。これについては後述します。
Ruby on Rails
Railsはフレームワーク(協調動作するライブラリの集合体)であると同時に、製品を短期間で構築するためのコードはいかにあるべきかという哲学でもあります。
他の言語からRails世界に飛び込んだ開発者は、多くの場合Railsの歴史や価値体系の大きな違いを見落としています。
- Doctrine | Ruby on Rails(Rails開発者になる前に絶対読むべき)
- YouTube: RailsConf 2014 - Keynote: Writing Software by DHH
- Podcast: DHH on Rails web development - Ruby Rouges podcast Dec. 2017
- Podcast: DHH on testing
これらを視聴してRailsの意図を正しく理解できるようになると、Railsの作者たちが2018年に提案するソリューションが10年前と変わっていないこと、つまり今も通用していることがわかるでしょう。サーバーサイドレンダリングされるHTMLやCSS、ちりばめられたJavaScriptは今もそのままです(例のRJSはともかく)。
BasecampやShopifyの収益(何しろ営利企業ですから)や、開発者が幸せそうにしている様子(ソース)は、Railsのアプローチがうまくいっている証拠です。
Railsでは、開発者の生産性を高めるためにさまざまな要素が互いに結合(癒着)しています。たとえばRailsのモデルはデータベースに直接書き込みますし、フロントエンドはデフォルトでバックエンドと結合(癒着)しています。
最近の大きな潮流といえばSPA(シングルページアプリケーション)ですが、RailsはとりたててSPAに逆らおうとはしていません。Railsの作者たちは、単にSPAを使うことを好んでいないだけです。
ですからRailsのフロントエンドでSPAを使っても別に構いません。しかし独特なものになってしまうのも確かです。Rails 5でWebpackが標準として導入されたのはつい最近の話です。ある時期までのRailsでは、(gemを使って)アセットパイプラインでSPAライブラリをレンダリングするのが一般的でした。これはRailsバックエンド開発者とフロントエンド専門の開発者の間に緊張をもたらし、JavaScriptとRailsの「ショットガンマリッジ(shotgun marriage: できちゃった婚)」は不評を買いました。
別のアプローチは、API専用のRailsアプリを生成してSPAをまったく別のVMに配置するというものですが、DevOpsと開発チームの同期を取るために文字どおり2つの異なるプロジェクトを立ち上げるという余分な手間がかかります。
ポイントは、RailsはSPAの利用を望んでいないこと、しかしSPAが必要なら3とおりの方法が使えるということです。これは、Rails初心者や「トレンディな」最新技術であるSPAなどを教えたいコーディングブートキャンプが「RailsでSPAをやっていいのかどうか」で戸惑うだろうと私は考えます。だからブートキャンプはRailsを捨ててピュアJSバックエンドを教えるようになったのです。
理由についてはJavaScriptのセクション(後編)で説明します。
Railsの人気が落ちているように見える理由はこれです。しかし人気が落ちたのではありません。ブートキャンプがRailsを教えなくなっているらしいというだけであって、スタートアップ企業は今も新規プロジェクトでRailsを選択しています。
ここで忘れてはならないことがひとつあります。何か新しいトレンドが出現したからといって、即それ一択ということにはなりません。何年か前にもNoSQLデータベースで同じことがありました。当時はMongoDBだのCassandraだのRiakだのが、MySQLやPostgreSQLなどのSQLデータベースを置き換えようとする巨大なムーブメントが巻き起こりました。その結果どうなったかというと、置き換えは起こりませんでした。SQLデータベースを使いたいシナリオもあれば、NoSQLデータベースの方が適切なシナリオもある、それだけのことです。
昨今のマイクロサービスも似たような傾向を示し、いつか来た道をたどっています。マイクロサービスが2018年のアプリにおいていかに「ベストプラクティス」であるかが方々で力説されていますが、製品リリース前に資金を使い果たしてしまうことについての説明はとんと見かけません。
開発者はいずれ、Railsがモノリスアプリに適していることと、Railsのマイクロサービスは少々メモリを食い過ぎることに気づき、Sinatraのような軽めのソリューションを採用したりするでしょう。
同じことが「コーディングのベストプラクティス」「テストのベストプラクティス」「デプロイのベストなんちゃら」などにも言えます。
チームやプロジェクトは、ひとつとして同じものはありません。プロジェクトをどう構築するか、どんな技術を使いたいか、どんな計画で進めたいのかは、他ならぬあなたがじっくり腰を据えてチームと議論しなければ決まりません。プロジェクトにとって最も迷惑なのは、毎回意見がコロコロ変わる人です。
そういうわけで、たとえば「開発速度と開発の容易さ」が主要な懸案事項だとすると、私ならSPA抜きのRailsを採用するでしょう(Turbolinksは皆さんが思っている以上に強力ですよ)。特に、チーム開発でなくワンマンプロジェクトであればきっとそうするでしょう。
「SPAとJavaScriptに専念するフロントエンド開発チーム」と「APIの提供に専念するバックエンド開発チーム」の2チーム編成が目的であれば、RailsのAPI専用オプション(rails new myapp --api
)を採用するでしょう。
そのAPIで膨大なトラフィックを扱う必要があるならRailsを使いますが、EventMachineなどの別のエンジンも検討するでしょう。とはいうものの、RailsのデフォルトWebサーバーであるPumaも実に強力です。Railsのキャッシュの適用方法をきちんと学べば、相当なトラフィックを扱えるようになります。
APIでメガ単位のトラフィック(数百万リクエスト級)を扱う必要があるなら、ElixirとPhoenixがずっと優れた選択肢になる可能性もあります。
とあるPodcastで知ったのですが、米国の某市が運営する犯罪レポーティングソフトウェアはかつてRailsサーバーで運用されていたのですが、平均トラフィックが大きいため6台ほどサーバーを使っていたそうです。同市がサーバーをリファクタリングしてElixirに置き換えたところ、2台のサーバーでまかなえるようになりました。平均負荷は30%だったので実際には1台のサーバーで回せるのですが、サーバーダウンに備えて2台編成にしているのだそうです。