Backbone.js(http://documentcloud.github.com/backbone/)を2,3ヶ月触ってみて、導入して良かったことをまとめます。

Backbone.js単体での威力はそこまでではないかもしれませんが、Server側も含めた設計思想を絡めて考えると大きな効果が期待できます(サーバー側も含めた構造改革が全体的に必要になるとは思いますが・・・)。

ViewとControllerの結合強度低下 = Viewのアプリ化

viewとcontrollerが1対1対応だった頃

Rails単体で作成している場合、Viewにロジックが入れられない以上、 そのViewで必要な変数などは、全てControllerに書く必要がありました。

この状態では、ControllerがViewによって処理内容を変更する必要があり、結合強度が高くなってしまっていました。

このため、HTMLをレンダリングするためのControllerと、iPhoneなどでJSONを返すAPI的なControllerは分ける必要がありました。

これは、『DRYじゃないし、FatControllerになってしまって気持ち悪い』ということになりました。

ajaxの導入

そこで、ControllerとViewの1対1対応を割けるために、ajaxを導入し、 1つのViewをレンダリングするために、複数のAPIを叩くような構成をとることにしました。

こうすることで、Controllerは素直なCRUDのみを提供すれば良くなり、FatControllerは解消されました。 しかし、Railsでajaxを多用すると、

  • jQueryで書く場合
  • link_to remote: true などRailsの機能で書く場合

と、ajaxの管理が煩雑になってしまい、メンテナンス性が落ちてしまいました。 今まで、Controllerがやってくれていた処理を、Viewのjaxに回したために、View側で混乱してしまったという状態でした。

Backbone.jsの導入

そこで、View側にも構造を導入してあげようということで、Backbone.jsを導入しました。 導入するルールとして、Railsとは完全に切り離し、通信はBackbone.jsを通して行うことにしました。 こうすることで、煩雑だったViewの整理整頓ができました。 つまり、

  • ControllerはシンプルなCRUDのみを提供するAPIでOK => プラグイン一発で完了
  • ViewはRailsなどとは独立して設計・製造され、View側が必要なAPIを叩く
  • Viewが複雑になるため、Model, Viewと構造化できるBackbone.jsを導入。

と、こんな感じです。 こうして、スッキリと開発できるようなり、Server側の製造負担は飛躍的に軽くなりました。

アプリ化へ

以上のように、ViewはControllerから完全に切り離されることになります。 こうすることで、View側はAPI通信をMockにし、完全独立な形態で開発できます。 また、API側はRailsである必要がないため、node.jsなどの用途にあったserverを準備できます。

サーバー側のエンジニアは単純にAPIを作り、クライアント側はBackbone.jsとデザインを作るだけになるので、分業しやすくもなりました。

さらに、View側は完全にstaticなファイルになるため、nginxから直接配布すこともできます。 つまり、HTML/CSS/JSをnginxから配布し、必要な情報を必要なServerから取得する構成ということになります。

これは、iPhoneアプリをダウンロードし、jsonなどで裏でサーバー通信するのと全く同じ構成になります。 つまり、Viewをアプリ化できることになります。

アプリ化すれば、iPhoneアプリなどとAPIを共有でき、開発のパワーを集中化させることができます。 また、静的ファイルは高速に配布できますし、jsonだけになるため通信量が低下、パフォーマンス自体も向上します。 websocketを使った通信をserverとのやりとりに使えば、pushなど面白い仕掛けもできます。

こうして、ViewとControllerの結合強度を下げることで、設計・製造の自由度やパフォーマンスが向上しました。

Viewの汎用化とモジュール化 = 使い捨てコード0へ

上記の通り、Viewが必要なAPIを叩くという構成をとったことにより、 APIは汎用的かつ、シンプルなツールを提供することになります。 これにより、API群は複数のViewから流用化できるため、開発自体が一気にDRYになり、 使い捨てのコードはなくなります。

次に、課題になったのが、Viewの開発スピードを向上させることでした。 Viewは、デザインが絡む部分なども多く、汎用化しにくいと考えていましたが、 ページを構成する各パーツに関しては同じようなものが多いのが現状です。

そこで、下記のような方針でViewの汎用化ツールを作ることにしました。

構造と内容の分離

HTMLでViewをレンダリングする場合、

  1. ページのどこに何を配置するか決める(配置)
  2. 配置されたDivを埋める内容に即した、ツールバーなどの構造をレンダリング(構造)
  3. 実際の内容をレンダリング(内容)

のようなステップで考えることが多いかと思います。 例えば、Twitterのタイムラインのページでは、

  1. 左右にコマ割りをし、右にツイートの一覧を表示する。
  2. ツイートの一覧を表示するするに当たり、タイトルとして「ツイート」や最後尾に「つづきをよむ」のような構造を準備
  3. 実際にツイートの一覧を挿入する

という形になると思います。

そこで、この(構造)の部分をどこにでも配置できるように作成し、流用化することにしました。 実際に使う場合は、(配置)と(内容)を決定してあげます。 Backboneの用語で言えば、(構造)がBackbone.Viewで、(配置)がelに、(内容)がmodelやcollectionになります。

例えば、一覧系のようにArrayをとりあつかう(構造)であれば、 MacOSXのFinderのような汎用的なUIを作れば十分そうです。 Finderを一つ作ってしまえば、どのcollectionでも使えてDRYですし、 継続的にメンテナンスすることでどんどんリッチにすることができます。

これまで、一覧系はバラバラに開発してきましたが、 FinderというBackbone.View=(構造)を作成し、実際に配置するタイミングで、Backbone.Collectionを詰めて使う。 こんな構成構成に全体的に変更しました。 結果的に、UI的にも統制のとれたものになり、機能としてもリッチになり、一石二鳥になりました。

なお、配置場所は、bodyの直下に配置すれば単なる一覧ページなりますし、ポップアップに配置すれば、リッチなセレクタにもなります。

Backbone.jsでは、内容(model,collection)と配置(el)をインスタンス化するときに決定できますので、 上記の構成がとても自然に実装できます。

さらにモジュール化

各Modelはアイコンのみ、プレビュー、編集ページ、詳細表示など様々なViewを持ちます。 しかし、これらの見せ方は、Model間で共通化した方がUI的にも統一間がでてきます。

つまり、ちょっとしたプレビューやアイコンなども全てBackbone.Viewにmodelを挿入する形で作成し、各modelを横断したデザインができることになります。 (蛇足ですが、DBやAPIなどのサーバー側は縦割で、デザインは横割で作るイメージがありますよね)

コード的にもDRYになりメンテナンス性も向上、機能追加もそのViewをリッチにしていけば良いので、蓄積していくことができます。

こうして、使い捨てのコードはドンドン減っていきます。

Eventを利用した、Viewの同期

上記のように、1つのmodelに対して、様々なViewを作ることになります。 ポップアップで表示し、その場で編集する場合など、 同一のページに同一のmodelの様々なViewが混在することが多々あります。

この場合、modelの名前を編集すれば、全てのViewを更新する必要があります。 昔であれば、ページをreloadさせるところですが、そんなダサイことは今更したくありません。

そこで、Backbone.jsではModelやCollectionのeventをViewがキャッチしてレンダリングする仕組みを取っています。

流れはこんな感じです。

  1. 一覧ページのレンダリングをします。
  2. 一覧ページ中のとあるmodelを編集するために、ポップアップウィンドウをajaxで出します。
  3. ポップアップ内でmodelを編集し、saveします。
  4. modelの内容を書き換え、serverに通信します。
  5. modelの内容が書き変わると、modelからchangeイベントが発生します。
  6. 一覧とポップアップ内のBackbone.Viewがmodelのchangeイベントをキャッチします。
  7. 各Backbone.Viewが内容を書き換えます。
  8. ユーザーがポップアップを閉じます。
  9. 一覧にあるmodelの内容も書き変わっています(=>カッコイイ!!)。

このように、ViewにつめるModelやCollectionのイベントをキャッチして、 Viewのレンダリングを行うことを前提に作っていけば、自動的に各種Viewの同期が取れることになります。

こうして、reloadすることなく最小限の更新でViewの同期が取れることになります。

まとめ

以上、まとめです。

  • Backbone.jsを使うことで、Server側、Client側両面で汎用化・モジュール化した設計が可能になります(使い捨てコードを理論的には0にすることが可能です)。
  • 上記設計にすることで、設計・製造の自由度、パフォーマンスを向上させることができます。
  • Eventを利用することで、View間の同期問題も解消し、ajaxでのview開発がスムーズに行えます。

長くなりましたが、以上です。

  1. y-u reblogged this from techs-empty
  2. lollipedo reblogged this from techs-empty
  3. akuwano reblogged this from techs-empty
  4. ruhenheim0716-blog reblogged this from techs-empty
  5. nemuru-jaggjagg reblogged this from techs-empty
  6. tomato360 reblogged this from techs-empty
  7. sentas-blog reblogged this from techs-empty
  8. hiro88hyo reblogged this from techs-empty
  9. fifty-six reblogged this from techs-empty
  10. rrreeeyyy reblogged this from techs-empty
  11. uokada reblogged this from techs-empty
  12. ise0615-blog reblogged this from techs-empty
  13. wevnote reblogged this from techs-empty
  14. techs-empty posted this