Wednesday, August 31, 2016

How Pure is your React?

One of the recommended patterns for using React is that all mutations to your application state should be pure.

Now what do we mean by pure? Before we get into that, let me first describe what we mean by application state

Application State
This is essentially React's version of what most other people call the model in MVC parlance. It is the data that you are rendering.

In React, there are two common patterns for representing your application state:
  1. The application state is stored inside of the various view components that comprise your UI. This is done using this.state from within a your view components.
  2. The application state is stored completely separate from the view components. That is, the entire object graph representing your application's data model is in it's own object, separate from your view components. That state data is then hierarchically passed down to your view components as props (i.e. html attributes).
For all but the simplest apps, I prefer the second method.

Model Mutations
A conventional MVC app might work like this: 
  1. You update (or mutate) the model
  2. You re-render all or a portion of your UI to reflect those model changes
There are a few twists on this pattern. 

For example, with some frameworks, model updates are detected (and UI refreshes triggered) by subscribing to change events on the model. Thus, you must make sure that all of your model objects are capable of broadcasting change events (this is how Backbone and Flex work). 

Other frameworks use dirty checking, comparing the old model to the new model, to figure out when the model has changed and when a UI refresh is necessary. This is how Angular works. The nice thing about this is that your model objects can be dumb. That is they do not need special "change broadcasting" plumbing.

React
React is somewhat different. It's technique is sort of but not exactly like the dirty checking scenario. But if React's dirty checking is to work correctly, you must ensure that all of your state mutations are pure

Pure
Now, back to the whole pure thing. Whether you put your application state inside your view components or you keep your state separate from your view, React wants your state changes (i.e. model updates) to be based on pure functions

A pure function is a function that doesn't change any state. It simply takes some arguments and returns a value. The return value is computed solely based on the arguments. It is a pure function. It has no side effects and mutates no state. Args in. Return value out. Simple.

So how can you update a model using a function that isn't allowed to update anything?

The answer, we don't technically update the model. Instead we replace the model with an updated version of itself. 

As an analogy lets compare two standard JavaScript methods of the Array object: array.push() versus array.concat().

Take a look at this example using array.push():

const a1 = [1,2,3];
a1.push(4);  
console.log(a1); //[1,2,3,4]

Using push, a1 is mutated in-place.

Now look at this example, using array.concat():

const a1 = [1,2,3];
const a2 = a1.concat(4)l
console.log(a1); //[1,2,3]
console.log(a2); //[1,2,3,4]

Using concat, a1 is left unchanged. But an entirely new array is returned.

So push()is a mutating method. concat() is more of a pure method.

React wants your model updates to be more like concat() and less like push().

Let's compare a conventional model update, with a React style model update. Suppose we were rendering a simple array:

updateModelConventionalWay(){
    this.state.list.push("New row");
    refreshUI(); //or UI is automatically refreshed on model change
}

updateModelReactWay(){
    const newList = this.state.list.concat("New row");
    this.setState({list:newList});
    //change detected because you set the state.
}

So to summarize, React doesn't actually want you to update your model. React wants you to completely replace your model with an updated version of itself.

The reason for this is two fold.
  1. Updating state is what triggers React to refresh the UI.
  2. Dirty checks is how React is prevented from refreshing every single component on the page.
The most efficient way to do the per-component dirty checks is to use the === operator. i.e. if oldState === newState then don't re-render the component. For example, you can define, in your view component:

shouldComponentUpdate: function(nextProps, nextState) {
    return nextProps.list !== this.props.list;
}

This would not work if you used push() but it would work if you used concat().

The Problem
As your application state gets more and more complex, doing these kind of updates can get cumbersome. Imagine you are developing an outlining tool. Your data model is a complex tree of nodes. You need to modify one tiny node deeply nested somewhere in the tree-structure. Making this update is super easy using good old fashioned mutations. It's not so simple using the recommended pure function techniques.

Also, you could naively make a deep copy of your entire object graph and then make the change on that. But then React would incorrectly conclude that every node in the entire tree is dirty and re-render everything. Also, you would be consuming extra memory and CPU cycles if you did it this way. 

What you really need is a smart copy, that copies the part of the tree that needs to be copied but reuses any nodes that are unchanged.

But this can be non-trivial for someone unschooled in the art of functional programming.

Functional Programming
Pure functions fall under the category of functional programming. As your data structures become more complex, you will need to become a better JavaScript functional programmer. For example, we already learned that you can use concat() instead of push() for arrays.

For objects there is a similar trick. Here is the mutating way to update an object:

const o1 = {x:10,y:10};
o1.x = 5; //o1 is mutated

