読者です 読者をやめる 読者になる 読者になる

webネタ

技術系ブログ。web系SE。1988。♂。@rhong_

中規模開発のためのBackbone.js

はじめに

Backbone.jsを使って、管理画面を作ったときのことを備忘録も兼ねてまとめて記事にします。

Backboneは入門やHelloWorldはたくさん情報があるんですが、実際使うとなると色々と考えることが多くて大変です。少しでも役に立てればと思います。(・ω・ )

開発メンバー

5人。JavaScript経験者2人。Backbone経験者0人。(・ω・`;)..

全員JavaScalaの経験がそれなりにある。

まずはじめに

今回は、全員3日程度ですがBackbone.jsを勉強する時間がありました。

その間に自分がBackboneで一部分実装し、ベースを作成することに。

勉強に使ったのは、主に Backbone.jsガイドブック

学習のとっかかりとしては、ドットインストールがいいんじゃないかと思います。

ベースの作成

コーディング規約

まずはJavaScriptのコーディング規約を決めるところから始めました。

ベースとした規約は、GoogleのJavaScriptStyleGuideです。

このドキュメントは、とても長いのでポイントだけをまとめてコーディング規約としました。

自分が規約を保守できる形で、かつメンバーが読みやすくしないと浸透しないと思います。

もちろんjQueryやBackbone用の規約を色々追加してもいます。

例えば、

jQueryオブジェクトをいれる変数には$をつける。

// Good
$elem = $('#hoge');

// Bad
elem = $('#hoge');

・View内でDOM探索する場合は、this.$を使う。

// Good
this.$('.hoge');

// Bad (viewが扱うDOMの範囲が不明瞭になるため)
$('.hoge');

などなど決めました。

随時追加していくのがいいと思います。

ディレクトリ構成

次にディレクトリ構成を決めました。大体以下のような感じです。

.
├── app
│   ├── collections
│   ├── configs
│   ├── events
│   ├── models
│   ├── templates
│   └── views
├── core
├── test
│   ├── app
│   └── core
└── vendor

名前空間

名前空間を切って、どこに何があるか一発でわかるようにしました。

  • app.views.Hoge -> app/views/Hoge.js
  • app.models.Hoge -> app/views/Hoge.js
  • app.collections.Hoges -> app/collections/Hoges.js

というような感じです。

さらに構造が複雑になると、

  • app.views.hoge.HogeFoo -> app/views/hoge/HogeFoo.js

というようにしました。

javaとかと同じです。(・ω・`)

全体のView設計

まず、画面のどこを何のViewにするか決めました。

ヘッダーは、app.views.Header。

サイドメニューは、app.views.Sidemenu。

ページ切り替え時に再描画するエリアを、app.views.Content。

という感じで大枠だけいろいろ決めました。

テンプレート

JavaScriptのテンプレートエンジンは多々ありますが、今回はUnderscore.jsのtemplateを使っています。

最初はHogan.jsを使ってたんですが、ロジックレス過ぎて辛かったのでやめときました。

しかしUnderscoreのtemplateは、ロジックが書け過ぎて辛い..。

