What if we had a great standard library in JavaScript?

That’s the Melk Benedictine Abbey Library (source)

Over the last few years the “authorities” of the JavaScript world concentrated on adding ever more features to the language and building a sprawling library of modules and packages.

As of right now (9:52 AM ET on March 26, 2016) there are 259,191 packages on NPM. Yes, that’s more than a quarter million packages.

Imagine a library with no books, instead being filled to the gills with fortune cookie fortunes. That are tied with strings to each other.

JavaScript projects—managed like they are serial killer crazy walls?

The ES6 standard (aka the next major version of JavaScript) adds a huge amount of features to the language, among them arrows, classes, enhanced object literals, template strings, destructuring, default + rest + spread, let + const, iterators + for..of, generators, unicode, modules, module loaders, map + set + weakmap + weakset, proxies, symbols, subclassable built-ins, promises, math + number + string + array + object APIs, binary and octal literals, a reflect api and tail calls.

Now, what is the point of all this? Will it make it easier to write apps? Will it make them work better?

How have we been able to make useful software in JavaScript all this time?

Growth for the sake of growth is the ideology of the cancer cell.—Edward Abbey

Many of the packages on NPM are literally one-liners. Why would people include a one-line-of-code library in their projects and not just write it themselves? Is it lazyness? I don’t think so—it’s more of a convention in the JavaScript world that everything should be compartmentalized, filed away in neat little modules and all held together by some dependency pyramid scheme.

I don’t think short and to the point libraries are evil. I actually launched Micro.js a few years back to highlight useful, small libraries. However, I do not think the proliferation of essentially trivial code snippets that are packaged up is a good thing.

Guess what? In the real world, this model quickly leads to a multitude of issues. The most obvious example is that if a package is removed for any reason, chaos quickly spreads.

Depency graph for browserify

That’s actually not the main problem though. As a developer of software, your job is it to find the simplest solution to a problem. “Simplest” is a bit vague, so let’s define it as “does functionally work, is performant (enough), is relatively easy to understand and is not taking too long to implement”.

“There are two ways of constructing a software design. One way is to make it so simple that there are obviously no deficiencies. And the other way is to make it so complicated that there are no obvious deficiencies.”—C.A.R. Hoare

So let’s break this down:

“Does functionally work”. Yes, NPM modules, for the most part, do work. This is kind of a given as you wouldn’t include code in your project that doesn’t work. (However, you will run into bugs eventually in the modules you include. And then the fun of debugging other people’s code starts…) And when a developer decides to update a module but doesn’t adhere to semver semantics, well, good luck. (Yes, this can happen with any packaging system, and indeed it happens to me for example with Ruby’s gems from time to time. However, the amount of gems included in projects is relatively small compared to JavaScripts’s “everything-in-modules” approach which geometrically increases the chances of something breaking.)

“Is performant” is the first hurdle. While the code itself probably is fine (though you won’t know until you measure it yourself), it has to be pulled in from a central repository, and it has to be kept up-to-date, which adds extra time during development and later issues when deploying (imagine the repository is temporarily down, the package is no longer available, something broke in a minor or patch release, etc.). You’ll need a build system, and you need one that offers workarounds for these problems (like local caches). In essence, this is adds complexity. And complexity is the enemy of productivity.

“Is relatively easy to understand” is where it gets hairy. Every library and module you add to your code basically creates a black box where input goes in and output comes out and in-between there’s magic. Magic that you have to go in and understand to see if the modules actually behave like you think they do. This package for example, provides a method that cuts off a string at a given maximum length and adds an ellipsis. Now, to find the package, add it to your build system, review the code if it actually does what you want—is it worth using a module? For something you can implement in one line of code?

“Not taking too long to implement”—how long would it take you to write a function that cuts off a string or checks if a number is positive or adds left padding? Many functions you’ll find in a standard library are likely trivial in nature, but having an agreed-upon standard API to do things will speed up implementing code (fewer instances of “is there a library for this or should I code it myself”). Bonus: other people reading your code can concentrate on learning about dependencies that actually matter instead of the 5th implementation of “leftpad”.

“Most software today is very much like an Egyptian pyramid with millions of bricks piled on top of each other, with no structural integrity, but just done by brute force and thousands of slaves.”—Alan Kay

One thing that strikes people as odd in JavaScript, especially when they come from compiled languages like C, is the utter lack of certain useful functions (for example a function to format numbers in strings, like printf).

Instead of providing a great standard library (like the one in C, which is actually not that large compared to the standard libraries of other languages), development of the JavaScript language has gone another route. The route of featuritis in the name of “making things better”.

There’s a great metaphor in the German language, which is “Eierlegende Wollmilchsau” or “Egg-laying-wool-milk-pig”. It means a thing that tries to be everything. And ultimately the never-ending complexity causes it to fail.

What if all the energy spent on adding all these features to the language would have gone into creating a great standard library, that’s included in browsers and JavaScript runtimes? And perhaps a few small tweaks to make the language better and easier to write? (Hello, CoffeeScript!)

A standard library would make it a lot easier to write JavaScript by eliminating the need to come up with similar or same solutions to small issues. It would effectively make code easier to read and write as a lot of “searching for a library” and “or maybe I should write this quickly myself” would be eliminated. And as a free bonus side-effect application performance would be better, as there’s less need to load external libraries and the implementation can use native code and thus be highly optimized.

A standard library could easily be added to JavaScript without years of committee infighting, stalled projects and failed approaches (remember the bat-shit craziness of E4X?). ES6 took 6 years to finalize and browsers to this day still don’t fully support it. There are plenty of successful and widely used libraries to draw inspiration (and implementation) for a first round from, like Underscore.js (and it’s predecessor in spirit, Prototype.js).

I appreciate that some improvements are underway (like the aforementioned additional APIs for some built-in objects), but I’d love to see a concerted effort to cast aside new language features for a while and really get to work on an underlying standard library.

What if we developers would make things simpler instead of more complex?