この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
クライアントサイドJavaScriptのフレームワークとして人気のBackbone.jsが採用している Model–View–Presenter (MVP) というアーキテクチャパターン(以下MPVパターン)について考察してみます。
Model-View-Controllerなら聞いたことあるけど?
僕もそうでした。初めて知ったのはRuby on Railsを触った時です。
Modelはデータと手続きを担当し、ViewはUIを、Controllerは入力イベントを受付けてModelとView操作する…とまぁざっくり言うとこんな感じですよね。
MVPパターンも凄く似ていて、どうもMVCパターンから派生したものみたいです。以下が各パターンの図です。
Model-View-Controller
Model-View-Presenter
PresenterがModelとViewを操作しているところがControllerに似ています。
決定的に違うところはMVPのViewはModelと一切連携しないところですね。もう完全に赤の他人って感じです。
Backbone.jsってなんだっけ?
Backbone.jsは一言でいうとブラウザ上で動くJavaScriptのフレームワークです。jQueryと違うところはDOMの操作を便利にするわけではなくアプリケーションの構造を支える部分に特化しているところです。
通常のWebページはURL毎にサーバと通信してhtmlを書き換えますが、単一のWebページでダイナミックにUIを変更することで表示速度を向上させたり、リッチな表現をすることができます。しかし引き換えにコードは煩雑になりがちです。Backbone.jsがこの手助けをしてくれます。
そしてもう一つ特徴的なのはクラスベースであるところだと思います。しかしJavaScriptはオブジェクト指向の言語ですがRubyやPythonのように言語レベルでクラスをサポートしていません。プロトタイプベースの言語です。
ただこれは書き方を工夫してクラスをエミュレートすることができます。以下に例を紹介します。
Rubyのクラス
class Person
def initialize(name)
@my_name = name
end
def greeting
"Hello. I'm #{ @my_name }"
end
end
yamagata = Person.new('yamagata')
yamagata.greeting # => Hello. I'm yamagata
JavaScriptでクラスをエミュレート
var Person = (function() {
function Person(name) {
this.my_name = name;
}
Person.prototype.greeting = function() {
return "Hello. I'm " + this.my_name;
};
return Person;
})();
var yamagata = new Person('yamagata');
yamagata.greeting(); // => Hello. I'm yamagata
クラスベースを採用することでコードの見通しがとても向上すると思います。
またクラス同士のやりとりはイベントを用いてなるべく疎結合にしておくことでコードの再利用性を高めることができます。
例えばPersonクラスの goTo というメソッドに 'home' という引数を与えて実行すると homecoming というイベントを発火するとします。
var yamagata = new Person('yamagata');
yamagata.goTo('home'); // => homecomingイベント発火
すると homecoming イベントを購読している Dogクラスの welcomeHome というメソッドが呼び出されるといった感じです。
new hachi = new Dog('hachi');
yamagata.bind('homecoming', function() {
hachi.welcomeHome(); // => hachiが出迎えてくれる
});
これはjQueryでHTML要素のclickイベント等を扱うのとさほど変わりませんね。
Backbone.jsのクラスたち
ではBackbone.jsが提供するクラスにはどのようなものがあるのでしょうか。以下は現在(2013/02/26)公式ページに掲載されているクラスたちです。
Events
前述したイベントの購読と発火をするための機能が内包されています。
Model
データとビジネスロジックを担当します。
Collection
Modelの集合を扱えるようになります。
Router
URLの変化に応じてアクションを起こします。
View
UIの表示とユーザイベントをハンドリングします。
おや?Presenterというクラスがありませんね。これはPresenterに相当する機能は「ViewとRouterに分散している」または「アプリケーションごとに自分で実装する」という2つの考え方があると思います。
いずれにしてもPresenterの仕事はModelとViewの中間でそれぞれを操作することですので、アプリケーションの振る舞いが定義されている部分がPresenterになります。ということはURLの変化に応じて動作する部分も、UIのクリックイベントに応じて動作する部分もPresenterですね。
まとめ
今回は簡単にBackbone.jsが採用しているMVPパターンについて考察してみました。Backbone.jsは理解に少し時間がかかります。jQueryの様にデザイナーでも扱いやすいコードとは程遠いかもしれません。ただし導入することでテストが書きやすくなったり、メンテナンス性も向上するなどメリットが色々あります。次回からは実際に動くもので検証して行きたいと思います。