Ember Computed Properties and the Perks of Uniform Access


In almost any object-oriented programming system, you’ll sometimes have an object whose properties can be composed into more meaningful units of data about that object. For example, an address that you might use to send an envelope of papers consists of a number of properties — a street address, a city, a state, and maybe some kind mail-system code (in the US, that’s typically a 5 or 9 digit ZIP Code). These all form a single aggregate data unit you might want to fetch, but they’re also discrete units that you’ll probably do well to keep separated. So what? Well, first a quick diversion…

The Uniform Access Principle

Quoth the Wikipedia:

The Uniform Access Principle was put forth by Bertrand Meyer. It states “All services offered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation”. This principle applies generally to the syntax of object-oriented programming languages. In simpler form, it states that there should be no difference between working with an attribute, precomputed property, or method/query.

The idea then is pretty clear: let’s hide from a consumer of our object state the specific way in which it was implemented. We’d rather have it be the case that all things look the same from the outside, regardless of how they actually are on the inside.

In our concrete address example, we could in vanilla Javascript expose to the world a mailing address result. It would take the streetAddress, city, state, and zipCode properties of our object and spit them out as a two line blob. But to do that, you’d have to make it a method on your object, rather than a property. That means your method of getting the data has to know how to was implemented. They look different:

var city = address.city;
var address = address.getEnvelopeAddress();

It works. And it’s not really a problem at the scale of a single example. You’ll just remember that city is a property an address has, and that an envelope address is accessed via the getEnvelopeAddress method. Most programmers are probably even used to this sort of interface, as it’s what you get in many languages.

A Basic Example of Uniform Access for an Ember Computed Property

One of the first things people find meaningfully weird about Ember, coming from regular Javascript, is that you’re told to never access properties directly. You’ll find lots of documentation and community members advising that you never use address.city to discover the properties on an object. At first, this mostly just seems strange, even that they’re intentionally being obtuse in telling you to use address.get('city') instead. It’s longer and meaningfully more awkward to type.

But hidden in these recommendations to always get properties this way is something really awesome and great: inside of an Ember application you have real meaningful uniform interfaces to all properties on all objects, even ones that require putting together a number of properties or doing some kind of computation. How?

One of Ember’s most interesting ideas is “computed properties”, which allow us to have universal access. So we can have:

var address = Ember.Object.create({
    streetAddress: '123 Fake Street',
    city: 'Springfield',
    state: 'IL',
    zipCode: '62710',
    envelopeAddress: function() {
        return this.get('streetAddress')+'\n'+
                this.get('city')+', '+this.get('state')+' '+this.get('zipCode');
    }.property('streetAddress', 'city', 'state', 'zipCode');
});

var city = address.get('city');
var envelopeAddress = address.get('envelopeAddress');

It’s different under the hood, but to the outside world you get the city just like you get the envelopeAddress. There’s no need for the accessor to know or remember if they’re supposed to call a function or just access a property, because either gets the same result. That’s the core of the Uniform Access Principle, and how Ember makes it work in a language it typically doesn’t.

Some Further Consideration on Ember Computed Properties

Once you get over the slight awkwardness of using this.get('property') instead of this.property, you can stop worrying and just love the power and simplification of uniform access.

The complaint about this whole thing is that Ember has broken a fundamental and well-established Javascript syntax. People are used to getting properties through one syntax and getting method results for a different one. As I hope this article’s structure has made clear, there are really two parts of that complaint: one is that you don’t think the Uniform Access Principle has value, and the other is that you don’t like how Ember has built it into a language (Javascript) which doesn’t typically offer it. Separating the two possible objections gives us better understanding of what’s at play.

Speaking for myself — having never before worked in an environment that provided an easy and universal interface to object properties of any arbitrary internal complexity — I think it’s pretty great. Once you get over the slight awkwardness of using this.get('property') instead of this.property, you can stop worrying and just love the power and simplification of uniform access.

Another bonus of Ember’s computed properties, that I’ve completely glossed over so far, is that you get immediate change awareness as a result. That weird-looking function() {}.property() syntax is used by Ember, such that when anything in that property declaration changes, your computed property will too. When your template is using a computed property to display a list, and a user action knocks a member from that list, or changes which contents that list should have, your template’ll just effortlessly change to match. Method calls from complex data access definitely don’t get you that!

I hope I’ve given you a good grounding to understand computed properties, though I’ve not really explained them fully. Ember’s documentation of computed properties is a great place to start to master them if you’re ready to dive in. And if not, I hope you’ve got a better sense of where Ember’s insistence on this.get() and this.set() is really coming from.

About David Hayes

David likes learning, solving hard problems, and teaching. He bikes a lot, and lives in (and loves) Colorado. You can find him on Twitter as @davidbhayes and check out his latest hobby-project, Quodid, a monument to his love for pithy bits of wisdom.

Leave a Reply

Your email address will not be published. Required fields are marked *