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 N1
namespace A
namespace N2
namespace N3
namespace B

namespace N4

namespace C

namespace N5

namespace D

namespace N6

13年12月3日火曜日
依存関係を動的に解決
namespace N1
namespace A
namespace N2
namespace N3
namespace B

namespace N4

namespace C

namespace N5

namespace D

namespace N6

13年12月3日火曜日
依存関係を動的に解決
namespace N1
namespace A
namespace N2
namespace N3
namespace B

namespace N4

namespace C

namespace N5

namespace D

namespace N6

13年12月3日火曜日
依存関係を動的に解決
namespace N1
namespace A
namespace N2
namespace N3
namespace B

namespace N4

namespace C

namespace N5

namespace D

namespace N6

13年12月3日火曜日
依存関係を動的に解決
namespace N1
namespace A
namespace N2
namespace N3
namespace B

namespace N4

namespace C

namespace N5

namespace D

namespace N6

13年12月3日火曜日
依存関係を動的に解決
namespace N1
namespace A
namespace N2
namespace N3
namespace B

namespace N4

namespace C

namespace N5

namespace D

namespace N6

13年12月3日火曜日

# Makefile
N2 : N1
N5 : N4
N6 : N1
A : N2
B : N3 N4
C : N5
D : N6
依存関係を動的に解決
namespace N1
namespace A
namespace N2
namespace N3
namespace B

namespace N4

namespace C

namespace N5

namespace D

namespace N6

13年12月3日火曜日

# Makefile
N2 : N1
N5 : N4
N6 : N1
A : N2
B : N3 N4
C : N5
D : N6
結合/読込順序に非依存
•

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

よくある実装
namespace N1
namespace N2
namespace A

13年12月3日火曜日

o

x
namespace A
namespace N1
namespace N2

Namespace.js
namespace N1
namespace N2
namespace A

o

o
namespace A
namespace N1
namespace N2
必要なときにロードする

依存関係木の中で平行に処理できるものは
並列化できる。
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.widget
Markup Resource
widget A
- meta data
- meta data
widget A
- meta data
- meta data

namespace N1
namespace A
namespace N2
namespace N3

widget B
- meta data
- meta data

namespace B

widget C
- meta data
- meta data

namespace C

namespace N5

namespace D

namespace N6

13年12月3日火曜日

namespace N4
brook.widget
Markup Resource
widget A
- meta data
- meta data
widget A
- meta data
- meta data

namespace N1
namespace A
namespace N2
namespace N3

widget B
- meta data
- meta data

namespace B

widget C
- meta data
- meta data

namespace C

namespace N5

namespace D

namespace N6

13年12月3日火曜日

namespace N4
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

Controllerにイベントを伝える
View
Controller

13年12月3日火曜日
MVC is ..
ユーザからアクションを受ける

Model

Controllerにイベントを伝える
View
Controller

13年12月3日火曜日

Modelに修正を伝える
MVC is ..
ユーザからアクションを受ける

Model

Controllerにイベントを伝える
View
Controller

13年12月3日火曜日

Modelに修正を伝える
Viewに修正完了を伝える
MVC is ..
ユーザからアクションを受ける

Model

Controllerにイベントを伝える
View
Controller

13年12月3日火曜日

Modelに修正を伝える
Viewに修正完了を伝える
async callback
•

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

•

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

•

13年12月3日火曜日

Node.jsもGUIも基本的にEvent Drivenの世界
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
•

•

13年12月3日火曜日

未来の処理を渡されるcallbackを抽象化
どこで切ってもモジュール化できる
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

•

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

•
13年12月3日火曜日

JSDeferredとかもこの性質を満たす。
MVC is ..
Model

View
Controller

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

13年12月3日火曜日
MVC is ..
Model

View
Controller

// mvc as a stream of callbacks
userAction
.bind( viewToController )
.bind( controller )
.bind( model )
.bind( viewFromModel )
userAction.subscribe();

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

13年12月3日火曜日
brook.channel
•

promiseの流れをforkする
Promise

Promise

Promise

Promise

Promise

Channel

Promise

Promise

13年12月3日火曜日
brook.channel
•

promiseの流れをforkする
// mvc as a stream of callbacks
var channel = ns.channel();
channel.observe( action1.bind( fin ) );
channel.observe( action2.bind( fin ) );

before.bind( channel.send() );

13年12月3日火曜日
flip flop
Flip

Flip Content

13年12月3日火曜日

Flop

Flop Content
flip flop
var flip = new Tab(flipElement);
var flop = new Tab(flopElement);
Flip

Flip Content

Flop

Flop Content

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
Model

create

delete

notify(“create”)

13年12月3日火曜日
brook.model
var model = ns.createModel();
Model

create

delete

notify(“create”)

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
Model

View
Model
View

Controller

13年12月3日火曜日
MVC is just a event
network
Model

View
// in controller
Model
var model = ns.model;
var view = ns.view;
View

Controller

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に記
事があります。

•
•

DI in Perl

•

13年12月3日火曜日

Software Metrics

アーキテクチャパターン

Bitter Sweet Javascript