响应式编程及框架

44
Reactive Programming and Framework Zhao Jie - SNDA - Sep. 2010

Upload: jeffz

Post on 10-May-2015

2.960 views

Category:

Technology


0 download

DESCRIPTION

Largely inspired by (and stealed from) Erik's talk at Mix10.

TRANSCRIPT

Page 1: 响应式编程及框架

Reactive Programming and FrameworkZhao Jie - SNDA - Sep. 2010

Page 2: 响应式编程及框架

About me

赵劼 / 老赵 / Jeffrey Zhao / 赵姐夫

日写代码三百行,不辞长作程序员

Blog: http://blog.zhaojie.me/

Twitter: @jeffz_cn

F#, Scala, JavaScript, Python, .NET, mono...

Java (as the language) hater

Page 3: 响应式编程及框架

What?

Fundamentally change the way you think about coordinating and

orchestrating asynchronous and event-based programming

Page 4: 响应式编程及框架

Why?

Because the essence ofCloud, Web, Mobile

is asynchronous computations

Page 5: 响应式编程及框架

How?

By showing that asynchronous and event-base computations are just

push-based collections

Page 6: 响应式编程及框架

Interactive & Reactive

Page 7: 响应式编程及框架

a := b + c

Page 8: 响应式编程及框架

Environment

Program

Interactive Reactive

Page 9: 响应式编程及框架

Let’s implement both interfaces with...

Page 10: 响应式编程及框架
Page 11: 响应式编程及框架

Enumerable Collections

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

interface  IEnumerator<out  T>{        bool  MoveNext();        T  Current  {  get;  }}

Page 12: 响应式编程及框架

EnumeratorGetEnumerator()

1

MoveNext()2

true/falseConsumer pulls

successive elements from the collection

3

Current

Page 13: 响应式编程及框架

interface  IEnumerable<out  T>{        //  void  -­‐>  enumerator        IEnumerator<T>  GetEnumerator();}

interface  IObservable<out  T>{        //  observer  -­‐>  void        IDisposable  Subscribe(IObserver<T>  o)}

Dualize Enumerable Collections

Page 14: 响应式编程及框架

Dualize Enumerable Collections

interface  IEnumerator<out  T>{        bool  MoveNext();  //  void  -­‐>  bool        T  Current  {  get;  }  //  void  -­‐>  T        //  throws  Exception}

interface  IObserver<in  T>{        void  OnCompleted(bool  done);  //  bool  -­‐>  void        T  Current  {  set;  }  //  T  -­‐>  void        void  OnError(Exception  ex);  //  accepts  Exception}

Page 15: 响应式编程及框架

Observable Collections

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

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

Page 16: 响应式编程及框架

ObserverSubscribe(o)

1

OnCompleted()

3

XProducer pushes

successive elements from the collection

2

OnNext(e)

Page 17: 响应式编程及框架

IEnumerable & IEnumerator areprototypical interfaces for interactive collections and interactive programs.

IObservable & IObserver are prototypical interfaces for observable collections and reactive, asynchronous & event-based programs.

Page 18: 响应式编程及框架

Iterator

Observer

Page 19: 响应式编程及框架

Iterator / ObserverPatterns in Java

class  Observable  {        void  addObserver(Observer  o);

       void  deleteObserver(Observer  o);        void  deleteObservers();        int  countObservers();        void  notifyObservers();        void  notifyObservers(Object  arg);        void  setChanged();        void  clearChanged();        boolean  hasChanged();}

interface  Observer  {        void  update(Observable  o,  Object  arg);}

interface  Iterable<T>  {        Iterator<T>  iterator();}

interface  Iterator<T>  {        T  next();

