I’ve been using ember for 2+ years and the more I deal with a single page application that exists in memory for an indeterminate length of time, the more tenets of functional programming I embrace to bring some sanity to the chaos. The problem with ember is that it is more class or object based than functional.
The move to ember 2.0 will see ember become more functional but I think it needs to go further and drop a lot of the class based paradigms to make it more robust.
I’ll quickly run through the important tenets that could make your code more robust if you can employ them:
You should always strive to make your functions as pure or side effect free as possible. Wikipedia gives the following definition for a pure function:
A pure function is a function where the return value is only determined by its input values, without observable side effects
Another way of expressing the above is that a pure function will always return the same value when given the same arguments.
Below is the most basic of basic examples of a pure function
1 2 3
This function is pure because it will always return the same result, given the same input. It only reads local variables and it only writes to local variables. This is also sometimes referred to as referential tranparency because the expression can be changed with its value without effecting the behaviour of a program. For example if we used the
addOne function like this:
We can replace the expression with its value and still get the same result:
1 2 3
A simple example of an impure function is below:
1 2 3 4 5 6 7 8
The side effect of this function is that it changes the value of the
number variable each time it is executed. The example above is not referentially transparent because if we call
sideEffect with 3 we would get a different result each time.
On the surface dealing with only pure functions is very limiting, we would need to avoid things like
new Date or
Math.Rand because they always return a different value.
console.log is also on the banned list because it accesses a global variable. In fact, any function that takes an object as an argument is potentially subject to impurity. The DOM is one big huge stateful side effect waiting to happen.
Ember’s Handelbars helpers can be pure functions but I have seen an RFC recently that wants to add all sorts of state and life cycle events which is something that made me shudder. I worry that if this rfc is pushed through then it will complicate something that is very useful and can be side effect free.
Purity and Idempotence
Idempotence entered the vernacular or at least resurfaced when REST went mainstream. An idempotent operation is one that has no additional effect if it is called more than once with the same input parameters. For example moving an item from a set can be considered an idempotent operation or deleting a record by GUID is idempotent becuase the row stays deleted.
Purity and idempotence are completely orthogonal, a pure function does not have to be orthogonal and vice versa. An idempotent function can cause idempotent side effects, a pure function cannot.
In functional prograaming, the ideal situation is that there is never mutation. I blogged previously about some of the benefits of immutability and gave an example of how it might be used.
One of the traps I fell down when I first started developing with ember was to observe changes on mutable arrays like this.
1 2 3
I see this type of code in a lot of stackoverflow answers and blog posts but I now consider this to be an antipattern. Two way databinding was one of the things that first drew me to ember but ended up causing me no end of pain. I think two way databinding still has its place for binding simple literals like an input’s value attribute to a string prop of a value but binding object to object causes pain. I believe in ember 2.0, binding will be one way only by default and this is the right move. You can stop this now by ensuring you use
Ember.computed.oneWay instead of
1 2 3 4 5 6 7
As Charles Lowell rightly pointed out in the comments, it is possible to create
readonly computed properties that will raise an exception if a
set is an attempted.
I’ll certainly be using this from now on.
Libraries like om in clojurescript use diffing on their immutable datastructures to great effect to negate needless re-renders with reacts virtual DOM.
But the main reason that I am starting to see the main use case for immutability is that, it makes your code much easier to reason about and you can avoid side effects using immutable data structures. For me, the biggest thing about using immutable data structures is that I am completely safe from some unkown mutation happening which in a long running single page application is great for my peace of mind. I’ve been surprised too many times in the past.
You don’t have to use a library like seamless-immutable but you should try and tranfrom or create new objects or arrays rather than mutating existing objects. You should favour
forEach must have a side effect somewhere to accomplish anything. The only time I would use
forEach is for something like this:
Imperative programming works by changing programming state to produce answers. Conversely, functional programming produces answers through stateless operations.
A good example of the contrast is looping, an imperative approach is to use looping:
1 2 3 4 5 6
The loop produces its results by constantly changing the value of
x. A functional approach would use recursion:
1 2 3 4 5 6 7 8 9 10
Functional programming requires us to write stateless expressions and keep our data immutable.
Back to The Real World……and Ember
The last thing I worked on was a custom query builder where the user builds a query on the fly from the html elements he is presented with. Query items can be added and removed: If I had attempted something like this 12 months ago, I would have used rampant mutation, observers and two way binding in a huge chaotic side effect soup. I have my battle scars and I see the world differently. I will now detail my solution. I have created this jsbin that you can play along at home with and is a pretty damn accurate duplicate of how I solved this.
The truth of the matter is that ember is very, very, very stateful and adheres more to a class or object based methodology. If you want to reference data structures in your templates then you need to create member properties and reference them.
My goal for any new piece of code that I create is to keep things as side effect free as possible. I will most definitely never use the
Ember.observer primitive, I use few computed properties if any and rarely use two way databinding. I will work with immutable copies of anything persistable. I want to keep surprises to a minimum and I want to keep things in my control and not be working or waiting for the run loop which is outside of my control.
In this custom query example, there is only ever one active query that you are manipulating, you are either building a new one or you are updating an existing query. These queries are persistable and I have modelled it as a parent query that contains a child collection of query parts. Here is the ember data CustomQuery definition:
1 2 3 4
And here is the queryPart:
1 2 3 4 5
My main goal for working with instances of these ember-data models is to not work with them. I am going to create copies of the data structure and work with those and only copy them back into the models when I want to persist anything. The last thing I am going to do is to use two way databinding to bind directly to the model properties. I have been down that path and it is the road to hell.
At any one time, we are dealing with a collection of query parts and we have query-builder component to add and remove query parts. Below is a screenshot of how the elements look:
IndexRoute in the jsbin, either creates an empty array and assigns it to a
queryParts variable that is passed to a
query-builder component, or if we are dealing with a persisted query from the models above then we create a raw hash to pass to the component:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
The user can navigate to the
IndexRoute via a link that will have the custom query id in the query params that you can see on
line 5 of the above code. I am creating a hash rather than using the ember-data model directly to keep things side effect free. I have already made my life much easier.
Here is the how query-builder component is referenced on the parent template or the index template in the jsbin. The binding of the
queryParts that are passed into
query-builder are sadly still two way bound at this time of writing with
ember 1.11.1 but we will work with them as if they were one way bound.
Below is the template for
2 to 4, a
query-part component is rendered for each part of the query. The template for
query-part.hbs is below:
query-part component will fire off queries in response to either user input in the textbox or changing the query part operator in the dropdown.
Below is the code for the
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
We want to adhere to data down and actions up. So queries are bubbled up from this component to the controller.
If input is entered into the text input, the
keyDown handler on
line 35 calls
line 12 that will
debounce a call to
The code in
executeQuery on lines
15-34, could definitely be accused of being more jQuery than ember. If that is the case, then I am guilty as charged. I am using simple selectors to extract the values from the element rather than relying on two way databinding. I don’t want any surprises about values not being sync’d, I just want to extract the values from the elements when the query is run. There really is no need for it to be any more complicated than that.
I then bubble the newly constructred immutable data structure up to the parent component by calling the
modifyQuery action. I don’t necessarily need these structures to be immutable but I want to guard against any side effects I might encounter unexpectedly. This action is then bubbled up to the controller where a it uses the raw hash to execute a
findQuery on the main data that the query is filtering:
1 2 3 4 5 6 7 8
When it comes to saving the query, the
query-builder component calls a
CustomQuery model and persists it or overrides the existing
queryParts collection of the existing instance:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
There are only 2 parts in this piece of functionality where I deal with the actual ember-data instances. The first is when I am creating copies of the structures to feed to the components and here when I am persisting the changes back to the server.
Congratulations if you made it this far, this is a long post. Staying side effect free and dealing with pure functions is next to impossible when working with something as stateful as the DOM. Ember also is very stateful and class based. I’ve used a real world example because there is no better example to illustrate just how challenging it is. I have 100% failed on the pure function front. But I’ve tried to stay as side effect free which for me means dealing with copies of anything persistable, avoiding observers, computed properties and two way data binding wherever possible. I’ve tried the other way and it is not pretty. The code I’ve described will give me a lot less headaches than other ways I might approach this.
I’m interested to see if we can take a much more functional approach with ember 2.0 but the rfc that wants to pollute handlebars helpers with state and life cycle events is not a step in the right direction.
I’ve heard of the benefits of functional programming for years but I now realise how sensible they are and how they lead to more robust code. When working in the chaotic world of the single page application, they make nothing but sense.
I would love any feedback at all on this. Good or bad, state your case.