High-level abstractions are one of the driving forces of technological and computing progress. Abstractions have allowed us to be productive and innovative by ignoring low level details. Overall, their advantage is indisputable. But there is a cost to abstracting. In mathematics, abstractions work by removing dependencies so a concept can be more widely applied. In programming, abstractions are often achieved by automating away low-level annoyances so we can focus on high-level solutions. Automation poses a few problems: loss of control, overreliance, and a disconnect between the user’s and system’s model (more on this in a bit)[1].
Let’s take a look at two examples of abstractions in the world of JavaScript which provide a unique perspective.
jQuery
Not many people would argue that jQuery is a bad thing (unless you’re David Mark), and I’m not going to either. For all the good jQuery does, there are very few disadvantages. Looking at the problem of automation, loss of control isn’t an issue thanks to its prototypal nature. The same can’t be said for overreliance. How many times have you seen a site that loads up 25kb of jQuery just to handle 1 click event? Or using jQuery to set CSS instead of just doing class manipulation? More importantly, overreliance leads to a dangerous problem: a disconnect between the user’s and system’s model.
Any time a user interacts with a system, they develop a mental model of that system. Good things happen when the user’s mental model is conceptually accurate with the system’s model[2]. If something works the way you think it does, interacting with it becomes easier. jQuery adds another level on top of the system (JavaScript) and this is where the problems start. Since jQuery is just a JavaScript library and not a complete abstraction, a disconnect in models arise.
Take JavaScript animations as an example. In the pre-library days, animations were done by messy setTimeouts/setIntervals. There’s no magic involved. A CSS property’s value is simply changed every few milliseconds. How are animations done in jQuery? The exact same way. Except most jQuery users don’t know that due to the simple function it’s been wrapped in. In fact, I’d argue they don’t even have a mental model for how animations happen. jQuery has abstracted that concept into oblivion.
According to Joel Spolsky’s Law of Leaky Abstractions, abstractions trade off work time for learning time. The problem is, however, that the majority of people using jQuery don’t learn how it works and what’s being abstracted. This widens the gap between jQuery and native JavaScript to a point where developers can be competent in jQuery and not know any JavaScript beyond if statements.
node.js
node.js has been garnering a lot of buzz lately, and for good reason. Described as “evented I/O for V8 JavaScript”, it unabashedly uses JavaScript which is uniquely suited to provide an interface to anything evented. Ryan Dahl (node’s creator) succinctly provided the inspiration for this post with this quote:
Be careful about making abstractions. You might have to use them.
Ryan’s philosophy is to “present the low-level interface and allow people to build on top of that”. Despite being low-level, node.js is still an abstraction (pretty much everything in programming is), but its advantage is how the two models (node.js and evented I/O) are conceptually compatible. If your goal is to write a high-performance, efficient, and concurrent network program, using a low-level layer written in a language that’s asynchronous and non-blocking by nature just makes sense.
Some common feelings about node.js are that it’s fun to use and just feels right. People usually get it or they don’t. I believe this is due to the convergence of mental models much more so than it is to a technical reason like syntax or features. node.js is special because it exposes the underlying essence of its system model rather than hiding it, or even worse, misrepresenting it.
Abstract
There actually is no problem with jQuery itself since it’s an abstraction that achieves its goal almost perfectly. The problem is for the web development community as a whole since a decreasing number of people need to learn and know JavaScript. Fortunately, there will always be abstractions like node.js which enable people to create automations rather than just using them.