A while ago I mentioned in a post that in order to “get” how the SproutCore framework works you really have to understand SproutCore’s key-value-observing (KVO) and binding paradigm since they are so central in how the rest of the framework works.

Looking back at that post, I realized that my explanation of KVO and bindings was too general and hand-wavy and may not make sense to a person new to SproutCore. In an effort to help all those out, I’m going back to the topic of KVO and bindings but this time making things (hopefully) more obvious and concrete.

Now bare in mind that KVO and bindings are big topics and there’s a lot to know behind the scenes. Therefore I’m going to be taking you down the path one simple step at a time. So, you know, brace yourself. Grab a beer while you’re at it.

Part 1: Theory is as Theory Does

Let’s first start out with a bit of background and theory. Now, now. No snoring in the back of the class ;).

When you normally work with JavaScript, you know that you can create an object pretty easily that consists of regular properties and methods like in the following ways:


/* A very simple way to create an object */
var user = {
  firstName: 'John',

  lastName: 'Doe',

  getFullName: function() {
    return firstName + ' ' + lastName
  }
}

/* Another, improved, way to create an object */
function UserObject(fname, lname) { /* a function acting as a class constructor */
  this.firstName = fname,
  this.lastName = lname
}

UserObject.prototype.getFullName = function() {
  return this.firstName + ' ' + this.lastName;
}

var user = new UserObject('John', 'Doe');

Pretty basic. When building a web-based application, or rich internet application (RIA) as people like to sometimes say now, you make lots and lots of objects in order to implement interesting functionality and modularize your work. Right? And when building your web app you no doubt have different visual components that display information about those objects and modify them.

If you’re following good design practices you probably even embrace the Model-View-Controller (MVC) architectural pattern to further structure your code into logical groups and ensure you decouple your domain model from your views using controllers. However, depending on how you tackle MVC you may end up writing a lot of plumbing/boiler-plate/glue code to get everything to work, such as making sure a model object is updated when you modify information in the view, syncing information between two or more views and so on.

Writing such code is annoying, time consuming and error-prone. It would be so much easier if you could have some mechanism that did most or all of the work to connect views, controllers and objects for you so you can focus on getting the real functionality done. Do I hear an “amen, brother” coming from you ;)?

Well wouldn’t it be great if you could just change an object’s property and any object that observes that property gets notified of the change automatically, but without having to write all the plumbing to make that happen? Yes. So what we want is to observe a property (or, rather, a key) and be notified when its value changes. Hmm… key… value… observing — Key-value-observing!

Let’s focus our attention on this observing term for a moment. If you’re up to par on your software design patterns, you’ve probably heard of the observer pattern written by the Gang of Four (GoF). The observer pattern is a great generalized solution that allows one object to observe (or listen for) changes or get notifications on another object, but in a decoupled way. Take a look at the following diagram that shows the observer pattern.

kvo-bindings-observer-pattern

See how the class Bar inherits the FooObserver interface? This decouples the Foo object from caring about the specific underlying type and only cares that an object inherits the FooObserver interface. For every object that inherits the FooObserver interface and registers with a Foo object, the Foo object will notify each observer after some change has occurred. Pretty cool, eh? But what does all this mean for the SproutCore framework? Well, as you may have guessed by now, SproutCore takes advantage of this observer pattern as a central corner stone towards making KVO and bindings a reality. Let’s go back to SproutCore now and see this observer pattern in action.

Part 2: Minding Your Ks, Vs and Os

All objects in SproutCore ultimately derive from SC.Object, and when you make your own class that derives from SC.Object is looks like the following example:


MyApp.User = SC.Object.extend({
  /* add your class's special properties and methods here */
})

The User class above now inherits all of SC.Object‘s properties and methods. But if you first shift through the code that makes up SC.Object (object.js in the frameworks/runtime/system directory) you don’t see any kind of observation logic. All the observation logic is actually contained within a mixin called SC.Observable (observable.js in frameworks/runtime/mixins directory). The SC.Observable properties and functions get added to SC.Object. And since that functionality is now part of SC.Object that means all objects that derive from SC.Object also get SC.Observable logic. Okay, great. Now that we’ve located the observation logic let’s dig in.

