のっけから宣伝で恐縮だが、Ruby Prize 2018が現在ノミネート対象者を募集している。Ruby Prizeは、「新規にRubyコミュニティ活動に参加した人を正当に評価し、Rubyの普及と利用促進を図る」ということを目的とした新人賞的な位置づけの賞で、2017年はkamipoさんこと上薗竜太氏が受賞した。2018年についてはこちらから一般推薦に応募できるので、広く協力していただけるとありがたい。
今さらながら最近気づいたのだが、最近 Web アプリケーション開発を始めた人からみると、Rails というのは Web 開発の王道をいく Web アプリケーションフレームワークであり、MVC といえば Rails であり、MVC の M として代表的な OR マッパーと言えば ActiveRecord である、という認識もめずらしくないらしい。
なにそれそんなやばいことになってるの? と思ってはみたものの、よくよく考えてみるとさほど不思議な事でもない。 Rails が公開されてから 10 年以上過ぎ、Rails 以降にメジャーになったサーバサイド Web アプリケーションフレームワークはあまりない(これは Rails がなんとか生き残り現在も活発に開発されているということと同時に、現代では新たなサーバサイド Web アプリケーションフレームワーク開発自体が流行っていないということの反映でもあるだろう)ということからすると、ある意味当然の認識なのかもしれない。 しかしながら、10 年前であればそれなりに常識的だった知見がいつの間にか失われてしまうというのもあまり健全ではない。
例えば最近でも『Clean Architecture』が翻訳され、好評を博している。しかし、Rails は Clean Architecture 的なクリーンな構成をしていない。 しかし、だから Rails はダメだとか、Rails もクリーンにするべきというのは短絡的すぎる。むしろ、Rails はクリーンではないことを重視し、そこに価値を見出している、とするべきだろう。 クリーンさを重視したものの上手く統御できず鈍重になってしまった開発プロセスに背を向け、規律がとれながらも簡単に現実的なWeb開発を行うことができるためのツールとして Rails は生まれた。Rails にとってクリーンではないことは欠点ではなく特長であった。
というわけで、本稿では初期 Rails が登場した背景について簡単に触れてみる。 もちろん当時と現在では状況が違うため、現在の Rails 開発には当てはまらないところもあるかもしれない。 そこは差し引いて、あくまで Rails の誕生当初での問題意識にのみ着目したものと割り切ってほしい。
Rails が公開されたのは 2004 年である。2004 年の Web アプリケーション開発というのは、一言で言えば Struts の時代だった。 Struts によって、Web アプリケーションフレームワークの世界でも、「MVC」という言葉が広く使われるようになった。
ちなみに Struts など、Web に MVC を適用したものを「MVC2」と呼ばれることが過去あったが、これは誤解であると言われている。 JSP の使い方としてコントローラもビューも何でも JSP にやらせていたのを「JSP Model 1」として、それに対して MVC パターンを導入し、JSP もビューのみにしたのを「JSP Model2」と呼んでいた。これがどこかで転倒し、「MVC2」なる謎の用語が生まれた、というのが真相のようである1。
とはいえ、同じ MVC を使ったフレームワークと言っても、Struts と Rails は大きく異なる。むしろ、MVC のあり方の違いにこそ Rails の本質がある。そして、その違いを理解するために紐解くべきものとして、PofEAA あるいは PoEAA こと『エンタープライズアプリケーションアーキテクチャパターン』(マーティン・ファウラー著)という書物がある。
PofEAA と Rails の関係性については、ActiveRecord の名前の由来である Active Record パターンの出典として本書が取り上げられている2ことが分かりやすい。 それ以外にも、MVC パターンはもちろんとして、一意フィールド、外部キーマッピング、関連テーブルマッピング、フロントコントローラ、テンプレートビューなど、Rails で使われているパターンが多数紹介されている。DHH 自身が Rails の開発の際に参考にしているのは間違いないだろう。 実際に、DHH は自身が多大な影響を受けたプログラミング書籍 5 冊の中の 1 冊として、本書を挙げている。3
その一方で、PofEAA を読みこんでいくと、Rails の設計方針とは若干の齟齬を感じる部分もあることに気づく。
例えば Active Record パターンにしても、PofEAA ではあまり掘り下げて紹介されているパターンではない。 そもそも、PofEAA の中では Active Record パターンは必ずしも優れたパターンとして紹介されているわけではない。 ドメインモデルが簡単なものであれば Active Record パターンでもよいかもしれないが、ドメインモデルを真面目に実装するのであれば Active Record パターンは避けるべきで、自由なマッピングが行える Data Mapper パターンを使うべき、というのが PofEAA の暗黙のスタンスと理解してよいだろう。
むしろ、PofEAA で出てくる Active Record パターンは、単に Row Data Gateway パターンにドメインモデルのメソッドを取ってつけたようなものにすぎない。
外部キーマッピングや関連テーブルマッピングも、PofEAA で想定しているのは Active Record パターンではなく、Data Mapper パターンのように、モデルと DB のテーブル(DDD 用語であればリポジトリ)が分離されている世界の話として記述されている。
Rails の ActiveRecord のように、has_many
や belongs_to
を Active Record に持たせるのは、PofEAA 由来ではなく、Rails の独自拡張によるものである。
なぜ Rails は PofEAA を参考にしつつも、PofEAA の理想的な設計とは異なる設計になったのか。 それは偶然や、単なる実装上の都合によるものではなく、Rails の思想に由来するものだろう。
Rails というのは決して適用範囲を広く定めた、あらゆるアプリに向いたフレームワークではない。 Web アプリケーションフレームワークの最適解として、クリーンさよりも便利さを重視したアーキテクチャを目指したものだ。 モデルがある程度 DB にマッピングされるものとして記述した方がよいのであれば、DB にマッピングするか、あるいは単なるオブジェクトとして記述すれば十分ではないか。 OR マッピングについても、テーブルとドメインオブジェクトの高度に自由なマッピングを頑張るよりも、素朴に一対一対応させるよう、あらかじめテーブルとモデルを揃えておけばよいのではないか。 そのために DBA とプログラマの権限の問題があるとすれば、プログラマがDB設計を行えるように権限を与えればよい(当時は DB は DBA がビジネスルールを踏まえて設計するべきものであり、アプリケーションフレームワークの都合でほいほい変えるのはありえないというか論外という見方も少なくなかったはずだ)。 そう割り切るのが Rails の考え方だった。
ドメインモデルを重視するスタンスの人であれば、Rails には違和感があっただろう。 「密結合」という Rails の特徴は、ソフトウェアエンジニアリングからするとある種の敗北を感じさせる両義性もあったのではないか。 しかし、PofEAA の背後にあるような、自由度を高めた汎用的な設計をあきらめ、レールの上での利便性に重きを置いた上で、柔軟性についてはメタプログラミングを駆使することで担保するという Rails の戦略は、Struts 全盛の界隈には異端のように思われつつも、いつの間にか広く使われるようになっていった。
もっとも、今は Rails 初期とはだいぶ趣も変わっている。 当時に比べると、今は Functional なデザインが広まりつつあり、OOP との関係もより複雑なものとなっている。 さらに、Web のアーキテクチャも変わりつつある中で、Rails もこれまでとは同じやり方が通用しなくなるのかもしれない。
とはいえ、バージョンアップに従って、ころころ路線を変えてきたのも Rails の特徴ではある。モバイルの興隆により Web の優位性がアプリに移り変わりつつも、PWA も目新しくなくなりつつある現在、Rails にも新しい流行を踏まえた新しい道具立てが生まれてくるのかもしれない。そんな期待も込めつつ、昔語りを書いてみた。
(るびま編集長 高橋征義)