Computed properties are built on top of the observer pattern, and let us take one or more properties and reactively transform or manipulate their data to return some new value. The computed property updates whenever one of their dependent values change, ensuring that relationships are always kept in sync.

You’ve probably seen this example a number of times:

This is great! We can now use fullName like we would any other property on the object that it sits in.

[Computed properties are] … super handy for taking one or more normal properties and transforming or manipulating their data to create a new value.

With computed properties, we can also avoid needless computation through caching, which prevents re-computation even though the input has not changed.

Computed property macros

As our application grows larger and more complex however, we might find that we have repetition in our computed properties.

In order to make our code DRY and testable, it’s a good idea to think about refactoring some of our shared computed properties into computed property macros. A computed property macro can really be thought of as a function that returns the definition of a computed property (you can return an observer as well). Ember ships with a few handy ones out of the box.

Let’s say we decide that instead of calling the property fullName on our object, we want to use name, for whatever reason. A naïve approach might be to do something like this:

An anti-pattern

This might seem superfluous, and it is. Let’s use one of the computed property macros (computed.alias) that Ember ships with instead.

That’s better! Computed property macros let us re-use common functionality and share them throughout our app, and avoids repeating the logic every time we need it. Because the above use case is so common, the fine folk in charge of Ember.js have included it as a default computed property macro.

Observers

Unlike computed properties, observers don’t return new values. Instead, they only observe changes to properties, and are synchronously invoked whenever the dependent properties change.

For example, let’s say we have an Ember.Object representing a Child.

The Child has properties for her first and last name, and whether or not she is at home. Note the use of Ember.computed.not in the isOutside property, which simply means that whether or not the child is at home is inversely related to whether or not she is outside. With computed properties, this relationship is always maintained, and we can be sure that our interface also updates accordingly when the dependent value changes.

The notifyParentsWhenAtHome observer then observes the property isAtHome, and if that is true, we notify the child’s parents the child’s full name and the exact time she returned home.

A Functional Reactive Example with Ember Data and Promises

As a simple example, let’s imagine we’re building an app that has 3 models: Teams, Players and Coaches. A Team has many players, and one Coach. I assume some familiarity with Promises in this example.

Players and Coaches

These are very simple models and are quite self-explanatory.

Teams

Let’s say that the Team’s score is made up of the sum of all its Players’ scores, multiplied by the Coach’s score. We first create two computed properties, coachScore and playersScore, which return a single score for the Coach and Player respectively. Because a Team only has one Coach, it’s easy to get the Coach’s Score using a computed alias.

As the Team has many Players, it’s a little bit trickier to calculate the sum of their scores. Unfortunately, we can’t do:

computed.alias('players.score')

Because the players property returns an array of Player models, the array itself does not have the property ‘score’. We actually need to map over each Player’s score, and then add them together. Using functional programming, we can make use of Ember.Array#mapBy to first return a new array of all Player scores.

We then reduce the array down to a single value by adding them all together. To get the Team’s score (score), we just multiply the Coach’s score with the Players’ score.

After defining these 3 computed properties, we’ll have three functional and reactive properties that can be then used in our template. Whenever a player’s or coach’s score changes, the team score updates immediately in the user interface, without us having to imperatively update DOM elements and the like. Awesome!

A Note on Dependent Computed Properties

Because you can have computed properties observe other computed properties, it’s easy to build overly complex data relationships. It’s also possible to create circular dependencies (i.e. infinite loops), so be careful about how deep down the rabbit hole you go.

Building Your Own Computed Property Macros

In another post, I wrote about writing your own computed property macro to do simple text search. I won’t go into the details here, but have a read if you’d like to see how you can write your own macros. If you notice your computed properties being repeated in multiple areas in your app, refactoring them into re-usable macros are a great way to improve the maintainability and testability of your app.

I also recommend looking at ember-cpm by @miguelcamba, which is a collection of more computed macros, available both as an ember-cli addon and for globals based Ember apps.

Why You Should Care

If you’ve ever built an app with complex user interactions without a framework like Ember before, you’ll know how difficult it is to effectively manage the flow of data through the app.

As front end developers, we strive to build delightful and reactive experiences our users. Using modern tools like Ember.js and functional reactive techniques help us write more declaratively, freeing us from the shackles of low level DOM manipulation and jQuery spaghetti.

Recommended Reading

As always, I hope you’ve enjoyed reading! Tweet me if you have any questions.

This post started its life as a draft from a few months ago, but finished from inside the @DockYard offices. Thanks for letting me hang out with you for the week!