Although there is a lot of functionality in SC.Observable let’s focus on a select few functions, namely set, addObserver, removeObserver… Wait, what were the the last two functions called again?! addObserver and removeObserver. Doesn’t that sound awfully familiar? Yep. Okay, take a moment and look at the declarations for addObserver and removeObserver, you have the following:


addObserver: function(key, target, method, context)

removeObserver: function(key, target, method)

The addObserver method takes four parameters. The first argument is a key (a property) of the object we want to observer. The second argument is a target which is the the object that wants to be notified of changes to the given key (again, property). The third argument is a method that is to be called on the target so that the target is actually notified of changes to the key. The fourth argument, context, isn’t important for this post, but it is passed to the target when it’s method is called to help give additional information about the notification.

The removeObserver method is almost the same, but it takes three arguments instead of the four. And as you can guess the method is to remove a target’s observation of a given key.

By assigning a value to a SproutCore object’s property using the set method, set will assure that the object’s that are observing the given property are notified, which will happen either immediately or later on. I’ll get to what “later” means soon.

So this is good stuff. We now have some important concepts about KVO under our belt. Now its time to see what this actually means. What we’re going to do is create a very small SproutCore application to get some objects set up, and we’ll be using a browser’s JavaScript console to see what is happening in real time as we hook the objects together. Use Firebug for Firefox or the JavaScript console that already comes with Safari and Google Chrome.

Go ahead and create a new SproutCore application using the sc-init tool and call your application MyApp. Great. Now, to keep things simple so that we can follow along with what is happening, we’ll create two basic SproutCore objects. The first object is an object whose properties we will change. The second object will be observing the changes. Create two new JS files under the app/my_app directory and call them user.js and the second monitor.js. In the user.js file, enter the following code:


MyApp.User = SC.Object.extend({

  firstName: '',

  lastName: '',

  age: 0

});

And for the monitor.js file enter the following:


MyApp.Monitor = SC.Object.extend({

  notifyPropertyChange: function(sender, key) {
    console.log( 'property %@ set to %@ for object %@'.fmt(key, sender.get(key), sender) );
  }

});

Good. For the monitor object, we’re just going to be watching for changes to a user object and writing information about it to the JavaScript console. (Note that for the method notifyPropertyChange we could have equally not provided any arguments but still get notified, minus any information. As well, you can add on another two arguments, value and rev. The value argument isn’t currently used in SproutCore and rev is beyond the scope of this post).

Alright. It’s time to fire up your browser of choice and follow along in the JavaScript console. I’ll be using Apple’s Safari.

In your console, first create an instance of a User object like so:

var user = MyApp.User.create();

Now create an instance of a Monitor object:

var monitor = MyApp.Monitor.create();

Perfect. We want the monitor object to observe a property on the user object. Let’s make it observe the firstName property. We do this by entering the following:

user.addObserver('firstName', monitor, 'notifyPropertyChange')

So this now makes the monitor object observe the user’s firstName property. Now let’s see what happens when we modify the first name. Enter the following:

user.set('firstName', 'Joe')

If everything went okay, what did you just see happen in the console? Did you get something that reads like the following:

property firstName set to Joe for object MyApp.User:sc263

You did? Success! Congratulations you have successfully got the monitor object to be an observer of user object. You’re now on your way to understanding KVO!

If you want to know if a property of an object does have observers you can call the object’s observersForKey** method, like so:

user.observersForKey('firstName')

You’ll get back true since the property does have an observer. What happens if you change the value of the lastName property of the user object? Let’s find out. Enter the following:

user.set('lastName', 'Doe')

Nothing got outputted to the console. That’s because the monitor is not observing the lastName property; however, if you check the value of lastName it was updated properly.

We’ve got to the point where we can now see how the SproutCore framework is making use of the observer pattern to act as a building block for key-value-observing. Now we’ll look at what builds on top of KVO and the observer pattern: bindings.

Part 3: The World is Nothing but a Bowl of Bindings

I will fully admit that when I first crossed paths with SproutCore bindings concept I was a bit mystified about what it was and how they actually worked. So if you feel like you didn’t or still don’t get bindings don’t feel alone. That being said, after working with the SproutCore framework to do my work, I quickly became comfortable with the idea of why they are so darn useful. Let me see if I can walk you through it.

