実践Backbone.Marionette
現場の悩みと解決まで
ryuma tsukano (@lxyuma)
塚野 龍馬
Presented By ...
自己紹介 : 塚野 龍馬 (@lxyuma)
● ServerSide寄りWeb Developer
○ 元々SIer出身:java/rubyで法人サービス開発してた
○ 今は、弊社でCGMを開発
○ 技術Skill
■ 言語FW:Rails ...
jsCafe
jsCafeというjavascriptの勉強会をやってる

今日のMarionetteも元はこちらで発表した物
良ければ是非お気軽にご参加を(次は2/2予定)
目的/目標
● 対象
○ ある程度、Backbone知ってる方

● 目的
○ 現実的にBackboneを使う上での悩み事を解決する

● 目標
○ 現場でBackbone適用して絶望する人を減らす
目次(& ダイジェスト)
● 導入編
○ Angularとの比較、BackboneでのDataBindings等

● 設計編
○ Marionetteでのコンポーネント構成等

● 実装編
○ オレオレ実装を如何に回避するか?等

● テスト...
導入編
javascriptのframework界隈の動き
といえば、Angularの勢いが強いですね
● DailyJSの2013年12月Survveyの利用率
○ Backbone:25%(辛うじて1位)
○ Angular:25%(僅差で2位)
...
Backboneやべぇ

結構古いし
そろそろ寿命?
^o^ /
老害ですか?
「老害」について
Engineer皆が好きな言葉だから
ついでにGoogleTrendsで調べてみた

着実に上昇中!

色々検索されてる!
「老害 Backbone」

良かった〜(> <;)
まだ、胸を張って生きていけそうです。
BackboneとAngularを比較する
● VictorSavkin氏の比較記事
○ infoQ訳
■

俺も前に訳してたんだけどね><

● この記事が良いのは、
○ Plugin付けた現実的な構成のBackboneと
○ Angular...
BackboneとPlugin
● Backbone = ただの背骨
○ 肉は自分で付けないといけない><
○ 肉付けは大体皆一緒 = Plugin化されてる

see BackPlug.io ⇒
BackboneとDataBindings
Angularのウリの1つ = DataBindings
⇒Backboneもplugin追加すれば動く
● NYTimesのBackbone.stickit

● 使い方は超簡単!
Backbone.stickit
Viewの中で
1. 紐づけたいセレクタとmodel属性名を定義
2. $el描写後にstickit()
①

②

⇒すげー簡単!form使うなら盲目的に使うべき
⇒他、Backbone単体の問題はPlugi...
Backbone単体の問題
● BoilerPlateばっかり
○ 多くはMarionette.jsのViewクラスで解決

● 俺俺実装でカオス
○ これもMarionette.jsのController/Region等で解決
Marionette.jsとは?
Marionette.jsはBackboneをwrapしたframework
⇒以前slideにまとめた
細かい説明は、そちらを見て
※次の章に行く迄に上の slideをチラ見しておくと良いかと。。

⇒特にV...
Marionette.jsは必要か?
● Yes!
○ Backbone使うなら絶対オススメ

● 以前blogに書いたがBackbone書いてると同じ
様なrenderやView構成に何度も出くわす
○ それをMarionette.jsが共通...
Backbone単体の問題の続き
● Testし辛い
○ これはsinon.jsのテストダブルで解決
■ sinon.jsもblog記事書いたので良ければ。
○ ⇒これらで、ある程度は、楽になるはず
■ ただ、この辺りはやっぱりAngularが...
Angularの問題
● 学習コストかかる
○ GoogleTrendsでAngular高い=調べ物多い(のが要因の1つ)
○ Backboneはsource grepで解決(simple素晴らしい!)

● ベンダーロックインに近い状態になる...
AngularとBackboneの大人のつきあい方

● 個人Lv : Angularは監視/学習し続けるとして
● 現場Lv : まだBackboneで良いのでは?
○ ※で、AngularはWebComponent繋がって、情報整理さ
れた...
ここ1年位のBackbone関係の話題
思いつく限り
● 海外
○ 2013年もカンファあった。Maionetteも出てくる
○ Airbnbがサーバサイドで動くrendr作った
○ addyさんの素晴らしい書籍も出た

● 国内
○ 春に、多...
という事で...
今年も皆Backboneやろうぜ!

⇒今から現場でBackbone入れた話をする
今日の話の前提条件
「普通の」rails3アプリに適用した話
● SinglePageAppliでない
● ちなみに、turbolinksも使ってない

⇒前提違うと、
構成や注意点等大分違うと思うのでご注意を
※なお、rails固有の話もしま...
設計編
どう設計?
Backbone使う前提
⇒気軽にajax/Event追加
⇒設計の可能性が広がる。

同時に、色々悩みが出て来る
Q:htmlは全部Backbone.Viewにする?
⇒No
SPAでも無いので、
いつも通りServerSideのViewを9割使ってる
DHHが昔disったダブルMVC!
● ServerSideのViewにメリットある
○ 値の連携
○ ...
Q:では、どこにBackbone.View?
A:jsが必要になる以下の時に書いてる
普通のWebアプリでよくあるパターン
● ①Eventキャッチ用View
● ②ajax通信が必要なView
○ A:単一リソース
○ B:複数リソース
■ ...
Q:①Eventキャッチ用Viewとは
殆どのjs処理がコレ。
例)#menuをclickしたらdiv.menu表示みたいな
● なぜ、これもBackboneで書くのか?
○ Backbone無いと、bindしてるDOMと処理内容がバラバ
ラで...
Q:Eventキャッチ用Viewはどれ使う?
⇒Marionette.Viewがオススメ
理由:uiがあるから
● ui
○ selectorを一カ所にまとめて、bindしてjQueryObjに
■ (後述するがこれがテストで重要)
○ 使う時...
Q:②ajax通信が必要なViewとは?
MarionetteのViewを使い分ける
● A:単一リソース
○ Marionette.ItemViewを使うと良いよ

