Top Banner
jQuery to Backbone アーキテクチャを意識したJavaScript入門 Frontrend Vol.4 さとう歩 / @ahomu CyberAgent, Inc.
132

jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Nov 07, 2018

Download

Documents

hoangtruc
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

jQuery toBackbone

アーキテクチャを意識したJavaScript入門

Frontrend Vol.4さとう歩 / @ahomuCyberAgent, Inc.

Page 2: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

さとう歩@ahomu

Page 3: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

2012年8月以前

名古屋でWebプログラマ(PHP・JSなど)

2012年9月〜

CAでフロントエンド専業にシフトnew!

Page 4: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

2012年後半

Gruntと自動化について

2013年1月

Stylus・CSSプリプロセッサ

2013年2月

jQuery to Backbonenew!

Page 5: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

詳しくはhttp://aho.mu

Page 6: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

1. はじめに

2. jQueryについて

3. Backboneについて

4. jQuery to Backbone

5. まとめ

流れ

Page 7: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

はじめに

Page 8: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

jQueryは無くなりません関心のフォーカスを移す機会

易しめに聞ける内容(のつもり)

Page 9: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js
Page 10: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

BACKBONE.JShttp://backbonejs.org/

Page 11: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Initial Release 2010/10/13

Gzipped Size6.3KB

Latest Version0.9.10

Page 12: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

構造化の手段を提供するモダンライブラリView, Model, Collection等を備える

Page 13: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

1500行程度の軽量さといじりやすい柔軟さ国内外を問わず利用が広がっている

Page 14: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

依存するライブラリ

✓ jQuery✓ Zepto.js (lightweight clone)

✓ Underscore.js✓ Lodash (more faster)

UtilityBelt

Library

SelectorBasedLibrary

_.$.

Page 15: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

jQueryの特徴と役割を振り返る

jQueryについて

Page 16: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

jQueryhttp://jquery.com/

Page 17: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

特徴と役割、3つのポイント

Page 18: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

①DOM APIを隠蔽して簡潔に記述するwrite less, do more.

Page 19: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

DOM API は煩雑すぎた

elemNode.parentNode.removeChild(elemNode);!

$(elemNode).remove();

Page 20: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

②クロスブラウザ対応の諸問題を解決するIE, Firefox, Safari, Opera, Chrome...

Page 21: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

かつての立役者の功罪ほか細々

Msxml.XMLHTTP? attachEvent?!

$.ajax, $.bind/$.on

Page 22: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

③プラグインの充実とエコシステム形成Useful and Awesome Plugins!

Page 23: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

プラグインがあれば何でもできる

User / Community / Ecosystem!

$.fn.awesomePlguin(‘feel good!’);

Page 24: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

jQueryが生まれた頃の問題を解決してくれた意識することは少なくなってきている

Page 26: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

フロントエンド実装の現状と変化今、求められるスキルと取り巻く状況

Page 27: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Webサイト

従来のWebサービスWebアプリ

新しめなWebサービスWebアプリ

ややリッチなインターフェース

静的HTMLCMS利用

シングルページリッチ&シームレスなUI

RESTful API

Page 28: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Webサイト

従来のWebサービスWebアプリ

新しめなWebサービスWebアプリ

サーバーサイドで画面遷移を設計

静的HTMLCMS利用

シングルページリッチインターフェース

RESTful API

次第に高まってきたフロントエンド実装の比重

Page 29: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

フロントエンドに生まれる新たな問題

Another new problems...

Page 30: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

jQueryが解決しない問題アプリケーションコードの肥大化スパゲティコードの技術的負債テスタビリティーの確保メンテナンスのたびに深まる業

Page 31: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

新しい問題のために向けるべき関心?

Page 32: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Most Developers realize that structured, maintainable code is important.

via. Digesting JavaScript MVChttps://speakerdeck.com/addyosmani/digesting-javascript-mvc?slide=10

ディベロッパーにとって、構造的でメンテナンスしやすいコードが何たるかを知ることが重要。

Page 33: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

MV*なJavaScriptとアーキテクチャ云々Backbone.jsについて

Page 34: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

アーキテクチャと言えば猫も杓子もMVCみんな1度は聞いたことあるはず

Page 35: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

MVCsince 1979

From: Trygve Reenskaug

Page 36: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

古典 of SmalltalkSmalltalk(スモールトーク)は、Simulaのオブジェクト(およびクラス)

Lispの機能、LOGOのエッセンスを組み合わせて作られたクラスベースの純粋オブジェクト指向プログラミング言語、および、それによって記述構築された

統合化プログラミング環境の呼称。

via. Smalltalk - Wikipediahttp://ja.wikipedia.org/wiki/Smalltalk

Page 37: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

⚠JavaScriptにおける

MVCまたはMV*の現状普及してるとは言いがたいが...

Page 39: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Backbone.js AngularJS Ember.js KnockoutJS

Dojo YUI Agility.js Knockback.js CanJS Maria cujo.js dermis

Montage Ext.js Sammy.js Stapes Epitome soma.js

DUEL PureMVC Olives PlastronJS Dijon rAppid.js

Funnyface.js Spine Batman.js GWT Closure

MVC Extension Frameworks MarionetteJS

Thorax Chaplin

巷に溢れかえるMV*フレームワークTodoMVCだけで30以上が列挙される

Page 40: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

MV*なアーキテクチャは身近になってきているMV*に限らず、色々考え出されている

Page 41: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Knockouthttp://knockoutjs.com/

Page 42: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

batman.jshttp://batmanjs.org/

Page 43: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Ember.jshttp://emberjs.com/

Page 44: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

AngularJShttp://angularjs.org/

Page 47: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

MV*に関した議論は定期的に盛り上がるそして常に変化しつづけている

Page 48: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

サバクラ両方で動くJavaScript の大規模

開発を行うためにhttps://gist.github.com/tily/

1362110

Page 49: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

flatironhttp://flatironjs.org/

Page 50: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

おまえのMVCは間違っている!

おれは新しいパターンを作る!

Page 51: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

このテの議論に今回はあまり触れませんBackbone的にも厳密すぎなくてOK

Page 52: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

は、

Page 53: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

厳格さと多機能で生産性を担保する強いフレームワーク

やさしい構造化をサポートする薄いライブラリ

×◎

です。

Page 54: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

1500行あまりの軽いコード

View Model Collection Router

Controllerの不在

Not MVCフレームワーク

Page 55: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

“it serves as a foundation for your application, you're meant to extend and enhance it in the

ways you see fit

方法は1つではないし、柔軟に拡張できる

via. Backbone.js FAQhttp://backbonejs.org/#FAQ-why-backbone

Page 56: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

MVCを気にしすぎることはない

と、思います。

Page 57: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

デザインパターンは知っておいて損はないアーキテクチャと併せて意識したい

Page 58: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Abstract Factory Builder Factory Method

Prototype Singleton Adapter Bridge

Composite Decorator Facade Flyweight Proxy Chain of Responsibility Command Interpreter

Iterator Mediator Memento Observer

State Strategy Template Method Visitor

GoFに代表される様々なデザインパターン一般に共有できるボキャブラリ

Page 59: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

⚠しかし現実は

独自パターンが跋扈するEveryone have own pattern

Page 60: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

デザインパターンから一般的なパターンを学ぶ

JSの例で、有名どころを少し紹介

Page 62: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Facade一番簡単な構造のパターン

Page 63: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

{}Facade - 複数の処理をまとめる

// クリックしたときに複数の操作を同時に行う// 最も広義には誰もがあたりまえに行うパターンonLikeClick: function() { this.likeModel.save(); this.changeState(‘liked’); this.$el.addClass(‘animate’);

// ... // .. // .}

Page 64: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Singleton/Flyweight生成および構造のパターン

Page 65: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

{}Singleton - ただひとつのオブジェクト

// 簡易には、不変的オブジェクトになるために// コンストラクタなしでオブジェクトリテラルで表現var singletonClass = { init: function() { // initialize logic }, method: function() { // some logic }}singletonClass.init();

Page 66: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

{}Flyweight - インスタンス生成

// 動的にインスタンスを作りたい場合など// 同じ役割のインスタンスは複数生成させずに使い回すvar factory1 = Flyweight.getFactory('model');var factory2 = Flyweight.getFactory('view');var factory3 = Flyweight.getFactory('model');

// 期待する動作として、modelとして呼んだら同一であることconsole.log(factory1 === factory2); //=> falseconsole.log(factory1 === factory3); //=> true

Page 67: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Observer/Mediator振る舞いのパターン

Page 68: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

{}Observer - イベントを監視

// 監視される側のModelと、監視する側のViewvar model = new FooModel();var view = new BarView();

// Modelに直接、Viewのメソッドをリスナーで登録model.on('change', view.render);

// fetch()によって、changeイベントがトリガーmodel.fetch(); // view.render()が実行される

Page 69: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

{}Mediator - イベントを仲介

// Mediatorを作成(Backboneの例)var mediator = _.clone(Backbone.Events);

// Mediatorにリスナーを登録mediator.on('model:change', view.render);

// Mediatorを通してイベントをトリガーmediator.trigger('model:change', this);

Page 70: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

急に当てはめるのは難しいことがほとんど何らかの取っかかりが必要、そこで...

Page 71: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

やさしい構造化をサポートするBackboneでパターンやアーキテクチャの実践を始めてみると吉

Page 72: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

jQuery to Backboneコードを構造化する学ぶためのリファクタリング

Page 73: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Backbone.jsにおけるコンポーネント

View, Model, Collection, Router

Page 74: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Backbone.View

View見た目とUIにおける入出力

DOM要素の管理ユーザー操作(イベント)制御

Page 75: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

{}典型的なView

var ViewClass = Backbone.View.extend({ el: ‘#main’, initialize: function() { // process... }, render: function() { this.$el.html(‘rendering html strings’); }});var view = new ViewClass(); // `initalize`view.render(); // `render`

Page 76: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

📦Backbone.Model

Model取り扱うデータの一単位

ストレージとの通信・同期APIや情報のレコードを表現

Page 77: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

{}典型的なModel

var ModelClass = Backbone.Model.extend({ defaults: {}, url: ‘api/v1/path/to’, initialize: function() { // process... }});var model = new ModelClass(); // `initalize`var view = new ViewClass({model: model});model.fetch({ success: view.render});

Page 78: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Backbone.Collection

CollectionModelが集合したリスト

リスト操作...where, filterなどModelと同様の通信・同期

Page 79: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

{}典型的なCollection

var Persons = Backbone.Collection.extend({ url: ‘api/v1/path/to’, model: Person});var persons = new Persons();persons.fetch({ success: function() { this.where({ name: ‘anonymous’ })[0].sayName(); // ‘anonymous!’ }});

Page 80: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Router

Backbone.Router

URLによるルーティングhashchange, pushstate

遷移処理のnavigate

Page 81: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

{}典型的なRouter

var Router = Backbone.Router.extend({ routes: { 'store/:storeId': 'gotoStore' }, gotoStore: function(storeId) { new StoreView({ model: new Store(storeId); }); }});var app = new Router();Backbone.history.start();

Page 82: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

BackboneRouter

📦 📦 📦

Views

Models

Collection

via. Backbonification - Migrating NewsBlur From DOM Spaghetti to Backbone.jshttps://speakerdeck.com/samuelclay/backbonification-migrating-newsblur-from-dom-spaghetti-to-backbone-dot-js?slide=12

Page 83: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Backbone.jsを実際に使ってみるViewの分離とメソッドの抽出

Page 84: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

GitHub APIを使ったGistビューワー実用性はさておき、あくまでサンプル

Page 85: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

DEMO

1.Backbone.Viewを作成

2.renderメソッドを抽出

3.テンプレートの分離

4.イベントの定義

Page 86: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

{}ピュアなjQueryコードからスタートvar $list = $('#js-gists');$.ajax({ method: 'GET', url: 'https://api.github.com/gists', data: oauthData, dataType: 'json'}).done(function(data) { var i = 0, html = '', item; while (item = data[i++]) { html += '<li>'+ '<a data-src="'+item.url+'" href="#">'+item.description+'</a>'+ '<a href="'+item.html_url+'">Show in gists</a>'+ '</li>'; } $list.html(html);});$list.on('click', '[data-src]', previewGist);

Page 87: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

{}おもむろにViewを作成var GistsListView = Backbone.View.extend({ el: '#js-gists', initialize: function() { var $list = this.$el; $.ajax({ method: 'GET', url: 'https://api.github.com/gists', data: oauthData, dataType: 'json' }).done(function(data) { var i = 0, html = '', item; while (item = data[i++]) { html += '<li>'+ '<a data-src="'+item.url+'" href="#">'+item.description+'</a>'+ '<a href="'+item.html_url+'">Show in gists</a>'+ '</li>'; } $list.html(html); }); $list.on('click', '[data-src]', previewGist); }});var gistsList = new GistsListView();

Page 88: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

{}renderメソッドを抽出var GistsListView = Backbone.View.extend({ el: '#js-gists', initialize: function() { _.bindAll(this); $.ajax({ method: 'GET', url: 'https://api.github.com/gists', data: oauthData, dataType: 'json' }).done(this.render); this.$el.on('click', '[data-src]', previewGist); }, render: function(data) { var i = 0, html = '', item; while (item = data[i++]) { html += '<li>'+ '<a data-src="'+item.url+'" href="#">'+item.description+'</a>'+ '<a href="'+item.html_url+'">Show in gists</a>'+ '</li>'; } this.$el.html(html); return this; }}); var gistsList = new GistsListView();

Page 89: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

{}テンプレートの分離var GistsListView = Backbone.View.extend({ el: '#js-gists', tmpl: _.template($('#tmpl-js-gists').html()), initialize: function() { _.bindAll(this); $.ajax({ method: 'GET', url: 'https://api.github.com/gists', data: oauthData, dataType: 'json' }).done(this.render); this.$el.on('click', '[data-src]', previewGist); }, render: function(data) { this.$el.html(this.tmpl({items: data})); return this; }});var gistsList = new GistsListView();

Page 90: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

{}Underscoreテンプレート<script id="tmpl-js-gists" type="tmpl/text"><% _.each(items, function(item) { %><li> <a data-id="<%= item.id %>" data-src="<%= item.url %>"> <%= item.description %> </a> <a href="<%= item.html_url %>">Show in gists</a></li><% }); %></script>

Page 91: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

{}イベントの定義var GistsListView = Backbone.View.extend({ el: '#js-gists', tmpl: _.template($('#tmpl-js-gists').html()), events: { 'click [data-src]': previewGist }, initialize: function() { _.bindAll(this); $.ajax({ method: 'GET', url: 'https://api.github.com/gists', data: oauthData, dataType: 'json' }).done(this.render); }, render: function(data) { this.$el.html(this.tmpl({items: data})); return this; }});var gistsList = new GistsListView();

Page 92: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

コンポーネントで分割すれば構造化される自然とTestableなコードにもなる

Page 93: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

モジュラーなJavaScript

依存性の低さによる変更のしやすさ個々が独立していることによる交換のしやすさ

継続的なメンテナンスのしやすさリファクタリングとテスト

■ ➡

Page 94: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

大きな現実小さな実装細かい実装を構造化して現実の要件へ

Page 95: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

ModelとCollectionの利用GitHub APIの関連処理を抽出

📦

Page 96: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

📄 📄📄📄Model Collection

Gist Gists

Page 97: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

DEMO

ModelとCollection

Page 98: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

{}Collectionを作成var Gists = Backbone.Collection.extend({ url: 'https://api.github.com/gists?' + $.param(oauthData)});var GistsListView = Backbone.View.extend({ el: '#js-gists', tmpl: _.template($('#tmpl-js-gists').html()), events: { 'click [data-src]': 'preview' }, initialize: function() { _.bindAll(this); this.collection.fetch({ success: this.render }); }, render: function() { this.$el.html(this.tmpl({items: this.collection.toJSON()})); return this; }});var gistsList = new GistsListView({ collection: new Gists() });

Page 99: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

{}Modelを作成// Model & Collectionvar Gist = Backbone.Model.extend({ url: function() { return this.get('url'); }});var Gists = Backbone.Collection.extend({ url: 'https://api.github.com/gists?' + $.param(oauthData), model: Gist});

// GistListView#previewpreview: function(event) { gistPreview.model = this.collection.where({ id: $(event.currentTarget).attr('data-id') })[0]; gistPreview.show(); return false;},

Page 100: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

{}Collectionのソートvar Gists = Backbone.Collection.extend({ url: 'https://api.github.com/gists?' + $.param(oauthData), model: Gist, order_by: 'updated_at', comparator: function(gist) { switch(this.order_by) { case 'updated_at': return - new Date(gist.get('updated_at')).getTime(); } }});// GistListViewevents: { 'click #js-sort-updated': 'sortByUpdatedAt',},initialize: function() { _.bindAll(this); this.collection.fetch({success: this.render}); this.collection.on('sort', this.render);},sortByUpdatedAt: function() { this.collection.order_by = 'updated_at'; this.collection.sort();},

Page 101: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

ライブラリの利用強度とパフォーマンス

ぶっちゃけパフォーマンスに影響は?

Page 102: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

jQueryにも言えるが使い方によっては簡単に重くなる

// ループ内でappendすんな、毎回セレクタ走らせんな!!$.each(persons, function(person) { $(‘ul’).append(‘<li>’+person.name+’</li>’);});

Page 103: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

パフォーマンスを考えて慎重に使うことが重要

ライブラリの努力を無駄にしないため

Page 104: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

まとめ

より良い学びのために、その他

Page 105: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

アーキテクチャを考えるためのBackbone学習手段としてのライブラリ

Page 106: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Backbone has made me a better programmer

via. Backbone has made me a better programmer | Float Lefthttp://floatleft.com/notebook/backbone-has-made-me-a-better-programmer

Page 107: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

フルスタックでないので学習コストは低いもちろんデフォルトの機能は限られる

Page 108: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

良い習慣のためにとりあえず分けてみる「ものはためし」が一番大事

Page 109: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

ライブラリの利用が学習につながるフレームワークで言語に入る例もある

Page 110: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

RequireJShttp://requirejs.org/

Page 111: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Dependencies? AMD?勉強会資料シェア Getting Started with RequireJS

http://havelog.ayumusato.com/develop/javascript/e525-into_requirejs.html

Page 112: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

to から with へBackbone with jQueryあらためて次の関心へ

Page 113: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

アーキテクチャやデザインパターンは手を動かしてみるのが一番自分で良い方法を選んで書けるようになるのがこれから大事になる(と思う)

Page 114: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

参考リソース

手を動かすときのお供に📖

Page 119: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

最後に派生ライブラリThere's More Than One Way To Do It

用途に合わせて拡張された具体例

Page 120: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Marionettehttp://marionettejs.com/

Page 121: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Chaplinhttp://chaplinjs.org/

Page 122: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Thoraxhttp://thoraxjs.org/

Page 124: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

ぼくのかんがえたさいきょうの...

凝ったロジックと新たな複雑性の罠

Page 125: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

悪いこと?

だれもが考える

Page 126: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

学習目的であればとても良い手段他と比較しながら、作って理解する

Page 127: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Deciding good approach by yourself

Become FrontendROCKSTAR

Page 128: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

JavaScript Development Tools

jQuery Performance Tips

Testable Javascript

JavaScript Architecture

Page 129: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

キャッチアップはつづく!Architecture / ModularDependency / AMDPromises / FlowControlBuild / Package ManagementTesting / Refactoring etc...💡

Page 130: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js
Page 131: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

Thank you! おしまい

http://aho.mu @ahomu github.com/ahomu

Page 132: jQuery to Backbone - s.aho.mu · Knockback.js CanJS Maria cujo.js dermis Montage Ext.js Sammy.js Stapes Epitome soma.js DUEL PureMVC Olives PlastronJS Dijon rAppid.js Funnyface.js

1. Two equestrian riders, girls on horseback, in low tide reflections on serene Morro Strand State Beach http://www.flickr.com/photos/mikebaird/2985066755

2. Energy Drinks - Monster, Red Bull and Rockstar http://www.flickr.com/photos/aukirk/8170825503

3. - Good Friends http://www.flickr.com/photos/ngmmemuda/4166182931

4. Rhino relaxation http://www.flickr.com/photos/macinate/2810203599

5. Whale backbone http://www.flickr.com/photos/vagawi/2257918524/

6. Sleeping 猫 http://www.flickr.com/photos/hansel5569/7687221498/

7. Alien vs Predator http://www.flickr.com/photos/steampirate/1056958115/

Photo Credits...thx♡