Bitter Sweet Javascript

Preview:

Citation preview

bitter sweet javascript

daichi hiroki

13年12月3日火曜日

about me.

たんぽぽT / JavaScript委員会

08年度入社

@hiroki_daichi

13年12月3日火曜日

what i am not talking about:

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

html5の話もしません。

jQuery/prototypeの話もしません。

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

coffee scriptの話もしません。

13年12月3日火曜日

talking about shibui.js

javascriptのnamespaceの話

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

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

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

13年12月3日火曜日

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

commonJSとかに準拠しない!

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

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

13年12月3日火曜日

brook.js

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

monad ! モナド! monad!

MVC / Resource Driven Widget / Channel

13年12月3日火曜日

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

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

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

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

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

13年12月3日火曜日

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

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

13年12月3日火曜日

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

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

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

• 結局グローバルを汚す

13年12月3日火曜日

namespace.js

13年12月3日火曜日

定義を遅延できる

13年12月3日火曜日

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

namespace B

namespace C

namespace N2

namespace N3

namespace N4

namespace D

namespace N5

namespace N1

namespace N6

13年12月3日火曜日

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

namespace B

namespace C

namespace N2

namespace N3

namespace N4

namespace D

namespace N5

namespace N1

namespace N6

13年12月3日火曜日

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

namespace B

namespace C

namespace N2

namespace N3

namespace N4

namespace D

namespace N5

namespace N1

namespace N6

13年12月3日火曜日

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

namespace B

namespace C

namespace N2

namespace N3

namespace N4

namespace D

namespace N5

namespace N1

namespace N6

13年12月3日火曜日

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

namespace B

namespace C

namespace N2

namespace N3

namespace N4

namespace D

namespace N5

namespace N1

namespace N6

13年12月3日火曜日

依存関係を動的に解決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日火曜日

依存関係を動的に解決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日火曜日

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

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

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日火曜日

必要なときにロードする

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

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

13年12月3日火曜日

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

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

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

13年12月3日火曜日

便利。

13年12月3日火曜日

さらに便利にする,

フレームワーク”brook”

13年12月3日火曜日

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日火曜日

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日火曜日

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日火曜日

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日火曜日

brook mvc

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

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

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

13年12月3日火曜日

MVC is ..Model

View

Controller

13年12月3日火曜日

MVC is ..Model

View

Controller

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

13年12月3日火曜日

MVC is ..Model

View

Controller

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

Controllerにイベントを伝える

13年12月3日火曜日

MVC is ..Model

View

Controller

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

Controllerにイベントを伝える

Modelに修正を伝える

13年12月3日火曜日

MVC is ..Model

View

Controller

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

Controllerにイベントを伝える

Modelに修正を伝える

Viewに修正完了を伝える

13年12月3日火曜日

MVC is ..Model

View

Controller

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

Controllerにイベントを伝える

Modelに修正を伝える

Viewに修正完了を伝える

13年12月3日火曜日

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

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

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

13年12月3日火曜日

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日火曜日

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日火曜日

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日火曜日

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日火曜日

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

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

13年12月3日火曜日

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

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

13年12月3日火曜日

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日火曜日

brook.promise is monad

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

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

13年12月3日火曜日

MVC is ..Model

View

Controller

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

13年12月3日火曜日

MVC is ..Model

View

Controller

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

userAction.subscribe();

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

13年12月3日火曜日

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

Promise Promise Promise

Promise PromisePromise

Promise

Channel

13年12月3日火曜日

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日火曜日

flip flop

Flip Flop

Flop ContentFlip Content

13年12月3日火曜日

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日火曜日

brook.model

Modelcreate

delete

notify(“create”)

13年12月3日火曜日

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日火曜日

MVC is just a event network

View

Controller

Model View

Model

13年12月3日火曜日

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日火曜日

todo brook / namespace• ふふふふ。

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

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

13年12月3日火曜日

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

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

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

13年12月3日火曜日

全く関係ない話

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

• Software Metrics

• DI in Perl

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

13年12月3日火曜日

Recommended