The central premise of a binding is to connect one object’s property with another object’s property and communicate changes between those properties. Really. That’s it. All we’re doing is keeping properties in sync. Take a look at the following picture.

bindings-basic-concept

Above we can see that on the left there is an object A that has a property named foo, and on the right there is an object B that has a property named bar. The binding object you see in the middle is what acts an the intermediary, or go between, in assuring that when foo is changed then bar is updated with the same value. And when bar is changed that foo is updated with the same value. We can see this in the following diagram:

bindings-how-it-works

Okay, that’s cool. The concept seems kind of trivial after you take a step back and look at it. And SproutCore is designed so that working with bindings to synchronize the values of properties is simple, such as in the following code:


var objA = SC.Object.create({

  foo: ''

});

var objB = SC.Object.create({

  bar: '',

  barBinding: 'objA.foo'

})

That’s all it took to bind the properties together. All we had to do was add barBinding as a property of objB and assign the value objA.foo to it. SproutCore takes care of the rest automatically. In fact, let’s give it a try! Remember the SproutCore app we made back when discussing KVO? Go ahead and reload the page if your browser is still has it open. Now open up the JavaScript console and begin by typing in the following:

var objA = SC.Object.create({ foo: ''})

We have objA loaded into memory. Enter the following into the console:

var objB = SC.Object.create({ bar: '', barBinding: 'objA.foo' })

Now we have objB loaded into memory and its bar property is bound to objA’s foo property. Fo’shizzle. If you do a get on either property they will both have empty strings, which is what we expect. Now let’s go ahead and change the value of foo in objA. Type in the following:

objA.set('foo', 'cat')

Go ahead and check the value of foo by calling objA.get('foo'). The value should be cat. And because foo is bound to bar that must mean that bar is cat too! Check by calling objB.get('bar'). Yes! We see that bar is now… an empty string?!? Oh no! What did we do wrong?! Remember back when I talked about KVO and I said that when you call the set method to modify the value of a property, the observers of the property can get notified either immediately or later? Well this is the later part I was refering too. Surprise!

When you use bindings in SproutCore they do transfer the value from one property to another but it is deferred. The changes that go through bindings actually get queued up. Why? Welcome to the world of SproutCore’s run loop mechanism. Yay, yet more to know ;).

I won’t say too much about the run loop since that’s a big topic in and of itself. However, all you need to know is that the run loop is a central device to coordinate how events get propagated and property values get changed using bindings, among other things. So what does this mean for us? It means that we have to kick the run loop to get things rockin’. Let’s go back to our JavaScript console. If you haven’t done anything after the last step we took (objB.get('bar')), then go ahead and type in the following:

SC.RunLoop.begin()

And now type this:

SC.RunLoop.end()

Finally, check the value of objB’s bar property by once again calling objB.get('bar'). Holy crap on a cracker! It worked! bar is now set to cat! As Cartman from South Park likes to say, “sweeeeeeet”. Since we’re on a role, let’s change the value of objB’s bar property by first doing the following:

SC.RunLoop.begin()

Now go ahead and change the value of bar by entering objB.set('bar', 'dog'). Finish with the following:

SC.RunLoop.end()

Now check the value of foo by entering objA.get('foo'). It’s dog! This is great. We see that the binding has actually synced the properties foo and bar.

While you may have this sense of warm, fuzzy feelings, you may also have this other thought in the back of your head saying what we did is very cool, but I don’t get how SproutCore really got the properties connected. All I see is this special property called barBinding. What did SproutCore actually do? If you didn’t have this thought rolling around in your noggin’ I’ll pretend that you did. Work with me here.

It’s time to pull back the curtains and see what’s going on behind the scenes that make this seemingly trivial binding mechanism work.

Part 4: Deeper Into the Binding Abyss We Go

In SproutCore bindings are objects just like anything else. No special magic here. That means you actually have to create an instance of a binding and set it up to connect properties together, but SproutCore takes care of that for you. And bindings work like other objects that just want to observe the changes to some other object’s property. That would mean, yep, that bindings are leveraging KVO. And if they are leveraging KVO then its a good bet that they are probably adding themselves as observers to an object. Are you recognizing a running theme going on?

