56
bitter sweet javascript daichi hiroki 13123日火曜日

Bitter Sweet Javascript

Embed Size (px)

Citation preview

Page 1: Bitter Sweet Javascript

bitter sweet javascript

daichi hiroki

13年12月3日火曜日

Page 2: Bitter Sweet Javascript

about me.

たんぽぽT / JavaScript委員会

08年度入社

@hiroki_daichi

13年12月3日火曜日

Page 3: Bitter Sweet Javascript

what i am not talking about:

mobile webkit特有の話はしません。

html5の話もしません。

jQuery/prototypeの話もしません。

ソーシャルな話もしません。

coffee scriptの話もしません。

13年12月3日火曜日

Page 4: Bitter Sweet Javascript

talking about shibui.js

javascriptのnamespaceの話

javascriptのweb appを作る為のコアの話

オシャレじゃないjavascriptの世界

渋いハードボイルドを目指す。

13年12月3日火曜日

Page 5: Bitter Sweet Javascript

namespace.js名前空間ライブラリ

commonJSとかに準拠しない!

いまどき遅延評価、平行ダウンロード

アプリケーションコードが汚染0。エコ。

13年12月3日火曜日

Page 6: Bitter Sweet Javascript

brook.js

非同期パーツ群(promise)を組み合わせる

monad ! モナド! monad!

MVC / Resource Driven Widget / Channel

13年12月3日火曜日

Page 7: Bitter Sweet Javascript

the namespace名前が衝突すると大惨事になる

変数のスコープを切りたい

依存関係を適切に処理したい

分かってる場所ではexportしたい

読み込み順序に依存したくない

13年12月3日火曜日

Page 8: Bitter Sweet Javascript

よくある実装• objectとして定義してその中に代入していく。

• scopeは別途無名関数で定義

13年12月3日火曜日

Page 9: Bitter Sweet Javascript

だめなとこ• 必要なものがすべて事前に定義されている必要がある。

• FQNでアクセスする必要があるのでめんどくさい

• すべての名前空間が評価されてしまう。

• 結局グローバルを汚す

13年12月3日火曜日

Page 10: Bitter Sweet Javascript

namespace.js

13年12月3日火曜日

Page 11: Bitter Sweet Javascript

定義を遅延できる

13年12月3日火曜日

Page 12: Bitter Sweet Javascript

依存関係を動的に解決namespace A

namespace B

namespace C

namespace N2

namespace N3

namespace N4

namespace D

namespace N5

namespace N1

namespace N6

13年12月3日火曜日

Page 13: Bitter Sweet Javascript

依存関係を動的に解決namespace A

namespace B

namespace C

namespace N2

namespace N3

namespace N4

namespace D

namespace N5

namespace N1

namespace N6

13年12月3日火曜日

Page 14: Bitter Sweet Javascript

依存関係を動的に解決namespace A

namespace B

namespace C

namespace N2

namespace N3

namespace N4

namespace D

namespace N5

namespace N1

namespace N6

13年12月3日火曜日

Page 15: Bitter Sweet Javascript

依存関係を動的に解決namespace A

namespace B

namespace C

namespace N2

namespace N3

namespace N4

namespace D

namespace N5

namespace N1

namespace N6

13年12月3日火曜日

Page 16: Bitter Sweet Javascript

依存関係を動的に解決namespace A

namespace B

namespace C

namespace N2

namespace N3

namespace N4

namespace D

namespace N5

namespace N1

namespace N6

13年12月3日火曜日

Page 17: Bitter Sweet Javascript

依存関係を動的に解決namespace A

namespace B

namespace C

namespace N2

namespace N3

namespace N4

namespace D

namespace N5

namespace N1

namespace N6

# MakefileN2 : N1N5 : N4N6 : N1A : N2B : N3 N4C : N5D : N6

13年12月3日火曜日

Page 18: Bitter Sweet Javascript

依存関係を動的に解決namespace A

namespace B

namespace C

namespace N2

namespace N3

namespace N4

namespace D

namespace N5

namespace N1

namespace N6

# MakefileN2 : N1N5 : N4N6 : N1A : N2B : N3 N4C : N5D : N6

13年12月3日火曜日

Page 19: Bitter Sweet Javascript

結合/読込順序に非依存• 必要になるときに初めて評価されるので

結合/読込順序に依存しない

namespace A

namespace N2

namespace N1 namespace A

namespace N2

namespace N1

よくある実装 xo

namespace A

namespace N2

namespace N1 namespace A

namespace N2

namespace N1

Namespace.js o o

13年12月3日火曜日

Page 20: Bitter Sweet Javascript

必要なときにロードする

依存関係木の中で平行に処理できるものは並列化できる。

XHRやscriptタグのロードで、モジュールを定義すると必要なタイミングでは並列化してロードできる

13年12月3日火曜日

Page 21: Bitter Sweet Javascript

