reactive programming

316
Reactive Programming @maruyama097 丸丸丸丸丸

Upload: maruyama097

Post on 24-May-2015

2.640 views

Category:

Technology


4 download

TRANSCRIPT

Page 1: Reactive Programming

Reactive Programming

@maruyama097丸山不二夫

Page 2: Reactive Programming

In a recent post on the NetBeans developer site, one of the core maintainer observed that a single class had been patched over 14 times to fix threading related problems. --- Brian Goetz et al “Java Concurrency In Practice”

Page 3: Reactive Programming

1/3 of the code in Adobe’s desktop applications is devoted to event handling logic 1/2 of the bugs reported during a product cycle exist in this code

--- quoted in Martin Odersky’s “Deprecating the Observer Pattern”

Page 4: Reactive Programming

Merriam-Webster defines reactive as “readily responsive to a stimulus”, i.e. its components are “active” and always ready to receive events. This definition captures the essence of reactive applications, focusing on systems that: event-driven, scalable, resilient, responsive

--- “Reactive Manifesto”

Page 5: Reactive Programming

はじめに Reactive プログラミングの歴史は、インタ

ラクティブな UI の登場とともに古い。表計算ソフトは、もっとも身近な最も成功したReactive プログラミングの一つである。

現代の Reactive プログラミングをドライブしている力の一つは、 Responsive な UI への欲求である。その主要な舞台は、 Web UIである。 Web Component とともに、 post HTML5 の中心的な Web 技術の一つである、Model Driven View(MDV) は、こうしたReactive プログラミング技術と見ることが出来る。

Page 6: Reactive Programming

はじめに 現代の Reactive プログラミングをドライブ

しているもう一つの力は、非同期でイベント・ドリブンな処理への志向である。この方向は、 CPU のメニコア化と分散処理の巨大なクラウドへの拡大という、まったく異なる二つの分野でともに強力に押し進められている。

2010 年頃に公開されたマイクロソフト社のRx(Reactive Extention) は、 Observableの役割に注目し、 Reactive プログラミングの新しい手法を切り開いた画期的なものであった。

Page 7: Reactive Programming

はじめに Rx は、オープンソース化され、多くの言語

に移植され、また多くの Reactive プログラミング言語に大きな影響を与えた。

Rx の応用で注目すべき事例は、 Netflix による Rx の Java への移植と、それに基づく APIの書き換え・システムの再構築の成功である。

それはまた、小さな関数から大きな関数を合成するという関数型のアプローチの、大規模な実システムでの有効性を示すものでもあった。

Page 8: Reactive Programming

Agenda Part I   Web と Reactive プログラミング

非同期とイベント・ドリブンへの志向 Web UI と Reactive プログラミング Meteor   AngularJS   Dart Polymer.dart

Page 9: Reactive Programming

Agenda Part II

Reactive Extension の基礎 LINQ と Enumerable Rx と Observable Observable を使った Event 処理 Rx for JavaScript Observable を使った非同期処理 Android と Rx

Page 10: Reactive Programming

Agenda Part III

Observable を活用する Observable のストリームを処理する Observable を変形・加工する合成可能な

関数  Server サイドでの Rx の事例  Netflix Netflix での Observable の利用

Page 11: Reactive Programming

Agenda   Part IV

Reactive Manifesto The Need to Go Reactive Reactive Applications Event-driven Scalable Resilient Responsive Cocclusion

Page 12: Reactive Programming

Part I

Web と Reactive プログラミング

Page 13: Reactive Programming

表計算と Reactive Web UI

Page 14: Reactive Programming

表計算ソフトは Reactive最も身近で、成功したアプリの一つ

Page 15: Reactive Programming

表計算のアルゴリズムを考える

Loop { セル Cij への入力 / 修正のイベント検出

   Loop { セル Cij への入力 / 修正は終了したか?  }

  セル Cij に関連付けられている全てのマクロ Mn の検索

   Loop { 新しいセル Cij の値で全ての Mn を再計算

   Mn が定義されているセル Ckl の値を再表示 }}

Page 16: Reactive Programming

AngularJS の処理

Page 17: Reactive Programming

AngularJS の処理1. ‘X’ key が押されると、ブラウザーは input コントロールに

keydown イベントを発する。2. input directive は、 input の値の変化を捉えて、 Angular 実

行コンテキスト内のアプリケーション・モデルを変更する為に、 $apply(“name = ‘X’;”) を呼び出す。

3. Angular は、 name = ‘X’; をモデルに適用する。 4. $digest ループが始まる。5. $watch リストは、 name 属性の変化を検出すると、

{{name}} 補完に通知をして、それが、つづいて DOM を更新する。

6. Angular は実行コンテキストを抜け出す。それで、 keydownイベントは終わり、それとともに JavaScript の実行コンテキストも終わる。

7. ブラウザーは、更新されたテキストで、ビューを再描画する。

Page 18: Reactive Programming

非同期とイベント・ドリブンへの注目

Page 19: Reactive Programming
Page 20: Reactive Programming

2009 年 11 月  JSConf

Ryan Dahl の登場 ここでは、 node.js の爆発的な拡大の起点となっ

た、 2009 年ベルリンで行われた、 JSConf でのnode.js の創始者 Ryan Dahl の講演の一部を見てみよう。

“Node.js, Evented I/O for V8 Javascript”

by Ryan Dahl http

://jsconf.eu/2009/speaker/speakers_selected.html#entry-3356

http://s3.amazonaws.com/four.livejournal/20091117/jsconf.pdf

Page 21: Reactive Programming

I/O は、違ったやり方で行われる必要がある。 多くの Web アプリは、次のようなコードを

使う。 var result = db.query("select * from T"); // use result データベースを検索している間、ソフトウェ

アは何をしているのだろう? たいていの場合、ただレスポンスを待っているだけである。

それに加えて、 IO による遅延は、コンピュータの能力と比較すると、次のように、巨大なものである。http://s3.amazonaws.com/four.livejournal/20091117/jsconf.pdf

Page 22: Reactive Programming

I/O による遅延 L1: 3 cycles L2: 14 cycles RAM: 250 cycles DISK: 41,000,000 cycles NETWORK: 240,000,000 cycles

別の例を挙げよう。サーバーのパフォーマンスも実装によって大きな違いが生まれている。次のズは、 Appache と NGINX を比較したものである。

Page 23: Reactive Programming

“Latency as an Effect”

“Principles of Reactive Programming”Coursera lecture by Erik Meijerhttps://class.coursera.org/reactive-001/lecture/51

Page 24: Reactive Programming

2013 Nov 4th“Principles of Reactive Programming”

https://www.coursera.org/course/reactive

Page 25: Reactive Programming

trait Socket { def readFromMemory(): Array[Byte] def sendToEurope(packet: Array[Byte]): Array[Byte]}

val socket = Socket()val packet = socket.readFromMemory()val confirmation = socket.sendToEurope(packet)

Page 26: Reactive Programming

PC での処理時間

Page 27: Reactive Programming

シーケンシャルな実行時間

val socket = Socket()val packet = socket.readFromMemory()  // 50,000 ナノ秒ブロックする  // 例外が発生しない時には、次の処理へval confirmation = socket.sendToEurope(packet)  // 150,000,000 ナノ秒ブロックする  // 例外が発生しない時には、次の処理へ

Page 28: Reactive Programming

1 ナノ秒を 1 秒だと思うと

Page 29: Reactive Programming

1ナノ秒を 1秒だとした場合の実行時間

val socket = Socket()val packet = socket.readFromMemory()  // 3日間ブロックする  // 例外が発生しない時には、次の処理へval confirmation = socket.sendToEurope(packet)  // 5 年間ブロックする  // 例外が発生しない時には、次の処理へ

Page 30: Reactive Programming
Page 31: Reactive Programming

このようなコードは、全体のプロセスをブロックするか、複数のプロセスの実行をスタックさせることになるかのいずれかである。

しかし、次のようなコードでは、プログラムは、すぐに event loop に戻ることが可能である。どのようなメカニズムも必要としない。

これが、 I/O が行われるべき方法である。 では、何故、誰もが event loop や Callback

や Non-BlokingI/O を使わないのだろうか?

db.query("select..", function (result) { // use result});

var result = db.query("select..");

Page 32: Reactive Programming

文化的偏見 我々は、 I/O を次のように行うと教えられて

きた puts("Enter your name: "); var name = gets(); puts("Name: " + name);

我々は、入力を要求されたら、それが終わるまで何もしないと教えられてきた。次のようなコードは、複雑すぎるとして、退けられてきた。 puts("Enter your name: "); gets(function (name) { puts("Name: " + name); });

Page 33: Reactive Programming

インフラの不在 それでは、何故、誰もが event loop を使わ

ないのだろう? シングル・スレッドの event loop は、 I/O

が non-blocking であることを要求するのだが、ほとんどのライブラリーはそうなっていない。 POSIX async file I/O は使えない . Man pages は、関数がディスクにアクセスする

ことがあることを触れていない。 (e.g getpwuid())

C に、クロージャーや無名関数がないことが、コールバックを難しくしている。

データベースのライブラリーは (e.g. libmysql) 、非同期のサポートをしていない。

Page 34: Reactive Programming

JavaScript

Javascript は、 event loop と一緒に使われるように、特別にデザインされた言語である。 無名関数、クロージャー 同時には、一つだけのコールバック DOM のイベントコールバックを通じた I/O

JavaScript のカルチャーは、既に、イベント中心のプログラミングの準備ができている。

Page 35: Reactive Programming

node.js project:

高度な並列プログラムを記述する、純粋にイベント中心で、 non-blocking なインフラを提供すること。

Page 36: Reactive Programming

Libuv

libuv enforces an asynchronous, event-driven style of programming.

Its core job is to provide an event loop and   callback based notifications of I/O and other activities.

libuv offers core utilities like timers, non-blocking networking   support, asynchronous file system access, child processes and more.

Page 37: Reactive Programming

“Brief Hisory of Node.js”Ben Noordhuis

http://vimeo.com/51637038

Page 38: Reactive Programming

“An Introduction to libuv”Nikhil Marathe

November 10, 2013 Release 1.0.0http://nikhilm.github.io/uvbook/An%20Introduction%20to%20libuv.pdf

Page 39: Reactive Programming

#include <stdio.h>#include <fcntl.h>#include <unistd.h>#include <uv.h>

void on_read(uv_fs_t *req);

uv_fs_t open_req;uv_fs_t read_req;uv_fs_t write_req;

char buffer[1024];

void on_write(uv_fs_t *req) { // callback の signiture    uv_fs_req_cleanup(req);    if (req->result < 0) {        fprintf(stderr, "Write error: %s\n",        uv_strerror(uv_last_error(uv_default_loop())));    }    else {        uv_fs_read(uv_default_loop(), &read_req, open_req.result,        buffer, sizeof(buffer), -1, on_read); // callback    }} // on_write callback の中で、 on_read callback が呼ばれる

libuv スタイルでのcat の実装

open, red, write のlibuv版は、第一引数にloop を取る。最終引数はcallback

イベントのようなもの

Page 40: Reactive Programming

void on_read(uv_fs_t *req) { // callback の signiture    uv_fs_req_cleanup(req);    if (req->result < 0) {        fprintf(stderr, "Read error: %s\n",         uv_strerror(uv_last_error(uv_default_loop())));    }    else if (req->result == 0) {        uv_fs_t close_req;        // synchronous        uv_fs_close(uv_default_loop(),             &close_req, open_req.result, NULL);    } // callback が NULL 、同期型    else {        uv_fs_write(uv_default_loop(),             &write_req, 1, buffer, req->result, -1, on_write);    } // callback}    // on_read callback の中で、 on_write callback が呼ばれる

Page 41: Reactive Programming

void on_open(uv_fs_t *req) { // callback の signiture    if (req->result != -1) {        uv_fs_read(uv_default_loop(), &read_req, req->result,                   buffer, sizeof(buffer), -1, on_read); // callback    }    else {        fprintf(stderr, "error opening file: %d\n", req->errorno);    }    uv_fs_req_cleanup(req);} // on_open callback の中で、 on_read callback が呼ばれる

int main(int argc, char **argv) {    uv_fs_open(uv_default_loop(),        &open_req, argv[1], O_RDONLY, 0, on_open); // callback    return 0;} // open は、 on_open callback を呼んで、すぐループに入る。

Page 42: Reactive Programming

Callback Hell

“A guide to writing asynchronous javascript programs” http://callbackhell.com/Asynchronous javascript, or javascript that uses callbacks, is hard to get right intuitively.

“Callback hell in nodejs?”http://stackoverflow.com/questions/18095107/callback-hell-in-nodejsIn below code am I in callbackhell? How to overcome such scenario without using any async modules in pure javascript?

Page 43: Reactive Programming

Web UI と Reactive プログラミング

Page 44: Reactive Programming

Web UI での Reactive / Model Driven View(MDV) への志向 Meteor.js

Reactive プログラミング Reactive-context と Reactive-data-source publish/subscribe モデル

AngularJS Imperative から declarative Data binding

Polymer.js Model Driven View

.....

Page 45: Reactive Programming

MeteorReactive プログラミング

http://docs.meteor.com/https://github.com/meteor/meteor

Page 46: Reactive Programming

<template name="hello"> <div class="greeting">Hello there, {{first}} {{last}}!</div></template>

// in the JavaScript console> Template.hello({first: "Alyssa", last: "Hacker"}); => "<div class="greeting">Hello there, Alyssa Hacker!</div>"

Meteor.render(function () { return Template.hello({first: "Alyssa", last: "Hacker"});}) => automatically updating DOM elements

Meteor Template

Page 47: Reactive Programming

var fragment = Meteor.render( function () { var name = Session.get("name") || "Anonymous"; return "<div>Hello, " + name + "</div>"; });document.body.appendChild(fragment);

Session.set(“name”, “Bob”); // ページは自動的に更新される

Meteor LiveHTML

Page 48: Reactive Programming

Meteor.render() Meteor.render は、 rendering function 、ある

HTML を文字列として返すを関数を引数に取る。それは、自動更新する DocumentFragment を返す。

rendering function で利用されたデータに変更があったとき、それは、再実行される。 DocumentFragment 内の DOMノードは、ページのどの場所に挿入されていても、その場で自分自身を更新する。それは全く自動的である。

Meteor.render は、 rendering function によって、どのデータが利用されたかを発見する為にreactive context を使う。

Page 49: Reactive Programming

Meteor: reactive context + reactive data source

reactive context + reactive data source という単純なパターンは、広い応用可能性をもっている。

それ以上に、プログラマーは、 unsubscribe/resubscribe の呼び出しのコードを書く手間が省け、それらは、正しい時に確実に呼び出されことになる

一般的に、 Meteor は、そうでなければ、誤りを犯しやすいロジックで、アプリケーションの邪魔になる、データ伝搬の全てのクラスを取り除くことが出来る、

Page 50: Reactive Programming

AngularJSData Binding

http://angularjs.org/https://github.com/angular/angular.js

Page 51: Reactive Programming
Page 52: Reactive Programming

AngularJSData Binding デモ

<!doctype html><html ng-app> <head> <script src="http://code.angularjs.org/1.2.0rc1/angular.min.js">   </script> </head> <body> <input ng-model="name"> <p>Hello {{name}}!</p> </body></html>

Page 53: Reactive Programming

Controller

controller は、 view の背後にあるコードである。その役割は、モデルを構築して、コールバック・メソッドにそって、それをビューに公開することである。

view は、 scope の template( HTML)上への投射である。

scope は、モデルを view につなげ、イベントを Controller に向けさせる「つなぎ」の役割を果たす。

Page 54: Reactive Programming

The separation of the controller and the view controller は、 JavaScript で書かれる。

JavaScript は命令型である。命令型は、アプリケーションの振る舞いを指定するには、もっとも適している。 controller は、( DOM への参照、 HTML の断片のような)レンダー用の情報を含むべきではない。

view template は HTML で書かれる。 HTML は宣言型である。宣言型は、 UI の指定に最適である。 view は、振る舞いを含むべきではない。

controller は view のことを知らないので、同一のcontoroller に対して複数の view があり得る。このことは、スキンの変更・デバイス特有の view(モバイルと PC)・テスト可能性に取って、重要である。

Page 55: Reactive Programming
Page 56: Reactive Programming

Model model は、 template とマージされて view を生み

出すデータである。 model が view にレンダーされる為には、 model は、 scope から参照されなければならない。

他の多くのフレームワークとは異なって、 Angularは、 model について何の制限も要請も設けてはいない。 model にアクセス、あるいは model を変更する為に、継承すべきクラスも、特別のアクセス・メソッドもない。

model は、プリミティブでも、オブジェクト・ハッシュでも、全くのオブジェクト型でも構わない。要するに、 model は、” plain JavaScript object” なのである。

Page 57: Reactive Programming
Page 58: Reactive Programming

View

view は、ユーザーが見るものである。 viewのライフサイクルは、 template として始まる。 view は、 model とマージされて、最終的には、ブラウザーの DOM にレンダーされる。

Angular は、他の大部分の template システムと比較して、全く異なるアプローチを採用している。

Angular の template システムは、文字列の上ではなく DOM オブジェクトの上で動く。template は確かに HTML で書かれているが、それは HTML である。

Page 60: Reactive Programming

MDV templates in Dart

One-way data binding: Embed data into your UI

Two-way data binding: Keep data in sync with UI changes

Conditionals: Selectively show parts of the UI

Loops: Construct lists and tables by iterating over collections

Event listeners: Easily attach code that reacts to UI events

Page 61: Reactive Programming

One-way data binding<html lang="en"><head>  <meta charset="utf-8">  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">  <link rel="stylesheet” href="//cdnjs.cloudflare.com/ajax/libs /twitter-bootstrap/2.3.1/css/bootstrap.css"></head><body>  <div class="well">Hello {{dataValue}}!</div>  <script type="application/dart">    String dataValue;    main() {      var today = new DateTime.now();      dataValue = 'world ${today.year}-${today.month}-${today.day}';    }  </script></body></html>

Page 62: Reactive Programming

<html lang="en"><head>  <meta charset="utf-8">  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">  <link rel="stylesheet ”href="//cdnjs.cloudflare.com/ajax/libs /twitter-bootstrap/2.3.1/css/bootstrap.css"></head><body>  <div class="well">Hello counter: {{count}}</div>  <script type="application/dart">    import 'dart:async' as async;    import 'dart:html' as html;    import 'package:web_ui/watcher.dart' as watchers;    int count;    main() {      count = 0;      new async.Timer.periodic(const Duration(seconds: 1), (_) {        count++;        watchers.dispatch();      });    }  </script></body></html>

Page 63: Reactive Programming

Two-way data binding<html lang="en"><head> .....</head><body>  <div class="well">    Input:    <input type="text" bind-value="str" placeholder="type something here">    <div> Value: {{str}}</div>    <div> Length: {{str.length}}</div>  </div>  <script type="application/dart">    String str = '';    main() {}  </script></body></html>

Page 64: Reactive Programming

<html lang="en"><head> .....</head><body>  <div class="well">    <div> Input1: <input type="text" bind-value="str1"></div>    <div> Input2: <input type="text" bind-value="str2"></div>    <template if='str1 == str2'>      <div>They match!</div>    </template>  </div>  <script type="application/dart">    String str1 = '';    String str2 = '';    main() {}  </script></body></html>

Conditionals

Page 65: Reactive Programming

<html lang="en"><head> .....</head><body>  <input type="checkbox" bind-checked="show">Show phones  <br>  <table class="table">  <thead>    <tr>    <td>Last</td><td>First</td>    <td template if="show">Phone</td>    </tr>  </thead>  <tbody>    <tr>      <td>Bracha</td>      <td>Gilad</td>      <td template if="show">555-555-5555</td>    </tr>

Page 66: Reactive Programming

    <tr>      <td>Bak</td>      <td>Lars</td>      <td template if="show">222-222-2222</td>    </tr>    <tr>      <td>Ladd</td>      <td>Seth</td>      <td template if="show">111-222-3333</td>    </tr>  </tbody></table>  <script type="application/dart">    bool show = true;    main() {}  </script></body></html>

Page 67: Reactive Programming

Loops

<html lang="en"><head> .....</head><body>  <table class="table">  <tbody template iterate='row in table'>    <tr template iterate='cell in row'>      <td>{{cell}}</td>    </tr>  </tbody>  </table>  <script type="application/dart">    var table = [['X', 'O', '_'], ['O', 'X', '_'], ['_', '_', 'X']];    main() {}  </script></body></html>

Page 68: Reactive Programming

Event listeners

<html lang="en"><head> .....</head><body>  <div class="well">    <button on-click="increment()">Click me</button>    <span>(click count: {{count}})</span>  </div>  <script type="application/dart">    int count = 0;    void increment() { count++; }    main() {}  </script></body></html>

Page 69: Reactive Programming

Polymer.dartObservables and Data Binding with Web UI

https://www.dartlang.org/web-ui/observables/

Page 70: Reactive Programming

Overview of data binding in Web UI

Web UI helps you efficiently bind application data to HTML, and vice versa, with observables and observers.

Observables are variables, fields, or collections that can be observed for changes.

Observers are functions that run when an observable changes.

Page 71: Reactive Programming

Efficiently tracking changes

Instead of asking every possible observable “Did you change?” on every event loop over and over, Web UI has an efficient mechanism to notify only the right observers at the right time.

Page 72: Reactive Programming

Observing variables

<body> <h1>Hello Web UI</h1> <p>Web UI is {{ superlative }}</p> <button id="change-it" on-click="changeIt()"> Change</button> <script type="text/javascript" src="dart.js”> </script> <script type="application/dart" src="hello_world.dart"> </script> </body>

Page 73: Reactive Programming

library hello_world;import 'package:web_ui/web_ui.dart';

@observableString superlative = 'awesome';

const List<String> alternatives = const <String>['wicked cool', 'sweet', 'fantastic', 'wonderful'];int _alternativeCount = 0;String get nextAlternative => alternatives[_alternativeCount++ % alternatives.length];changeIt() { superlative = nextAlternative;}

main() { }

Page 74: Reactive Programming

Observing classes<p>Hello {{person.name}}!</p><p><button on-click="newName()"> Change Name</button></p>

@observableclass Person { String name; Person(this.name);}final Person person = new Person('Bob');const List<String> names = const <String> ['Sally', 'Alice', 'Steph'];newName() { person.name = nextName;}

Page 75: Reactive Programming

Observing collections

final List<DateTime> timestamps = toObservable([]);

void addTimestamp() { timestamps.add(new DateTime.now());}

void clear() { timestamps.clear();}

Page 76: Reactive Programming

Observing nested objects

@observableclass Person { String name; Address address;}

@observableclass Address { String city;}

@observablePerson person;

main() { person = new Person() ..name = 'Clark Kent' ..address = ( new Address() ..city = 'Metropolis' );}

Page 77: Reactive Programming

Expression Observers<p>The time is <span id="msg"></span></p><p><button on-click="updateMsg()"> Update</button></p>@observableString msg;

updateMsg() { msg = new DateTime.now().toString();}

main() { observe(() => msg, (_) { query('#msg').text = msg; });}

Page 78: Reactive Programming

Part II

Reactive Extension の基礎

Page 80: Reactive Programming

Reactive Extension とは? “The Reactive Extensions (Rx) is a

library to compose asynchronous and event-based programs using observable collections and LINQ-style query operators.”

「 Reactive Extension は、非同期かつイベント・ベースのプログラムをオブザーバブル・コレクションと LINQ スタイルの検索操作を利用して構成する為のライブラリーである。」

Page 81: Reactive Programming

講演資料 2010 年 11 月  DevCamp Keynote

“Rx: Curing your asynchronous programming blues”http://channel9.msdn.com/Blogs/codefest/DC2010T0100-Keynote-Rx-curing-your-asynchronous-programming-blues

2012 年 6 月  TechEd Europe “Rx: Curing your asynchronous programming blues”http://channel9.msdn.com/Events/TechEd/Europe/2012/DEV413

Page 82: Reactive Programming

Rx オープンソース化と移植 2012 年 11 月  MS Open Tech からオープン

ソースとして公開。Rx.NET :https://github.com/Reactive-Extensions/Rx.NET

あわせて、 JavaScript 、 C++ 、 Python 、 Ruby への移植版もオープンソースとして公開。 RxJS : https://github.com/Reactive-Extensions/RxJS

RxCpp :https://github.com/Reactive-Extensions/RxCpp

RxPy : https://github.com/Reactive-Extensions/RxPy

Rx.rb : https://github.com/Reactive-Extensions/Rx.rb

Page 83: Reactive Programming

RxJava

Netflix は、 Rx.NET を Java に移植し、オープンソースとして公開した。RxJava: https://github.com/Netflix/RxJava/

Netflix は、自社のシステムを RxJava を用いて書き換え、大規模システムでの Reactive プログラミングの有効性を示した。

2013 年 2 月 “ Functional Reactive in the Netflix API with RxJava”http://techblog.netflix.com/2013/02/rxjava-netflix-api.html

Page 84: Reactive Programming

RxJava の移植によって、 JVM上で走る、 Clojure, Scala, Groovy, Jruby等の言語でも Reactive Extension が走るようになった。

Page 85: Reactive Programming

LINQ と Enumerable

データソースの抽象化として、 .NET 3.0から導入された LINQ で、中心的な役割を果たすのは、 Enumerable インターフェースである。http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b

Page 86: Reactive Programming

interface IEnumerable<out T>{ IEnumerator<T> Enumerator();}

interface IEnumerator<out T> : IDisposable{ bool Next(); T Current { get; } void Reset();}

LINQ の最も重要なインターフェースEnumerable – pull-based

全ての Collection クラスは、 IEnumerable を実装している

Page 87: Reactive Programming

LINQ で利用出来るオペレータ

Projection: Select, SelectManyRestriction: WherePartitioning: Take, Skip, TakeWhile, ...Ordering: OrderBy, OrderByDecsending, ...Grouping: GroupBySet: Distinct, Union, Intersect, ..Conversion: ToList, ToArray, ..Generation: Range, RepeatAggregate: Count, Sum, Min, Max, Average,....

Page 88: Reactive Programming

public void Linq1() { int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; var lowNums = from n in numbers where n < 5 select n; Console.WriteLine("Numbers < 5:"); foreach (var x in lowNums) { Console.WriteLine(x); } }

LINQ は、 SQL ライクな検索構文で、データソースからデータソースを導出することが出来る

Page 89: Reactive Programming

public void Linq5() { string[] digits = { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" }; var shortDigits = digits.Where( (digit, index) => digit.Length < index); Console.WriteLine("Short digits:"); foreach (var d in shortDigits) { Console.WriteLine( "The word {0} is shorter than its value.", d); } }

LINQ では、検索式の中にラムダ式を利用出来る

Page 90: Reactive Programming

public void Linq14() {       int[] numbersA = { 0, 2, 4, 5, 6, 8, 9 };       int[] numbersB = { 1, 3, 5, 7, 8 };          var pairs =  from a in numbersA         from b in numbersB           where a < b           select new { a, b };          Console.WriteLine("Pairs where a < b:");       foreach (var pair in pairs)  {           Console.WriteLine( "{0} is less than {1}", pair.a, pair.b);     }  }

SelectMany (多段の Select)

Page 91: Reactive Programming

public void Linq15()  {       List<Customer> customers = GetCustomerList();

   var orders =         from c in customers         from o in c.Orders           where o.Total < 500.00M           select new {  c.CustomerID, o.OrderID, o.Total };          ObjectDumper.Write(orders);  }

SelectMany (多段の Select)

Page 92: Reactive Programming

public void Linq18()  {       List<Customer> customers = GetCustomerList();          DateTime cutoffDate = new DateTime(1997, 1, 1);         

var orders =         from c in customers           where c.Region == "WA"           from o in c.Orders           where o.OrderDate >= cutoffDate           select new { c.CustomerID, o.OrderID };          ObjectDumper.Write(orders);  }

SelectMany (多段の Select)

Page 93: Reactive Programming

public void Linq41() { string[] words = { "blueberry", "chimpanzee", "abacus", "banana", "apple", "cheese" }; var wordGroups = from w in words group w by w[0] into g select new { FirstLetter = g.Key, Words = g }; foreach (var g in wordGroups) { Console.WriteLine( "Words that start with the letter '{0}':", g.FirstLetter); foreach (var w in g.Words) { Console.WriteLine(w); } } }

Words that start with the letter 'b':blueberrybananaWords that start with the letter 'c':chimpanzeecheeseWords that start with the letter 'a':abacusapple

Page 94: Reactive Programming

Reactive Extension とObservable

Rx で中心的な役割を果たすのは、イベントのソースを抽象化した Observable である。それは、データソースの抽象化として、 LINQ で中心的な役割を果たすEnumerable とよく似ている。

Page 95: Reactive Programming

Observable と Observer

Observable は、 Enumerable と同様に、データの集まり。それは相互に変換可能。

Observable には時間の概念が入っている。それは時間とともにデータを生み出す。イベントの抽象に用いられる時に便利である。

データ・ソースとしての Observable が生成するデータは、 Observable に Observerが Subscribe した時に、はじめて利用出来る。

データは Observable から Subscribe の時に指定した Observer上の関数に自動的に送り出される。( Push)

Page 96: Reactive Programming

Observer上の三つの関数OnNext, OnError, OnComplete

Observable から Observer へデータがpush される時に、次の三つの関数のみが利用される。 OnNext(): 通常のデータの受け渡し。 OnError(): エラーが発生したこと伝える。 OnComplete(): 送るべきデータが終了したこ

とを伝える。 これらの関数の定義は、 Observable への

Subscribe の際に与えられねばならない。 Observable への Subscribe

は、 Subscription を返す。この値は、 Sunscribe をやめる時に利用される。

Page 97: Reactive Programming

Enumerable

Observable

Enumarable と Observable

時間の流れ

どちらもデータの集りである

Page 98: Reactive Programming

Enumerable と Observable は、相互に変換出来る

Enumerable Observable// Introduces concurrency to enumerate and signal…var xs = Enumerable.Range(0, 10).ToObservable();

Observable Enumerable// Removes concurrency by observing and yielding…var ys = Observable.Range(0, 10).ToEnumerable();

Page 99: Reactive Programming

interface IObservable<out T>{ IDisposable Subscribe(IObserver<T> observer);}

interface IObserver<in T>{ void OnNext(T value); void OnError(Exception ex); void OnCompleted();}

Rx の最も重要なインターフェースObservable push-based

Observer が実装する3つのタイプのメソッド

Page 100: Reactive Programming

Observable から Observer への通知

OnNext(42)

Observablesource1

OnNext(43)

OnCompleted

OnNext(“Hello”)

Observablesource2

OnError(error)

OnNext* (OnError | OnCompleted)?

Page 101: Reactive Programming

// Range() は、次のような Observabl を生成する// IObservable<int> source = Observable.Range(1, 10);

// ここでは、 Subscribe() は、三つの引数を取っている。// 順番に、 OnNext,OnError,OnComplete の定義であるIDisposable subscription = source.Subscribe( x => Console.WriteLine("OnNext: {0}", x), ex => Console.WriteLine("OnError: {0}", ex.Message), () => Console.WriteLine("OnCompleted"));

Console.WriteLine("Press ENTER to unsubscribe...");Console.ReadLine();// Subscribe をやめるsubscription.Dispose();

Observer が実装する3つのタイプのメソッド

-1-2-3-4-5-6-7-8-9-10-|

Page 102: Reactive Programming

internal class Generate_Simple{ private static void Main() { var observable = Observable.Generate(1, //  初期値 x => x < 6, //  条件 x => x + 1, //  増分 x => x, //  返り値 x=>TimeSpan.FromSeconds(1)).Timestamp();

// ここでは、 Subscribe には OnNext の定義だけが与えられている using (observable.Subscribe(x => Console.WriteLine( "{0}, {1}", x.Value, x.Timestamp))) { Console.WriteLine("Press any key to unsubscribe"); Console.ReadKey(); }

Console.WriteLine("Press any key to exit"); Console.ReadKey(); }}

-1-2-3-4-5-|

Page 103: Reactive Programming

class Select_Simple{ static void Main() {         // 一秒間隔で数列を生成する var oneNumberPerSecond = Observable. Interval(TimeSpan.FromSeconds(1)); var numbersTimesTwo = // 新しい Observable の生成 from n in oneNumberPerSecond select n * 2; // LINQ が使える!

Console.WriteLine("Numbers * 2:"); numbersTimesTwo.Subscribe(num => { Console.WriteLine(num); } // OnNext の定義が引数で与えられている ); Console.ReadKey(); }}

Page 104: Reactive Programming

LINQ と RxEnumerable と Observable

Environment

MoveN

ex

tGot next?

Application

On

Next

Have next!

IEnumerable<T>IEnumerator<T>

IObservable<T>IObserver<T>

Inte

racti

ve R

eactiv

e

Page 105: Reactive Programming

Observable を使った Event 処理

Page 106: Reactive Programming

var lbl = new Label(); var frm = new Form { Controls = { lbl } };

var moves = Observable. FromEvent<MouseEventArgs>(frm, "MouseMove"); using (moves.Subscribe (evt => { lbl.Text = evt.EventArgs.Location.ToString(); })) { Application.Run(frm); }

マウスイベントを Observable にするマウスは、イベントのデータベース!

Page 107: Reactive Programming

var txt = new TextBox(); var frm = new Form { Controls = { txt } };

var moves = Observable.FromEvent<MouseEventArgs> (frm, "MouseMove"); var input = Observable.FromEvent<EventArgs> (txt, "TextChanged");

var movesSubscription = moves.Subscribe( evt => { Console.WriteLine("Mouse at: " + evt.EventArgs.Location); }); var inputSubscription = input.Subscribe( evt => { Console.WriteLine("User wrote: " + ((TextBox)evt.Sender).Text); });

using (new CompositeDisposable( movesSubscription, inputSubscription)) { Application.Run(frm); }

Page 108: Reactive Programming

var moves = from evt in Observable. FromEvent<MouseEventArgs>(frm, "MouseMove") select evt.EventArgs.Location; var input = from evt in Observable. FromEvent<EventArgs>(txt, "TextChanged") select ((TextBox)evt.Sender).Text;

var movesSubscription = moves.Subscribe( pos => Console.WriteLine("Mouse at: " + pos)); var inputSubscription = input.Subscribe( inp => Console.WriteLine("User wrote: " + inp));

var overFirstBisector = from pos in moves where pos.X == pos.Y select pos; var movesSubscription = overFirstBisector.Subscribe( pos => Console.WriteLine("Mouse at: " + pos));

Page 109: Reactive Programming

var input = (from evt in Observable.FromEvent<EventArgs>(txt, "TextChanged") select ((TextBox)evt.Sender).Text) .Do(inp => Console.WriteLine("Before DistinctUntilChanged: " + inp)) .DistinctUntilChanged();

var input = (from evt in Observable.FromEvent<EventArgs>(txt, "TextChanged") select ((TextBox)evt.Sender).Text) .Throttle(TimeSpan.FromSeconds(1)) .DistinctUntilChanged();

var input = (from evt in Observable.FromEvent<EventArgs>(txt, "TextChanged") select ((TextBox)evt.Sender).Text) .DistinctUntilChanged();

using (input.ObserveOn(lbl).Subscribe(inp => lbl.Text = inp)) Application.Run(frm);

違った値が来た時のみデータを送る

Do は、 Observab l を変化させずに、 OnNext を実行する

Throttle は指定された時間の間、 Observable のイベントを抑制するTimeSpan.FromSecond(1) は、一秒間の指定

Page 110: Reactive Programming
Page 111: Reactive Programming

Reactive Extension for JavaScript

Page 112: Reactive Programming

var source = null; // Observable として source を生成するコード(省略)

var subscription = source.Subscribe( // 三つの関数の定義が順番に引数に与えられている function (next) { $("<p/>").html("OnNext: " + next) .appendTo("#content"); }, function (exn) { $("<p/>").html("OnError: " + exn) .appendTo("#content"); }, function () { $("<p/>").html("OnCompleted") .appendTo("#content"); });

Page 113: Reactive Programming

var source = Rx.Observable.Empty();

OnCompleted

var source = Rx.Observable.Throw("Oops!");

OnError: Oops

var source = Rx.Observable.Return(42);

OnNext: 42 OnCompleted

var source = Rx.Observable.Range(5,3);

OnNext: 5 OnNext: 6 OnNext: 7 OnCompleted

Page 114: Reactive Programming

var source = Rx.Observable.Generate( 0, function (i) { return i < 4; }, function (i) { return i + 1; }, // Like a for loop function (i) { return i * i; });

OnNext: 0 OnNext: 1 OnNext: 4 OnNext: 9 OnCompleted

Page 115: Reactive Programming

RxJS:DOM イベントを Observableに

Page 116: Reactive Programming

$(document).ready(function () { $(document).mousemove(function (event) { // A position tracking mechanism, // updating a paragraph called “content” $("<p/>") .text("X: " + event.pageX + " Y: " + event.pageY) .appendTo("#content"); }); });

$(document).ready(function () { $(document).toObservable("mousemove") .Subscribe(function (event) { // A position tracking mechanism, // updating a paragraph called “content” $("<p/>") .text("X: " + event.pageX + " Y: " + event.pageY) .appendTo("#content"); }); });

jQuery

RxJS

Page 117: Reactive Programming

$(document).ready(function () { $(document).toObservable("mousemove") .Subscribe(function (event) { $("<p/>") .text("X: " + event.pageX + " Y: " + event.pageY) .appendTo("#content"); });

$("#textbox").toObservable("keyup") .Subscribe(function (event) { $("<p/>") .text("User wrote: " + $(event.target).val()) .appendTo("#content"); }); });

Page 118: Reactive Programming

var moves = $(document).toObservable("mousemove") .Select(function(event) { return { pageX : event.pageX, pageY : event.pageY }; });

var inputs = $(“#textbox”).toObservable(”keyup”) .Select(function(event) { return $(event.target).val(); });

Page 119: Reactive Programming

var movesSubscription = moves.Subscribe( function (pos) { $("<p/>”) .text("X: " + pos.pageX + " Y: " + pos.pageY) .appendTo("#content"); });

var inputSubscription = input.Subscribe( function (text) { $("<p/>") .text("User wrote: " +text) .appendTo("#content"); });

Page 120: Reactive Programming

var overFirstBisector = moves .Where(function(pos) { return pos.pageX === pos.pageY; });

var movesSubscription = overFirstBisector .Subscribe(function (pos) { $("<p/>") .text("Mouse at: "+pos.pageX+","+pos.pageY) .appendTo("#content"); });

Page 121: Reactive Programming

var inputs = $(“#textbox”).toObservable(”keyup”) .Select(function(event) { return $(event.target).val(); } .DistinctUntilChanged(); );

var inputSubscription = input.Subscribe( function (text) { $("<p/>") .text("User wrote: " +text) .appendTo("#content"); });

Page 122: Reactive Programming

var inputs = $(“#textbox”).toObservable(”keyup”) .Select(function(event) { return $(event.target).val(); } .Throttle(1000) .DistinctUntilChanged(); );

var inputSubscription = input.Subscribe( function (text) { $("<p/>") .text("User wrote: " +text) .appendTo("#content"); });

Page 123: Reactive Programming

Observable と非同期処理

Page 124: Reactive Programming

FileStream fs = File.OpenRead("data.txt");byte[] bs = new byte[1024];fs.BeginRead(bs, 0, bs.Length, new AsyncCallback(iar => { int bytesRead = fs.EndRead(iar); // Do something with bs[0..bytesRead-1] }), null);

.NET の非同期プログラミング

Page 125: Reactive Programming

FileStream fs = File.OpenRead("data.txt");Func<byte[], int, int, IObservable<int>> read =

Observable.FromAsyncPattern<byte[], int, int,       int>( fs.BeginRead, fs.EndRead);

byte[] bs = new byte[1024];read(bs, 0, bs.Length).Subscribe(bytesRead => { // Do something with bs[0..bytesRead-1]});

Rx での非同期処理

Page 126: Reactive Programming

非同期サンプルネットワーク上のサービスの利用

ReactTextChanged Dictionary

web service

Asynchronous request

ReactionReactiveReactor

IObservable<string>

IObservable<DictionaryWord[]>

Data binding

on UI thread

$$$

Page 127: Reactive Programming

// IObservable<string> from TextChanged eventsvar changed =      Observable.FromEvent<EventArgs>(txt,"TextChanged");var input = (from text in changed select ((TextBox)text.Sender).Text); .DistinctUntilChanged() .Throttle(TimeSpan.FromSeconds(1));

// Bridge with the dictionary web servicevar svc = new DictServiceSoapClient();var lookup =         Observable.FromAsyncPattern<string,DictionaryWord[]> (svc.BeginLookup, svc.EndLookup);

// Compose both sources using SelectManyvar res = from term in input from words in lookup(term) select words;

Page 128: Reactive Programming

function searchWikipedia(term) {    return $.ajaxAsObservable(      { url: "http://en.wikipedia.org/w/api.php",        dataType: "jsonp",      data: { action: "opensearch",               search: term,              format: "json" } }) .Select(function (d) { return d.data[1]; }); } var searchObservable = searchWikipedia("react"); var searchSubscription = searchObservable.Subscribe( function (results) { $("#results").empty(); $.each(results, function (_, result) { $("#results").append("<li>" + result + "</li>"); }); }, function (exn) { $("#error").text(error); } );

Page 129: Reactive Programming

var searchObservable = terms.SelectMany( function (term) { return searchWikipedia(term); } );

var searchObservable = terms.SelectMany(searchWikipedia);

var res = from term in terms from words in searchWikipedia(term) select words;

Page 131: Reactive Programming

class DownloadTask extends AsyncTask<String, Void, File> {

protected File doInBackground(String... args) { final String url = args[0]; try { byte[] fileContent = downloadFile(url); File file = writeToFile(fileContent); return file; } catch (Exception e) { // ??? } }

protected void onPostExecute(File file) { Context context = getContext(); // ??? Toast.makeText(context, "Downloaded: " + file.getAbsolutePath(), Toast.LENGTH_SHORT) .show(); }}

現在の AsyncTask を使った処理

Page 132: Reactive Programming

private Observable<File> downloadFileObservable() { return Observable.create(new OnSubscribeFunc<File>() { @Override public Subscription onSubscribe( Observer<? super File> fileObserver) { try { byte[] fileContent = downloadFile(); File file = writeToFile(fileContent); fileObserver.onNext(file); fileObserver.onCompleted(); } catch (Exception e) { fileObserver.onError(e); } return Subscriptions.empty(); } });}

Page 133: Reactive Programming

class MyFragment extends Fragment implements Observer<File> { private Subscription subscription;

@Override

protected void onCreate( Bundle savedInstanceState) { subscription = AndroidObservables .fromFragment(this,downloadFileObservable()) .subscribeOn(Schedulers.newThread()) .subscribe(this); }

private Observable<File> downloadFileObservable() { /* as above */ }

@Override protected void onDestroy() { subscription.unsubscribe(); }

Page 134: Reactive Programming

Observable<String> filePathObservable = downloadFileObservable().map(new Func1<File, String>() { @Override public String call(File file) { return file.getAbsolutePath(); }});

// now emits file paths, not `File`ssubscription = filePathObservable.subscribe(                    /* Observer<String> */);

Page 135: Reactive Programming

public void onNext(File file) { Toast.makeText(getActivity(), "Downloaded: " + file.getAbsolutePath(), Toast.LENGTH_SHORT) .show(); }

public void onCompleted() {}

public void onError(Throwable error) { Toast.makeText(getActivity(), "Download failed: " + error.getMessage(), Toast.LENGTH_SHORT) .show(); }}

Page 137: Reactive Programming

def getAsyncUrl(urlString: String) :Observable[Option[String]] = Observable { (observer: Observer[Option[String]]) => { val url = new URL(urlString) val urlCon = url.openConnection() urlCon.setConnectTimeout(5000) urlCon.setReadTimeout(5000) val io = Source.fromInputStream( urlCon.getInputStream) val result = Option(io.getLines(). mkString.split("\n")(0)) io.close() observer.onNext(result) observer.onCompleted() Subscription() } }

Page 138: Reactive Programming

val mUnsubscribe = CompositeSubscription() mUnsubscribe += getAsyncUrl(lastScript) .execAsync.subscribe( _ match { case OnNext(Some(t)) => CInfo(t) case OnNext(None) => CAlert(getString( R.string.connection_error_message, "Server error")) case OnError(e) => CAlert(getString(R.string.connection_ error_message, e.getLocalizedMessage)) })

Page 140: Reactive Programming

Part III

Observable を活用する

Page 141: Reactive Programming

Observable のストリームを処理する Rx サンプル

Page 142: Reactive Programming

Stock Trade AnalysisMSFT27.01

ticks

INTC21.75

MSFT27.96

MSFT31.21

INTC22.54

INTC20.98

MSFT30.73

from tick in ticks

Page 143: Reactive Programming

MSFT27.01

ticks

INTC21.75

MSFT27.96

MSFT31.21

INTC22.54

INTC20.98

MSFT30.73

27.01

27.96

31.21

30.73

MSFT

21.75

22.54

20.98

INTC

from tick in ticksgroup tick by tick.Symbol

Stock Trade Analysis

Page 144: Reactive Programming

MSFT27.01

ticks

INTC21.75

MSFT27.96

MSFT31.21

INTC22.54

INTC20.98

MSFT30.73

MSFT

INTC

from tick in ticksgroup tick by tick.Symbol into companyfrom openClose in company.Buffer(2, 1)

[27.01, 27.96]

[27.96, 31.21]

[31.21, 30.73]

[21.75, 22.54]

[22.54, 20.98]

Stock Trade Analysis

Page 145: Reactive Programming

Stock Trade AnalysisMSFT27.01

ticks

INTC21.75

MSFT27.96

MSFT31.21

INTC22.54

INTC20.98

MSFT30.73

MSFT

INTC

from tick in ticksgroup tick by tick.Symbol into companyfrom openClose in company.Buffer(2, 1)

let diff = (openClose[1] – openClose[0])/openClose[0]

0.034

0.104

-0.01

5

0.036

-0.06

9

Stock Trade Analysis

Page 146: Reactive Programming

MSFT27.01

ticks

INTC21.75

MSFT27.96

MSFT31.21

INTC22.54

INTC20.98

MSFT30.73

MSFT

INTC

from tick in ticksgroup tick by tick.Symbol into companyfrom openClose in company.Buffer(2, 1)let diff = (openClose[1] – openClose[0])/openClose[0]where diff > 0.1

0.034

0.104

-0.01

5

0.036

-0.06

9

Stock Trade Analysis

Page 147: Reactive Programming

MSFT27.01

ticks

INTC21.75

MSFT27.96

MSFT31.21

INTC22.54

INTC20.98

MSFT30.73

from tick in ticksgroup tick by tick.Symbol into companyfrom openClose in company.Buffer(2, 1)let diff = (openClose[1] – openClose[0]) / openClose[0]where diff > 0.1

select new { Company = company.Key, Increase = diff }

res

Company = MSFTIncrease = 0.104

Stock Trade Analysis

Page 148: Reactive Programming

Observable を変形・加工する合成可能な関数を利用する

Page 149: Reactive Programming

Composable Functions

Transform: map, flatmap, reduce, Scan ...

Filter: take, skip, sample, takewhile, filter ...

Combine: concat, merge, zip, combinelatest, multicast, publish, cache, refcount ...

Concurrency: observeon, subscribeon Error Handling: onErrorreturn,

onErrorResume ...

Page 150: Reactive Programming

map

def map[B](f: A⇒B): Observable[B]

Page 151: Reactive Programming

filter

def filter(p: A⇒Boolean): Observable[A]

Page 152: Reactive Programming

merge

def merge(Observable[A],Obserbal[A]): Observable[A]

Page 153: Reactive Programming

def flatMap(f: T=>Observable[S]): Observable[S]= { map(f).flatten }

flatmap

Page 154: Reactive Programming
Page 155: Reactive Programming

val xs: Observable[Int] = Observable(3,2,1)val yss: Observable[Observable[Int]] = xs.map(x => Observable.Interval(x seconds) .map(_=>x).take(2))val zs: Observable[Int] = yss.flatten()

xs: Observable[Int]

yss: Observable[Observable[Int]]]

zs: Observable[Int]

flatmap

merge

Page 156: Reactive Programming

concat

Page 157: Reactive Programming

val xs: Observable[Int] = Observable(3,2,1)val yss: Observable[Observable[Int]] = xs.map(x => Observable.Interval(x seconds) .map(_=>x).take(2))val zs: Observable[Int] = yss.concat()

xs: Observable[Int]

yss: Observable[Observable[Int]]]

zs: Observable[Int]

Page 158: Reactive Programming

zip

Page 159: Reactive Programming

def groupBy[K](keySelector: T⇒K) : Observable[(K,Observable[T])]

groupBy

Page 160: Reactive Programming

def startWith(ss: T*): Observable[T]

startWith

Page 161: Reactive Programming

def reduce(f:(T, T) ⇒T): Observable[T]

reduce

Page 162: Reactive Programming

Server サイドでの Rx の利用Netflix --- RxJava

“a library for composingasynchronous and event-basedprograms using observablesequences for the Java VM”

Page 163: Reactive Programming

RxJavaJava 8 への Rx の移植

Observable.toObservable("one”,"two”,"three") .take(2) .subscribe( (arg) -> { System.out.println(arg); } );

https://github.com/Netflix/RxJava

Page 164: Reactive Programming

Netflix

Netflix は、北米のインターネットのダウンロード・トラフィックの 33% を占める。

Netflix の顧客は、一月に 10億時間以上、テレビを見ている。

API のトラフィックは、 2010 年の 2000万 / 一日から、 2013 年には 20億 / 一日に成長した。

Page 165: Reactive Programming

一日の Netflix API へのリクエスト数

Page 166: Reactive Programming

クライアントのデバイスは、 Netflix の二つの主要なサービスに接続する。第一のサービスは、ビデオの検索やそのコンテンツの紹介に関係した機能を提供する Netflix API である。第二のサービスは、ビデオ・ストリームの再生サービスである。

ここでは、ビデオの検索・発見にかかわるNetflix API について見ていく。

Page 167: Reactive Programming
Page 168: Reactive Programming
Page 169: Reactive Programming

Rx の発見は、システムの Re-Atchitecture から始まった

Page 170: Reactive Programming

ネットワーク・トラフィックは、API の改良で、劇的に改善した

9 つあったネットワークの呼び出しは1つになり、 WAN でのネットワーク遅延は一回だけになった

クライアントのロジックは、サーバに移され、 20以上の呼び出しが削除された

Page 172: Reactive Programming

Netflix での Observable の利用

Netflix では、ブロックする API をObservable を返す非同期の API に作り替え、ついで、それらの Observable を返すAPI を組み合わせてサービスを構成した。

Page 173: Reactive Programming
Page 174: Reactive Programming

Observable.create({   observer  ‐> try { observer.onNext(new ....)) observer.onCompleted(); } catch(Exception e) { observer.onError(e); }})

Observable<T> create(Func1<Observer<T>, Subscription> func)

Observable を作る

Page 175: Reactive Programming

def Observable<VideoRating> getRating(userId, videoId) { return Observable.create({ observer ‐> executor.execute(new Runnable() { def void run() { try { VideoRating rating = //.. do network call . observer.onNext(rating) observer.onCompleted(); } catch(Exception e) { observer.onError(e); } } }) }) }

Asynchronous Observable with Single Values

Page 176: Reactive Programming

def Observable<Video> getVideos() {return Observable.create({ observer ‐> executor.execute(new Runnable() { def void run() { try { for ( id in videoIds ) {         Video v = // .. do network call ... observer.onNext(v) } observer.onCompleted(); } catch(Exception e) { observer.onError(e); } } }) }) }

Asynchronous Observable with Multiple Values

Page 177: Reactive Programming

Observable を組み合わせて、サービスを作る

こうした情報を返すサービス

Page 178: Reactive Programming

Observable<Video> は、 OnNext に n個のビデオを送り出す

Observable を組み合わせて、サービスを作る

Page 179: Reactive Programming

def   Observable<Map>   getVideos(userId)   { return VideoService.getVideos(userId)}

Observable<Video> は、 OnNext に n個のビデオを送り出す

Page 180: Reactive Programming

def   Observable<Map>   getVideos(userId)   { return VideoService.getVideos(userId) // リストの最初の10本だけが欲しい .take(10)}

最初の 10個を取って、あとは unscribe する。10個のビデオを送り出す Observable<Video> を返す。

Page 181: Reactive Programming

最初の 10個を取って、あとは unscribe する。10個のビデオを送り出す Observable<Video> を返す。

Observable を組み合わせて、サービスを作る

Page 182: Reactive Programming

最初の 10個を取って、あとは unscribe する。10個のビデオを送り出す Observable<Video> を返す。

unscribe

Observable を組み合わせて、サービスを作る

Page 183: Reactive Programming

def   Observable<Map>   getVideos(userId)   { return VideoService.getVideos(userId) // リストの最初の10本だけが欲しい .take(10) .map( { Video video -> // Video オブジェクトを変形する })}

map operator は、入力値を他の出力値に変える

Page 184: Reactive Programming

Observable<R> b = Observable<T>.map({ T t -> R r = ... transform t ... return r;})

Page 185: Reactive Programming

def   Observable<Map>   getVideos(userId)   { return VideoService.getVideos(userId) // リストの最初の 10本だけが欲しい .take(10) .flatMap( { Video video -> // それぞれのビデオからメタデータを取り出す def m = video.getMetaData() .map( { Map<String, String> md -> return [ title: md.get(“title”), length: md.get(“duration”)] }) // ブックマークとレイティングも def b .... def r .... })}

ここでは、 flatMap / mapMany を使う。 map では Observable<T> の要素一つが、型 R の要素一つに変わったが、 flatMap / mapMany では、Observable<T> の要素一つ一つが、別の Observable<R> に変わる。

Page 186: Reactive Programming

Observable を組み合わせて、サービスを作る

Page 187: Reactive Programming

def   Observable<Map>   getVideos(userId)   { return VideoService.getVideos(userId) // リストの最初の 10本だけが欲しい .take(10) .mapMany( { Video video -> // それぞれのビデオからメタデータを取り出す def m = video.getMetaData() .map( { Map<String, String> md -> return [ title: md.get(“title”), length: md.get(“duration”)] }) // ブックマークとレイティングも def b .... def r .... })}

Observable<VideoMetadata>Observable<VideoBookmark>Observable<VideoRating>

mapMany は、三つの関数の定義に応じてObservable<Video> から、次の三つのObservable を生成する。

Page 188: Reactive Programming

一つの Video ‘v’ に対して getMetaData() は、Observable<MetaData> を返す

Observable を組み合わせて、サービスを作る

Page 189: Reactive Programming

def   Observable<Map>   getVideos(userId)   { return VideoService.getVideos(userId) // リストの最初の 10本だけが欲しい .take(10) .mapMany( { Video video -> // それぞれのビデオからメタデータを取り出す def m = video.getMetaData() .map( { Map<String, String> md -> return [ title: md.get(“title”), length: md.get(“duration”)] }) // ブックマークとレイティングも def b .... def r .... })}

それぞれの Observable は、 map を利用してデータを変換する

Page 190: Reactive Programming

Observable<MetaData> は、 map 関数で変形される

Observable を組み合わせて、サービスを作る

Page 191: Reactive Programming

Observable<Bookmark> 、 Observable<rating> も同様に処理される

Observable を組み合わせて、サービスを作る

Page 192: Reactive Programming

def   Observable<Map>   getVideos(userId)   { return VideoService.getVideos(userId) // リストの最初の 10本だけが欲しい .take(10) .mapMany( { Video video -> // それぞれのビデオからメタデータを取り出す def m = video.getMetaData() .map( { Map<String, String> md -> return [ title: md.get(“title”), length: md.get(“duration”)] }) // ブックマークとレイティングも def b .... def r .... // これらを結合する })}

Page 193: Reactive Programming

def   Observable<Map>   getVideos(userId)   { return VideoService.getVideos(userId) // リストの最初の 10本だけが欲しい .take(10) .flatmap( { Video video -> // それぞれのビデオからメタデータを取り出す def m ... def b .... def r .... // これらを結合する })}

Page 194: Reactive Programming

def   Observable<Map>   getVideos(userId)   { return VideoService.getVideos(userId) // リストの最初の 10本だけが欲しい .take(10) .flatmap( { Video video -> // それぞれのビデオからメタデータを取り出す def m ... def b .... def r .... // これらを結合する return Observable.zip( m, b, r, {         metadata, bookmark, rating -> // 完全なデータの辞書に変換する return [ id: video.videoId ]           << metadata << bookmark << rating }) })}

zip は、三つの非同期の Observable を一つの Observable にまとめる

Page 195: Reactive Programming

Observable を組み合わせて、サービスを作る

Page 196: Reactive Programming

Observable を組み合わせて、サービスを作る

Page 197: Reactive Programming

public Data getData();を考える -- NetFlix RxJava

もしも、同期型から非同期型に変わったら、実装はどう変化するだろうか?クライアントは、ブロックしないように実行するには、どうすればいいだろうか?

Page 198: Reactive Programming

getData の実装の候補 public Data getData(); public void getData(Callback<T> c); public Future<T> getData(); public Future<List<Future<T>>>

getData(); ...

?

Page 199: Reactive Programming

Iterable と Observable

Iterable

Pull

T next()throw Exception

returns;

Observable

Push

onNext[T]onError[Exception]onCompletion

Page 200: Reactive Programming

Iterable と Observable

同じ高階関数が、 Iterable にも Observableにも、同じように適用出来る。

Page 201: Reactive Programming

getData() の分類 同期 / 非同期、返り値の単数 /複数で表を作ってみると、 getData() の次のような分類が可能である。

Page 202: Reactive Programming

String s = getData(args);if (s.equals(x)) { // do something} else { // do something else}

scalar を返り値に持つ、典型的な同期型 getData() のコード

Page 203: Reactive Programming

scalar 値が返る場合とほとんど同じだが、処理はループする

Iterable<String> values = getData(args);for (String s : values) { if (s.equals(x)) { // do something } else { // do something else }}

Page 204: Reactive Programming

Future<String> s = getData(args);if (s.get().equals(x)) { // do something} else { // do something else}

古い Java の Future コード。非同期だが、 get でブロックする。

Page 205: Reactive Programming

Future<String> s = getData(args);Futures.addCallback(s, new FutureCallback<String> { public void onSuccess(String s) { if (s.get().equals(x)) {...} else {...} } public void onFailure(Throwable t) { // handle error }}, executor);

Future と callback をつかった非同期のコード・サンプル

Page 206: Reactive Programming

Observable を使った getData() のコード・サンプル

Observable<String> s = getData(args);s.map({ s -> if (s.get().equals(x)) { // do something } else { // do something else });

Page 207: Reactive Programming

Iterable と Observable の「双対性」 Observable/Observer は、同期型の

Iterable/Iterator の非同期の双対形である。

“Subject/Observer is Dual to Iterator”Erik Meijer”http://csl.stanford.edu/~christos/pldi2010.fit/meijer.duality.pdf

“Introduction to the Reactive Framework Part II ”http://codebetter.com/matthewpodwysocki/2009/11/03/introduction-to-the-reactive-framework-part-ii/

Page 208: Reactive Programming

Part IV

Reactive Manifesto

Page 209: Reactive Programming

Reactive Manifesto

2013 年9月 23日  version 1.1http://www.reactivemanifesto.org/

Page 210: Reactive Programming

Reactive に移行する必要性 近年、アプリケーションの要請は劇的に変わってき

た。ほんの数年前には、大規模なアプリケーションは、数十台のサーバ、数秒のレスポンスタイム、数時間のオフライン・メンテナンス、数ギガバイトのデータから構成されていた。今日、アプリケーションは、モバイル・デバイスから数千のマルチコア・プロセッサーが走るクラウド・ベースのクラスターにいたるまであらゆるところに配備されている。ユーザはミリセカンドさらにはナノセコンドのレスポンスタイムと、 100% の稼働を期待している。データの要求は、ペタバイトに拡大しようとしている。

Page 211: Reactive Programming
Page 212: Reactive Programming

当初は、 Google や Twitter といった革新的なインターネット・ドリブンの企業の領域だけだったが、こうしたアプリケーションの特徴は、ほとんどの産業で表面化した。金融や通信事業者が、最初に新しい要請を満たす実践を受け入れ、その他の産業がそれに続いた。

新しい要請は、新しいテクノロジーを要求する。それ以前のソリューションは、管理されたサーバとコンテナに力点を置いたものだった。規模拡大は、より大きなサーバを買うことと、マルチスレッドによる並行処理を通じて達成された。追加されたサーバは、複雑で非効率かつ高価なプロプライエトリなソリューションを通じて追加された。

Page 213: Reactive Programming

しかし今では新しいアーキテクチャーが進化し、開発者が今日の要求を満たすアプリケーションを概念的に把握し、アプリを構築するのを可能にしている。我々は、これらをリアクティブ・アプリケーションと呼んでいる。このアプリケーションは開発者が、イベント・ドリブンで、拡張性を持ち、耐障害性の高い、応答性に優れたシステムを構築することを可能とする。すなわち、このアプリケーションは、リアルタイム感に富み、拡張可能で耐障害性の高いアプリケーション層で支えられ、マルチコアでもクラウド・コンピュータのアーキテクチャでもすぐに配備されうる、高い応答性のユーザ体験を提供出来るアプリケーションである。 この Reactive Manifesto は、リアクティブに移行するのに必要な本質的な諸特徴を記述するものである。

Page 214: Reactive Programming
Page 215: Reactive Programming

Reactive アプリケーション 辞書の Merriam-Webster は、 reactive を「刺激に対してすぐに反応できること」と定義している。すなわち、そのコンポーネントは「アクティブ」で、常にイベントを受け取る準備ができているということである。この定義は、リアクティブなアプリケーションの本質を捉えている。それはシステムの次のようなところに焦点を合わせている。

Page 216: Reactive Programming

react to events  イベントに反応するイベント・ドリブンの性質は、次のような特質を可能にする

react to load  負荷に反応する共有リソースの競合を避けることで、拡張可能性にフォーカスする

react to failure  失敗に反応する全てのレベルでエラー回復の能力を持たせることで、耐障害性の高いシステムを構築する

react to users  ユーザに反応する負荷のいかんにかかわらず、高い反応時間を保証する

Page 217: Reactive Programming

これらの一つ一つが、リアクティブなアプリケーションの本質的な特徴である。一方で、それらのあいだには、相互に従属関係が存在する。ただ、これらの特徴は、標準的な階層型のアプリケーションの意味での「層」にあたるものではない。その代わりに、それらは全ての技術をつらぬいた設計の諸特徴を記述したものである。

Page 218: Reactive Programming

Event-driven重要なこと 非同期通信に基づいたアプリケーションは、疎結合

デザインを実装する。それは、純粋に同期型のメソッド呼び出しに基づいたアプリケーションよりもいいものである。イベントの送り手と受け手は、如何にイベントが伝播するのかの詳細を考えなくても実装されることが出来る。インターフェースは通信の内容に集中出来る。このことで、拡張も改良も保守も、より容易な実装ができるようになり、開発の柔軟性を増やすと同時に保守コストを低減出来る。

Page 219: Reactive Programming

非同期通信のメッセージの受け手は、イベントが起きるまで、あるいは、メッセージを受け取るまで、眠っていることが出来るので、イベント・ドリブンのアプローチは、多数の受け取り手が、単一のハードウェア上のスレッドを共有することで、既存のリソースを有効に利用することが出来る。重い負荷の下にある、ブロックしないアプリケーションは、こうして、ブロックする同期型の通信単位に基づいた伝統的なアプリケーションより、低遅延と高スループットを持つことが出来る。結果として、オペレーションのコストは低いものになり、可用性は高まり、エンドユーザはハッピーになる。

Page 220: Reactive Programming

Event-drivenキーとなる構成ブロック イベント・ドリブンのアプリケーションでは、様々

な事実を記述する離散型の情報の断片であるイベントの生産と消費を通じて、コンポーネントは相互作用を行う。これらのイベントは、ブロックしない非同期なスタイルで、送られ受け取られる。イベント・ドリブンのシステムは、 Pull や Poll より、 Push に依存することが多い。すなわち、イベントの消費者にデータをいつまでも要求するか待たせることなく、それが利用可能になった時点で消費者に向けてデータを Push する。

Page 221: Reactive Programming

非同期のイベントの送信は、メッセージ・パッシングとも呼ばれるのだが、それはアプリケーションが設計から高度に並列化され、変更なしでマルチコアのハードウェアを利用出来るということを意味する。 CPU 内の全てのコアがいかなるメッセージ・イベントをも処理出来るということは、並行実行の可能性を劇的に増大させる。

ノン・ブロッキングは、エラーや処理の爆発的な増大が起きた場合でさえも、アプリケーションが、どんな時でも反応を返すことが出来る為に、処理を連続的に進める能力を意味する。この為には、反応に必要とされる全てのリソースは—例えば、 CPU 、メモリー、ネットワーク等は、独占されてはならない。こうして、それは低い遅延と高いスループットとより良い拡張性を可能とする。

Page 222: Reactive Programming

伝統的なサーバサイドのアーキテクチャーは、変更可能な状態の共有と単一スレッド上のブロック操作に依存している。両者はともに、こうしたシステムを変化する要求に適合するようにスケールしようとした時遭遇する様々の困難の原因となる。変更可能な状態の共有は、同期を要求する。これは、思わぬ複雑さと非決定性を導入することになり、プログラムのコードの理解を難しいものにし、保守も難しいものにする。ブロッキングでスレッドを眠らせることは、有限の資源を浪費し、また、起き上がらせる時に高いコストを払うことになる。

Page 223: Reactive Programming

イベントの生成と処理を分離することで、ランタイムのプラットフォームは、同期の詳細とスレッドをまたいでいかにイベントが送り出されるかを意識することが可能となる。一方で、プログラムの抽象はビジネスのワークフローのレベルまで持ち上げられる。スレッドやロックといった低レベルの諸機能にかかわることなしに、イベントがどのようにシステムの中を伝播し、コンポーネントがどのように相互作用するかを考えればいい。

イベント・ドリブンのシステムは、コンポーネント間、サブシステム間の疎結合を可能とする。この間接性のレベルは、あとで見るように、拡張可能性と耐障害性の前提条件の一つである。コンポーネント間の複雑で強い従属性を取り除くことで、イベント・ドリブンのアプリケーションは、既存のアプリケーションに最低限のインパクトを与えるだけで拡張が可能である。

Page 224: Reactive Programming

アプリケーションが、高いパフォーマンスと大規模な拡張可能性を求める要求の圧力のもとにおかれた時、どこにボトルネックが生ずるかを予測するのは難しい。それ故、ソリューション全体が非同期でノン・ブロッキングなものであることが重要である。典型的な例では、このことは、 UI のユーザのリクエスト(ブラウザーなり、 REST のクライアントなりなんでも)からリクエストのパージングと web層での送り出しまで、ミドルウェアのサービス・コンポーネントに取っては、キャッシングからデータベースにいたるまで、デザインがイベント・ドリブンである必要があることを意味する。

もしこれらの層の一つでもこれに参加せず、データベースにブロックするような呼び出しを行ったり、変更可能な共有状態に依存したり、高価な同期処理を行ったとすれば全てのパイプラインはとどこおり、ユーザは遅延の増大と拡張可能性の減少に苦しめられるだろう。

Page 225: Reactive Programming

アプリケーションは、その全体がリアクティブでなければならない。

この鎖の一番弱い環を取り除くことの必要性は、 Amadahl の法則に、よく表現されている。この法則は、 Wikipedia によれば次のように説明されている。

パラレル・コンピューティングで複数のプロセッサーを使ったプログラムのスピードアップは、そのプログラムのシーケンシャルな部分によって制限付けられる。例えば、プログラムの 95% が並列化されたとしても、パラレル・コンピューティングを使った理論上の最大のスピードアップは、次の図に示すように、どんなに多くのプロセッサーを使ったとしても、 20倍にとどまる。

Page 226: Reactive Programming

Amdahl's Law

Page 227: Reactive Programming

Scalable重要なこと “scalable” という言葉は、 Merriam-Webster によ

れば、次のように定義されている。 “要求に応じて、容易に拡張ないしは格上げが可能であること” .拡張可能なアプリケーションは、その利用に応じて拡張することが出来る。これは、アプリケーションに柔軟性を付加することで達成出来る。要求に応じてスケール・アウトまたはスケール・イン(ノードを追加または削除する)することが可能なオプションである。さらに、アーキテクチャは、アプリケーションの再デザインや書き直しなしで、スケール・アップまたはスケール・ダウン(ノードにより多くのあるいはより少ない CPU を配備する)することを容易にする。 柔軟性は、アプリケーションをクラウド環境で走らせるコストを最小化する。そして「使った分だけ払う」というモデルで、利益を得ることができる。

Page 228: Reactive Programming

拡張可能性はまたリスクを管理するのを助ける。ユーザの負荷に対してあまりにも少ないハードウェアしか提供しないのは、ユーザの不満足を引き起こし、顧客を失うことになる。逆に、理由もなく遊んでいる多くのハードウェアとオペレーションの要員を与えるのは、不必要な経費でしかない。拡張可能なソリューションは、使うにふさわしい新しいハードウェアを使うことが出来ずに、アプリケーションを使い続けるリスクを緩和する。 10 年以内には、我々は、ことに数千ではないにしろ数百のハードウェア・スレッドが走るプロセッサーを見ることになるだろう。こうした潜在的な可能性は、アプリケーションが、非常に細かな粒度のレベルでスケーラブルであることを要求している。

Page 229: Reactive Programming

Scalableキーとなる構成ブロック 非同期のメッセージ・パッシングに基づいたイベン

ト・ドリブンのシステムは、拡張可能性の基礎を提供する。コンポーネントとサブシステム間の疎結合と位置独立性は、同じセマンティックをもった同じプログラミング・モデルを維持したまま、システムを複数のノードにスケールアウトすることを可能にする。 コンポーネントのインスタンスを追加することで、システムのイベント処理の能力は増大する。実装に関して言えば、複数のコアを利用してスケール・アップすることと、データセンターやクラスターで沢山のノードを利用してスケール・アウトすることの間に違いはない。

Page 230: Reactive Programming

アプリケーションのトポロジーは、アプリケーションの利用に応じた配置やランタイムのアルゴリズムの採用を通じて表現される配備の決定になる。このことを、位置透過性と呼ぶ。

目標は、透過的な分散コンピューティング、分散オブジェクト、 RPC スタイルの通信を実装しようと試みることなどではないのだと理解することは重要である。こうしたことは以前に試みられ、そして失敗してきた。我々に必要なことは、非同期メッセージ・パッシングを通じたプログラミング・モデルで直接に表現されるネットワークを擁護することなのである。真の拡張可能性は、分散コンピューティングを自然に含み、そしてそこには、本質的に信頼出来ないと言っていい、ネットワークをまたぐことを意味するノード間の通信が含まれている。

Page 231: Reactive Programming

それゆえ、プログラミング・モデルの中で、物事を「簡単にする」という見落としの多い抽象の背後にそれらを隠すことなく、ネットワーク・プログラミングの制約やトレードオフや失敗のシナリオを明確にすることは重要である。結果として、分散環境で起きてくる典型的な問題を解決する為の共通の構成ブロックをカプセル化するツール – 高い段階の信頼性を提供する合意の形成やメッセージの抽象を与えるようなツールを提供することは、同じように重要なことである。

Page 232: Reactive Programming

Resilient重要なこと アプリケーションのダウンは、ビジネスに起きうる

もっともダメージの多い問題の一つである。通常の帰結は、オペレーションが単に止まっただけでも、収入の流れに穴があいたままになるということである。長い期間でみれば、それは顧客の不満と悪い評判につながって、ビジネスをもっと深刻に傷つけることになりかねない。アプリケーションの対障害性が、大部分では無視されたり、経験的なテクニックで対応されている要請であることは驚くべきことである。このことは、あまりに荒い粒度のツールを使うという粒度のレベルの間違いに基づいていることを意味する。

Page 233: Reactive Programming

実行時やサーバのエラーからの回復の為に、通常は、アプリケーション・サーバのクラスタリングの手法を用いる。不幸なことに、サーバのフェール・オーバーは、非常にコストがかかる、しかも危険なものである。それは、潜在的には、失敗の連鎖をおこして全てのクラスターの停止を招きかねない。コンポーネント・レベルの細粒度の耐障害性を利用して対応すべきことを、事故管理の間違ったレベルの粒度で対応しているというのは、こうした理由に基づく。

Merriam-Webster は、耐障害性を次のように定義している。 実体あるいはオブジェクトの、もとの形に戻ろう

とする能力。 困難からすぐに立ち戻る能力

Page 234: Reactive Programming

リアクティブ・アプリケーションでは、耐障害性は結果論ではなく、最初からデザインの一部である。失敗を、プログラミング・モデルの中で、第一級のクラスの構成物とすることは、それに反応しそれを管理する手段を提供することを意味する。それは、アプリケーションを、それらを実行時に修復し回復する能力を持たせることで、失敗に対して高い耐久性を持たせることになる。伝統的な障害の処理は、こうしたことを達成出来ない。なぜなら、それは、例外が発生した時にはいつでもどこでもそれを処理するか、あるいは、障害が起きたらアプリケーションの全てのインスタンスをフェールオーバーするかということで、小規模なものではあまりに防御的で、大規模なものにはあまりに攻撃的だからである。

Page 235: Reactive Programming

Resilientキーとなる構成ブロック 失敗を管理する為には、それが他の健全なコンポーネントに広がらないようにそれを隔離する手段と、また、失敗のコンテキストの外側の安全な地点からそれを観察する手段を必要とする。思い浮かぶ一つのパタンは、次の絵に示すような「隔壁」というパターンである。そこでは、システムはそれらに一つで事故が発生しても他の部分は影響を受けないように、安全な区域によって構成されている。これは、古典的な問題である事故の連鎖を防止し、管理の問題を隔離することを可能にする。

Page 236: Reactive Programming

拡張可能性を可能とするイベント・ドリブン・モデルは、事故管理のこのモデルを実現する為の必要な基本的な単位でもある。イベント・ドリブン・モデルの疎結合は、事故はそのコンテキストとともに補足されるとともに、メッセージとしてカプセル化され、他のコンポーネントに送られてエラー検知を可能にしそれにどう対応するか決定出来るように、完全に隔離されたコンポーネントを提供する。

Page 237: Reactive Programming

このアプローチは、ビジネス・ロジックはクリーンに残し、予期しなかったことの処理から分離したままで、事故は区分けされ観察され管理され、そして宣言的な仕方で処理されるようなシステム、そこでは、システムは自分自身を自動的に修復し回復出来るようなシステムを作り出す。それは、大きな企業では、問題はそれを処理する権限を持ったレベルの部署に到達するまで上層部に伝えられるのとほとんど同じように、区分けが階層的な仕方で構造化されていると最もうまく機能する。

このモデルの美しい点は、それが純粋にイベント・ドリブンで、リアクティブなコンポーネントと非同期のイベントに基づいており、それ故、位置通過的であることである。実践的には、このことは、分散環境においても、ローカルなコンテキストでの同じセマンティックでそれが動くことを意味する。

Page 238: Reactive Programming

Responsive重要なこと Responsive は、 Merriam-Webster によれば「応答が素早く、適切に反応すること」と定義されている。我々は、この言葉をそうした一般的な意味で用いる。それは、 Web デザインにおける Responsive Web Design と混同されてはならない。それは、もともとは、 CSS の media query とその改良・強化にかかわるものだ。

Responsive アプリケーションは、リアルタイムで魅力的で豊かで共同的なものだ。ビジネスはその顧客と、レスポンシブでインタラクティブな経験を通じて顧客を歓迎することで、オープンで進行する対話を作り出すことが出来る。

Page 239: Reactive Programming

それはビジネスをより効率的なものにし、人々はつながっていて問題を解決し課題を達成する手段を持っているという感覚を作り出す。一つの例が、 Google Doc である。 それはユーザがドキュメントを共同で編集することを可能とし、リアルタイムに、参加者が互いに編集やコメントを、書いたらすぐに生き生きと見ることが出来る。

イベントに反応するアプリケーションは、たとえ事故があったとしてもタイムリーな仕方でそれを行う必要がある。もし、アプリケーションが、別の言い方をすると遅延と見なされる、適切な時間の制約以内で反応しなかったら、それは実際には使い物にはならなくて、それ故、耐障害性を持つとは考えられなくなる。

Page 240: Reactive Programming

厳しい実時間システムの制約に応えることが出来ないことは、軍事や医療コントロールシステムのようなアプリケーションの場合には、システム全体の事故と見なされる。全てのアプリケーションが、こうした厳しい要請を持つ訳ではない。多くのアプリケーションは、応答時間の制約から外れると、急速に有用性が失われるのを見ることになる。例えば、金融トレーディングのアプリケーションは、タイムリーな応答なしには、現在の取引を失うことになる。

小売りやネット購買のような、主流のより多くのアプリケーションは、反応時間が遅くなるにつれ確実に有用性が落ち始める。ユーザが、レスポンシブなアプリケーションと相互作用すればするほど、購買のボリュームは増大する。

Page 241: Reactive Programming

Responsiveキーとなる構成ブロック リアクティブなアプリケーションは、 Observable

なモデルとイベント・ストリーム、クライアントの状態を利用する。

Observable モデルは、状態が変わった時に、他のシステムがイベントを受け取ることを可能とする。このことは、ユーザとシステムとのあいだにリアルタイムの接続を提供する。例えば、複数のユーザが同じモデルで同時に仕事をしていた時、変化は彼らの間でリアクティブに双方向に同期されうる。こうして、そのモデルはロックの制約なしに共有されているように見える。

Page 242: Reactive Programming

イベント・ストリームは、その上にこうした接続が構築される基本的な抽象を形成する。これらをリアクティブにすることは、ブロッキングを排除して、その代わりに、非同期でノンブロッキングな転送と通信を可能とする。

リアクティブ・アプリケーションは、デザイン・パターンとテストを利用してアルゴリズムの順序を守る。これによって負荷のいかんにかかわらずイベントへの応答が O(1) あるいは少なくとも O(log n)時間で返ることを保証する。このスケール因子には、顧客、セッション、製品、取引を含むことが出来るが、それに限られない。

Page 243: Reactive Programming

それらは、負荷のプロファイルのいかんにかかわらず応答の遅延を一定にするように、いくつかの戦略を利用している。

爆発的なトラフィックの条件下では、リアクティブ・アプリケーションは、遅延を一定のものに保つ為に、リソースをある了解と配慮の下で、結合したバッチ処理を適用して、 IO や同時並行でのデータの交換のような高価な処理を、後回しにする。

キューは適切なバックの圧力で制限されている。キューの長さは、与えられたレスポンスの制約条件の下で、 Little の法則を適用することで決定される。

システムは、その場で計画された適切な容量でモニターされる。

事故は、回路遮断機がトリガーされると、あらかじめ利用可能にされている代替処理戦略によって隔離される。

Page 244: Reactive Programming

レスポンシブ・アプリケーションの例として、ブラウザ・ベースであれモバイル・アプリであれ、魅力的なユーザ経験を作り出す、リッチ・クライアントの Web アプリを考えよう。このアプリケーションは、クライアント側でロジックを実行し状態を記憶しているしよう。 Observable モデルは、データが変更された時、リアルタイムでユーザ・インターフェースを変更するメカニズムを提供する。 WebSocket や Server-Sent-Event のような技術が、ユーザ・インターフェースを直接にプッシュされたイベント・ストリームに接続することを可能とする。こうして、イベント・ドリブン・システムは、バックエンドからクライアントにいたるまで、あらゆる方法で拡張される。このことが、リアクティブ・アプリケーションが、非同期でノン・ブロッキングなデータ転送を使って、ブラウザやモバイル・アプリに、スケーラブルで耐障害性を持ったやり方で、イベントをプッシュすることを可能とする。

Page 245: Reactive Programming

このことを心に留めておけば、いかにして四つの特質、イベント・ドリブン、拡張可能性、耐障害性、レスポンシブが、相互に関連し全体として密接に結びついていることは、明らかになる。

Page 246: Reactive Programming

結論 リアクティブ・アプリケーションは、ソフトウェア

開発の現代における幅広い挑戦に向けられたバランスの取れたアプローチを表現している。イベント・ドリブン、メッセージ・ベースの基礎の上に硬直されることで、それは拡張可能性と耐障害性を保証するのに必要なツールを提供している。これらの上に、それは豊かでレスポンシブなユーザ・インタラクションをサポートしている。我々は、この数年以内にこの青写真に従うシステムの数が、急速に増えていくことを期待している。

Page 247: Reactive Programming

参考資料

Meteor AngularJS polymer.js

Page 248: Reactive Programming

Meteor Concept

Structuring your app Data and security Reactivity Live HTML Templates

Page 249: Reactive Programming

Meteor アプリケーションの構造

Meteor アプリケーションは、クライアントの Webブラウザの内部で走る JavaScript と、 Node.js コンテナーの内部の Meteor サーバー上で走るJavaScript 、それにサポートされている全てのHTML フラグメントと CSS ルール、静的なアセットから構成される。

Meteor は、これらの異なるコンポーネントのパッケージングと連携を自動化する。ファイル・ツリーの中で、これらのコンポーネントに、どのような構造を選ぶかについては、 Meteor は、極めて柔軟である。

Page 250: Reactive Programming

Data and security

Page 251: Reactive Programming

In Memory DB Cache

全ての Meteor クライアントは、イン・メモリーのデータベース・キャッシュを持っている。

このクライアントのキャッシュを管理する為に、サーバーは、 JSON ドキュメントの集合を publishし、クライアントは、これらの集合に subscribeする。

集合内のドキュメントが変化すると、サーバーは、それぞれのクライアントのキャッシュを変更する。

Page 252: Reactive Programming

publish function

それぞれのドキュメントの集合は、サーバー上のpublish 関数によって定義される。

publish 関数は、新しいクライアントが、ドキュメントの集合に対して subscribe するたびに、実行される。

ドキュメントの集合の中のデータは、どこから来てもいいのだが、一般的な場合は、データベースのクエリーを publish することである。

Page 253: Reactive Programming

// server: publish all room documentsMeteor.publish("all-rooms", function () { return Rooms.find(); // everything);// server: publish all messages for a given roomMeteor.publish("messages", function (roomId) { return Messages.find({room: roomId});});

// server: publish the set of parties the logged-in user can see.Meteor.publish("parties", function () { return Parties.find({$or: [{"public": true}, {invited: this.userId}, {owner: this.userId}]});});

Page 254: Reactive Programming

subscribe

いったん subscribe されると、クライアントは、そのキャッシュを高速なローカル・データベースとして利用するので、劇的に、クライアントのコードは、単純化される。

Read は、サーバーへの高価な回り道を、要求されることはない。 そして、それらは、そのキャッシュの内容に限られている。クライアント上の集合中のドキュメント全てに対するクエリーは、サーバーがクライアントに publish したドキュメントを返すのみである。

Page 255: Reactive Programming

// client: start a parties subscriptionMeteor.subscribe("parties");

// client: return array of Parties this client can readreturn Parties.find().fetch(); // synchronous!

Page 256: Reactive Programming

allow/deny rule

クライアントが、いくつかのドキュメントを変更した時、クライアントはサーバーに、その変更を要求するメッセージを送る。

サーバーは、提案された変更を、 JavaScript の関数で書かれた allow/deny ルールに照らしてチェックする。

サーバーは、全てのルールをパスした変更のみを受け入れる。

Page 257: Reactive Programming

// server: don't allow client to insert a partyParties.allow({ insert: function (userId, party) { return false; }});

// client: this will failvar party = { ... };Parties.insert(party);

Page 258: Reactive Programming

データの更新と伝搬

サーバーが変更を受け付けると、サーバーは、データベースにその変更を適用して、影響を受けたドキュメントに subscribe していた他のクライアントに、その変更を、自動的に伝搬する。

もし、受け付けなかったら、更新は失敗する。サーバーのデータベースは、変わらないまま残り、他のクライアントは、誰も、更新を見ることはない。

Page 259: Reactive Programming

データの更新と伝搬

Meteor は、キュートなトリックも使う。クライアントがサーバーに対して書き込みをしようとした時、サーバーの返答を待つこと無しに、ローカルキャッシュをただちに書き換える。このことは、スクリーンは、ただちに再描画されることを意味する。

もし、サーバーが更新を受け付けた時、これは 、クライアントが正しく動作している時には、大部分の時間は、そうなるべきなのであるが、クライアントは、変化にただちにジャンプして、スクリーンを更新するのに、サーバーへの回り道を待つ必要がない。

Page 260: Reactive Programming

Reactivity

Page 261: Reactive Programming

Reactive Programming

Meteor は、 reactive programming のコンセプトを擁護する。このことは、コードを単純な命令スタイルで書くことを可能にし、その結果は、コードに従って、データが変更された時にはいつでも、自動的に再計算されることを意味する。

Page 262: Reactive Programming

reactive context この自動的な再計算は、 Session と

Meteor.autosubscribe の協調によって達成される。

Meteor.autosubscribe のようなメソッドは、” reactive context” を確立する。そのコンテキストの中で、データの従属性が追跡され、必要な時に、関数の引数を再実行するように準備している。

Session のような Data provider は、それに対して、 それらが呼び出されたコンテキストと、どのようなデータが要求されているかを意識して、データが変更された時、 invalidation シグナルを送るように準備している。

Page 263: Reactive Programming

reactive context + reactive data source

この reactive context + reactive data source という単純なパターンは、広い応用可能性をもっている。

それ以上に、プログラマーは、 unsubscribe/resubscribe の呼び出しのコードを書く手間が省け、それらは、正しい時に確実に呼び出されことになる

一般的に、 Meteor は、そうでなければ、誤りを犯しやすいロジックで、アプリケーションの邪魔になる、データ伝搬の全てのクラスを取り除くことが出来る、

Page 264: Reactive Programming

reactive-context

次の Meteor 関数は、コードを、 reactive-contextで走らせる。 Templates Meteor.render and Meteor.renderList Meteor.autosubscribe Meteor.autorun

Page 265: Reactive Programming

reactive data sources

変更をトリガーできる、 reactive data sources には、次のようなものがある。 Session variables Database queries on Collections Meteor.status Meteor.user Meteor.userId Meteor.userLoaded

Page 266: Reactive Programming

LiveHTML

Page 267: Reactive Programming

LiveHTML HTML templating は、 Web アプリの中心である。

Meteor のライブ・ページ更新技術で、 HTMLを、 reactive にレンダー出来る。それは、ページを生成するのに利用されたデータの変化を追跡して、自動的に更新が行われることを意味する。

この特徴は、全ての HTML テンプレート・ライブラリーで機能し、手で書かれた JavaScript で生成された HTML でも機能する。

Page 268: Reactive Programming

var fragment = Meteor.render( function () { var name = Session.get("name") || "Anonymous"; return "<div>Hello, " + name + "</div>"; });document.body.appendChild(fragment);

Session.set(“name”, “Bob”); // ページは自動的に更新される

LiveHTML の例

Page 269: Reactive Programming

Meteor.render()

Meteor.render は、 rendering function 、あるHTML を文字列として返すを関数を引数に取る。それは、自動更新する DocumentFragment を返す。

rendering function で利用されたデータに変更があったとき、それは、再実行される。 DocumentFragment 内の DOMノードは、ページのどの場所に挿入されていても、その場で自分自身を更新する。それは全く自動的である。

Meteor.render は、 rendering function によって、どのデータが利用されたかを発見する為にreactive context を使う。

Page 270: Reactive Programming

Template

Page 271: Reactive Programming

<head>  <title>Advanced Template Demo</title></head><body>  {{> page}}</body>

<template name="page">  <h1>Advanced Template Demo</h1>  <p>    This demo shows off the advanced features of Meteor's optional   </p>

  {{> preserveDemo }}  {{> constantDemo }}  {{> stateDemo }}  {{> d3Demo }}</template>

Page 272: Reactive Programming

<template name="preserveDemo">  <h2>Element preservation</h2>

  <input type="button" value="X++" class="x”>  ...</template>

<template name="constantDemo">  <h2>Constant regions</h2>

  <div>   <input type="button" value="X++" class="x"> <br>   <input type="checkbox" class="remove" which="1" {{checked 1}}>   Remove map 1<br>   <input type="checkbox" class="remove" which="2" {{checked 2}}>   Remove map 2  </div> ...

Page 273: Reactive Programming

<template name="hello"> <div class="greeting">Hello there, {{first}} {{last}}!</div></template>

// in the JavaScript console> Template.hello({first: "Alyssa", last: "Hacker"}); => "<div class="greeting">Hello there, Alyssa Hacker!</div>"

Meteor.render(function () { return Template.hello({first: "Alyssa", last: "Hacker"});}) => automatically updating DOM elements

Page 274: Reactive Programming

データベースへのクエリー

<template name="players"> {{#each topScorers}} <div>{{name}}</div> {{/each}}</template>

Template.players.topScorers = function () { return Users.find({score: {$gt: 100}}, {sort: {score: -1}});};

Page 275: Reactive Programming

// in a JavaScript fileTemplate.players.leagueIs = function (league) { return this.league === league;};

<template name="players"> {{#each topScorers}} {{#if leagueIs "junior"}} <div>Junior: {{name}}</div> {{/if}} {{#if leagueIs "senior"}} <div>Senior: {{name}}</div> {{/if}} {{/each}}</template>

Page 276: Reactive Programming

// Works fine with {{#each sections}}Template.report.sections = ["Situation", "Complication", "Resolution"];

<template name="scores"> {{#each player}} {{> playerScore}} {{/each}}</template><template name="playerScore"> <div>{{name}}: {{score}} <span class="givePoints">Give points</span> </div></template>

Template.playerScore.events({ 'click .givePoints': function () { Users.update({_id: this._id}, {$inc: {score: 2}}); }});

Page 277: Reactive Programming

Meteor Examples

Page 278: Reactive Programming

<head>  <title>Leaderboard</title></head>

<body>  <div id="outer">    {{> leaderboard}}  </div></body>

<template name="leaderboard">  <div class="leaderboard">    {{#each players}}      {{> player}}    {{/each}}  </div>

Page 279: Reactive Programming

  {{#if selected_name}}  <div class="details">    <div class="name">{{selected_name}}</div>    <input type="button" class="inc" value="Give 5 points" />  </div>  {{/if}}

  {{#unless selected_name}}  <div class="none">Click a player to select</div>  {{/unless}}</template>

<template name="player">  <div class="player {{selected}}">    <span class="name">{{name}}</span>    <span class="score">{{score}}</span>  </div></template>

Page 280: Reactive Programming

Players = new Meteor.Collection("players"); .......if (Meteor.isServer) {  Meteor.startup(function () {    if (Players.find().count() === 0) {      var names = ["Ada Lovelace",                   "Grace Hopper",                   "Marie Curie",                   "Carl Friedrich Gauss",                   "Nikola Tesla",                   "Claude Shannon"];      for (var i = 0; i < names.length; i++)        Players.insert({name: names[i],                  score: Math.floor(Math.random()*10)*5});    }  });}

Page 281: Reactive Programming

Players = new Meteor.Collection("players");

if (Meteor.isClient) {  Template.leaderboard.players = function () {    return Players.find({}, {sort: {score: -1, name: 1}});  };

  Template.leaderboard.selected_name = function () {    var player = Players.findOne(Session.get("selected_player"));    return player && player.name;  };

  Template.player.selected = function () {    return Session.equals("selected_player", this._id) ? "selected" : '';  }

Page 282: Reactive Programming

  Template.leaderboard.events({    'click input.inc': function () {      Players.update( Session.get("selected_player"), {$inc: {score: 5}});    }  });

  Template.player.events({    'click': function () {      Session.set("selected_player", this._id);    }  });}

Page 283: Reactive Programming

  Template.leaderboard.events({    'click input.inc': function () {      Players.update( Session.get("selected_player"), {$inc: {score: 5}});    }  });

  Template.player.events({    'click': function () {      Session.set("selected_player", this._id);    }  });}

Page 284: Reactive Programming

  Template.leaderboard.events({    'click input.inc': function () {      Players.update( Session.get("selected_player"), {$inc: {score: 5}});    }  });

  Template.player.events({    'click': function () {      Session.set("selected_player", this._id);    }  });}

Page 285: Reactive Programming

AngularJS Developer GuideConceptual Overview

http://docs.angularjs.org/guide/concepts

Page 286: Reactive Programming

Hello World デモ

<!doctype html><html ng-app> <head> <script src="http://code.angularjs.org/1.2.0rc1/angular.min.js">   </script> </head> <body> <p ng-init=" name='World' ">Hello {{name}}!</p> </body></html>

Page 287: Reactive Programming

Hello World Startup1. ブラウザーは、 HTML をロードして DOM にパーズする。2. ブラウザーは、 angular.js スクリプトをロードする。3. Angular は、 DOMContentLoaded イベントを待つ。4. Angular は、 ng-app directive を探す。それがアプリケー

ションの境界を指定する。5. ng-app で指定されたモジュールが、 $injector を構成する。6. $injector は、 $compile サービスと $rootScope を生成する

為に利用される。7. $compile サービスは、 $rootScope の元で、 DOM とリンク

をコンパイルする為に利用される。8. ng-init directive が、スコープの名前属性に「World」を割り当てる。

9. {{name}} が、表現式を「 Hello World!」に補完する。

Page 288: Reactive Programming
Page 289: Reactive Programming

Data Binding デモ

<!doctype html><html ng-app> <head> <script src="http://code.angularjs.org/1.2.0rc1/angular.min.js">   </script> </head> <body> <input ng-model="name"> <p>Hello {{name}}!</p> </body></html>

Page 290: Reactive Programming

コンパイル時

1. ng-model と input directiveは、 <input> コントロール上に、 keydown listener を設定する。

2. {{name}} 補完は、名前が変わった場合に、 $watch に通知がいくように設定される。

Page 291: Reactive Programming

実行時1. ‘X’ key が押されると、ブラウザーは input コントロールに

keydown イベントを発する。2. input directive は、 input の値の変化を捉えて、 Angular 実

行コンテキスト内のアプリケーション・モデルを変更する為に、 $apply(“name = ‘X’;”) を呼び出す。

3. Angular は、 name = ‘X’; をモデルに適用する。 4. $digest ループが始まる。5. $watch リストは、 name 属性の変化を検出すると、

{{name}} 補完に通知をして、それが、つづいて DOM を更新する。

6. Angular は実行コンテキストを抜け出す。それで、 keydownイベントは終わり、それとともに JavaScript の実行コンテキストも終わる。

7. ブラウザーは、更新されたテキストで、ビューを再描画する。

Page 292: Reactive Programming
Page 293: Reactive Programming

Controller デモ

Page 294: Reactive Programming

Controller デモ<!doctype html><html ng-app> <head> <script src="http://code.angularjs.org/1.2.0rc1/angular.min.js">   </script> <script src="script.js"></script> </head> <body> <div ng-controller="GreetCtrl"> Hello {{name}}! </div> <div ng-controller="ListCtrl"> <ol> <li ng-repeat="name in names">{{name}}</li> </ol> </div> </body></html>

Page 295: Reactive Programming

Controller デモ

function GreetCtrl($scope) { $scope.name = 'World';} function ListCtrl($scope) { $scope.names = ['Igor', 'Misko', 'Vojta'];}

.show-scope .doc-example-live.ng-scope,

.show-scope .doc-example-live .ng-scope { border: 1px solid red; margin: 3px;}

Page 296: Reactive Programming

Controller

controller は、 view の背後にあるコードである。その役割は、モデルを構築して、コールバック・メソッドにそって、それをビューに公開することである。

view は、 scope の template( HTML)上への投射である。

scope は、モデルを view につなげ、イベントを Controller に向けさせる「つなぎ」の役割を果たす。

Page 297: Reactive Programming

The separation of the controller and the view controller は、 JavaScript で書かれる。

JavaScript は命令型である。命令型は、アプリケーションの振る舞いを指定するには、もっとも適している。 controller は、( DOM への参照、 HTML の断片のような)レンダー用の情報を含むべきではない。

view template は HTML で書かれる。 HTML は宣言型である。宣言型は、 UI の指定に最適である。 view は、振る舞いを含むべきではない。

controller は view のことを知らないので、同一のcontoroller に対して複数の view があり得る。このことは、スキンの変更・デバイス特有の view(モバイルと PC)・テスト可能性に取って、重要である。

Page 298: Reactive Programming
Page 299: Reactive Programming

Model model は、 template とマージされて view を生み

出すデータである。 model が view にレンダーされる為には、 model は、 scope から参照されなければならない。

他の多くのフレームワークとは異なって、 Angularは、 model について何の制限も要請も設けてはいない。 model にアクセス、あるいは model を変更する為に、継承すべきクラスも、特別のアクセス・メソッドもない。

model は、プリミティブでも、オブジェクト・ハッシュでも、全くのオブジェクト型でも構わない。要するに、 model は、” plain JavaScript object” なのである。

Page 300: Reactive Programming
Page 301: Reactive Programming

View

view は、ユーザーが見るものである。 viewのライフサイクルは、 template として始まる。 view は、 model とマージされて、最終的には、ブラウザーの DOM にレンダーされる。

Angular は、他の大部分の template システムと比較して、全く異なるアプローチを採用している。

Angular の template システムは、文字列の上ではなく DOM オブジェクトの上で動く。template は確かに HTML で書かれているが、それは HTML である。

Page 302: Reactive Programming

View

ブラウザーは、 HTML をパーズして DOM にし、 DOM は、コンパイラーとして知られている templateエンジンの入力になる。

コンパイラーは、 directive を探して、それが Model上に watches を設定する。その結果は、 template model の再マージを必要としない連続的な view の更新になる。

Model は、 view にとって、ただ一つの真実のソースになる。

Page 303: Reactive Programming
Page 304: Reactive Programming

Module と Injector

Injector は、 Service Locator である。 Angular アプリケーションごとに、一つの

injector が存在する。 injector は、オブジェクトのインスタンスを名前で探す方法を提供する。

injector は、全てのオブジェクトを内部のキャッシュに保持し、同じ名前のオブジェクトを取得する為の呼び出しの繰り返しが、同じインスタンスを返すようにする。もし、オブジェクトが存在しなければ、その時はinjector は、インスタンス factory に、新しいインスタンスの生成を依頼する。

Page 305: Reactive Programming
Page 306: Reactive Programming

// Create a modulevar myModule = angular.module('myModule', []) // Configure the injectormyModule.factory('serviceA', function() { return { // instead of {}, put your object creation here };}); // create an injector and configure it from 'myModule'var $injector = angular.injector(['myModule']); // retrieve an object from the injector by namevar serviceA = $injector.get('serviceA'); // always true because of instance cache$injector.get('serviceA') === $injector.get('serviceA');

Page 307: Reactive Programming

// You write functions such as this one.function doSomething(serviceA, serviceB) { // do something here.} // Angular provides the injector for your applicationvar $injector = ...; ///////////////////////////////////////////////// the old-school way of getting dependencies.var serviceA = $injector.get('serviceA');var serviceB = $injector.get('serviceB'); // now call the functiondoSomething(serviceA, serviceB); ///////////////////////////////////////////////// the cool way of getting dependencies.// the $injector will supply the arguments to the function automatically$injector.invoke(doSomething); // This is how the framework calls your functions

Page 308: Reactive Programming

Time Example

<!doctype html><html ng-app="timeExampleModule"> <head> <script src="http://code.angularjs.org/1.2.0rc1/angular.min.js"> </script> <script src="script.js"></script> </head> <body> <div ng-controller="ClockCtrl"> Current time is: {{ time.now }} </div> </body></html>

Page 309: Reactive Programming

Time Exampleangular.module('timeExampleModule', []). // Declare new object called time, // which will be available for injection factory('time', function($timeout) { var time = {}; (function tick() { time.now = new Date().toString(); $timeout(tick, 1000); })(); return time; }); // Notice that you can simply ask for time// and it will be provided. No need to look for it.function ClockCtrl($scope, time) { $scope.time = time;}

Page 311: Reactive Programming

<head> <script src="mdv.js"></script></head><body> <h1>Model-driven Views</h1> <ul> <template id="greeting" repeat="{{ salutations }}"> <li>{{ what }}: <input type="text" value="{{ who }}"></li> </template> </ul><script>var t = document.getElementById('greeting');var model = { salutations: [ { what: 'Hello', who: 'World' }, { what: 'GoodBye', who: 'DOM APIs' }, { what: 'Hello', who: 'Declarative' }, { what: 'GoodBye', who: 'Imperative' } ]};t.model = model;</script></body>

Page 312: Reactive Programming

Template Instantiation MDV

<template bind="{{ singleton }}"> Creates a single instance with {{ bindings }}   when singleton model data is provided.</template>

<template repeat="{{ collection }}"> Will create maintain exactly instance with {{ bindings }} for every element in the array collection, when it is provided.</template>

bind

repeat

Page 313: Reactive Programming

Template Instantiation MDV

<template bind if="{{ conditionalValue }}"> Binds if and only if conditionalValue is truthy.</template>

<template if="{{ conditionalValue }}"> Binds if and only if conditionalValue is truthy. (same as *bind if*)</template>

<template repeat if="{{ conditionalValue }}"> Repeat if and only if conditionalValue is truthy.</template>

if

Page 314: Reactive Programming

Template Instantiation MDV

<template id="myTemplate"> Used by any template which refers to this one by the ref attribute</template>

<template bind ref="myTemplate"> When creating an instance, the content of this template will be ignored, and the content of #myTemplate is used instead.</template>

ref

// Causes any bind, repeat or if attribute directives on // #myTemplate to begin acting.document.getElementById('myTemplate').model = jsData;

Page 315: Reactive Programming

Node.bind() MDV

var obj = { path: { to: { value: 'hi' } }};

var textNode = document.createTextNode('test');textNode.bind('textContent', obj, 'path.to.value');

Page 316: Reactive Programming

Node.bind() MDVBinding types

Text nodestextNode.bind('textContent', someObj, 'path.to.value');

Element attribute valuesmyElement.bind('title', someObj, 'path.to.value');

Element attribute presencemyElement.bind('hidden?', someObj, 'path.to.value');

Input element value and checked propertiesmyValueInput.bind('value', someObj, 'path.to.value');myCheckboxOrRadioInput.bind('checked', someObj, 'path.to.value');