Let’s go back to the SC.Observerable code in the observable.js file. If we look around the file a bit more you’ll come across a method called bind that has the following declaration:

bind(toKey, target, method)

This method is what you can use to do manual binding on an object’s key. If you read the comments for the method it says that this is the manual equivalent of doing the more traditional propertyBinding: 'property path' approach. Ah, interesting. Looking at the body of the method you’ll notice that a binding object gets created:


// Starting at line 1068 of observable.js (SproutCore v1.0 Beta)
var pathType = SC.typeOf(target) ;
if (pathType === SC.T_STRING || pathType === SC.T_ARRAY) {
  binding = this[toKey + 'BindingDefault'] || SC.Binding; // 1) Get the binding class
  binding = binding.beget().from(target) ; // 2) Now create the binding
} else binding = target ;

Basically we see that the binding is either being derived from a path (a property path) or it is the target argument. It’s the path we’re focusing on. I added comments just to make it a bit clearer. The given target (an object) is assigned to the binding’s “from” property. This is one end of the binding. What about the other end? Look further down the body of the method and you’ll see these lines of code:


// Starting on line 1075 of observable.js (SproutCore v1.0 Beta)
binding = binding.to(toKey, this).connect() ;
this.bindings.push(binding) ;

Above we now see the called object being passed to the binding’s to method. So the object is now assigned to the binding’s to property — the other end of the binding. The binding has a from and a to. This seems to imply direction. It does. With bindings we can control the flow of information by manipulating what is actually assigned to a propertyBinding property. However, for now, let’s not worry about manipulating flow and data being passed through a binding. We’ll just keep focusing on the basics. The default binding used will make sure that two properties are always in sync with each other.

Right after a binding’s to property is set the final thing to do is call the binding’s connect method. Despite what you might think, the call to connect doesn’t bind properties together immediately. Instead, the bind object is passed to a queue to then later connect properties together. If you’re asking if this has anything to do with SproutCore’s run loop mechanism, you’d be right.

The real guts and the glory happens in another method called _connect which is intended to be private. You can find the method starting on line 347 in the observable.js. There’s a bunch of code going on here, but just laser in on two lines: line 379 and line 384, where you’ll see the following:


SC.Observers.addObserver(path, this, this.fromPropertyDidChange, root) ; // 379

SC.Observers.addObserver(path, this, this.toPropertyDidChange, root) ; // 384

Notice anything that stands out like a sore thumb? It would be the addObserver method. Hello old friend. We’re right back to where we started. Yep. The binding is just leveraging KVO and the observer pattern so it can be notified when either a particular property on the from object changes or when a property on the to property changes. There’s obviously a lot of code to make this all happen, but it rests on the fundamentals. There is no spoon.

That was a lot to take in and we haven’t even had a chance to do anything in part 4 of this blog post. Well, guess what? Let’s jump back into our JavaScript console and take the bind method for a ride.

First, reload your web application we created earlier on so we can start fresh. We’re going to be using our trusty objA and objB that we’ve used in the last few coding exercises in this blog entry. Create objA like so:

var objA = SC.Object.create({ foo: '' })

And go ahead and create objB like so:

var objB = SC.Object.create({ bar: '' })

Notice that we didn’t include the barBinding this time because we’re going to manually create the binding with the bind method, which we’ll do right now:

objB.bind('bar', 'objA.foo')

Great. We’ve got the binding preped. Let’s go ahead and modify the value of foo:

SC.run(function() { objA.set('foo', 'cat') })

The run method is just a more convenient way of executing the run loop with a given anonymous function. If we check the value of bar and foo, what do we get? cat! Awesome. The manual binding worked. Now let’s go the other way:

SC.run(function() { objB.set('bar', 'dog') })

And what do we get when we check the values of the properties? dog! We are at zen with the universe.

Part 5: The Long Journey Home to propertyBinding

Great we’ve figured it all out. The observer pattern, KVO and bindings. It took some time but hopefully you found the journey worth it. Good luck and thanks for all the fish.

… But wait! There’s one more thing we haven’t figured out. Just how does SproutCore detect the propertyBinding on an object and covert it into a actual binding object? Ah, yes. Let’s tackle this final puzzling question.

