Reactive Extensions for Retlang Developers

Most of the talk about Rx has been about the “Push LINQ” aspects of it, so I thought I’d have a bash at explaining it from a Retlang perspective instead.  Let’s start with IObserver:

    public interface IObserver<in T>
    {
        void OnNext(T value);
        void OnError(Exception error);
        void OnCompleted();
    }

Now, in the same place Retlang just uses an Action<T> (or IPublisher<T>, depending on context).  If you want to catch exceptions, you implement IBatchExecutor and catch the exception yourself.  As for OnCompleted, there just isn’t a straight parallel, really.

Now, let’s see the equivalent of IFiber:

    public interface IScheduler
    {
        DateTimeOffset Now { get; }
        IDisposable Schedule(Action action);
        IDisposable Schedule(Action action, TimeSpan dueTime);
    }

Okay, so what’s different?  Well, you can’t “EnqueueAll” and schedulers can’t keep track of their own subscriptions.  On the other hand, Schedule returns a Disposable: every scheduled action should be cancellable.  The scheduling by time is a little less directly usable, but fine.  It’s nice to see that “Now” is abstracted out, but it seems to be a bit of a strange implementation detail.  Also, when you actually examine the code, you discover that CurrentThreadQueue, for instance, is hardwired to Scheduler.Now anyway, which renders it all a bit pointless.

So far, this is all pretty similar to Retlang.  But the equivalent of ISubscriber is rather unexpected:

    public interface IObservable<out T>
    {
        IDisposable Subscribe(IObserver<T> observer);
    }

Ignoring all of the overloads subscriber has, there’s one big thing missing: you specify the listener, but not the fiber.  That’s because an IObservable can include a thread.  The command for this is “observable.ObserveOn(scheduler)”*, which returns another observable.  (There’s also observable.SubscribeOn(observer, scheduler).  As far as I can figure out, this causes the subscriptions to run against that scheduler, which isn’t really what you want, but is likely the routine you’d try first if you were a Retlang user.)

Finally, while Channel in Retlang is a combination of IPublisher and ISubscribable, ISubject does the same thing in Rx: it’s the combination of IObserver and IObservable and hence is the natural place to put a buffer.

Some Interesting Implementation Details

If you look at the implementation of CurrentThreadScheduler, you’ll see it uses a priority queue rather than the Timer model Retlang uses.  This is actually really rather cool.  In particular, it means that you can actually schedule events to occur in the past.  It may seem like that’s a stupid thing to do, but in practice it means that you can cause certain messages to be processed out of band, which is actually pretty powerful.  Imagine, for instance, a set of workers responding to HTTP connections.  This would allow you to prioritize messages from existing (keep-alive) connections.  (Let’s be honest, this is a bit of a hack, but out of band messages can be useful.)

There’s all sorts of simple and useful classes running around here: BooleanDisposable, CompositeDisposable.  It’s a pity they aren’t just in the .NET framework to begin with.  Of course, Microsoft give with one hand and take with the other.  PriorityQueue is marked internal, continuing Microsoft’s long tradition of not letting you near the code.  Equally, AnonymousObserver, a simple class that takes three delegates and constructs the obvious IObservable, is marked internal, making writing your own Subscribe overloads just that tiny bit less convenient.

Different Sorts of Schedulers

As you can see, the basic building blocks for a Retlang-style structure are all there.  The various sorts of schedulers/fibers are also worth looking at:

  • Scheduler.Immediate: Pretty much the same as StubFiber.  Runs on the current thread and blocks if you schedule something in the future.
  • Scheduler.CurrentThread : Okay, I’m just perplexed by this one.  As far as I can tell, it behaves identically to Immediate, but the code is significantly more complex.  It’s not thread-safe: you couldn’t enqueue something from another thread the way you can with ThreadFiber; it’s got this curious EnsureTrampoline function that I frankly don’t understand.  I imagine this will become more clear at some point in the future when I understand Rx better.
  • Scheduler.DispatcherScheduler:  WPF support
  • ControlScheduler:  WinForms support
  • EventLoopScheduler:  ThreadFiber with fewer options.  Would it be so hard to put a Func<ThreadStart, Thread> into the constructor?
  • Scheduler.ThreadPoolScheduler: PoolFiber
  • TaskPool scheduler: for integration with the parallel tasks library.

This is all harder to figure out than it should be.  There’s no source code download and no documentation worth speaking of.  My personal opinion: if they can open source ASP.NET MVC, why can’t they open source this?

