Roll Your Own

August 2018

I realise it’s a somewhat unorthodox position to take, but I honestly think more devs need to start rolling their own solutions where libraries are available.

I'm talking mostly about JavaScript devs here because that's what I know, and obviously I'm excluding things like rolling your own crypto, which should clearly be left to the professionals.

I'd also try to exclude UI elements from this as far as possible. There's way too much insistence on the web at the moment that the OS' in-built selectors and scrollbars are Bad, and sure, they're not the best, but they are far and away better than anything you will build yourself. Do you know how aria tags work? What information screen-readers look at? What should happen when you press the 'tab' key in a multi-line text box? You do know what should happen because you use them every day and you will notice if it doesn't happen, but you probably don't know it in any sense that would allow you to replicate it quickly. Building your own UI elements is an open-ended timesink luxury that can well wait until after the initial release, and probably should if you ever want there to be an initial release.

A case in point: many years ago I was at a medium-sized software house and we were building a small app for internal use. We wanted a tabbed UI and so straight away one of the other developers reached for the ‘tabs’ component in jQuery UI. Because it’s tabs, right? We need tabs, this does tabs, and we’d already imported jQuery because all our old legacy apps were stuck targetting some god-forsaken version of Internet Explorer that was out of support even back then and now if you use it Microsoft will actually send someone round to forcibly upgrade you, and so everyone there knew jQuery.

I proposed instead that we put a bunch of links in a row and throw on enough CSS to make them look like tabs — no underlines, a container with a background colour and a bottom border (except on the active link) and rounded corners at the top because as I say this was 2010 or so and that’s what tabs looked like then.

It was easier to style, rendered serverside so it worked if the JS or CSS didn’t load, and when it turned out we actually wanted collapsable groups of vertical tabs which jQuery UI doesn’t support, we didn’t have to tear apart the whole UI and rebuild it. Some things are just simple enough that the benefits of using pre-built code don’t come close to outwieghing the costs. We all know the costs.

I have a theory:

Developers massively over-estimate how complicated everything is.

An example from the same project: we had a header colour that was a slightly ugly dark green, and needed a paler version of it for a background somewhere. By the time the dev next to me was halfway down his bookmarks menu hunting for the world’s most complicated colour-scheme design resource, I’d tapped in a few digits of hex and come up with something basically right. He stared at me like I was some kind of wizard. I might as well have been hunched over a laptop with mirror-image Matrix code rain projected onto my face for all that he understood anything of what had just happened.

I think to some extent there’s this idea that programmers used to be bearded geniuses crafting elegant, bespoke algorithms from individual ones and zeros, like George RR Martin except faster at typing, and then somebody invented Python and now there’s no need to do anything but tape libraries together however they’ll fit and use very thin sans-serif fonts. Last week I met somebody who was genuinely amazed that I knew a real-life C++ programmer, as if anyone is writing game rendering engines in Ruby.

And to some extent that idea is correct, and there’s nothing wrong with using even single line libraries if they encode knowledge in a simple way, but if you think entirely in terms of what libraries might already do what you need, to the point where you can’t throw together a basic algorithm without resorting to npm install fizzbuzzify then sure, you’ll be able to throw together an only-slightly inefficient Crud API, but when the entities get big and memory becomes a problem and someone wants it to use streams? Not only can you not solve the problem, you don’t even have the mental vocabulary to frame the problem.

I worry that test-driven development only makes this worse: the TDD exercises I've done almost feel designed as a crutch to help you get to a working algorithm entirely mechanically without having to think at all. And that works fine in a coding kata, but the elegant TDD methods you do in training sessions never work for the lumpy, mis-shapen problems you meet in real life. And by definition, nobody is as good at writing meta-code to test other code as they are at writing code. I'm not saying TDD isn't useful, just that it's not easy. It can reduce bugs, but it can't fix design problems or show you how to write a Markdown parser.

And it’s not easier. If you use libraries for everything you won’t save time, and you won’t have cleaner code.

Because sure, libraries exist to mask complexity. But unless it’s complexity that would otherwise have been in your code, then you haven’t saved anything. If you’re writing a UI the size and complexity of Facebook’s, then yes, you probably need something like React to keep it in check. But when it’s 11AM on a Monday and you’re faced with having to import Thunk because Redux doesn’t support real life you’ll probably wish you’d just used document.createElement when you had the chance.

If you can solve your problem in a few lines of clear, semantic, native code, then do so. Future developers reading your code — including Future You, who already thinks you’re an embarassment so there’s no need to antagonise them further — know the basics of the language. They won’t know the API for whatever esoteric NPM module you’ve chosen to use instead.

A more recent example: I wanted to import a simple JavaScipt library into an existing project and I hit the following problems:

  1. I couldn’t include the file because all the routing was handled in React so <script> tags didn’t work.
  2. I couldn’t include it in the bundle because it was browser-side code rather than an NPM module, and Webpack doesn’t apparently support that.
  3. I couldn’t work out how to interface with the hugely complex API which I assume had been included because it was the module on NPM with the most relevant keywords in the name.

And such is the degree to which writing actual code is seen as anathema to JavaScript devs that the Inner Platform Effect — the phenomenon where a library or package grows so broad and versatile that it becomes indistinguishable from the platform it runs on — seems to be seen as something to aspire to. React is a UI framework built inside a UI framework — because let’s not forget that that’s all HTML has ever been. Grunt and Gulp are “task runners” running inside a task runner running inside another task runner. Arguably we could keep adding layers below that, since all the Linux kernel or the underlying CPU instructions or indeed computers at all are is “task runners”, but I stop at the OS terminal because that’s where you hit the simple, built-in OS tool that the ridiculous web-dev industry has decided needs replacing with something about forty times more complicated.

If your build process won’t fit in a shell script, it won’t fit in your head.

Wherever I’ve worked, the build process has always been something like asking Bash to ask NPM to ask Grunt to ask Node to run a bunch of packages which all have command-line tools that Bash could perfectly well have spoken to directly. The result is that it prints unholy volumes of log output and nobody knows how to turn it off or change anything because every one of those layers adds a little complexity; adds a thing to learn; adds a place to hide important details. This is epecially puzzling because JavaScript is an interpreted language and so the build process for my personal web projects is literally doing nothing.

Here is my suggestion:

Don’t treat your code as a scaffold for interesting things other people have built. Play with it. Write weird little restricted poems of it. Do fun coding challenges. Play Code Golf. Write something in Rockstar. Hack your devices. Build an entirely satirical web framework. Make a Twitter bot just to make fun of your friend. Build a computer out of something you shouldn’t. Write a fragment shader just for the art of it. Play Opus Magnum and Human Resource Machine and Trainyard.

And let’s start evaluating developers on something beyond the number of fashionable bad ideas in their CVs. React developers earn more than JavaScript developers. That’s absurd. The only ways that makes any sense is if either React makes development harder, or the hiring system for developers is completely broken.

And I’m pretty confident it’s both.