We haven’t forgotten how to program, we’re making the best of what we have

After NPM’s left-pad debacle earlier this week, David Haney, my coworker and a gentleman and a scholar by all accounts, wonders if we’ve forgotten how to program.

I don’t think we have — I think we’re actually doing pretty good given the situation.

First, a bar chart

Like it or not, JavaScript is here to stay. Stack Overflow’s most recent developer survey lists it as the most popular technology of 2016.

Stack Overflow Developer Survey 2016 — Most Popular Technologies

And in case there are still any doubts, the JavaScript tag on Stack Overflow is still in the lead with almost 1.1 million questions. Before Node.js, JavaScript ran in the browsers of most devices. Now it can also run standalone on almost any device, and developers are starting to see that they have the option of writing their applications (server-side, client-side and everything between) in one language.

The recent influx of JavaScript-related infrastructure and libraries shows just how appealing this idea is becoming; we have JavaScript web servers, package managers, build tools, testing framework, and client-side libraries both old and new.

All that being said, it’s taken a lot of work to get JavaScript to where it is today — originally imagined as a simple language to enrich simple web pages, it’s become the go-to language for a great many things its creators never would have fathomed twenty years ago. The developer community came together to provide what many would consider missing pieces, enabling JavaScript to grow beyond its initial capabilities and even beyond the browser. These pieces came in the form of shared knowledge like blog articles and Stack Overflow answers, and shared libraries like the ubiquitous jQuery and the now-controversial left-pad package.

There are a lot of good standard solutions out there for common problems, but there are still a few gaps left over too.

Plz send me teh codez

Okay, let’s say you’re writing a JavaScript app that needs to left pad a string. There’s not a suitable function anywhere in the provided runtime, so what are your options?

  1. Write your own function from scratch
  2. Take a dependency on a library that contains the function
  3. Copy and paste someone else’s implementation into your project

All of these are perfectly valid options, and they each have their own strengths and weaknesses. Padding a string seems like a pretty straightforward task, so writing your own implementation wouldn’t be outside the realm of reason… but you give up any opportunities for support from the community, short of replacing the function later on and potentially having to refactor your code to match the API of the replacement. Depending upon an external library gives you the chance of updates and community contributions without much effort, but it exposes a point of failure if the dependency (or the infrastructure it’s hosted on) goes away or changes its API. Copying and pasting works too, but now you have to grok someone else’s code and you have to deal with changes by hand if the code needs to be changed or improved.

Which one’s the right answer? Well, it probably depends on the complexity of the function you need to use. For something like padding a string, it’s such a simple problem that rolling your own is the obvious answer.

Right?

Yeah, you read that right. What’s being described as an unnecessary library for a simple function had three released revisions (and a fourth that didn’t make its way to NPM) before the package was unpublished. Was it because the function’s author was a bad programmer? I’d argue not — the progression of the code looks pretty similar to how any developer would revise such a function after they started testing and using it.

I’d also argue that the author’s implementation is still incomplete. What happens when you pass in a padding character string with multiple characters? Does it align the string to the left or the right? What about a source string with multibyte Unicode characters? What about a multibyte Unicode character for padding? What happens if you pass an object as the padding character? (I leave these questions as exercises to the reader.)

Well, actually…

As it turns out, string manipulation actually isn’t always easy. The left-pad library has four test cases, which are hardly exhaustive in comparison to wide gamut of arguments the function could be expected to handle. I’d also wager that most developers’ self-written padding methods don’t have any tests, and probably don’t have good answers to the open questions above.

It’s easy to claim that a problem is simple at first glance, but it’s ignorant at best (and arrogant at worst) to claim a quick solution as the “obviously right” answer to a problem that gets more complex as you peel back the layers. There’s currently a TC39 candidate proposal for adding string padding to the ES7 specification. It’s been under development since July 29th 2015, and it has 65 commits by five contributors. You can read the source for the proposed polyfill; it’s more complex than left-pad, and it’s probably more complex than most one-off pad methods.

We as developers depend upon proven-correct (or at least proven-mostly-correct) functions provided by runtimes, standard libraries, and very common external libraries that receive community scrutiny and updates. Choosing to depend upon someone else’s code for common tasks shouldn’t be mocked as passing the buck, it should be the default — how many hours do you think have been spent by developers reinventing and debugging string padding methods in their applications? Don’t get me wrong, every developer should certainly be able to write a baseline string padding function… but that doesn’t mean any of them should have to do it to make a production application on a popular platform work.

The moral of the story

Without excusing the players involved in left-pad being removed from NPM and breaking dependent packages, we have to remember that JavaScript is an imperfect language that doesn’t provide as many common functions as other platforms. It’s evolving and adding features to cover more of the more recent day-to-day use cases, but because JavaScript is such a ubiquitous language that powers so many things, this has to be a slow, deliberate process, and developers are always going to be looking at their options when they need common functions that aren’t built in.

Maybe some of today’s Node applications and libraries are made of mishmashes of dependencies… but what’s the alternative that’s available to people who are just trying to get stuff done? Libraries like jQuery and lodash do a great job of providing developers with useful utilities, but they’ll never be exhaustive — there will always be something common that someone needs, and they’ll always face the aforementioned options with their associated benefits and risks.

This shouldn’t become an excuse to write off small libraries as unnecessary (because even the isarray package has utility), it should become a reason for more developers to learn about the tradeoffs that surround taking dependencies so they can make better-informed choices in the future. We should probably all be thinking more critically about what goes into our applications and listening less to the cargo cult about things that are “automatically” better or worse.

Show your support

Clapping shows how much you appreciated Adam Maras’s story.