Home > Uncategorized > Eventless Programming – Part 1: Why the heck?

Eventless Programming – Part 1: Why the heck?

Posts in this series:

An “event” is a list of routines that all get executed (in unpredictable order) whenever something occurs. It is the low-level building block of complex interactive software.

But as abstraction, it fits poorly with our needs. Rather than the abstract idea of an event occurring, it is far more useful to think more specifically of a value changing. That is, we should always pair together two things: storage for a unit of information, and the event that the information has changed. This pairing is an observable.

In Windows Forms this pattern occurs, but only informally. For example, controls have a property called Enabled, and a corresponding event called EnabledChanged. Many controls have a property called Text, and an event called TextChanged. And so on. Unfortunately nothing links these together apart from the naming pattern.

WPF/Silverlight tried to fix this through Dependency Properties. A dependency property has a value, and there is a standard mechanism for notifying of a change in that value. But the results aren’t pretty: essentially it is just more manual event firing and handling, leading people to cook up various complex techniques to avoid writing so much boilerplate code.

There is a basic difficulty that occurs with stateful software. In mathematics once a value is defined and given a name, we don’t change it some time later on in the proof. In most programming languages that rule is tossed out carelessly. If x is said to be 5 and y is said to be x + 5, then y is surely 10… until x changes. Of course we could define y as a function of x, and recompute it every time we need to know the value, but in real programs we soon find that we’re repeating a lot of identical calculations, so instead we cache our values in variables, and then try to figure out manually when it would be an appropriate time to recompute them.

Events are the way we do this, but it’s crazy because we are repeatedly building, by hand, something that should be happening automatically, as simply as it does in Excel. If you put a 5 in cell B3 and then in another cell you put =B3+5, the spreadsheet is smart enough to know that it will need to recompute the second cell whenever the value in B3 changes. Excel gives us a model for declaring what our variables should contain, expressed in terms of other variables, and it harnesses the power of events to keep everything consistent, but we as users never have to manually hook up a single event handler, and nor should we.

Brothers and sisters, let us, here and now, build a C# framework for providing us with the convenience and minimal recomputation of Excel, but with the considerable advantage that we get to define the UI ourselves (and specify our own meaningful variable names instead of unhelpful cell references…)

(By the way, if you’re familiar with knockout.js, this is all going to seem eerily familiar, but a lot more statically typed.)

Now, buried beneath whatever we cook up, we will need an event. Let’s see how far we can get with a single solitary event doing all the work.

public interface IGetable
{
    event Action Changed;
}

[Sidenote: I was going to call it IObservable but as Brandon Wallace pointed out in the comments, there’s already System.IObservable. Then I called it IReadable, but then I realised properties have getters and setters, and as you’ll see, we’re really just building an abstraction over a property with a Changed event.]

I’m breaking the rules of the event pattern by using the super-bland Action delegate, but I don’t care. A basic principle here is that Changed will never need to provide any further information about the event, other than the fact that it has occurred. By the way, that interface is already finished! I’m not going to add anything more to it, ever.

Well, kind of. It is just a base for us to extend:

public interface IGetable<out T> : IGetable
{
    T Value { get; }
}

This turns out to be very useful because it means from an event-handling perspective we can treat all observables alike, regardless of what type of value they hold. And again, we’re entirely done with that interface. It’s already being all it will ever need to be. Note that we only have a getter for the value, however. Which leads us to:

public interface ISetable<T> : IGetable<T>
{
    new T Value { get; set; }
}

All very pretty and abstract, but still no code that does anything. Patience, I’m building to it. Good grief, this is only part 1! Seriously, don’t you ever shut up? Alright, alright, here’s our first class, the actual implementation of an observable:

public sealed class Setable<T> : ISetable<T>, IEquate<T>
{
    private T _value;
    private bool _changing;

    public Setable(T value = default(T))
    {
        _value = value;
        EqualityComparer = DefaultEqualityComparer;
    }

    public T Value
    {
        get
        {
            Computed.Listeners.Notify(this);
            return _value;
        }

        set
        {
            if (EqualityComparer(_value, value))
                return;

            if (_changing)
                throw new RecursiveModificationException();

            _value = value;

            var evt = Changed;
            if (evt == null) 
                return;

            _changing = true;
            try { evt(); } 
            finally { _changing = false; }
        }
    }

    public event Action Changed;

    public Func<T, T, bool> EqualityComparer { get; set; }

    public static bool DefaultEqualityComparer(T a, T b)
    {
        return ReferenceEquals(a, b) || (!ReferenceEquals(a, null) && a.Equals(b));
    }

    public static implicit operator T(Setable<T> from)
    {
        return from.Value;
    }
}

It fully implements ISetable – not especially hard to do. The critically important part is that the Value property setter doesn’t fire the event unless the value has truly changed.

[Update: In the comments Mark Knell mentioned the problem of re-entrance. The check for equality before firing the event is a partial solution to that; it silently allows recursive attempts to set Value to the same value it already holds, without triggering a further event, and so endless unnecessary ping-ponging events are eliminated. But originally I also allowed recursive modification of Value during the firing of Changed, in mimicry of Knockout.js. As an experiment, I’m going ban this outright. Hence the _changing field, which is true while the exception is being fired. If Value is genuinely modified again while Changed is firing, that suggests a problem has arisen in the way events have been wired up. So a “Please don’t do that” assertion seems called for. End of update]

