Declarative Programming and Autosubscribe

While I was watching the Meteor screencast (if you haven’t already seen it,
go watch it), I paused around 1:35. They had just said “There’s no callbacks, no
bindings, and no controllers. It just works.” after showing off the code
something like the following:

From an application developer’s perspective, I thought “Wow. That is really
amazing”. This is a perfect example of how incredible working with declarative
programming can be. Meteor itself focuses on reactive programming, but it
facilitates declarative style in its live templates.

From working on my own libraries and frameworks, I thought “Wow. How the hell
did they get that to work?” More on this later.

Declarative Programming (The What)

Whenever you’re trying to make anything, you want to spend your time figuring
out what you want in your application, not how to get it there. Declarative
programming tries to shift the focus from control flow to logic and state.

A prime example of this is the divide between the creation and updating of views
in imperative style. For example, consider a simple view that wraps an h1
that reflects some data stored in a model.

Ultimately the goal here is to have an h1 that says “Salutations, NAME”, where
NAME is always synchronized with the model.

Imperative Creation and Update

If you were to write it in this style, you would probably do it with jQuery or
some similar DOM manipulation library, so that’s what we’ll use here.

Mentally, I had to translate the original task into “create an element,
listen for any updates to the model, then update the view to match the model”.
This isn’t so bad, and is definitely better than the model knowing about the
view, but there’s room for improvement.

Namely, it’s very apparent that the creation of the elements and the
synchronization of the data exist as two distinct tasks, when they really don’t
need to.

Declarative Creation and Update

Here’s the same example written in Meteor style declarative programming.

In this style, we aren’t manually wiring up synchronization at all. We aren’t
thinking in a “when this, then that” kind of mindset. We just say “this is how
it always should be”. As a side effect, the mental separation between create and
update becomes unnecessary. You don’t need to consider what happens when the
model changes - the view just always reflects the model.

While the amount of code isn’t significantly different between these two
examples, I believe that as applications become more complex, the savings in the
declarative style will increase, and the logic will be easier to follow.

Autosubscribe (The How)

I’ve done a bunch of JS development by now, and this is one of the first things
I’ve tripped over in a long time thinking “How is this possible?”. I’m not
talking about how the task was algorithmically complicated, I’m talking about
how it looked like there was something essential missing from the code.

In particular, I couldn’t understand how the views knew when to update, since
there was no event binding anywhere.

The solution comes from Meteor’s concepts of “autosubscribe”.

The basic idea is to establish a global context that things are currently
running in and check this whenever any mutable data is accessed. If the accessor
notices that a global context is active, it will subscribe that context to be
re-run when that data changes.

A basic implementation would look something like this:

varMagic={context:nullautosubscribe:function(cb){Magic.context=cb;Magic.context();}};varModel=function(){this.props={};};Model.prototype.get=function(prop){if(Magic.context!=null){// An autosubscribe context is active, so subscribe it to future// changes to the propertythis.bind('change:'+prop,Magic.context);}returnthis.props[prop];}Model.prototype.set=function(prop,val){this.props[prop]=val;this.trigger('change: '+prop);}// Implementations of bind and trigger omitted, but they would act exactly // like Backbone's

While Meteor did not invent the concept of live templates, this method of
dodging event binding seems the most powerful. While the idea of client-side
access to the database seems a little scary, and it might end up hairier than
normal client-server architecture if you want security, there are some ideas
from Meteor that I think are a definite step in the right direction.