2. 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”
3. 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”
4. 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”
8. Agenda Part I
WebとReactiveプログラミング
非同期とイベント・ドリブンへの志向
Web UIとReactiveプログラミング
Meteor
AngularJS
Dart
Polymer.dart
9. Agenda Part II
Reactive Extensionの基礎
LINQとEnumerable
RxとObservable
Observableを使ったEvent処理
Rx for JavaScript
Observableを使った非同期処理
AndroidとRx
10. Agenda Part III
Observableを活用する
Observableのストリームを処理する
Observableを変形・加工する合成可能な
関数
ServerサイドでのRxの事例 Netflix
NetflixでのObservableの利用
11. Agenda
Part IV
Reactive Manifesto
The Need to Go Reactive
Reactive Applications
Event-driven
Scalable
Resilient
Responsive
Cocclusion
36. Libuv
libuv enforces an asynchronous, eventdriven 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.
37. ―Brief Hisory of Node.js‖
Ben Noordhuis
http://vimeo.com/51637038
38. ―An Introduction to libuv‖
Nikhil Marathe
November 10, 2013 Release 1.0.0
http://nikhilm.github.io/uvbook/An%
20Introduction%20to%20libuv.pdf
42. 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/callbackhell-in-nodejs
In below code am I in callbackhell? How to
overcome such scenario without using any
async modules in pure javascript?
47. Meteor LiveHTML
var fragment = Meteor.render(
function () {
var name = Session.get("name") || "Anonymous";
return "<div>Hello, " + name + "</div>";
});
document.body.appendChild(fragment);
Session.set(“name”, “Bob”);
// ページは自動的に更新される
59. MDV templates in Dart
https://www.dartlang.org/articles/we
b-ui/#one-way-binding
60. 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
70. 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.
71. 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.
80. 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スタイルの検索操作を利
用して構成する為のライブラリーである。」
81. 講演資料
2010年 11月 DevCamp Keynote
―Rx: Curing your asynchronous
programming blues‖
http://channel9.msdn.com/Blogs/codefest/DC2010T010
0-Keynote-Rx-curing-your-asynchronous-programmingblues
2012年 6月 TechEd Europe
―Rx: Curing your asynchronous
programming blues‖
http://channel9.msdn.com/Events/TechEd/Europe/2012/
DEV413
89. LINQでは、検索式の中にラムダ式を利用出来る
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);
}
90. SelectMany (多段のSelect)
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);
}
91. SelectMany (多段のSelect)
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);
92. SelectMany (多段のSelect)
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 };
93. 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) Words that start with the letter 'b':
blueberry
{
banana
Console.WriteLine(w);
Words that start with the letter 'c':
chimpanzee
}
cheese
}
Words that start with the letter 'a':
abacus
apple
112. 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");
}
);
113. 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
114. 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
127. // IObservable<string> from TextChanged events
var 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 service
var svc = new DictServiceSoapClient();
var lookup =
Observable.FromAsyncPattern<string,DictionaryWord[]>
(svc.BeginLookup, svc.EndLookup);
// Compose both sources using SelectMany
var res = from term in input
from words in lookup(term)
select words;
128. 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);
} );
129. 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;
130. Functional Reactive
Programming on Android
With RxJava
http://mttkay.github.io/blog/2013/08
/25/functional-reactiveprogramming-on-android-withrxjava/
202. String s = getData(args);
if (s.equals(x)) {
// do something
} else {
// do something else
}
scalarを返り値に持つ、典型的な同期型 getData()のコード
203. Iterable<String> values = getData(args);
for (String s : values) {
if (s.equals(x)) {
// do something
} else {
// do something else
}
}
scalar値が返る場合とほとんど同じだが、処理はループする
204. Future<String> s = getData(args);
if (s.get().equals(x)) {
// do something
} else {
// do something else
}
古いJavaのFutureコード。非同期だが、getでブロックする。
205. 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をつかった非同期のコード・サンプル
206. Observable<String> s = getData(args);
s.map({ s ->
if (s.get().equals(x)) {
// do something
} else {
// do something else
});
Observableを使ったgetData()のコード・サンプル
207. 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/
253. // server: publish all room documents
Meteor.publish("all-rooms", function () {
return Rooms.find(); // everything
);
// server: publish all messages for a given room
Meteor.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}]});
});
257. // server: don't allow client to insert a party
Parties.allow({
insert: function (userId, party) {
return false;
}
});
// client: this will fail
var party = { ... };
Parties.insert(party);
Speaker tips:We want to solve the asynchronous problem, so let’s first look at something extremely synchronous.Everyone should know IEnumerable<T>… Why synchronous?First, let’s not care about Reset which is a historical thing (notice that iterators even don’t bother to implement it).Look at the words: Get (= beg to get something), Move (= ask for something to happen).C# 4.0 variance indicates how information flows: you have to drag the data out of the source.Implication: you can get stuck (e.g. your favorite SQL Server on the other side of the world is taking a nap).
Speaker tips:Summary slide to drive concept home:Use comparison with enumerable interfaces here!Instead of begging for an enumerator, you now give the source an observer…Data flow is reversed:A value of type T is given to you……reflected as input and hence contravariance in C# 4.0Implication:Getting stuck in enumerators means getting too little……which is dual to getting too much or getting flooded for observers!Can compare to subscribing to a news paperWhen calling subscribe:You give the address of your letter box (the observer)You get a way to undo the subscription in the future (the IDisposable is like a letter to cancel the subscription)Asynchronous nature! You’re not blocked till the next news paper arrives.The observer is the letter box:OnNext happens when the postman drops the newsletter in itOnError happens when someone bombs your letter box or the postman drops deadOnCompleted happens when the newspaper publisher goes bankrupt
Speaker tips:The essential difference is who controls how the data is received.Philosophically this is nothing but how the application and the environment work together.Looking from the application’s point of view:Does it ask the environment – interactively – for data? enumerableDoes it passively wait for the environment to send data and react to it? observableBoth are complementary models. One doesn’t (aim to) replace the other.Matter of which one aligns more closely to which model:SQL’ s TDS protocol is pull-based, hence IE<T> is the best fit.Stock broker services may be push-based, hence IO<T> is a better match.Will see how one can convert between those.
Speaker tips:Ask the audience about the pain of asynchronous method patternsWonder about any of the clouds that will pop up later…Same problems as with eventsHave to see the EndXXX signature to see the result type of the operationIn fact, for the sample, even the byte[] is not the real result (EndRead returns the number of bytes read…)Passing such a “pattern” around is hardReally need to pass two methods, maybe a Tuple<T1,T2> with two Func delegates? AarrghSame problem as with the GPS sensor sample – can’t abstract over itEmphasize interfaces help to save the mission – IObservable<T> can abstract over events, asynchronous methods, etc…Composition again lacksEveryone has to write code in the callback to do common operationsCode runs off the screen due to the continuous indentation (especially when trying to compose with another asynchronous call inside the callback of the first one!)
Speaker tips”FromAsyncPattern just like FromEventGive us what you’d be doing otherwiseHere we need two delegatesSignature requires some explanationFirst inputs (as on BeginXXX method), then output (comes from EndXXX method)Result is a function that takes the BeginXXX inputs……but returns an IObservable around the resultNow we can do composition (refer to later)
Speaker tips:Time to connect up the textbox to the listbox, using the web serviceUse types something after projection really a sequence of string valuesNow we want to compose this with a web service callAnd stay asynchronous throughout the entire composition!!!Notice we’ll want to reduce the number of calls triggered by the userAssume every call costs money ($$$ on arrow)What if the user types fast?What if the user enters duplicates?Will see how to tackle those concerns in the demo…After composition we should get an observable with wordsBut can throw an error too!!!Finally we do data binding on the UI thread ObserveOn as we saw before (messages will come to us from the background thread of the service callback)
Speaker tips:How to do composition?Skip over the input code quicklyWe’ll talk about this in the demoHint at DistinctUntilChanged and Throttle (recall the $$$ aspect from previous slide)Recall how we bridged with the web service, no surprises hereNote: slightly simplified code here (see HOL), e.g. “wn” and “prefix” are omittedWhat matters is SelectManyHow would you query suppliers across different products?Recall Northwind scheme in SQL…Use of two from clauses is some kind of join reallyEffect shows how C# translates this syntax in a call to SelectMany
Speaker tips:How to do composition?Skip over the input code quicklyWe’ll talk about this in the demoHint at DistinctUntilChanged and Throttle (recall the $$$ aspect from previous slide)Recall how we bridged with the web service, no surprises hereNote: slightly simplified code here (see HOL), e.g. “wn” and “prefix” are omittedWhat matters is SelectManyHow would you query suppliers across different products?Recall Northwind scheme in SQL…Use of two from clauses is some kind of join reallyEffect shows how C# translates this syntax in a call to SelectMany
Speaker tips:How to do composition?Skip over the input code quicklyWe’ll talk about this in the demoHint at DistinctUntilChanged and Throttle (recall the $$$ aspect from previous slide)Recall how we bridged with the web service, no surprises hereNote: slightly simplified code here (see HOL), e.g. “wn” and “prefix” are omittedWhat matters is SelectManyHow would you query suppliers across different products?Recall Northwind scheme in SQL…Use of two from clauses is some kind of join reallyEffect shows how C# translates this syntax in a call to SelectMany