Reactive Framework Finally Explained

I have been intrigued by the Reactive Extensions for .NET (Rx Framework) for quite a while now, especially the fundamental shift from a “push” data model as opposed to the “pull” model most familiar to us.  I have thought to myself that this must be a game changer in how data and events are consumed in every-day software.  I didn’t quite understand how it all works or how to use it from the few samples I had seen, but I knew if I gave myself a little time to really sit down and look at it, my life would be changed forever.

However, after reading some articles, watching some recorded presentations, and even attending a MIX ‘10 session in-person on the Reactive Extensions, I felt increasingly lost and confused by what this framework could offer me.  I wasn’t understanding some fundamental ideology of the framework and it was jading my learning experience when watching/reading sample code.  Well, I think I have finally figured out what the mental roadblock was and will attempt to explain the framework here as I best as I understand it, in hopes that it can be of help to others not getting what the fuss is all about.  I can sense that I’m not the only one who has been turned off by the unsuccessful attempts by Microsoft to explain this revolutionary framework to the average developer.  Apparently those who had a hand in designing the framework are just so incredibly intelligent that they are having a hard time discerning that the common man is not immediately getting it.

IEnumerable<T>, Meet IObservable<T>

Essentially what Microsoft did is create a mathematical dual of the IEnumerable and IEnumerator interfaces using Category Theory, and named them IObservable and IObserver respectively.  In its bare simplicity, this is done by merely reversing the direction of your arrows in your mathematical functions and compositions.  The following images of a few slides from Erik Meijer’s MIX ‘10 Session that were the best visual explanation I have seen:

Duality Example with De Morgan’s Laws

rxSlide2

Creating a Dual of IEnumerable

rxSlide3

Creating a Dual of IEnumerator

rxSlide4 

The reason the mathematical proof part is significant is because we can guarantee that LINQ syntax and operators will work on these new collection and data subscriber interfaces, just like they did with IEnumerable collections in LINQ-to-Objects.  This new LINQ provider is commonly called “LINQ over Events.”

Reacting to Data is Asynchronous

This is actually where I think some of the confusion came in for me.  Mostly what I didn’t understand is how you can write LINQ queries into pushed data (already sent and also yet to be sent), when essentially that task is indeterminate by nature.  What I have figured out is that the LINQ syntax is not entirely for the data being pushed, but also used for molding the subscriptions themselves.  What the LINQ syntax provides you is a way to compose, filter, project, aggregate, and throttle data and event subscriptions in a powerful, declarative way.

A common workflow seems to be to create one or more observable collections (and there are many ways to do so) and then customize and compose a subscription based on the subscription(s) using LINQ syntax.  All that’s left then is to set the subscription in motion, giving it some sort of callback or lambda expression to be called as data is asynchronously pushed in and processed.

Here is a very simple code example that illustrates this process quite plainly:

using System;
using System.Linq;

namespace TestRX
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var oneNumberPerSecond = Observable.Interval(TimeSpan.FromSeconds(1));

            var numbersTimesTwo = from n in oneNumberPerSecond
                                  select n * 2;

            Console.WriteLine("Numbers * 2:");

            numbersTimesTwo.Subscribe(num =>
            {
                Console.WriteLine(num);
            });

            Console.ReadKey();
        }
    }
}

It is interesting to watch the code run and think about what it’s actually doing.  It sits on the Console.ReadKey() line while the observable collection is asynchronously pushing data to the lambda expression containing the Console.WriteLine() statement.

It looks like the Reactive Framework is not just a better way to handle events and pushed data, but it also appears from what I’ve read that it could be used as a nicer API for sending off asynchronous process threads.

Additional Reading

Microsoft DevLabs has created the Reactive Extensions for .NET (and it’s associated languages), but it has also came up with the Reactive Extensions for Silverlight and JavaScript (can be found on same webpage).  This proves very interesting as JavaScript (and Silverlight) tends to be quite event driven because of its close interactions to UI elements in HTML (or XAML).  In fact, one of the most encouraging example use cases that I’ve heard was that of having some HTML text field that you wanted to auto-search as the user types, but not until the user pauses for a second; they can also hit Enter.  What the Reactive Framework could provide you is a way to aggregate more than one event source (alphabetic and Enter key strokes and the timer) into a single event handler using clear, declarative framework statements.

Here are other links I would recommend for additional examples and explanation:

Enjoy!  Let me know via comments if you start using it for something real cool and useful.

Comments

Michael
Nice post on a complex topic. You are indeed correct that there has been confusion around explaining the why and how of Reactive Extensions. Thanks Mike.
Paul
Great post on getting started with Rx! One of the things I've been working on is a MVVM framework for Silverlight / WPF that uses the Reactive Extensions - I've written about it quite a bit in my blog at http://blog.paulbetts.org/index.php/category/programming/reactive-extensions/ and the code is at github.com/xpaulbettsx/ReactiveXaml ; it's got some great examples of doing more than just handling events together, I'd love to hear any feedback you've got on the project