普通のrailsアプリにbackbone適用して思った事
普通のrailsのwebアプリにbackboneを埋め込んでみて思った事等を書く。
賛否あるかもだが、あくまで個人的な意見。
1)ウチの現場でBackboneを使うべきか否か?
どこも初めに考える事。
大規模になったら使えとか、Single Page Applicationなら使えとか、色々意見あると思うが、
今時の普通のwebアプリならjsガリガリ動くので、迷わずBackbone使っていいと思う。
※単調なB向けの基幹システム作ってるとかは例外として。
どこで使う?
別に全てのpageでBackbone使う必要は無いけど、
フォーム送信系で色々js動かす所とか、検索条件指定、絞り込みとか、
画像/詳細表示、LightBoxとか、
こういう所でjsガリガリ書かないと行けなくなったら
Backboneでモジュールを整理していけばいいと思う。
実際使ってみてどうだったか?
before
元々、自分たちの現場では、coffeescript + classで画面毎にjsファイル区切って、
(要はrails generatorがはいてくれるfile内で) jQueryをダラダラ書いていた。
別にsingle page applicationでもない普通のwebアプリなのだが、
非常に長いjs(coffee)ファイルが複数あり、
作ってる時は良いのだが、改修する時が非常に大変だった。
最悪、触れない。(特に人の作った物で、癖が強い物)
触れなければ作り直せば良いのだが、そうすると、次に、
古いソースを気軽に削除できない問題が出て来る。(どこまで消せるか分からない)
恥ずかしい話だが、しばらく経つと、jsのゴミコードが結構残ってる。
after
これらが、Backboneにする事で、
- View構成要素毎に処理が分かれて分かりやすくなって
- イベントの動きが分かり易い(Events見れば分かる
- 画面描写何やってるかもパッと見で理解できる(template + render())
- 気軽にajax書くようになって、usability向上に貢献!
そう、ハッピーになれた! ※beforeに対してね。新たな悩みが出てきたが。
2)BackboneかMarionetteか?
Backbone単体か、Marionetteまで使おうか?
どうしようかなーと初めは悩んだ。
marionetteとは?
これね。
Marionetteの美味しい所
Marionetteの美味しい所を端的に言うと、
- Viewの階層管理(親子、tree)
- layout管理
- メモリ管理
で、自分のアプリがどうなるのか?考えれば良い。(と初め思ってた)
※後述するが、もう一つ、重要な事があった。
当初考えていた事
Marionetteの美味しい所に対して当初考えていたのは
- Viewの階層管理
- 階層作る程大掛かりな作りにしたくない
- TODOMVCのソースみたいに、なるべく少ないViewクラスの中で多くのUIを扱うような気軽な作りにしようと思ってた
- layout管理
- そんなに大掛かりに作らない。Event紐付けして少しrenderする位。全体的な管理要らない気がしてた。
- メモリ管理
- 厳密なsingle page appliじゃないからメモリ管理そこまで気にしない。
結論。これらの美味しい所は要らないと思ってた。
なので、Backboneで良いと思ってた。
今振り返れば。
Marionetteの美味しい所に対して今振り返れば
- Viewの階層管理
- 後述するが、結局、楽しようとすると、色々遠回りになるので、結局、モジュール分割して階層化が必要だった。
- layout管理
- 上の話の続きで、結局一画面の中での構成要素が分かり辛いので、layout管理が有った方が良い。
- メモリ管理
- ここは、とりあえず困ってない。普通のwebアプリならあまり気にしなくて良い。(作り次第だが)
あと、重要なのが、Marionetteはrenderを初めから決めている所。これも後述する。
3)Viewの階層について
初めに上記に書いた通り、少ないViewで気軽に使いたかった。
1画面1viewとまで行かないが、1画面内で意味上で分けた少ないViewがあって、
この中にEventsまとめて画面描写が必要な時だけrenderするような軽いイメージだった。
が、なんだかんだ言って、button押す=>データを”複数”取得=>表示する
という箇所が非常に多く、ここで、結局、VIewを親子で分けざるを得なかった。
Viewの親子階層
なんで、親のulタグと子供のliタグみたいなのを分けないといけないのか?というと、
親子を一つのviewで管理すると、個別のmodelとviewのマッピングが毎回の処理毎に必要で、
これがスゲー汚い。DRYじゃない。
viewでelとmodel準備しているのは、このmappingを楽にする為?なのかもしれない。
という事で、親子で画面描写しているような所は初めから親子クラスで書いてしまった方が良い。
marionetteで言うCollectionViewとItemView。初めから、これ使えば良かったんじゃんか。
4)renderの自由っぷり
renderがとにかく自由に書けるのがBackboneの良い所であり悪い所でもある。
自由で何でも書けるので、どんなアプリでも柔軟に対応でき、
気づけばダラダラ汚いソースを書いてしまったりする。
初めは気軽に使うつもりだったのだが、上記親子階層の件等から、結局viewが構成要素毎に分かれた。
色々render書いたが、構成見直しに伴い、結構書き直して時間食ってしまった。
そして、「あれ?この要素全部templateに入れれるな?」とか色々気づいて行く。
そして、気づければ、それぞれtemplateもばっちり持ってしまった。
あれ?
結局、最終系がmarionetteのrenderと変わんなくねーか?と。
自由に書いて、行き着く先がsimpleな形で、これがFWとして外出しされているなら、
初めから、このFWに沿っていれば、余計な悩みが無かったと思う。
つまり、初めからMarionette使ってrender楽したら、逆にそこから今の構成が決まってたんじゃねーかと思う。
5)なんちゃってrender
よくBackboneのsampleでイベントの実行する関数の中で画面描写系の処理書いている物があるが、
これ、なんか間違ってると思う。
render()が画面描写という共通認識があるから、
何も知らないviewクラス読む時でも、render見ればそのViewの描写処理が全部分かる。
それを破ると、どんな画面が出来るのかimageが湧かない。
だから、とにかくrenderに画面描写を書くべき。
例外
でも、どんな事にも例外はあって、どうしても、そのviewのrenderとは別の描写させたい事がある。
この場合、そのviewがstatusとなる変数を持って、
renderの中で、そのstatusを分岐して、あくまで、renderの中だけで全部書くべきだと思う。
この処理が複雑になったら、Viewクラスを分けた方が良いと思う。
っていうか、todomvcのtodoも、renderの中で、分岐がある。
(このソースは少しこのブログと文脈違うのだが、)このimageでいいと思う。
※ちなみに、ある要素をshowするhideするみたいな事は、普通の関数でもやっていいと思う。とにかく、renderにどんな画面が出来るかのimageを残してあげるのが、次の誰かに仕様を伝える上で大切だと思う。
一旦、まとめ
何か長くなったので、ここまで。
とにかく、ここまでをまとめると、
気軽にBackbone使おうとしても、結局行き着くのは、marionetteっぽい作りなので、
初めからMarionette使ってしまっていいと思う。
逆に決まったruleに沿う事で構成が出来上がってくると思う。
※気に要らない所/無理のある所は自分でオーバーライドか生Backbone書けばいいし。
この方が悩んだり、書き直したりする時間削減できると思う。
また、この続きをいつか書く。