● B:複数リソース
○ 1:単純な親子
■ Marionette.Coll...
Q:複数リソースのViewとは
Backboneで複数data取得/表示する
situationが非常に多い!
例)検索して結果一覧表示
⇒ここで親子にView分割する

※ただのイメージ図です

子View

子View

● なぜ親子分割が...
親子ViewとMarionette.js
Marionetteで親子View用のclassが準備されてる
● 親View
○ CollectionViewか
○ CompositeViewのいずれか。

● 子View
○ ItemView
Q:2種類の親Viewをどう使い分ける?
※ただのイメージ図です

⇒親戚要素(仮)がいるかどうか
● 親戚要素(仮)とは
○ 親子に働きかける別の要素
○ 俺以外誰も使わないので(仮)を付けてる
CompositeView

要素のActio...
2種類の親Viewを整理する
● CollectionView
○ 単純に親子階層だけ必要な時に使う

● CompositeView:親にTemplate使える
○ 親子要素と、
○ その親子要素に働きかける別の要素(親戚要素(仮))が
必要...
Q:component構成は?
⇒Backbone MV* in MVC model2っぽい構成
AppRouter

Controller
生成

連携event

表示

監視

Region

View
描写

html

Model/C...
意図している所
Controller一カ所見ればhtml上でのレイアウト構成
と処理概要が分かるようにしたい
● ①レイアウト構成
○ Region使ってる

● ②処理概要:Controller
○ Marionette.Controller...
①レイアウト構成:Region
DOM要素とViewを紐付け表示管理するclass。
● ItemView継承してる
○ show()でそのまま使う

● ItemView継承してない
○ attachView()で強制的に紐づけてる

⇒どの...
②処理概要:Controller
Marionette.Controller使ってる
● Controllerの関数に書く事
○ 宣言的な所
■ A)Regionの定義
○ 命令的な所
■ B)Viewの連携Event
A)Controller内のRegion管理
⇒基本ApplicationのRegionに追加
(Layoutを使ってない)

● いつかFatControllerになったら、
○ Region管理してる所(宣言的な所)をLayoutに外出しし...
B)Controller内のView連携Eventとは
あるViewのイベントをきっかけに、
別のViewの要素を変える時のイベント
Controller

View A

View B

● あえて、Controller挟んでる
○ ⇒Con...
Q:なぜControllerに寄せてる?
⇒Controllerの単位で処理切替るから
● ちなみにこれがSPAなら...
○ App.jsみたいなのがglobalな連携event持って
○ Controllerはview小片call程度のTh...
実装編
Backboneの実装といえば

オレオレ実装でしょ!
オレオレ実装とは
特にBackbone.View周辺で見られる
● オレオレ自由系render() !
○ view毎バラバラでカオスなrender()記述

● オレオレ深層SubView構成!
○ 深くまで辿らないと全貌が分からない

● ...
オレオレ実装との戦い

Backboneで書いたのにsource追えない
何の為にコレ入れたんだっけ?
はい、しゅーりょー
^o^/
これは、どうにかしないと...
Backboneに素直に従う
与えられた物をその範囲内で素直に使う事で
絡まる事無くsimpleでtestableな状態に!

● Backbone.Viewが用意してくれる事
● Marionetteが用意してくれる事
● stickitが用...
Backboneが用意してくれる事
● $el
○ Viewは$el内のDOM要素だけを扱う
○ globalな$使って外の要素を勝手に変えない
■ やりたければさっきの連携eventをtrigger

● Model/Collection
○...
Marionetteが用意してくれる事
● render()
○ 自分でrender書かないで、カオスを回避
○ Template準備して、誰かと作業し易く

● ui
○ ui経由でjQuery objとって冗長さを避ける

● Event系...
大原則
当たり前の事だけど、
これらに沿うだけで大分違う。
※勿論、例外はあるが。
基本的に、
与えられた物を素直に使う事に徹する
のがオススメ
Q:ぱっと見でViewの動きが掴めない
⇒関数名にevent入れる規約にする
● event関数名 = on + イベント名 + 対象
○ 例)onClickSaveButton / onSyncModel

● これでevents一々見なくて...
Q:view内の関数同士の関係がカオス
⇒関数同士の継ぎ目になるstatusを区別する
status?
● 関数横断して相互利用する要素があった時
○ 例えば、tab/modal/load anime等
○ testでbuggyなのは、この辺り...
Q: statusどう管理する?
⇒methodにstatus/画面操作を統一で妥協
結局、どこまでやり過ぎるかのせめぎ合い
● デザパタState pattern
○ ⇒Backbone.ViewのSubview構成に行き着く

● Back...
Q:変な動きするんだけど
⇒ソースgrepが早くて一番正確。
● BackboneもMarionetteもstickitも全部
● どれもそんなに長くなくてsimple
○ 例えば、Backbone.Viewはたった百行前後しかない

ソース辿...
Q:書いてて不安になるんだけど
⇒分かる。だから、TDD必須
● 実装からBrowser表示まで時間かかる事ある
○ こまめにTestFirstでjs levelの動作確認が必要