Everything else in the class is about allowing you to supply an alternative way to compare values for equality. That other interface IEquate is part of that stuff, and is only there to support some generic constraints that aren’t particularly important:

public interface IEquate<T>
{
    Func<T, T, bool> EqualityComparer { get; set; }
}

The only puzzle here is that call to Computed.Listeners.Notify(this) in the Value getter. How can it be that a getter needs to do any notification? To see why that is, we’ll have to start trying to build support for computed observables, in part 2

Advertisements
Categories: Uncategorized Tags: , ,
  1. February 25, 2013 at 3:49 pm

    I sure wish this was a built-in feature of the language though. Having the mutable be an “object” rather than just a value, you can do

    var fredPhone = fred.Phone;
    fredPhone.Value = “1234”;
    fred.Save();

    which just makes me feel dirty.

    • earwicker
      February 25, 2013 at 5:50 pm

      Or even worse:


      favouritePhoneNumbers.Add(fred.Phone);
      fred.Dispose(); // does this dispose fred.Phone too?

      Aliasing goes with the territory of reference types: the essential difference between value types and references types is: how many names can be bound to the same object? For value types, it’s 1, for reference types there is no limit.

      Suppose the language had a modifier % that could be applied to reference type declarations (in the same way that ? is a modifier that adds nullability to value type declarations). This new modifier would mean “don’t allow any names to be bound to this”.

      So if Phone was declared:

      TelephoneNumber% Phone { get { ... } set { ... } }

      That would make it impossible to bind a name to the value of that property. You’d be able to directly operate on the value, e.g. use the . operate to access a member:

      Console.WriteLine(fred.Phone.Length); // okay

      But you could never store the object in a variable or field, or pass it as a parameter to a method (because that would also bind it to a name).

      list.Add(fred.Phone); // obviously not okay
      Console.WriteLine(fred.Phone); // hmmm...?

      However, the WriteLine example should be allowed, because if you pass an object to Console.WriteLine it doesn’t store the reference; it just calls ToString on it and prints the string. So methods like that should be updated:

      void WriteLine(object% obj) { ... }

      It declares (to outsiders) “After I return, there will be no additional surviving references to that object anywhere”. We know that’s true because WriteLine would have to bind it to a name somehow, and the compiler wouldn’t let it.

      Note that an ordinary reference is assignment compatible with a %-reference (C% is a supertype of C) so you wouldn’t need two overloads of WriteLine.

      There’s an odd connection here with C++11 rvalue references, which are references identified by the modifier &&. Such a reference refers to an object that has no other aliases (as far as the compiler can tell…), meaning that you can “safely” (whatever that means in C++) mess with the object without disrupting anything else (typically you want to steal its contents instead of copying them, an operation known as “moving”).

      So: rvalue references let you provide an overload to handle unaliased objects, whereas this mythical % operator would stop further aliases being created.

  2. Brandon Wallace
    February 25, 2013 at 3:56 pm

    Nice article. I can’t wait for part 2. My only complaint is your use of IObservable, which is an interface that already exists as System.IObservable.

    I also like the fact, that in Knockout, the change event provides the new value in the notification event. It lets you subscribe to an observable without needing to then maintain a handle to the observable within your event callback. And also saves you from situations where, heaven forbid, one of the event handlers recursively changes the observable again before your event callback even sees the first notification.

    • earwicker
      February 25, 2013 at 5:15 pm

      Good point about the name IObservable. I’ll have to do some renaming and update part 1 before I get too far into part 2. (I was also tempted to go with the Excel metaphor and say Cell instead of Observable and Formula instead of Computed, but I don’t want to diverge from Knockout terminology unnecessarily).

      Re: event parameters, my aim here is to build up a pattern where in application code we don’t write event handlers or explicitly subscribe to events, hence “eventless”. We just define observables, and also computeds in terms of the observables (and other computeds). They just layer over each other until we have the data structures we need for our UI, and all the subscribing to events is hidden from us – hence we don’t know or care what information is carried in the events (that’s dirty low-level stuff that we float above happily!)

      Re: the second problem, agreed, that is nasty: side-effects in event handlers such that the event handlers becomes sensitive to the order that they execute in. As I say in this post, an event is a list of routines that all get executed in unpredictable order. If each handler works by having uncontrolled side-effects on other data, such problems are bound to occur sometimes. To avoid this, work in a strictly layered fashion: make each event handler responsible for updating only its own bit of data (some computed transformation of the data it consumes). That update in turn triggers a second event, which notifies consumers of the transformed data, etc. So handlers automatically run in the right order according to how they depend on the results of other handlers.

      And the nice thing about eventless programming is that it effectively implements that exact pattern.

      • Brandon Wallace
        February 26, 2013 at 3:36 pm

        Good deal. If you haven’t explored it yet, take a look at Reactive Extensions which makes heavy use of the System.IObservable interface. There’s a .NET version, a JavaScript version, and I think Netflix just open sourced a Java version. It has a different focus than your post. It is entirely focused on events instead of values. But the 2 concepts actually play very nicely together.

        As for the Change event passing around the value of the change….I’m worried about the developers that indeed need to subscribe to the event so they can integrate with other systems. It cannot be turtles all the way down after all. Sooner or later something will want to subscribe to change events so a database can be updated or a message can be sent over a socket. Besides the cyclic subscriptions scenario, in multi-threaded scenarios (which KnockoutJs did not need to worry about), by the time the subscriber sees the event, the value of the original Mutable might be different than the value which triggered the event. The functional programmer in me screams out that the value of the event must be part of the immutable event state so that any downstream subscribers know exactly what occurred. They can then choose to use the event state provided, or ignore it and read the mutable value.

      • earwicker
        February 28, 2013 at 12:47 pm

        Yep, I got familiar with Rx in pre-release, very entertaining videos from Erik Meijer at the time. NB. Rx is not only about events – it does model a stream of values that may be finite in length.

        But the real difference with knockout (and hence Eventless) is that we are only interested in a recent consistent snapshot of all values, rather than being sure that we observe every intermediate state in between. In fact in this scenario, far from caring about skipping states, it is actually advantageous to skip states if a more up-to-date one is available (and I really should add a knockout-style “throttle” feature to make that easy). We just want the UI to appear “current”, i.e. to be continually converging on it. So it’s a different problem space really, and if that’s all we want we can simplify the pattern considerably.

        Regarding threads, I’ve just touched on that in part 2. Basically any system of observables is thread-local (typically they’re on the UI thread). If you want to mutate a Writeable from another thread, marshal that operation onto the UI thread. Not as hard as it used to be – with async/await it’s pretty much automatic, and I’m going to do an example of it (currently slated for part 5), something like:

        var responseText = Computed.From(async () => 
        {
            if (uri.Value == null)
                return "You haven't entered a valid url yet...";
            try
            {
                return await new HttpClient().GetStringAsync(uri.Value);
            }
            catch (HttpRequestException x)
            {
                return "Error: " + x.Message;
            }
        }));
        

        The uri is another observable (could be Computed, could be Writable). The value of responseText will be a string, automagically updating soon after uri changes.

  3. Mark Knell
    February 25, 2013 at 8:43 pm

    I’ve tried things like this before, especially with XAML. A comprehensive solution is non-trivial.

    To start, I’d recommend you make your event notifiers re-entrant. Object graphs don’t have to get too complex before it’s easy to have cycles.

    So for example, you might have an Updating property which indicates that the flow of control for this thread is somewhere out in the event handlers (line 27 as currently listed). Any incoming mutations during that time must choose the concurrency response they want: ignored? blocking? exception? etc. That suggests more than one kind of event subscription.

    Also, what should be the granularity of the Updating mode: per property? per object? per graph? per synchronization context? Different tasks will have different needs. Good luck wrestling them into a framework that’s simpler than the various .NET models. The Reactive extensions are probably the most elegant approach I’ve seen yet. Hope you can do them one better.

    For me, I’m increasingly interested in immutable object patterns. Immutability doesn’t solve concurrency and eventual consistency, but it does simplify some parts of it. While complicating others…

    • earwicker
      February 25, 2013 at 10:33 pm

      Thanks. Re: re-entrancy, the Value property setter is basically:

      1. compare old and new values. If the same, quit.
      2. store new value.
      3. fire event

      This means that if the event is handled by some code that recursively sets the same property again, there are two possibilities:

      1. it stores the same value as is currently stored.
      2. It stores a different value – that is, it disagrees with the value change it was just notified about and attempts to fight against it…

      The first circumstance is okay and is expected if (for example) two observables are mutually bound. They “converge” on an agreed value immediately. So this should be harmless and ignored (which is what happens, and is what knockout.js does also.) This simple protection alone gets rid of the vast majority of problems with endlessly rebounding events.

      The second circumstance is yucky, and suggests some foul hackery is afoot. It’s not impossible for it to be correct, because the sequence of values could converge on a fixed point at which point the recursion will stop. But equally they could hit a limit set and cycle through a set of values until we run out of stack space.

      But it can be avoided by following the complete pattern I’m going to discuss here, where we never write and hook up our own event handlers by hand.

      Consequently there should be an opportunity here for a hard precondition i.e. always throw a low-level exception when the second situation is detected. It shouldn’t really need to be configurable for different scenarios. If it throws, you’re doing something nasty. So I’m going to add that check right now, as I want to know if I’m breaking this rule!

      Re: granularity, hopefully it will become clearer how the framework isn’t going to have to impose a level of granularity, any more than the idea of a plain variable has to do that. A variable can store something as simple as a single bool, or it can store a whole sequence of objects built from a series of chained LINQ operators applied to source sequence of other objects. Same goes for computed observables (which are going to be in part 2).

  4. April 20, 2013 at 10:38 am

    A language nitpick: I think the interface should be named Gettable analogously to getters.

  1. March 7, 2014 at 8:36 pm
  2. February 21, 2015 at 12:29 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: