Successfully reported this slideshow.
Your SlideShare is downloading. ×

Rx: Curing Your Asynchronous Programming Blues | QCon London

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad

Check these out next

1 of 58 Ad

Rx: Curing Your Asynchronous Programming Blues | QCon London

Download to read offline

At Microsofts Professional Developers Conference (PDC) a few years back, we introduced the LINQ project to solve the impedance mismatch between various data models by means of integrated query syntax in mainstream programming languages. Today, we’re seeing a rich ecosystem around LINQ providers that allow developers to reach out to many more data sources. However, there’s a lot of opportunity left to democratize even more data models. Based on the theory of monads, we’ll explore the incredibly powerful nature of query comprehensions to build reactive queries.

Asynchronous, event-driven "reactive" programming is way too hard in today's world of development tools and frameworks. The huge amount of manual and error-prone plumbing leads to incomprehensible and hard to maintain code. As we reach out to services in the cloud, the desire for asynchronous computation is ever increasing, requiring a fresh look on the problems imposed by reactive programming. Centered around the concept of observable data sources, Rx provides a framework that takes care of the hard parts of reactive programming. Instead of focusing on the hard parts, you now can start dreaming about the endless possibilities of composing queries over asynchronous data sources, piggybacking on convenient LINQ syntax.

In this session, we'll cover the design philosophy of Rx, rooted on the deep duality between the interactive IEnumerable interface and the new reactive IObservable interface in .NET 4.

From this core understanding, we'll start looking at various combinators and operators defined over observable collections, as provided by Rx, driving concepts home by a bunch of samples. Finally, if time permits, we'll look at the Reactive Extensions for JavaScript which allows us to take the concepts we already know from Rx and apply them to JavaScript and have deep integration with libraries such as jQuery. Democratizing asynchronous programming starts today. Don't miss out on it!

At Microsofts Professional Developers Conference (PDC) a few years back, we introduced the LINQ project to solve the impedance mismatch between various data models by means of integrated query syntax in mainstream programming languages. Today, we’re seeing a rich ecosystem around LINQ providers that allow developers to reach out to many more data sources. However, there’s a lot of opportunity left to democratize even more data models. Based on the theory of monads, we’ll explore the incredibly powerful nature of query comprehensions to build reactive queries.

Asynchronous, event-driven "reactive" programming is way too hard in today's world of development tools and frameworks. The huge amount of manual and error-prone plumbing leads to incomprehensible and hard to maintain code. As we reach out to services in the cloud, the desire for asynchronous computation is ever increasing, requiring a fresh look on the problems imposed by reactive programming. Centered around the concept of observable data sources, Rx provides a framework that takes care of the hard parts of reactive programming. Instead of focusing on the hard parts, you now can start dreaming about the endless possibilities of composing queries over asynchronous data sources, piggybacking on convenient LINQ syntax.

In this session, we'll cover the design philosophy of Rx, rooted on the deep duality between the interactive IEnumerable interface and the new reactive IObservable interface in .NET 4.

From this core understanding, we'll start looking at various combinators and operators defined over observable collections, as provided by Rx, driving concepts home by a bunch of samples. Finally, if time permits, we'll look at the Reactive Extensions for JavaScript which allows us to take the concepts we already know from Rx and apply them to JavaScript and have deep integration with libraries such as jQuery. Democratizing asynchronous programming starts today. Don't miss out on it!

Advertisement
Advertisement

More Related Content

Slideshows for you (20)

Advertisement

Similar to Rx: Curing Your Asynchronous Programming Blues | QCon London (20)

Recently uploaded (20)

Advertisement

Rx: Curing Your Asynchronous Programming Blues | QCon London

  1. 1. Rx:  Curing  your  Asynchronous   Programming  Blues   Bart  J.F.  De  Smet   Microso'  Corpora,on   bartde@microso'.com  
  2. 2. Why  Should  I  Care?   GPS   RSS            feeds   Stock   ,ckers   Social   media   Server  management  
  3. 3. Mission  Statement   Too  hard  today!   (!  ◦  ")(#)  =  !("(#)) Rx is a library for composing asynchronous and event-based programs using observable sequences. Queries?  LINQ?   •  .NET  3.5  SP1  and  4.0   •  Silverlight  3  and  4   •  XNA  3.1  for  XBOX  and  Zune   •  Windows  Phone  7   •  JavaScript  (RxJS)   MSDN  Data  Developer  Center   NuGet  
  4. 4. Essen,al  Interfaces   interface  IEnumerable<out  T>   {          IEnumerator<T>  GetEnumerator();   }   C# 4.0 covariance interface  IEnumerator<out  T>  :  IDisposable   {   You could get        bool      MoveNext();   stuck        T            Current  {  get;  }          void      Reset();   }  
  5. 5. Essen,al  Interfaces   (WaiHng  to  move  next)   C# 4.0 covariance moving  on   You could get stuck
  6. 6. Mathema,cal  Duality   Because  the  Dutch  are  (said  to  be)  cheap   –  Electricity:    inductor  and  capacitor   –  Logic:    De  Morgan’s  Law   ¬(%∧&)≡¬%∨¬&   ¬(%∨&)≡¬%∧¬&   –  Programming?  
  7. 7. What’s  the  dual  of  IEnumerable?   The  recipe  to  dualiza,on   h^p://en.wikipedia.org/wiki/Dual_(category_theory) Reversing arrows… Input becomes output and vice versa Making  a  U-­‐turn   in  synchrony  
  8. 8. What’s  the  dual  of  IEnumerable?   interface  IEnumerable<out  T>   {      IEnumerator<T>  GetEnumerator();   }     interface  IEnumerator<out  T>  :  IDisposable   {      bool    MoveNext();      T          Current  {  get;  }   Properties    void    Reset();   are methods }  
  9. 9. What’s  the  dual  of  IEnumerable?   interface  IEnumerable<out  T>   {      IEnumerator<T>  GetEnumerator();   }     interface  IEnumerator<out  T>  :  IDisposable   {      bool    MoveNext();      T          GetCurrent();      void    Reset();   A historical mishap }  
  10. 10. What’s  the  dual  of  IEnumerable?   interface  IEnumerable<out  T>   {      IEnumerator<T>  GetEnumerator();   }     interface  IEnumerator<out  T>  :  IDisposable   {      bool    MoveNext();   No checked    T          GetCurrent();   exceptions in .NET / C# }  
  11. 11. What’s  the  dual  of  IEnumerable?   interface  IEnumerable<out  T>   {      IEnumerator<T>  GetEnumerator();   }     interface  IEnumerator<out  T>  :  IDisposable   {      bool    MoveNext()  throws  Exception;      T          GetCurrent();   }  
  12. 12. What’s  the  dual  of  IEnumerable?   interface  IEnumerable<out  T>   {      IEnumerator<T>  GetEnumerator();   }     interface  IEnumerator<out  T>  :  IDisposable   {      bool    MoveNext()  throws  Exception;      T          GetCurrent();   This is an }   output too!
  13. 13. What’s  the  dual  of  IEnumerable?   interface  IEnumerable<out  T>   {      IEnumerator<T>  GetEnumerator();   }     interface  IEnumerator<out  T>  :  IDisposable   {      (bool  |  Exception)  MoveNext();      T          GetCurrent();   Discriminated  union   }   Really only two type  (“or”)   values
  14. 14. What’s  the  dual  of  IEnumerable?   interface  IEnumerable<out  T>   {      IEnumerator<T>  GetEnumerator();   }     interface  IEnumerator<out  T>  :  IDisposable   {      (true  |  false  |  Exception)  MoveNext();      T          GetCurrent();   }   Got true? Really got T!
  15. 15. What’s  the  dual  of  IEnumerable?   interface  IEnumerable<out  T>   {      IEnumerator<T>  GetEnumerator();   }     interface  IEnumerator<out  T>  :  IDisposable   {      (T  |  false  |  Exception)  MoveNext();   }   Got false? Really got void!
  16. 16. What’s  the  dual  of  IEnumerable?   interface  IEnumerable<out  T>   {      IEnumerator<T>  GetEnumerator();   }   Every enumerator is disposable   interface  IEnumerator<out  T>  :  IDisposable   {      (T  |  void  |  Exception)  MoveNext();   }  
  17. 17. What’s  the  dual  of  IEnumerable?   interface  IEnumerable<out  T>   {      (IEnumerator<T>  &  IDisposable)  GetEnumerator();   }   Hypothe4cal  syntax  (“and”)     interface  IEnumerator<out  T>   {      (T  |  void  |  Exception)  MoveNext();   }  
  18. 18. What’s  the  dual  of  IEnumerable?   interface  IEnumerable<out  T>   {      (IEnumerator<T>  &  IDisposable)  GetEnumerator();   }   Variance will flip!   interface  IEnumerator<out  T>   {      (T  |  void  |  Exception)  MoveNext();   }   Will rename too This is really void
  19. 19. What’s  the  dual  of  IEnumerable?   interface  IEnumerable<out  T>   {      (IEnumerator<T>  &  IDisposable)  GetEnumerator();   }     interface  IEnumeratorDual<in  T>   {      void      OnNext(T  |  void  |  Exception);   }   Can encode as three methods
  20. 20. What’s  the  dual  of  IEnumerable?   interface  IEnumerable<out  T>   {      (IEnumerator<T>  &  IDisposable)  GetEnumerator();   }     interface  IEnumeratorDual<in  T>   {   Color of the    void      OnNext(T  value);   bikeshed (*)    void      OnCompleted();      void      OnError(Exception  exception);   }   (*)  Visit  h^p://en.wikipedia.org/wiki/Color_of_the_bikeshed  
  21. 21. What’s  the  dual  of  IEnumerable?   Will leave this interface  IEnumerable<out  T>   part alone {      (IEnumerator<T>  &  IDisposable)  GetEnumerator();   }   This is the data   source Need to patch interface  IObserver<in  T>   this one up too {      void      OnNext(T  value);      void      OnCompleted();      void      OnError(Exception  exception);   }  
  22. 22. What’s  the  dual  of  IEnumerable?   Color of the interface  IEnumerableDual<out  T>   bikeshed (*) {      IDisposable  SetObserver(IObserver<T>  observer);   }     interface  IObserver<in  T>   {      void      OnNext(T  value);      void      OnCompleted();      void      OnError(Exception  exception);   }   (*)  Visit  h^p://en.wikipedia.org/wiki/Color_of_the_bikeshed  
  23. 23. What’s  the  dual  of  IEnumerable?   interface  IObservable<out  T>   {      IDisposable  Subscribe(IObserver<T>  observer);   }     interface  IObserver<in  T>   {      void      OnNext(T  value);      void      OnCompleted();      void      OnError(Exception  exception);   }  
  24. 24. Essen,al  Interfaces   interface  IObservable<out  T>   {      IDisposable  Subscribe(IObserver<T>  observer);   }   C# 4.0   contravariance interface  IObserver<in  T>   {   You could get    void      OnNext(T  value);   flooded    void      OnError(Exception  ex);      void      OnCompleted();   }  
  25. 25. Essen,al  Interfaces       ApplicaHon   InteracHve   MoveNext   Got  next?   OnNext   ReacHve   Have  next!   IEnumerable<T>   IObservable<T>   IEnumerator<T>   IObserver<T>   Environment
  26. 26. Demo  
  27. 27. Geeng  Your  Observables   OnCompleted .Empty<int>() new  int[0]   OnNext .Return(42) new[]  {  42  }   OnError .Throw<int>(ex) Throwing  iterator   .Never<int>() Iterator  that  got  stuck   Notion of time
  28. 28. Geeng  Your  Observables   OnNext OnError   OnCompleted   OnNext(0) OnNext(1) OnNext(2) .Range(0, 3) yield 0 yield 1 yield 2 .Range(0, 3)
  29. 29. Geeng  Your  Observables   A variant with time notion Hypothetical anonymous exists (GenerateWithTime) iterator syntax in C# o  =  Observable.Generate(   new IEnumerable int      0,   for int      i  =>  i  <  10,        i  =>  i  +  1,        i  =>  i  *  i   yield  return   );   Asynchronou Synchronous s o.Subscribe(x  =>  {   foreach var in      Console.WriteLine(x);   Console });  
  30. 30. Geeng  Your  Observables   IObservable<int>  o  =  Observable.Create<int>(observer  =>  {      //  Assume  we  introduce  concurrency  (see  later)…      observer.OnNext(42);      observer.OnCompleted();      return  ()  =>  {  /*  unsubscribe  action  */  };   });   IDisposable  subscription  =  o.Subscribe(      onNext:            x    =>  {  Console.WriteLine("Next:  "  +  x);  },      onError:          ex  =>  {  Console.WriteLine("Oops:  "  +  ex);  },      onCompleted:  ()  =>  {  Console.WriteLine("Done");  }   );   C# doesn’t have anonymous interface C# 4.0 named implementation, so we provide various parameter syntax extension methods that take lambdas.
  31. 31. Geeng  Your  Observables   IObservable<int>  o  =  Observable.Create<int>(observer  =>  {      //  Assume  we  introduce  concurrency  (see  later)…      observer.OnNext(42);      observer.OnCompleted();      return  ()  =>  {  /*  unsubscribe  action  */  };   });   IDisposable  subscription  =  o.Subscribe(      onNext:            x    =>  {  Console.WriteLine("Next:  "  +  x);  },      onError:          ex  =>  {  Console.WriteLine("Oops:  "  +  ex);  },      onCompleted:  ()  =>  {  Console.WriteLine("Done");  }   );   Thread.Sleep(30000);  //  Main  thread  is  blocked…   F10
  32. 32. Geeng  Your  Observables   IObservable<int>  o  =  Observable.Create<int>(observer  =>  {      //  Assume  we  introduce  concurrency  (see  later)…      observer.OnNext(42);      observer.OnCompleted();      return  ()  =>  {  /*  unsubscribe  action  */  };   });   IDisposable  subscription  =  o.Subscribe(      onNext:            x    =>  {  Console.WriteLine("Next:  "  +  x);  },      onError:          ex  =>  {  Console.WriteLine("Oops:  "  +  ex);  },      onCompleted:  ()  =>  {  Console.WriteLine("Done");  }   );   Thread.Sleep(30000);  //  Main  thread  is  blocked…   F10
  33. 33. Geeng  Your  Observables   IObservable<int>  o  =  Observable.Create<int>(observer  =>  {      //  Assume  we  introduce  concurrency  (see  later)…      observer.OnNext(42);      observer.OnCompleted();      return  ()  =>  {  /*  unsubscribe  action  */  };   });   IDisposable  subscription  =  o.Subscribe(      onNext:            x    =>  {  Console.WriteLine("Next:  "  +  x);  },      onError:          ex  =>  {  Console.WriteLine("Oops:  "  +  ex);  },      onCompleted:  ()  =>  {  Console.WriteLine("Done");  }   );   Thread.Sleep(30000);  //  Main  thread  is  blocked…   F5
  34. 34. Geeng  Your  Observables   IObservable<int>  o  =  Observable.Create<int>(observer  =>  {      //  Assume  we  introduce  concurrency  (see  later)…      observer.OnNext(42);      observer.OnCompleted();      return  ()  =>  {  /*  unsubscribe  action  */  };   });   Breakpoint got hit IDisposable  subscription  =  o.Subscribe(      onNext:            x    =>  {  Console.WriteLine("Next:  "  +  x);  },      onError:          ex  =>  {  Console.WriteLine("Oops:  "  +  ex);  },      onCompleted:  ()  =>  {  Console.WriteLine("Done");  }   );   Thread.Sleep(30000);  //  Main  thread  is  blocked…  
  35. 35. Demo  
  36. 36. Bridging  Rx  with  the  World   How to pass around? Hidden data source form1.MouseMove += (sender, args) => { if (args.Location.X == args.Location.Y) // I’d like to raise another event }; Lack of composition form1.MouseMove -= /* what goes here? */ Resource maintenance?
  37. 37. Bridging  Rx  with  the  World   Source of Point Objects can be passed values IObservable<Point> mouseMoves = Observable.FromEvent(frm, "MouseMove"); var filtered = mouseMoves .Where(pos => pos.X == pos.Y); Can define operators var subscription = filtered.Subscribe(…); subscription.Dispose(); Resource maintenance!
  38. 38. Bridging  Rx  with  the  World     Exceptions? Hidden data source   FileStream  fs  =  File.OpenRead("data.txt");   byte[]  bs  =  new  byte[1024];   fs.BeginRead(bs,  0,  bs.Length,   Really a method pair        new  AsyncCallback(iar  =>  {                int  bytesRead  =  fs.EndRead(iar);   Cancel?              //  Do  something  with  bs[0..bytesRead-­‐1]          }),          null   Lack of composition );   Synchronous State? completion?
  39. 39. Bridging  Rx  with  the  World   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]   });   Tip: a nicer wrapper can easily be made using various operators
  40. 40. Bridging  Rx  with  the  World   don’t  replace   unify composiHonality   generic operators   build  bridges!  
  41. 41. Bridging  Rx  with  the  World   •  Cold  observables   var   Observable.Return Triggered by subscription   .Subscribe( ) //  Prints  42     .Subscribe( ) //  Prints  42  again   •  Hot  observables   var Observable.FromEvent MouseEventArgs "MouseMove" Mouse events going before subscription Console
  42. 42. Demo  
  43. 43. Composi,on  and  Querying   Parameterization IScheduler   of operators var .Return Scheduler.ThreadPool Console Will run on the source’s scheduler
  44. 44. Composi,on  and  Querying   duality –  Convert  between  both  worlds   //  Introduces  concurrency  to  enumerate  and  signal…   var .ToObservable();   //  Removes  concurrency  by  observing  and  yielding…   var .ToEnumerable() •  “Time-­‐centric”  reacHve  operators:   Race! .Amb( )
  45. 45. Composi,on  and  Querying   synchronize .Return Scheduler.ThreadPool "Answer  =  " IScheduler interface •  WPF dispatcher •  WinForms control •  SynchronizationContext .ObserveOn(frm)       "Answer  =  "
  46. 46. Composi,on  and  Querying   •  Observables  are  sources  of  data   –  Data  is  sent  to  you  (push  based)   –  Extra  (op,onal)  noHon  of  Hme   •  Hence  we  can  query  over  them   //  Producing  an  IObservable<Point>  using  Select   var  mme  =  from  mm  in  Observable.FromEvent<MouseEventArgs>(                                                    form,  “MouseMove”)                      select  mm.EventArgs.Location;     //  Filtering  for  the  first  bisector  using  Where   var  res  =  from  mm  in  mme                      where  mm.X  ==  mm.Y                      select  mm;  
  47. 47. Composi,on  and  Querying   Asynchronou s request IObservable<string> TextChanged   React Dictionary web service Reaction Reactive Reactor IObservable<DictionaryWord[]> Data binding on UI thread
  48. 48. Composi,on  and  Querying   //  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   input.SelectMany(term  =>                      from  words  in  lookup(term)   lookup(term))                      select  words;  
  49. 49. Demo  
  50. 50. Composi,on  and  Querying   Reactive| Reacti| React| Reac| Rea| Re| | Reactiv| R| input Reactive Reaction Reactive Service  call  1   Reactor Service  call  2   UI  data  binding   Source: http://scrapetv.com
  51. 51. Composi,on  and  Querying   Reactive| Reacti| React| Reac| Rea| Re| | Reactiv| R| input UnHl   Reactive Service  call  1   Take   Service  call  2   UI  data  binding  
  52. 52. Composi,on  and  Querying   //  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);   Very local fix //  Compose  both  sources  using  SelectMany   J var  res  =  from  term  in  input                      from  words  in  lookup(term).TakeUntil(input)                      select  words;  
  53. 53. Composi,on  and  Querying   //  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);   //  Alternative  approach  for  composition  using:   //      IObservable<T>  Switch<T>(IObservable<IObservable<T>>  sources)   var  res  =  (from  term  in  input   Hops from source                      select  lookup(term)).Switch();   to source
  54. 54. Demo  
  55. 55. Mission  Accomplished   Way  simpler  with  Rx   (!  ◦  ")(#)  =  !("(#)) Rx is a library for composing asynchronous and event-based programs using observable sequences. Queries!  LINQ!   •  .NET  3.5  SP1  and  4.0   •  Silverlight  3  and  4   •  XNA  3.1  for  XBOX  and  Zune   •  Windows  Phone  7   •  JavaScript  (RxJS)   MSDN  Data  Developer  Center   NuGet  
  56. 56. Related  Content   •  Hands-­‐on  Labs   –  Two  flavors:   •  Curing  the  asynchronous  blues  with  the  Reac,ve  Extensions  (Rx)  for  .NET   •  Curing  the  asynchronous  blues  with  the  Reac,ve  Extensions  (Rx)  for  JavaScript   –  Both  can  be  found  via  the  Rx  forums   •  Rx  team  web  presence   –  Rx  team  blog  –  h^p://blogs.msdn.com/rxteam   –  DevLabs  –  h^p://msdn.microso'.com/en-­‐us/devlabs/ee794896.aspx   –  MSDN  forums  –  h^p://social.msdn.microso'.com/Forums/en-­‐US/rx   –  Channel9  –  h^p://channel9.msdn.com/Tags/Rx  
  57. 57. Thanks!   Bart  J.F.  De  Smet  

×