Jump over to the SC.Object in the object.js file and take a look and the class’s initialization method init starting on line 446. The body of the method is pretty small but there’s definitely one import line that speaks volumes to us: this.initObservable(). Initialize observable, eh? Hmm. Okay, now let’s jump back over to the SC.Observable mixin in the observable.js file and go to the initObservable function. Looks pretty meaty, right? Not to worry. We’ll just go to line 843 where bindings get created. And here’s the code:


this.bindings = [];
if (keys = this._bindings) {
  for(loc=0;loc<keys.length;loc++) {
    // get propertyKey
    key = keys[loc] ; value = this[key] ;
    var propertyKey = key.slice(0,-7) ; // contentBinding => content
    this[key] = this.bind(propertyKey, value) ;
  }
}

The logic above is iterating over the object’s array called _bindings which is a pre-compiled list of properties that were already determined to have a key with a suffix of “Binding”. The suffix “Binding” is sliced off from the key to give us the actual property name. With the key and it’s assigned value, the object’s bind method is called to set up the binding. Okay, great. This partly answers our question of how the bindings are set… but where did this pre-compiled array of properties that have keys with “Binding” as a suffix come from? More to discover! And you thought this would be just a walk in the park ;). We’re almost there. There’s one final piece to the puzzle.

When an object is created using the SC.Object‘s create method, you can extend it with your own properties and methods. As well, when you extend a class to create a new class you use SC.Object‘s extend method. Okay, you’re asking yourself so what? Both of these methods are two sides of the same coin to our final answer.

When you extend a SproutCore class, the extend function does some interesting stuff. One of those interesting things is to create a new function that will be the class’s constructor, which if you go to line 240 in object.js you will see it. In the constructor it makes a call to SC._object_init. SC._object_init is the actual method that gets called first when you create an instance of a class in SproutCore. The method will in turn call the init method that will initialize the object’s observers. We’ll come back to SC._object_init in a second. Further down in the extend function is another interesting statement on line 256 where there is a for-loop making calls to SC._object_extend. What’s SC._object_extend? Just wait. Switching back to SC._object_init, go to line 376. What do you see? Why it’s another for-loop making calls to SC._object_extend. This is the final piece to the puzzle.

Go to the function SC._object_extend on line 37 in the object.js file. If you read the comments for the function you’ll see a statement that says the following:

prepping a list of bindings, observers, and dependent keys

Preparing a list of bindings? Ah-ha! A clue. There’s a lot going on inside of SC._object_extend but the function is basically taking the properties and methods from one object and sticking them on to the object that is to be extended all while doing some special processing. Take a look at line 65 that has the following statement:

var bindings = base._bindings, clonedBindings = NO;

Yes! We’ve found were the base object’s _bindings array is added. Now where does the array get its content from? Inside the for-loop that iterates over the keys, take a look at lines 90 to 101 where you’ll see the following:


// Possibly add to a bindings.
if (key.slice(-7) === "Binding") {
  if (!clonedBindings) {
    bindings = (bindings || SC.EMPTY_ARRAY).slice() ;
    clonedBindings = YES ;
  }

  if (bindings === null) bindings = (base._bindings || SC.EMPTY_ARRAY).slice();
  bindings[bindings.length] = key ;

  // Also add observers, outlets, and properties for functions...
}

From above, look at the second line down. It’s an if-statement that checks if the key has the suffix “Binding” — Eureka! We’ve finally found where all those properties with the word “Binding” get collected to be later processed in the initObservable in SC.Observable.

Now you finally know how we got from the propertyBinding: 'property.path' approach to actually making a binding between two objects’ properties.

That’s All Folks!

There has been a lot to take in to really understand how two central concepts in SproutCore, KVO and bindings, really work. While there are still many more things to know about SproutCore, this will hopefully take a lot of the mystery out of what it really going on behind the scenes.

Oh ya. At the beginning of this post I told you to get a beer. I’m sure by now you’ve probably ended up drinking three or four beers and that means you forgot what you read half way through ;). Sorry.

Have fun!

** (Update: Feb 14, 2010) The observersForKey does not function correctly in SproutCore v1.0. It now throws an type error when provided a key string.