省エネもできる• 必要とされるまで定義の中身は実行されない

• 実行どころか必要時までコンパイルもしないこともできる

Namespace('jp.co.mixi').use('hoge').use('fuga').define (ns)-> ns.provide eval """/**your great code **/"""

13年12月3日火曜日

Page 22: Bitter Sweet Javascript

便利。

13年12月3日火曜日

Page 23: Bitter Sweet Javascript

さらに便利にする,

フレームワーク”brook”

13年12月3日火曜日

Page 24: Bitter Sweet Javascript

brook.widget• マークアップにnamespaceを対応

• マークアップに現れない処理は駆動しない

<div class=”widget” data-widget-namespace=”app.user.profile” data-user-id=”user:232323” data-user-nickname=”daichi.hiroki” data-user-thumbnail=”daichi.hiroki.jpg”/>.....

13年12月3日火曜日

Page 25: Bitter Sweet Javascript

brook.widget• マークアップにnamespaceを対応

• マークアップに現れない処理は駆動しない

<div class=”widget” data-widget-namespace=”app.user.profile” data-user-id=”user:232323” data-user-nickname=”daichi.hiroki” data-user-thumbnail=”daichi.hiroki.jpg”/>.....

13年12月3日火曜日

Page 26: Bitter Sweet Javascript

brook.widgetMarkup Resource

widget A- meta data- meta data

widget A- meta data- meta data

widget B- meta data- meta data

widget C- meta data- meta data

namespace A

namespace B

namespace C

namespace N2

namespace N3

namespace N4

namespace D

namespace N5

namespace N1

namespace N6

13年12月3日火曜日

Page 27: Bitter Sweet Javascript

brook.widgetMarkup Resource

widget A- meta data- meta data

widget A- meta data- meta data

widget B- meta data- meta data

widget C- meta data- meta data

namespace A

namespace B

namespace C

namespace N2

namespace N3

namespace N4

namespace D

namespace N5

namespace N1

namespace N6

13年12月3日火曜日

Page 28: Bitter Sweet Javascript

brook mvc

• brookは簡易なMVCサポート機能を持っています。

• 簡単なUI追加機能はbrook.widget単体で表現できます。(e.g. jquery mobile)

• よりhard coreなアプリケーションでは、brook.widget = controllerとしてMVCを展開

13年12月3日火曜日

Page 29: Bitter Sweet Javascript

MVC is ..Model

View

Controller

13年12月3日火曜日

Page 30: Bitter Sweet Javascript

MVC is ..Model

View

Controller

ユーザからアクションを受ける

13年12月3日火曜日

Page 31: Bitter Sweet Javascript

MVC is ..Model

View

Controller

ユーザからアクションを受ける

Controllerにイベントを伝える

13年12月3日火曜日

Page 32: Bitter Sweet Javascript

MVC is ..Model

View

Controller

ユーザからアクションを受ける

Controllerにイベントを伝える

Modelに修正を伝える

13年12月3日火曜日

Page 33: Bitter Sweet Javascript

MVC is ..Model

View

Controller

ユーザからアクションを受ける

Controllerにイベントを伝える

Modelに修正を伝える

Viewに修正完了を伝える

13年12月3日火曜日

Page 34: Bitter Sweet Javascript

MVC is ..Model

View

Controller

ユーザからアクションを受ける

Controllerにイベントを伝える

Modelに修正を伝える

Viewに修正完了を伝える

13年12月3日火曜日

Page 35: Bitter Sweet Javascript

async callback• MVCはイベントや通知の方向を定めたパターン。

• JS上にあらわれる処理には非同期なコールバックが多い。

• Node.jsもGUIも基本的にEvent Drivenの世界

13年12月3日火曜日

Page 36: Bitter Sweet Javascript

callbackで継続 function (callback) { get(anchor.href, callback); }, function (callback, html) { var m = html.match(PATTERN); if (m) { callback(m[0]); } }, function (callback, uri) { get(uri, callback); }, function (callback, js) { var images = eval(js); images.forEach(function (image) { li.appendChild(createImage(image)); }); }

13年12月3日火曜日

Page 37: Bitter Sweet Javascript

callbackで継続 function (callback) { get(anchor.href, callback); }, function (callback, html) { var m = html.match(PATTERN); if (m) { callback(m[0]); } }, function (callback, uri) { get(uri, callback); }, function (callback, js) { var images = eval(js); images.forEach(function (image) { li.appendChild(createImage(image)); }); }

13年12月3日火曜日

Page 38: Bitter Sweet Javascript

callbackで継続 function (callback) { get(anchor.href, callback); }, function (callback, html) { var m = html.match(PATTERN); if (m) { callback(m[0]); } }, function (callback, uri) { get(uri, callback); }, function (callback, js) { var images = eval(js); images.forEach(function (image) { li.appendChild(createImage(image)); }); }

13年12月3日火曜日

Page 39: Bitter Sweet Javascript