And here is the non-mutating way using Object.assign():

const o1 = {x:10,y:10};
const o2 = Object.assign({},o1,{x:5});

For more complex object graphs, this can get ugly fast. So there is a tool provided by React called Immutability Helpers to make it easier to update complex object graphs. You will want to check that out. 

Performance
As you might guess, updating large object graphs this way can start to get expensive. This is true. But the creators of React would argue that it is even more expensive to unnecessarily re-render parts of your UI that don't need to re-render.

Also, there are libraries, like immutable.js, that provide immutable data structures (lists, maps, etc.) and functions for efficiently returning updated copies.

Work Around
With all that said, you can still use React in the old mutate-your-model kind of way if you really want to. You can do something like this:

this.state.list.push("new row");
this.forceUpdate();

The Functional Way
Proponents of React and functional programming would argue that designing your apps based on this functional style has benefits beyond efficient dirty checking. Functional programming can lead to more predictable, testable programs that are easier to understand and easier to maintain. That is unless you are totally new to functional programming, in which case the opposite may be true.

A few other parting thoughts
  1. In the React world, they don't use the word model. You will likely here the terms state, application state or store used instead.
  2. If you decide to keep your application state completely separate from your view components, and want to pursue the recommended functional approach, there is a helper library called Redux that can be used coordinate the interaction between model and view.

Monday, August 22, 2016

JavaScript: The Universal Language


Two facts about JavaScript:
  1. JavaScript is the universal byte code. It runs everywhere. 
    • Mac, Linux, Windows
    • Browser, Server, Command Line
    • Web Apps, Native GUI Apps (VS Code is a JS app)
  2. Nobody wants to write JavaScript in JavaScript. This is why we have so many languages that compile into JavaScript:
    • TypeScript, Flow*, CoffeeScript
    • Dart, Kotlin, Elm
    • GWT, Pyjamas
    • JSX

Tuesday, August 16, 2016

To Write Readable Code Know Your Audience

I like clean and easy to understand code. 

Like most programmers, I have encountered code that (to me) appears clean, elegant and easy to understand. And I have encountered code that is too clever for it's own good. 

I have personally written code that, at the time I wrote it, seemed clever and clear. Then, six months later, I couldn't figure out what I had written. It's not good when you can't figure out your own code.

But here is the interesting thing. I have been writing and teaching code for years. And one thing I have observed over and over again is that not every one agrees on what is clean, elegant and easy to understand. What's more, my idea of what is clean, elegant and easy to understand evolves over time.

Let me give you 3 examples of things that, at one point in my career, made code far less readable. And now, at least to me, make my code more readable than alternative techniques that do the same thing.

1. Callbacks. I still remember the first time I attempted to use a callback. It was forced on me by the tool I was using. It was needed to customize a Microsoft Access combo box. And your average Microsoft Access developer was not, in general, required to know about callbacks. The callback concept completely blew my mind. Very counter intuitive. 

Needless to say, I now use callbacks all the time, and consider them, when used appropriately, to be a valuable part of good, clean code.

Also, in retrospect, I realize that, as an Access programmer, I was already using callbacks unknowingly. That is because an event handler, like button1_onClick, is really just a type of callback.

2. Recursion. The first time I saw recursion, it was hard to understand and unintuitive. I tried to avoid it at all cost. Many of the things that can be done with recursion can be done using other techniques. But after having written 1000s of lines of code dealing with graph and tree structures, I now know that for many things, recursion is simply the most simple and elegant solution.

3. Functional Programming with Lambdas. Take a look at this chunk of JavaScript:

return 
  products
    .filter((p) => p.price < 100)
    .map( (p) => p.title )
    .sort();

There was a time in my career, when I would avoid this style of code like the plague. If I came across code like this, I would rewrite it in a more imperative way, just so I could comprehend it. 

Fast forward a few years, and, as you may have guessed, I now find this chunk of code to be perfectly elegant, concise and easy to understand. 

Know You Audience.
So here is the point: if you are writing code and you expect your code to be readable by others, you have to know your audience

My guess is that the average Google or Facebook programmer will be perfectly comfortable reading code that makes liberal use of callbacks, recursion and functional code style. Also, I am sure that if you checked out some random samples of recent code written by Google or Facebook, you would find these things.

On the other hand, a few years ago I had written an app for the state of California. This app was to be eventually maintained by a group of government programmers, who all come from a background that did not make use of things like recursion, callbacks or functional programming. So I explicitly tried to write my code in a way that they would understand.

So here is a question: should you dumb down your code to make it more readable to less experienced programmers? Or should you expect other developers to step up their game and figure it out?