フレームワーク作りの一歩はRouterから
「RubyでオレオレWebアプリケーションフレームワークを作ろう」と思ってからどれほど経ったのか、過去記事をさかのぼれば分かりそうですが、きっと呆れるくらい経っているので、あえて調べないことにした岩本です、こんばんは。
フレームワーク作りにこれだけ時間がかかっているのは「フルスタックにしなければならない」という固定観念があったせいだと、最近ようやく気づきました。id:dannさんによる「Angelosで学ぶ優しいWAFの作り方」のおかげです。
フレームワーク作りはそんなに大変じゃない
dannさんのプレゼンテーションでは、フレームワークの最小構成要素が下記のように示されています。
- Engine - req/res, サーバー抽象化
- Dispatcher - URLとControllerのmapping
- Component Loader - controllerのload + controller検索
言い換えると、たったこれだけの仕組みを作れば、フレームワークのできあがりというわけです。
Rubyには、Rackという素晴らしいEngineがあるので、これを使わない手はありません。つまり、実質的に自前で用意すべきは、DispatcherとComponent Loaderの2つだけということになります。はい、俄然やる気が出てきました。
フレームワークの最小構成要素はRouterとDispatcher
ここからは私独自の考えになるのかもしれませんが、DispatcherとComponent Loaderの責務を単純化して考えると:
- Rackから渡されるenvを解析し、処理を委譲すべきコントローラとアクションを決定する
- コントローラのインスタンスを生成し、アクションを実行する
となります。PHPのZend Frameworkでは、前者をRouter、後者をDispatcherと呼んでいます。
これらを区別せずに、ただRouterと呼んだりDispatcherと呼んだりすることもあるようですが、区別したほうがフレームワークユーザの理解を助けるのではないかと私は思っています。
なお、Component Loaderは、Dispatcherが依存する内部ライブラリというイメージです、今のところ。
Routerインターフェースの決定版を定義したい
以前作ったRuptaは、DispatcherではなくてRouterです。「あとはDispatcherさえ作れば、フレームワーク完成」といいたいところですが、Ruptaへの不満がいろいろ募ってきたので、また別のRouterを作ろうと考えています。
新しいRouterの詳細は後日の日記に譲りますが、いま漠然と浮かんでいるのは「RouterやDispatcherもプラガブルにしたい」という野望です。プラガブルにするには、Routerのインターフェースを決めなければなりません。Rackのような抽象化をRouterレベルでトライしてみたいということですが、どうなりますやら。