(今思うと、Hogan.jsのままでよかったカモシレナイ...(・ω・`;)

テンプレートは以下のような感じで配置し、

├ app
├─ templates
├── hoge
├─── foo.html
├── pyo.html

gruntで一つのファイルに結合させて、

var html = JST['hoge/foo.html']();
や
var html = JST['pyo.html']({params: {a: 1}});

のようにして使いました。

grunt-contrib-jstです。

実践的なBackboneの使い方

view

viewは何らかのDOMを管理していているが、viewを初期化時に、

DOMを生成する方法と、探索する方法の2つがあります。

DOMを生成する方法。

特に何も指定しなければ空divが作られます。

var view = Backbone.View;
(new view).render().el
// <div>

クラスや属性を指定することもできます。

var view = Backbone.View.extend({
  tagName: 'p',
  className: 'aaa',
  attributes: { 'data-hoge': 1 }
});
(new view).render().el
// <p class="aaa" data-hoge="1">

DOMを探索する方法

elにセレクタを指定すると、初期化時に探して保持してくれます。

var view = Backbone.View.extend({
  el: '#hoge'
});
(new view).render().el
// <div id="hoge">

大体はDOMを生成する方を使いますが、HeaderやFooterなどはページ読み込み時に出てると思うので、DOMを探索するほうを使います。

ロジックは極力viewに書かない

viewはコントローラーでもあるので、ロジックを書くとテスト書けないし共通化もできなくなってしまいます。

なので、今回はhelperを作りロジックを切り出しました。

helperは、ロジックやテンプレに渡す前処理を行ったりしたので、view-modelの役割もしていたようです。

細かなTips

  • onではなくlistenToを使う。(メモリリーク対策)
  • el: '#hoge'el: $('#hoge')とすると後者はview初期化時でなく、ページ読み込み時に探索されることに注意。
  • (思い出したら追加してく...)

model

modelは以下のように基本的な使い方しかしてません。

var model = Backbone.Model.extend({
  url: '/api/hoge'
});
(new model).fetch();

モデルは、viewでfetch()したりsave()したりしますが、fetch()した後の処理は、fetch成功時に発火されるsyncイベントを使います。

// とあるview

this.listenTo(model, 'sync', this.hoge);

collection

collectionもmodelとほぼ同じ使い方でした。

Pagerを使うときは、Pager用のcollectionを継承させて使ってました。

Backbone用のPaginateはいくつかありますが、APIの結果の都合上今回は自前で作りました。

Underscore.jsについて

BackboneはUnderscore.jsを使ってます。

とても便利なので極力Underscoreのメソッドを使うようにしてます。

可能なら es5-shim とか使ってみたいです。

View間をまたいだやり取り

例えば、何かを登録したときに、サイドメニューを再描画させたいとか。

例えば、ユーザー名を編集したときに、グローバルメニューに出てるユーザー名を変えたいとか。

view間をまたいだやり取りにはイベントを使います。

app.events.Hoge のようなHoge用のイベントを管理するクラスを作ります。このクラスはBackbone.Eventsを継承しています。

例えば、

グローバルメニューのviewで、app.events.HogeをlistenToしておきます。

そしてユーザー編集のviewで、保存が完了したらtriggerしてあげます。

そうするとlistenToしてるところでrenderを呼ぶようにしておけば、再描画できます。

単体テスト

今回は、jasmineを使いました。

テストを書くところは、ロジックのみです。

DOMがどうなったとかのテストが書いてません。保守が大変だし、書く手間もだいぶかかるからです。デザイン変えただけでテストがこけるとかやばいれす。というものの、実際テストを書いてたわけじゃないので、実はそうでもないのかもしれません...ね。誰か教えてください。(・ω・...)

テストの実行はgruntを使い、jenkinsでも動かしてciしてました。

デバッグ

console.logしてもいいですが、debuggerを使うととても開発が捗ります。

var hoge = 1;
debugger;
alert(hoge);

こうすると、debuggerのところがブレイクポイントのような感じで、処理がストップしローカル変数をthisの中身をみれたり、ストップした状態で処理をconsoleで実行できます。

console.logでデバックする時代は終わりました。(・ω・!

コードレビュー

Backboneと関係ないですが、うちの会社ではプルリクエストを送らないと開発の本流ブランチにマージできないので、ほぼ全コードをレビューしています。

やはり最初のほうは色々レビュー指摘があったんですが、徐々に指摘する箇所が減っていってコードの質も上がっていきました。

Backboneのような新しい取り組みでこそ、コードレビューが大切だし効果を発揮するなぁと思いました。

さいごに

Backboneは自由度が高く、色々と決めごとが多いため、最初のとっかかりは大変でしたが、軌道に乗るとみんなスムーズに開発進んでました。

JavaScriptMVCは、(・ω・)イイ!のでぜひぜ挑戦してみてください。

以上。