callbackで継続 function (callback) { get(anchor.href, callback); }, function (callback, html) { var m = html.match(PATTERN); if (m) { callback(m[0]); } }, function (callback, uri) { get(uri, callback); }, function (callback, js) { var images = eval(js); images.forEach(function (image) { li.appendChild(createImage(image)); }); }

13年12月3日火曜日

Page 40: Bitter Sweet Javascript

brook.promise• 未来の処理を渡されるcallbackを抽象化

• どこで切ってもモジュール化できる

13年12月3日火曜日

Page 41: Bitter Sweet Javascript

brook.promise• 未来の処理を渡されるcallbackを抽象化

• どこで切ってもモジュール化できるfunction(next,value){ next(value);}

13年12月3日火曜日

Page 42: Bitter Sweet Javascript

brook.promise• 未来の処理を渡されるcallbackを抽象化

• どこで切ってもモジュール化できるfunction(next,value){ next(value);}

var $promise = ns.promise(function(next,value){! next(value);});var $wait = ns.promise(function(next,value){! setTimeout(next.bind(value),100);});var get = function(path){! return ns.promise(function(next,value){! ! get(path,next.bind( value ) );! });};var $waitGet = $wait.bind( get( “hoge.xml”))

13年12月3日火曜日

Page 43: Bitter Sweet Javascript

brook.promise is monad

• コールバックを連結可能なリストとしてモジュールかできる。

• JSDeferredとかもこの性質を満たす。

13年12月3日火曜日

Page 44: Bitter Sweet Javascript

MVC is ..Model

View

Controller

単純なデータフローとして考えるとこのようにモデル化できる。

13年12月3日火曜日

Page 45: Bitter Sweet Javascript

MVC is ..Model

View

Controller

// mvc as a stream of callbacksuserAction .bind( viewToController ) .bind( controller ) .bind( model ) .bind( viewFromModel )

userAction.subscribe();

単純なデータフローとして考えるとこのようにモデル化できる。

13年12月3日火曜日

Page 46: Bitter Sweet Javascript

brook.channel• promiseの流れをforkする

Promise Promise Promise

Promise PromisePromise

Promise

Channel

13年12月3日火曜日

Page 47: Bitter Sweet Javascript

brook.channel• promiseの流れをforkする

// mvc as a stream of callbacksvar channel = ns.channel();

channel.observe( action1.bind( fin ) );channel.observe( action2.bind( fin ) );

before.bind( channel.send() );

13年12月3日火曜日

Page 48: Bitter Sweet Javascript

flip flop

Flip Flop

Flop ContentFlip Content

13年12月3日火曜日

Page 49: Bitter Sweet Javascript

flip flop

Flip Flop

Flop ContentFlip Content

var flip = new Tab(flipElement);var flop = new Tab(flopElement);

flip.select.observe( flop.toHide() );flop.select.observe( flip.toHide() ); flip.select.observe( ! displayLoading .bind( flipContent ) );

flop.select.observe( ! displayLoading .bind( flopContent ) );

13年12月3日火曜日

Page 50: Bitter Sweet Javascript

brook.model

Modelcreate

delete

notify(“create”)

13年12月3日火曜日

Page 51: Bitter Sweet Javascript

brook.model

Modelcreate

delete

notify(“create”)

var model = ns.createModel();

model.addMethod('create', requestFilter .bind( jsonrpc.createRPCPromise('create.entry') ) .bind( responseFilter ) );

model.addMethod('delete', requestFilter .bind( jsonrpc.createRPCPromise('delete.entry') ) .bind( responseFilter ) )

userAction.observe( eventToRequest.bind( model.notify("create"));

model.method('create').observe( actionA );model.method('create').observe( actionB );

13年12月3日火曜日

Page 52: Bitter Sweet Javascript

MVC is just a event network

View

Controller

Model View

Model

13年12月3日火曜日

Page 53: Bitter Sweet Javascript

MVC is just a event network

View

Controller

Model View

Model// in controllervar model = ns.model;var view = ns.view;

observeEvent( element, 'click',! viaEvent.bind( model.notify('update') );

model.observe( 'update', view! .bind( updateHTML(element) )! .bind( ns.bindAllWidget ));

13年12月3日火曜日

Page 54: Bitter Sweet Javascript

todo brook / namespace• ふふふふ。

• ドキュメントが。。が。

• ほんとはモテる感出したい

13年12月3日火曜日

Page 55: Bitter Sweet Javascript

まとめ。非同期コールバックをそのまま使っていいのは小学生まで。

依存性の記述=並列性の記述

resource駆動 + MVC + promiseを使ってモジュラプログラミングしよう

13年12月3日火曜日

Page 56: Bitter Sweet Javascript

全く関係ない話

• Perl Hackers Hubに記事があります。

• Software Metrics

• DI in Perl

• アーキテクチャパターン

13年12月3日火曜日