Upload
vadym-khondar
View
35
Download
0
Embed Size (px)
Citation preview
1SEC-2015
Reactive programmingevery day
2SEC-2015
Who am I?
Vadym Khondar
Senior Software engineer 8 years experience 2.5 years with EPAMDevelopment team leadWeb, JavaScript, Java
3SEC-2015
Goals
Why to useWhat is
How to usereactive programming
4SEC-2015
Why?
5SEC-2015
Evolution of Internet
938 millions in June, 20043,035 millions in June, 2014
http://www.internetworldstats.com/emarketing.htm
1,440 millions in May, 2015
6SEC-2015
Evolution of expectations
• You see response to your actions quite quickly• You don’t notice if something breaks• You can collaborate• You have everything you need at the place you are
7SEC-2015
1995 1997 1999 2001 2003 2005 2007 2009 2011 2013 2015
Evolution of challenges
Tens of servers
Seconds of response time
Hours of offline maintenance
Gigabytes of data
Millisecond response times
100% uptime
Cloud
Mobile devices
Internet of Things
8SEC-2015
Definition of reactive system
Reactive Systems are:
• Message-driven (react to events)• Elastic (react to load)• Resilient (react to failures)• Responsive (react to users)
http://www.reactivemanifesto.org/
9SEC-2015
Why those qualities?
Responsive
Resilient
Message-Driven
Elastic
Loose couplingLocation transparency
Responsive irrespectively to load Responsive irrespectively to failures
Asynchronous
10SEC-2015
So, if you still don’t
11SEC-2015
Tasks
We want our UI to not block.
We want our backend to not block.
* where it should not block
12SEC-2015
Reduce network latency influence
13SEC-2015
Events
14SEC-2015
Plain Old Observer pattern
15SEC-2015
1. Encapsulation principle may be violated
2. Separation of concerns principle may be violated
3. Not easily composable
4. Inversion of control
Observer pattern problems
16SEC-2015
$(function() { var currentWord = '';
$('#textin').keypress(function(event) { var key = String.fromCharCode(event.keyCode || event.charCode);
if (!key.match(/[\w]/) && currentWord) { var link = 'https://twitter.com/hashtag/' + currentWord;
$('#textout').append($(' ')).append( $('<a/>').attr('href', link).text('#' + currentWord) );
currentWord = ''; } else if (key) { currentWord += key; } });});
Example: Hash tagger
State
Mixing logic with presentation
No easy way to compose with another handler of keypress
17SEC-2015
Callback hellpublic class ReportsEntryPoint { @Override public void onModuleLoad() { String documentIdString = Window.Location.getParameter("docId"); if (documentIdString != null && !documentIdString.isEmpty()) { try { final Long documentId = Long.parseLong(documentIdString); MainService.Util.getInstance().findReport(documentId, new AsyncCallback<ReportDto>() { // Getting Report information first @Override public void onSuccess(ReportDto result) { final ReportDto processedReport = result; MainService.Util.getInstance().getUserInfo(processedReport.getUserId(), processedReport.getCompanyId(), new AsyncCallback<UserCompanyDto>() { // Getting user information for future form initialization @Override public void onSuccess(UserCompanyDto result) { UserDataHolder.getInstance().setUserCompanyDto(result); MainService.Util.getInstance().getDProfile(processedReport.getCompanyId(), new AsyncCallback<DProfileDto>() { // Getting company profile for future form initialization @Override public void onSuccess(DProfileDto result) { UserDataHolder.getInstance().setDProfileDto(result); MainService.Util.getInstance().getPProfile(processedReport.getCompanyId(), new AsyncCallback<PProfileDto>() { // Getting company profile for future form initialization @Override public void onSuccess(PProfileDto result) { UserDataHolder.getInstance().setPProfileDto(result); MainService.Util.getInstance().getFormDto(processedReport, new AsyncCallback<FormDTO>() { // Getting report document form @Override public void onFailure(Throwable caught) { Window.alert("Can't get document: " + caught.getMessage()); ReportEditorEntryPoint.windowClose(); } @Override public void onSuccess(FormDTO result) { if (result == null) { Window.alert("Can't get document."); ReportEditorEntryPoint.windowClose(); return; }
// -- some code to process if finally everything is ok! } })
http://callbackhell.com
18SEC-2015
Goods
// handling single valueOptional<Double> amount = Optional.of(1.0);int roundedAmount = amount.orElse(2.0).intValue();
// handling multiple valuesStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15).filter(i -> i % 2 == 0).skip(1).limit(2).forEachOrdered(System.out::println);
19SEC-2015
List<String> yellowFruits = new LinkedList<>();for (String fruit : fruits) { if (fruit.toLowerCase().contains("yellow")) { yellowFruits.add(fruit); }}
Collections.sort(yellowFruits);
for (String fruit : yellowFruits) { System.out.println(fruit);}
fruits.stream() .filter(f -> f.toLowerCase().contains("yellow")) .sorted() .forEach(System.out::println);
20SEC-2015
But…
Pulling
Pushing
21SEC-2015
22SEC-2015
Definition
Reactive programming is paradigm oriented around data flows and propagation of change.
http://en.wikipedia.org/wiki/Reactive_programming
23SEC-2015
Reactive programming approach
Provide handy abstractions:
• Events and Event streams
• Behaviors
24SEC-2015
Event stream transformation
‘E’ pressed ‘a’ pressed
69 97
map()
•e -> e.charCode
25SEC-2015
combine() – stream containing events from either combined streams
concat() – stream containing items of first stream and then of another stream
Stream transformation
map(Type1 => Type2) – stream of values from given function applied to each element in source streamfilter(Type => Boolean) – stream of values from source stream for which given function returns Truereduce((Type1, Type2) => Type1) (or scan(Fn, seed)) – stream of single value which is result of applying given function to element in source stream and result of previous call to given functionskip(num) – stream produced from source stream by skipping num elements
take(num) – stream produced from source stream by taking num first elements
Transforming
Combining
26SEC-2015
Example: Hash tagger reactive
No global state
Clear separation of concerns
Declarative description
$(function () { var keyStream = Rx.Observable.fromEvent($('#textin'), 'keypress') .map(function (event) { return String.fromCharCode(event.keyCode || event.charCode); }); var endOfWordStream = keyStream.filter(function (char) { return !String(char).match(/[\w]/); }); var wordStream = keyStream.buffer(endOfWordStream);
var uiUpdater = Rx.Observer.create(function (word) { word = word.join('').trim(); var link = 'https://twitter.com/hashtag/' + word;
$('#textout').append($(' ')).append( $('<a/>').attr('href', link).text('#' + word) ); });
wordStream.subscribe(uiUpdater);});
Composable API
27SEC-2015
Behavior (Signal)
Behaviors are used to express continuous dependency between values.They are often referred to as function from time domain to value domain.They are also called signals or properties.
Example: 90 - minute x 6 angle of minute
arrow on the clock
28SEC-2015
Signal <> Event
29SEC-2015
Example: Arkanoid
30SEC-2015
Example: Arkanoid – using property for mouse control
// some constantsvar canvasLeft = $('#gamecanvas').offset().left + window.screenX;var canvasRight = canvasLeft + $('#gamecanvas').width();var canvasMid = (canvasRight + canvasLeft) / 2;// define event stream for mouse movementvar mousePos = $('html') .asEventStream('mousemove') .map(function (event) { return {x: event.screenX, y: event.screenY}; });// define paddle position as a property in terms of mouse – stateless computationvar vausPos = mousePos.map(function (canvasLeft, canvasMid, canvasRight, coords) { return ((coords.x < canvasLeft || coords.x > (canvasRight - 40)) ? (coords.x < canvasMid ? canvasLeft : (canvasRight - 40)) : coords.x) - canvasLeft;}, canvasLeft, canvasMid, canvasRight).toProperty();// tie property to presentationvausPos.assign($('#vaus'), 'css', 'left');
31SEC-2015
Futures and promises
Promise Future
Deferred PromiseJavaScript
Scala
CompletableFutureJava 8
Single write Multiple read
32SEC-2015
Producer Consumer
import scala.concurrent.{ future, promise }import scala.concurrent.ExecutionContext.Implicits.globalval p = promise[T]val f = p.future
val producer = future { // async val r = produceSomething() p success r // completion of future scontinueDoingSomethingUnrelated()}
val consumer = future { // async startDoingSomething() f onSuccess { // what to do on completion case r => doSomethingWithResult() }}
33SEC-2015
Single item Many itemsPull/Synchronous
OptionalIterator/Iterable
Push/Asynchronous
FutureObserver/
Observable
34SEC-2015
Reactive programming
Benefits
• gives you a base for creating reactive systems
• gives you means of handling async in more elegant way
• stimulates you to write more concise code
Drawbacks
• might be harder do debug
35SEC-2015
36SEC-2015
Think abouthow data should flow
instead ofwhat you do to make it flow
37SEC-2015
Designing your API consider making it asynchronous
38SEC-2015
Get acquainted with functional programming
39SEC-2015
• Rx JS (http://reactivex.io/) – Observable on steroids• Bacon.js (https://baconjs.github.io/) – EventStreams and
Properties (behaviors)• Kefir.js (https://rpominov.github.io/kefir/) - inspired by
Bacon.js and RxJS with focus on high performance and low memory usage
Tools - Frontend
40SEC-2015
• Java 8 (hello to Streams, lambdas, CompletableFuture)• Scala (gives a good taste of functional paradigm while
letting you have old habits)• RxJava (https://github.com/ReactiveX/RxJava/)
Tools - Backend
41SEC-2015
References• http://en.wikipedia.org/wiki/Reactive_programming• http://en.wikipedia.org/wiki/Dataflow_programming• http://www.reactivemanifesto.org/• https://github.com/Reactive-Extensions/RxJS• https://baconjs.github.io/• What does it mean to be reactive by Erik Meijer https://
www.youtube.com/watch?v=sTSQlYX5DU0• http
://www.infoq.com/presentations/Netflix-API-rxjava-hystrix/• https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
42SEC-2015
43SEC-2015
Code Presentation
https://goo.gl/BlJSCy http://goo.gl/suJ2Xg