● しかし、生でtestは限界がある。
● 結局、幾つかの慣例...
テスト編
jsのTest Frameworkざっくり流れ
● 数年前

● 2年前

● 去年
⇒コロコロ主流が
変わってきましたね
Q:Test Frameworkどれがいい?
● ちょっと前迄、mochaでいいと思ってた
○ mocha使う=chai使う=language chainが気持ち悪い
○ chai以外にどのassertionLibに落ち着けばいいか謎。
(それ...
jasmine
● jasmine2が出てdone(非同期test機能)付いた
● 呼出し口が固定されてる(当たり前だけど)
○ ※jasmineのspy周りは、機能詰め過ぎ/関数名長過ぎで
気持ち悪いので、sinon(後述)使ってる

● 調...
BackboneとTest
BackboneのTestはFrontEnd特有の問題がある
● ①jsがDOM/htmlに依存してる問題
● ②素直に検証書けない問題

これらの解決策を知らないとかなり悩む事に!
①jsがDOM/html依存してる問題
● 頻発するデザイン変更の度にtest修正が必要
○ test修正自体正しい事だが量が多い点が問題><

● DOM調整作業やってるとTDDし辛い
○ DOM調整でhtml注力すると開発flowにTest...
TDD進める為に
● ゴール
○ ServerSideのTDDの様にTest/Targetだけの行き来に
する

● 方向性
○ DOM/htmlの分離
■ 勿論、完全分離は不可能だが、距離をあける
○ jsを書く事と、DOM調整作業を分ける
...
BackboneでのDOM/html分離
● DOMselector書かずMarionette. View.ui使う
○ TestCodeから要素掴むのもview.ui使う
○ targetもtestも中身が絡まるのをおさえる
○ 変更時の修正...
②素直に検証書けない問題
● instance変数の変更等は普通に検証書けるが
● event/server通信はそのまま書けない

⇒後者の対応の為に結局TestDoubleが必要
テストダブルとは
テスト対象が別コンポーネントに依存しており
この別コンポーネントの為テストが困難な時に
別コンポーネントを置換/監視する仕組み。
spy/stub/mock等がある。
テストコード
mocha等
置換/監視
テスト対象
Bac...
spy/stub/mockざっくり解説
● spy
○ ある関数の入出力を監視

● stub
○ ある関数の戻り値を改ざん

● mock
○ 検証作業自体をobject化
Q:jsでどうやってTestDouble?
⇒sinon.jsがある

● spy/stub/mockに加え、fakeTimerや
fakeServer等非常に便利
● ※jasmineにもあるが、前述の通り、機能詰め
過ぎと関数名長過ぎでオス...
Q:いつTestDouble?
⇒主に、以下
●
●
●
●

イベントトリガー
サーバー通信
アニメ
localなinstance
イベントトリガー例
Event掴む為にTestDouble
● spyを作ってイベントにbindしておく
● spyが呼ばれたか確認

※view.model等も一緒
※ちなみに、bindは_event確認すると良い
サーバー通信
● TestDouble無しでそのまま書くと
○
○
○
○

テスト検証非同期callback深くなる
Serverside経由する分、testの時間もかかる
POST/PUTの検証にtest用GET自作する必要あり
問題有った...
Q:サーバー通信どこでTestDouble?
どこにTestDouble張るかは色々やり方がある
● 1.元の口にTestDouble
○ $.ajaxやsyncメソッド等

● 2.xhr自体をTestDouble
○ sinon.creat...
個別メソッドにTestDouble例
● 普通にspyしてlogicの検証してもいいし
● fetch等はstubで仮のデータを返すのも有り
○ yieldsTo使うと、success/error等も叩ける
アニメ
普通に書くとテストで数秒待ちする必要
⇒sinon.fakeTimer使うと、すぐ終わる
localなinstanceのcheck
ある関数の中でModelのinstance作って、save等
する時、普通にやると掴めない
⇒TestDouble(Mock)
● Model.prototypeにmockかける
● sinonのstu...
localなinstanceの例
こんな感じ
テストダブルの注意
stub/mock等使うと実際の動きと異なる
⇒stub等経由しないテストが必要
● ※必ずしも全自動化の必要は無いと思うが
Q:sinonつらい
⇒分かる。
ServerSide他言語のtest書いてて、こんなに
TestDouble頻繁に書かないし。ありえない。
● cursor戻して逐一before書くのが苦痛
○ stubは必要なのは分かる。処理異なるし。
○...
Backboneのbug
BackboneのViewの関数は
(特にMarionetteと一緒に使うと)
行も少ないsimpleな物になる。
⇒1関数LVの挙動でbug入り込む余地が少ない
それより、event駆動に起因するbugが多い
event駆動
● FrontEnd ≒ event駆動
○ 関数はeventに応じて実行(順番通りの部分もあるが)
○ 例
■ 開発:関数A ⇒ 関数B ⇒ 関数Cを意図
■ 実際:関数A ⇒ click ⇒ 関数C ⇒ click ⇒ 関数...
独立していない関数とは、例えば。
● statusに依存している/影響与える関数
○ これは、先程の話
○ 思わぬ前提条件statusの違いや思わぬstatus影響等

● 非同期処理を伴う関数
○ 処理中に別の関数あると影響与える?与えない?...
まとめ
● 設計編
○ 親子ViewはCollection/CompositeViewを使う
○ Controllerに処理寄せる(not SPAならね)

● 実装編
○ Backbone/Marionetteに素直に作る
○ status外...
Backboneの悩みを解決できた?
オレオレ実装/設計から逃れられそう?
これでBackboneに絶望する人を
少しでも救えたら幸い
(皆で渡れば怖くない。
まだ老害になりたくない。
今年もBackboneでしょ!)
Q:今日の内容もお前のオレオレだろ?

そうですね。
書いてて思った。
俺のオレオレと、
お前のオレオレと...
新しい宇宙と......
なに言ってんの?(゚д゚ )
オレオレとの付き合い方
Marionetteやstickitみたいなpluginにして
● オレオレをルールにしなければ。
● 人に同意されなければ。
という事で、Backbone周辺libraryを

皆で色々作っていこう!

おわり
SNS等
●
●
●
●

Twitter
Github
Slideshare
jsCafe(javascript勉強会)のFacebookGroup

⇒それぞれfollow/参加ご自由に!
Blogもやってる
http://lxyuma.hatenablog.com/

● 今日の内容も殆どここから
○ いつも酒飲みながらダラダラ書いてる
○ 今日言葉足りなかった所は是非読んで頂けると幸い
○ 「はてぶくれ!」
Presented By ...
Upcoming SlideShare
Loading in...5
×

実践Backbone.Marionette 現場の悩みと解決まで

13,099

Published on

2014/1/22 gooラボopen tech talkで話したBackbone.jsとMarionette.jsの話です。

Published in: Technology
0 Comments
70 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
13,099
On Slideshare
0
From Embeds
0
Number of Embeds
13
Actions
Shares
0
Downloads
50
Comments
0
Likes
70
Embeds 0
No embeds

No notes for slide

実践Backbone.Marionette 現場の悩みと解決まで

  1. 1. 実践Backbone.Marionette 現場の悩みと解決まで ryuma tsukano (@lxyuma) 塚野 龍馬
  2. 2. Presented By ...
  3. 3. 自己紹介 : 塚野 龍馬 (@lxyuma) ● ServerSide寄りWeb Developer ○ 元々SIer出身:java/rubyで法人サービス開発してた ○ 今は、弊社でCGMを開発 ○ 技術Skill ■ 言語FW:Rails + Backbone ■ storage:MySQL + MongoDB ■ 他rails周辺技術 ● 趣味 ○ 旅行/音楽/美味しい物食べる事 ○ 去年は台湾とFrance行った(今年は国内巡ろう) ○ 2013年ハマったのは、あまちゃんと叛逆
  4. 4. jsCafe jsCafeというjavascriptの勉強会をやってる 今日のMarionetteも元はこちらで発表した物 良ければ是非お気軽にご参加を(次は2/2予定)
  5. 5. 目的/目標 ● 対象 ○ ある程度、Backbone知ってる方 ● 目的 ○ 現実的にBackboneを使う上での悩み事を解決する ● 目標 ○ 現場でBackbone適用して絶望する人を減らす
  6. 6. 目次(& ダイジェスト) ● 導入編 ○ Angularとの比較、BackboneでのDataBindings等 ● 設計編 ○ Marionetteでのコンポーネント構成等 ● 実装編 ○ オレオレ実装を如何に回避するか?等 ● テスト編 ○ javascriptのtestし辛い所と救済措置 ⇒これらQA形式で書いて行く。
  7. 7. 導入編
  8. 8. javascriptのframework界隈の動き といえば、Angularの勢いが強いですね ● DailyJSの2013年12月Survveyの利用率 ○ Backbone:25%(辛うじて1位) ○ Angular:25%(僅差で2位) ● GoogleTrendsでAngularが急上昇 ○ 日本でも2013年9月に逆転してAngular>Backboneに [世界] [日本]
  9. 9. Backboneやべぇ 結構古いし そろそろ寿命? ^o^ / 老害ですか?
  10. 10. 「老害」について Engineer皆が好きな言葉だから ついでにGoogleTrendsで調べてみた 着実に上昇中! 色々検索されてる!
  11. 11. 「老害 Backbone」 良かった〜(> <;) まだ、胸を張って生きていけそうです。
  12. 12. BackboneとAngularを比較する ● VictorSavkin氏の比較記事 ○ infoQ訳 ■ 俺も前に訳してたんだけどね>< ● この記事が良いのは、 ○ Plugin付けた現実的な構成のBackboneと ○ Angularを比較してる所
  13. 13. BackboneとPlugin ● Backbone = ただの背骨 ○ 肉は自分で付けないといけない>< ○ 肉付けは大体皆一緒 = Plugin化されてる see BackPlug.io ⇒
  14. 14. BackboneとDataBindings Angularのウリの1つ = DataBindings ⇒Backboneもplugin追加すれば動く ● NYTimesのBackbone.stickit ● 使い方は超簡単!
  15. 15. Backbone.stickit Viewの中で 1. 紐づけたいセレクタとmodel属性名を定義 2. $el描写後にstickit() ① ② ⇒すげー簡単!form使うなら盲目的に使うべき ⇒他、Backbone単体の問題はPluginで補える
  16. 16. Backbone単体の問題 ● BoilerPlateばっかり ○ 多くはMarionette.jsのViewクラスで解決 ● 俺俺実装でカオス ○ これもMarionette.jsのController/Region等で解決
  17. 17. Marionette.jsとは? Marionette.jsはBackboneをwrapしたframework ⇒以前slideにまとめた 細かい説明は、そちらを見て ※次の章に行く迄に上の slideをチラ見しておくと良いかと。。 ⇒特にView周りで 頻繁に書く所をカバーしてくれる
  18. 18. Marionette.jsは必要か? ● Yes! ○ Backbone使うなら絶対オススメ ● 以前blogに書いたがBackbone書いてると同じ 様なrenderやView構成に何度も出くわす ○ それをMarionette.jsが共通化してくれる ○ 小規模でも使うと楽になる
  19. 19. Backbone単体の問題の続き ● Testし辛い ○ これはsinon.jsのテストダブルで解決 ■ sinon.jsもblog記事書いたので良ければ。 ○ ⇒これらで、ある程度は、楽になるはず ■ ただ、この辺りはやっぱりAngularが強い これらでBackboneの諸問題は回避可能 ⇒Angularの問題は?
  20. 20. Angularの問題 ● 学習コストかかる ○ GoogleTrendsでAngular高い=調べ物多い(のが要因の1つ) ○ Backboneはsource grepで解決(simple素晴らしい!) ● ベンダーロックインに近い状態になる ○ client側の動きや各componentが非常に独特 ■ これ勉強してもAngularだけでしか活かせない ■ なんか某Mの.n●tみたいだ... ● 空気のようなAngularWay ○ まだまだBestPracticeが定まってない感 ○ 今後、WebComponent化すると更にまた変わる?
  21. 21. AngularとBackboneの大人のつきあい方 ● 個人Lv : Angularは監視/学習し続けるとして ● 現場Lv : まだBackboneで良いのでは? ○ ※で、AngularはWebComponent繋がって、情報整理さ れた頃使えばいいんじゃねーの ● 大分枯れてきてる ● 情報も豊富(無料で一通り手に入る) ⇒現実解としてBackbone!
  22. 22. ここ1年位のBackbone関係の話題 思いつく限り ● 海外 ○ 2013年もカンファあった。Maionetteも出てくる ○ Airbnbがサーバサイドで動くrendr作った ○ addyさんの素晴らしい書籍も出た ● 国内 ○ 春に、多分単独で初めて?書籍も出た ○ C社さんがBackbone baseの独自FW作った 等、まだまだ現役。まだ終わってはいない。 ⇒「老害 Backbone」でつぶやかないように。
  23. 23. という事で... 今年も皆Backboneやろうぜ! ⇒今から現場でBackbone入れた話をする
  24. 24. 今日の話の前提条件 「普通の」rails3アプリに適用した話 ● SinglePageAppliでない ● ちなみに、turbolinksも使ってない ⇒前提違うと、 構成や注意点等大分違うと思うのでご注意を ※なお、rails固有の話もしません。
  25. 25. 設計編
  26. 26. どう設計? Backbone使う前提 ⇒気軽にajax/Event追加 ⇒設計の可能性が広がる。 同時に、色々悩みが出て来る
  27. 27. Q:htmlは全部Backbone.Viewにする? ⇒No SPAでも無いので、 いつも通りServerSideのViewを9割使ってる DHHが昔disったダブルMVC! ● ServerSideのViewにメリットある ○ 値の連携 ○ FWのhelper等
  28. 28. Q:では、どこにBackbone.View? A:jsが必要になる以下の時に書いてる 普通のWebアプリでよくあるパターン ● ①Eventキャッチ用View ● ②ajax通信が必要なView ○ A:単一リソース ○ B:複数リソース ■ 1:単純な親子 ■ 2:単純な親子+親戚 ⇒大体、このどれかに落ち着く ※要するに普段 js書いてるのを整理してるだけ
  29. 29. Q:①Eventキャッチ用Viewとは 殆どのjs処理がコレ。 例)#menuをclickしたらdiv.menu表示みたいな ● なぜ、これもBackboneで書くのか? ○ Backbone無いと、bindしてるDOMと処理内容がバラバ ラで読み辛い。テストもし辛い(=習慣化しない) ■ 昔blogに書いたが、jQueryダラダラ書いて長くteam 開発して量も増えるとゴミコード溜まるし、管理できな くなってくる
  30. 30. Q:Eventキャッチ用Viewはどれ使う? ⇒Marionette.Viewがオススメ 理由:uiがあるから ● ui ○ selectorを一カ所にまとめて、bindしてjQueryObjに ■ (後述するがこれがテストで重要) ○ 使う時、bindUIElements()忘れずに ■ ※ちなみに、ItemView継承してるclassは不要 ● なお、htmlについて ○ render()書かず、ServerSideのViewを元にしてる ○ もし、render()必要ならItemView使おう(自力でrender書 かない事)
  31. 31. Q:②ajax通信が必要なViewとは? MarionetteのViewを使い分ける ● A:単一リソース ○ Marionette.ItemViewを使うと良いよ ● B:複数リソース ○ 1:単純な親子 ■ Marionette.CollectionView使うと良いよ ○ 2:単純な親子+親戚 ■ Marionette.CompositeView使うと良いよ
  32. 32. Q:複数リソースのViewとは Backboneで複数data取得/表示する situationが非常に多い! 例)検索して結果一覧表示 ⇒ここで親子にView分割する ※ただのイメージ図です 子View 子View ● なぜ親子分割が必要か? ○ Blogにも書いた通り ○ 分割しないと ■ MとVの紐付けが毎回必要 ■ 冗長なクラス/htmlになる 子View 子View 親View
  33. 33. 親子ViewとMarionette.js Marionetteで親子View用のclassが準備されてる ● 親View ○ CollectionViewか ○ CompositeViewのいずれか。 ● 子View ○ ItemView
  34. 34. Q:2種類の親Viewをどう使い分ける? ※ただのイメージ図です ⇒親戚要素(仮)がいるかどうか ● 親戚要素(仮)とは ○ 親子に働きかける別の要素 ○ 俺以外誰も使わないので(仮)を付けてる CompositeView 要素のActionを起点として 親子呼び出すSituation多い ● 例)検索box/tab等 ⇒この時、CompositeView使う これで親子と親戚の連携がスッキリ! 親戚要素(仮) 子View 子View 子View 子View 親要素
  35. 35. 2種類の親Viewを整理する ● CollectionView ○ 単純に親子階層だけ必要な時に使う ● CompositeView:親にTemplate使える ○ 親子要素と、 ○ その親子要素に働きかける別の要素(親戚要素(仮))が 必要な時に使う
  36. 36. Q:component構成は? ⇒Backbone MV* in MVC model2っぽい構成 AppRouter Controller 生成 連携event 表示 監視 Region View 描写 html Model/Collection event event Template 元々のBackboneの基本的なMV*構成
  37. 37. 意図している所 Controller一カ所見ればhtml上でのレイアウト構成 と処理概要が分かるようにしたい ● ①レイアウト構成 ○ Region使ってる ● ②処理概要:Controller ○ Marionette.Controller使ってる
  38. 38. ①レイアウト構成:Region DOM要素とViewを紐付け表示管理するclass。 ● ItemView継承してる ○ show()でそのまま使う ● ItemView継承してない ○ attachView()で強制的に紐づけてる ⇒どのViewも必ずRegionと紐づける事で、 後でsrc辿る時にどこに何があるか分かり易い ● Regionからel貰うのでView内部でel持たない ○ これは、テストの為にもそうしてる(後述)
  39. 39. ②処理概要:Controller Marionette.Controller使ってる ● Controllerの関数に書く事 ○ 宣言的な所 ■ A)Regionの定義 ○ 命令的な所 ■ B)Viewの連携Event
  40. 40. A)Controller内のRegion管理 ⇒基本ApplicationのRegionに追加 (Layoutを使ってない) ● いつかFatControllerになったら、 ○ Region管理してる所(宣言的な所)をLayoutに外出しし ようと思ってる ○ が、直近困ってない
  41. 41. B)Controller内のView連携Eventとは あるViewのイベントをきっかけに、 別のViewの要素を変える時のイベント Controller View A View B ● あえて、Controller挟んでる ○ ⇒ControllerでどのViewがどう連携してるか分かる ○ View内に書くと処理全貌が掴み辛いので避けてる ● ちなみに、主にMarionetteのcmd使ってる
  42. 42. Q:なぜControllerに寄せてる? ⇒Controllerの単位で処理切替るから ● ちなみにこれがSPAなら... ○ App.jsみたいなのがglobalな連携event持って ○ Controllerはview小片call程度のThinなcontrollerにな るんだろうなぁ ● 比較的fat気味なControllerにしてるのは ○ 普通のwebアプリの延長で作った場合 ■ 連携eventはControllerの単位で変わるから ■ 連携eventがControllerまたぐ事ないから ⇒この辺りは、状況に応じてCaseByCase
  43. 43. 実装編
  44. 44. Backboneの実装といえば オレオレ実装でしょ!
  45. 45. オレオレ実装とは 特にBackbone.View周辺で見られる ● オレオレ自由系render() ! ○ view毎バラバラでカオスなrender()記述 ● オレオレ深層SubView構成! ○ 深くまで辿らないと全貌が分からない ● オレオレスパゲティdata bindings! ○ 1Viewが複数のModelに複雑にbindしてる 等々・・・
  46. 46. オレオレ実装との戦い Backboneで書いたのにsource追えない 何の為にコレ入れたんだっけ? はい、しゅーりょー ^o^/ これは、どうにかしないと...
  47. 47. Backboneに素直に従う 与えられた物をその範囲内で素直に使う事で 絡まる事無くsimpleでtestableな状態に! ● Backbone.Viewが用意してくれる事 ● Marionetteが用意してくれる事 ● stickitが用意してくれる事
  48. 48. Backboneが用意してくれる事 ● $el ○ Viewは$el内のDOM要素だけを扱う ○ globalな$使って外の要素を勝手に変えない ■ やりたければさっきの連携eventをtrigger ● Model/Collection ○ 1Viewは1Modelか1Collectionだけと紐づく ○ オレオレModel/Collection作らない ■ 連携が必要なら、同じく連携event使う ● render() ○ 画面描写はrenderで行うのであって、initialize等別の関 数で画面描写するべきでない ■ initializeに書くと画面描写とそれ以外が混合><
  49. 49. Marionetteが用意してくれる事 ● render() ○ 自分でrender書かないで、カオスを回避 ○ Template準備して、誰かと作業し易く ● ui ○ ui経由でjQuery objとって冗長さを避ける ● Event系 ○ 与えられたEventに処理を追加していく ● 親子View ○ Collection/CompositeView + Region管理でカバー ○ 可能な限り自力でsubview書かない(Backboneに準備 されてないし)
  50. 50. 大原則 当たり前の事だけど、 これらに沿うだけで大分違う。 ※勿論、例外はあるが。 基本的に、 与えられた物を素直に使う事に徹する のがオススメ
  51. 51. Q:ぱっと見でViewの動きが掴めない ⇒関数名にevent入れる規約にする ● event関数名 = on + イベント名 + 対象 ○ 例)onClickSaveButton / onSyncModel ● これでevents一々見なくても流れが掴める ○ Backbone.View関数名で動作を説明する必要は無い ■ (特にMarionette入れた)Backboneはviewの関数の 行数が少なくsrc見れば動きがすぐ分かるし ○ そもそも他のevent駆動programも同じ発想 ■ iOS/VB等々.. ○ 勿論event関数から呼ぶ別の関数は普通に名前付け(こ れでevent駆動の関数とそれ以外で分かれる)
  52. 52. Q:view内の関数同士の関係がカオス ⇒関数同士の継ぎ目になるstatusを区別する status? ● 関数横断して相互利用する要素があった時 ○ 例えば、tab/modal/load anime等 ○ testでbuggyなのは、この辺り! ○ そのままjQuery操作すると(特にsrcが長くなった時)独立 した表示要素の操作と区別がつかなくなって、埋もれて しまう ○ これはtestする上で致命的(追加改修時も大変) ⇒statusは変数として外出して変更箇所を統一
  53. 53. Q: statusどう管理する? ⇒methodにstatus/画面操作を統一で妥協 結局、どこまでやり過ぎるかのせめぎ合い ● デザパタState pattern ○ ⇒Backbone.ViewのSubview構成に行き着く ● Backbone.Events継承 ● pluginもやっぱりある(がっつり系 / 簡易系) ⇒いずれにせよ、冗長になるが ○ Viewがstatus持ってる事を明示出来る ○ testや追加時に、status確認する起点が出来る
  54. 54. Q:変な動きするんだけど ⇒ソースgrepが早くて一番正確。 ● BackboneもMarionetteもstickitも全部 ● どれもそんなに長くなくてsimple ○ 例えば、Backbone.Viewはたった百行前後しかない ソース辿れるとどうにかなる。 simpleって素晴らしいですね! ここがBackboneの良い所!
  55. 55. Q:書いてて不安になるんだけど ⇒分かる。だから、TDD必須 ● 実装からBrowser表示まで時間かかる事ある ○ こまめにTestFirstでjs levelの動作確認が必要 ● しかし、生でtestは限界がある。 ● 結局、幾つかの慣例表現を知らないと backboneのtest書けないので次に扱う ○ ※今日はTestとTDDまとめて話すが、blogに書いた通り 厳密には違う。これも知らないと、どう書くか悩む事にな るので、良ければ読んで頂ければ。今日はこの違いの 話はしない。
  56. 56. テスト編
  57. 57. jsのTest Frameworkざっくり流れ ● 数年前 ● 2年前 ● 去年 ⇒コロコロ主流が 変わってきましたね
  58. 58. Q:Test Frameworkどれがいい? ● ちょっと前迄、mochaでいいと思ってた ○ mocha使う=chai使う=language chainが気持ち悪い ○ chai以外にどのassertionLibに落ち着けばいいか謎。 (それぞれメリデメと、流行/廃りがある) ⇒最近、個人的にjasmineでいい気がしてきた
  59. 59. jasmine ● jasmine2が出てdone(非同期test機能)付いた ● 呼出し口が固定されてる(当たり前だけど) ○ ※jasmineのspy周りは、機能詰め過ぎ/関数名長過ぎで 気持ち悪いので、sinon(後述)使ってる ● 調べるときも公式pageだけで完結 ● 2013DailyJSアンケートでも、まだ1位 ⇒simple素晴らしい jasmine + sinonでいいんじゃない?
  60. 60. BackboneとTest BackboneのTestはFrontEnd特有の問題がある ● ①jsがDOM/htmlに依存してる問題 ● ②素直に検証書けない問題 これらの解決策を知らないとかなり悩む事に!
  61. 61. ①jsがDOM/html依存してる問題 ● 頻発するデザイン変更の度にtest修正が必要 ○ test修正自体正しい事だが量が多い点が問題>< ● DOM調整作業やってるとTDDし辛い ○ DOM調整でhtml注力すると開発flowにTest入らない ● target/testの2つだけで完結しない(htmlがある) のでTDDに集中できない ○ ServerSideではtargetとtestの2つだけで恵まれてた
  62. 62. TDD進める為に ● ゴール ○ ServerSideのTDDの様にTest/Targetだけの行き来に する ● 方向性 ○ DOM/htmlの分離 ■ 勿論、完全分離は不可能だが、距離をあける ○ jsを書く事と、DOM調整作業を分ける ※ちなみに、テストから完全にDOM排除せよとい う話ではない。違う形で確認は必要。
  63. 63. BackboneでのDOM/html分離 ● DOMselector書かずMarionette. View.ui使う ○ TestCodeから要素掴むのもview.ui使う ○ targetもtestも中身が絡まるのをおさえる ○ 変更時の修正の起点を作る ● test用templateを基本的に作らない ○ 変更時の修正costを下げるため ○ htmlは本物のfileだけ。 ● Viewは$elの範囲内だけ扱う相対View作る ○ test用template書かずに済む ○ htmlに無いので表示検証が難しいが、逆にそれでDOM 分離(logic検証spyでも可。jQuery関数自体を検証して も意味ない)
  64. 64. ②素直に検証書けない問題 ● instance変数の変更等は普通に検証書けるが ● event/server通信はそのまま書けない ⇒後者の対応の為に結局TestDoubleが必要
  65. 65. テストダブルとは テスト対象が別コンポーネントに依存しており この別コンポーネントの為テストが困難な時に 別コンポーネントを置換/監視する仕組み。 spy/stub/mock等がある。 テストコード mocha等 置換/監視 テスト対象 Backbone等 別の コンポーネント
  66. 66. spy/stub/mockざっくり解説 ● spy ○ ある関数の入出力を監視 ● stub ○ ある関数の戻り値を改ざん ● mock ○ 検証作業自体をobject化
  67. 67. Q:jsでどうやってTestDouble? ⇒sinon.jsがある ● spy/stub/mockに加え、fakeTimerや fakeServer等非常に便利 ● ※jasmineにもあるが、前述の通り、機能詰め 過ぎと関数名長過ぎでオススメしない
  68. 68. Q:いつTestDouble? ⇒主に、以下 ● ● ● ● イベントトリガー サーバー通信 アニメ localなinstance
  69. 69. イベントトリガー例 Event掴む為にTestDouble ● spyを作ってイベントにbindしておく ● spyが呼ばれたか確認 ※view.model等も一緒 ※ちなみに、bindは_event確認すると良い
  70. 70. サーバー通信 ● TestDouble無しでそのまま書くと ○ ○ ○ ○ テスト検証非同期callback深くなる Serverside経由する分、testの時間もかかる POST/PUTの検証にtest用GET自作する必要あり 問題有ったときの原因の切り分け面倒 ⇒これら回避するためサーバ通信もTestDouble
  71. 71. Q:サーバー通信どこでTestDouble? どこにTestDouble張るかは色々やり方がある ● 1.元の口にTestDouble ○ $.ajaxやsyncメソッド等 ● 2.xhr自体をTestDouble ○ sinon.createFakeServer()でxhr自体wrapする ○ stubとしては最も正しい姿だが設定面倒くさい ● 3.個別のメソッドにTestDouble ○ model.save等 現実的に3が多い気がする
  72. 72. 個別メソッドにTestDouble例 ● 普通にspyしてlogicの検証してもいいし ● fetch等はstubで仮のデータを返すのも有り ○ yieldsTo使うと、success/error等も叩ける
  73. 73. アニメ 普通に書くとテストで数秒待ちする必要 ⇒sinon.fakeTimer使うと、すぐ終わる
  74. 74. localなinstanceのcheck ある関数の中でModelのinstance作って、save等 する時、普通にやると掴めない ⇒TestDouble(Mock) ● Model.prototypeにmockかける ● sinonのstub ○ sinonはstubも検証できるobjなので、stubでも書けてし まうが、Testのcontextでは無い所での検証なのでmock の方が正しい。(主体となる視点の違い)
  75. 75. localなinstanceの例 こんな感じ
  76. 76. テストダブルの注意 stub/mock等使うと実際の動きと異なる ⇒stub等経由しないテストが必要 ● ※必ずしも全自動化の必要は無いと思うが
  77. 77. Q:sinonつらい ⇒分かる。 ServerSide他言語のtest書いてて、こんなに TestDouble頻繁に書かないし。ありえない。 ● cursor戻して逐一before書くのが苦痛 ○ stubは必要なのは分かる。処理異なるし。 ○ 問題はspy周り。普通にそのままevent等確認したい ⇒Viewの全部にまとめてspyできねーか?と今 plugin作ってみてる。良ければ。
  78. 78. Backboneのbug BackboneのViewの関数は (特にMarionetteと一緒に使うと) 行も少ないsimpleな物になる。 ⇒1関数LVの挙動でbug入り込む余地が少ない それより、event駆動に起因するbugが多い
  79. 79. event駆動 ● FrontEnd ≒ event駆動 ○ 関数はeventに応じて実行(順番通りの部分もあるが) ○ 例 ■ 開発:関数A ⇒ 関数B ⇒ 関数Cを意図 ■ 実際:関数A ⇒ click ⇒ 関数C ⇒ click ⇒ 関数B ⇒意図しない関数の組み合わせがあり得る ● 独立している関数は意識しなくていいが ● 独立していない関数は注意が必要
  80. 80. 独立していない関数とは、例えば。 ● statusに依存している/影響与える関数 ○ これは、先程の話 ○ 思わぬ前提条件statusの違いや思わぬstatus影響等 ● 非同期処理を伴う関数 ○ 処理中に別の関数あると影響与える?与えない?等 ○ これも結局、上と同じstatusの話に行き着く ⇒これらの関数を中心に、 別の関数との相互作用を重点的にTestする
  81. 81. まとめ ● 設計編 ○ 親子ViewはCollection/CompositeViewを使う ○ Controllerに処理寄せる(not SPAならね) ● 実装編 ○ Backbone/Marionetteに素直に作る ○ status外出し ● テスト編 ○ jsのテストとDOMを分ける ○ テストダブルを使う ○ 独立してない関数に注意
  82. 82. Backboneの悩みを解決できた? オレオレ実装/設計から逃れられそう?
  83. 83. これでBackboneに絶望する人を 少しでも救えたら幸い (皆で渡れば怖くない。 まだ老害になりたくない。 今年もBackboneでしょ!)
  84. 84. Q:今日の内容もお前のオレオレだろ? そうですね。 書いてて思った。
  85. 85. 俺のオレオレと、 お前のオレオレと... 新しい宇宙と......
  86. 86. なに言ってんの?(゚д゚ )
  87. 87. オレオレとの付き合い方 Marionetteやstickitみたいなpluginにして ● オレオレをルールにしなければ。 ● 人に同意されなければ。 という事で、Backbone周辺libraryを 皆で色々作っていこう! おわり
  88. 88. SNS等 ● ● ● ● Twitter Github Slideshare jsCafe(javascript勉強会)のFacebookGroup ⇒それぞれfollow/参加ご自由に!
  89. 89. Blogもやってる http://lxyuma.hatenablog.com/ ● 今日の内容も殆どここから ○ いつも酒飲みながらダラダラ書いてる ○ 今日言葉足りなかった所は是非読んで頂けると幸い ○ 「はてぶくれ!」
  90. 90. Presented By ...
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×