When all you have is a hammer...
As Alan Kay says, “A change in perspective is worth 80 IQ points”. One interpretation of that is the way we look at the world colors the kinds of solutions and approaches we take to solve the perceived problems. Take the case of the three most popular frameworks for building rich client side applications (sometime also knows as Single Page Applications or SPA), namely, ReactJS, Angular and EmberJS.
All three are mature frameworks, being used with fairly complex websites running successfully in production. So when the question normally comes up, “which one should I use?”, it looks like any or all of them would work, right?
But then is there another way to think about this? Maybe the question is not which one to use, but rather, what is one trying to do…
HyperText Markup Language
The HyperText Markup Language (aka HTML) was invented by Tim Berners-Lee as an application of the more generation purpose SGML which was used to structure documents. The creation of JavaScript by Brendon Eich allowed for the ability to run code on the client side, in a sandboxed environment, in addition to rendering a document.
In order for this client side code to be useful, along with the introduction of the programming language, browsers also started supporting a way to access the in-memory representation of the document, both to read and modify it using JavaScript. The representation, came to be known as the Document Object Model or DOM.
The “look and feel” of the elements are then defined using the Cascading Style Sheets, which separates the styling of the document from the representation of the document. This is fairly unique as CSS controls not just the look and feel of the elements, but also the position of the elements, which means that the same structure can appear very very differently based on the CSS applied, as exemplified by the CSS Zen Garden Site.
So unlike regular desktop programming that depends on widgets build on top of the core rendering API, in order to build a client side interface that responds to user interactions on the browser, three things need to happen:
- Use of the DOM API to create the elements that are shown on the screen
- Having to code to run that changes the elements as a reaction to user interactions.
- Listening to user interactions using the Event interfaces.
[Side Note: We are ignoring the Canvas API for now, which provides a 2D Rendering Context like in the case of regular desktop UI programming.]
How we do approach this depends on how we look at the HTML document. There are three possible ways:
DOM as a tree
The first way we can think about it, purely as a developer familiar with the core DOM API, is as a tree of nodes. This is the internal representation. If we think of the world as a tree and then look to optimize the tree manipulation to build the API, we get ReactJS. The core idea behind React is to minimize the cost of making these changes. So it essentially builds an in-memory tree, does a diff with the existing rendered tree on the page and then performs the minimal number of changes to make the rendered tree same as the in-memory tree.
So to effectively use React, one thinks of converting the current “state of the application” into a tree and then letting the library (as the captain in Picard in Star Trek TNG says) “make it so”. One can also see this in the tutorial which focuses on event listening and DOM tree manipulation. For example, in order to make the representation and manipulation of the tree easier, it even introduced the idea of JSX.
Other use-cases, logically, like listening to URL changes, etc., are considered “non-core” concerns in this model. Also, given that the core idea is to build a tree given the current state, it also encourages the use of Flux Architecture which essentially tires to route all changes through a central routing mechanism so that the render part of the code remains mostly stateless and produces immutable new data.
DOM as a HTML document
If you consider the UI to be a collection of HTML documents (like traditional web pages where you think in terms of the text representation of the DOM), each with it’s own URI and associated templates for rendering text from data, you get EmberJS.
Again you can see this mental model in action in the tutorial which starts by talking about routes and templates! Of course, Ember does have concepts of re-usable functionality, namely, components that can be embedded and referred to inside the templates and data binding to ease the wiring up of data to the templates, but the core mental model is still in terms of routes and templates, wired using controllers.
DOM as a combination of components
Instead, if you consider the UI as a collection of Components, each with it’s own logic, template and CSS, you get Angular. This is one of the few frameworks to directly address the need for managing CSS as part of the component! As part of the rendering, each component is given an unique ID and the CSS associated to that element is indexed by the ID to make sure that the different CSS elements don’t “stamp on each other”. In addition, it uses data binding as one of the key mechanisms to wire up the rendered templates to the data.
The whole UI is thought of as a collection of components anchored within a “root” component and any changes are thought of as changing the component tree.
Web Components
One common theme that one sees in all the above, is the idea of “encapsulation” and extension of the HTML syntax to introduce the concept of “components”. This idea of encapsulation is a recurrent theme in computer programming and in fact is thought of as such a good idea, that the core HTML specification itself is evolving to natively support this idea in the form of Web Components. Since browser support for this is still evolving, Google’s Polymer Project is trying to make usage and adoption of this user by defining polyfills for all the older browsers.
Observations
As one can see, it’s not that one framework is inherently better or worse than the other, but rather that a given framework might be a better fit for a given use-case. Say for example, if the application complexity is around managing the state of the DOM nodes, like in the case of a busy “chat application”, then React might be a better fit. But if the need is to support a series of URI’s with deep linking, then Ember might be your cup of tee. On the other hand, if it is mostly a master-detail kind of application, the Angular might be a easier to structure the application with…
The title “when all you have a hammer…” is not meant to be judgement, as much as to say, based on the kind of nail you have, you might want to pick the right hammer! :-)