       boolean  hasNext();        void  remove();}

Page 20: 响应式编程及框架

LINQ to Observable

Page 21: 响应式编程及框架

If you are writingLINQ or declarative codein an interactive program...

LINQ to Observable

Page 22: 响应式编程及框架

If you are writingLINQ or declarative codein an interactive program...

You already know how to use it!

LINQ to Observable

Page 23: 响应式编程及框架

... the principle we go by is, don't expect to see a particular concurrency model put into C# because there're many different concurrency model ... it's more about finding things are common to to all kinds of concurrency ...

- Anders Hejlsberg

Page 24: 响应式编程及框架

... the principle we go by is, don't expect to see a particular concurrency model put into C# because there're many different concurrency model ... it's more about finding things are common to to all kinds of concurrency ...

- Anders Hejlsberg

Page 25: 响应式编程及框架

LINQ to Object

Standard query operatorsSelectWhereSelectMany...

Extended query operatorsZipAggregate...

Page 26: 响应式编程及框架

LINQ to Observable

Standard query operatorsSelectWhereSelectMany...

Extended query operatorsZipThrottle...

Page 27: 响应式编程及框架

How to move a ball by keyboard (ASDW)?

Page 28: 响应式编程及框架

Imperative Impl.void  OnKeyPress(object  sender,  KeyPressEventArgs  e){        if  (isPlaying)        {                if  (e.KeyChar  ==  'a'  &&  ball.Left  >  0)                {                        ball.Left  -­‐=  5;                }                else  if  (e.KeyChar  ==  'w'  &&  ball.Top  >  0)                {                        ball.Top  -­‐=  5;                }                else  ...        }        else  ...}

Page 29: 响应式编程及框架

Declarative Impl.//  filter  the  KeyPress  events  when  playingvar  keyPress  =  GetKeyPress().Where(_  =>  isPlaying);

//  filter  the  events  to  move  leftvar  moveLeft  =  from  ev  in  keyPress                              where  ev.EventArgs.KeyChar  ==  'a'                              where  ball.Left  >  0                              select  ev;moveLeft.Subscribe(_  =>  ball.Left  -­‐=  5);

//  filter  the  events  to  move  topvar  moveTop  =  from  ev  in  keyPress                            where  ev.EventArgs.KeyChar  ==  'w'                            where  ball.Top  >  0                            select  ev;moveTop.Subscribe(_  =>  ball.Top  -­‐=  5);

Page 30: 响应式编程及框架

Mouse drag and draw

Page 31: 响应式编程及框架

var  mouseMove  =  GetMouseMove();var  mouseDiff  =  mouseMove.Zip(mouseMove.Skip(1),        (prev,  curr)  =>  new        {                PrevPos  =  new  Point(                        prev.EventArgs.X,  prev.EventArgs.Y),                CurrPos  =  new  Point(                        curr.EventArgs.X,  curr.EventArgs.Y)        });

var  mouseDrag  =  from  _  in  GetMouseDown()                                from  diff  in  mouseDiff.TakeUntil(GetMouseUp())                                select  diff;

mouseDrag.Subscribe(d  =>  DrawLine(d.PrevPos,  d.CurrPos));

Page 32: 响应式编程及框架

Everything in Web is Asynchronous

User actions

AJAX requests

Animations

...

Page 33: 响应式编程及框架

Reactive Framework in JavaScript

A full featured port for JavaScriptEasy-to-use conversions from existing DOM, XmlHttpRequest, etcIn a download size of less than 7kb (gzipped)

Bindings for various libraries / frameworksjQueryMooToolsDojo...

Page 34: 响应式编程及框架

Mouse drag and drawin JavaScript

Page 35: 响应式编程及框架

var  target  =  $("#paintPad");var  mouseMove  =  target.toObservable("mousemove");var  mouseDiff  =  mouseMove.Zip(mouseMove.Skip(1),          function(prev,  curr)  {                return  {                        prevPos:  {  x:  prev.clientX,  y:  prev.clientY  },                        currPos:  {  x:  curr.clientX,  y:  curr.clientY  }                };        });

var  mouseDown  =  target.toObservable("mousedown");var  mouseUp  =  target.toObservable("mouseup");var  mouseDrag  =  mouseDown.SelectMany(function()  {        mouseDiff.TakeUntil(mouseUp);});

mouseDrag.Subscribe(        function(d)  {  drawLine(d.prevPos,  d.currPos);  });

Page 36: 响应式编程及框架

Wikipedia lookup

Page 37: 响应式编程及框架

var  textBox  =  $("#searchInput");var  searcher  =  textBox        .toObservable("keyup")        .Throttle(500)        .Select(function(_)  {  return  textBox.val();  })        .Select(function(term)  {  return  queryWikipedia(term);  })        .Switch();

searcher.Subscribe(        function(data)  {                var  results  =  $("#results");                results.empty();                $.each(data,  function(_,  value)  {                        results.append($("<li/>").text(value));                });        },        function(error)  {  $("#error").html(error);  });

Page 38: 响应式编程及框架

Time flies like an arrow

Page 39: 响应式编程及框架

var  container  =  $("#container");var  mouseMove  =  container.toObservable("mousemove");

for  (var  i  =  0;  i  <  text.length;  i++)  {        (function(i)  {

               var  ele  =  $("<span/>").text(text.charAt(i));                ele.css({position:  "absolute"}).appendTo(container);

               mouseMove.Delay(i  *  100).Subscribe(function  (ev)  {                        ele.css({                                left:  ev.clientX  +  i  *  20  +  15  +  "px",                                top:  ev.clientY  +  "px"                        });                });

       })(i);

Page 40: 响应式编程及框架

Benefits of Rx

Easy to composite and coordinate async operations

Easy to express the algorithm (code locality)

Easy to be unit tested

...

Page 41: 响应式编程及框架

Rx & Language Features

Features in C# that Rx usesExtension methodLambda expression & closureType inferenceLINQ query expression

Rx has been implemented in ...C# & VBJavaScriptF#

Page 42: 响应式编程及框架

Port to other Languages

Rx can be easily ported to various languagesScalaRubyPythonmodern languages with basic functional features

Almost impossible to implement Rx in JavaCannot extend a type without breaking codeMissing enough functional features

Page 44: 响应式编程及框架

Q & A