Technorati Tags: ,

Contract Killers

Seriously, is this the most succinct way of expressing this?

[InheritedExport]
[ContractClass(typeof(RequestFailureContract))]
public interface IRequestFailure
{
    string FailureMessage { get; }
}

[ContractClassFor(typeof(IRequestFailure))]
public class RequestFailureContract : IRequestFailure
{
    public string FailureMessage
    {
        get { 
            Contract.Ensures(Contract.Result<string>() != null);
            return null;
        }
    }
}

Personally, I would prefer to write this:

public interface IRequestFailure
{
    string! FailureMessage { get; }
}

If you’re currently thinking there’s something very wrong with code contracts in C# you’d be right.  What’s wrong is that code contracts aren’t actually a language feature.  They’re implemented as a post-compilation rewrite.  Don’t get me wrong, it’s really impressive that they achieved it this way, and they’re still an improvement on what went before, but I can’t help feeling they lost sight of the ultimate goal on this one.  Worse, enforcing code contracts is achieved by a DevLabs download that’s feature-locked to particular versions of Visual Studio.  I’m pretty sure I missed the part of the Liskov Substitution Principle that said “This doesn’t apply if you happen to be running Visual Studio Professional”.

Handling Parameters with Caricature

I’m still finding my feet with RSpec, but early experiences are good.  I wish I could say the same for Cucumber.  Sadly, you can’t really use RSpec’s built-in mocking with the CLR, so we need an alternative.  Luckily Caricature takes the strain.  There’s not a great deal to say that isn’t covered by Ivan’s introductory articles, it’s that simple to use.  However, one thing I couldn’t figure out was how to return a value that was dependent on the inputs.  I ended up contacting Ivan, who was extremely helpful and even updated the gem to help me out.

Turns out the code I needed was:

@factory = Request::IRequestFactory.isolate 
@factory.when_receiving(:GetHeaders).returns { |x| HttpHeaders.new x }

(Note the new syntax with .isolate rather than Isolation.for)

One thing that I’m still not up to speed with in Ruby is API discovery.  All the documentation and even source code in the world isn’t as convenient as hitting auto-complete and seeing the help come up.  On the other hand, Caricature has extremely readable specs.  If I’d found this earlier I wouldn’t have had so many problems.  This, of course, one of the points of RSpec: tests you can actually read.

Running RSpec and Cucumber from C#

You might be wondering why on earth you’d want to do this, but it’s trickier than it looks.  I’ve published a gist for it.  There’s a couple of comments about how to get things set up as well.

The bad news is, RSpec works, but Cucumber doesn’t.  Instead I’m getting this:

can't convert Array into java::util::List (TypeError) 
C:/Program Files/IronRuby 1.0v4/lib/ironruby/gems/1.8/gems/gherkin-2.0.2-universal-dotnet/lib/gherkin/native/ikvm.rb:37:in `new' 
C:/Program Files/IronRuby 1.0v4/lib/ironruby/gems/1.8/gems/cucumber-0.8.3/bin/../lib/cucumber/cli/configuration.rb:29:in `parse!' 
C:/Program Files/IronRuby 1.0v4/lib/ironruby/gems/1.8/gems/cucumber-0.8.3/bin/../lib/cucumber/cli/main.rb:94:in `configuration' 
C:/Program Files/IronRuby 1.0v4/lib/ironruby/gems/1.8/gems/cucumber-0.8.3/bin/../lib/cucumber/cli/main.rb:43:in `execute!' 
C:/Program Files/IronRuby 1.0v4/lib/ironruby/gems/1.8/gems/cucumber-0.8.3/bin/../lib/cucumber/cli/main.rb:25:in `execute' 
C:/Program Files/IronRuby 1.0v4/lib/ironruby/gems/1.8/gems/cucumber-0.8.3/bin/cucumber:8 
C:Program FilesIronRuby 1.0v4bincucumber:19:in `load' 
C:Program FilesIronRuby 1.0v4bincucumber:19 

Yes, you’re reading the first line correctly.  The downside of IKVM, of course, is Java Exceptions that mean nothing to you.  This is quite frustrating for me, because I really wanted to start using Cucumber.  So if anyone’s managed to crack this, drop me a line.  Believe me, I’ve tried enough different versions of the gherkin and cucumber gems to last a lifetime.

On the other hand, I’m rather enjoying RSpec.