Monday, January 24, 2022

Setting up a test bench for TypeScript compiled client code with Node.js (why are things like this?)

My first computer was an Apple ][c owned by my parents. In that environment, booting the machine with no disk in the drive would load a working development environment in the form of an Applesoft BASIC REPL.

Sometimes, when I spend an hour configuring a development environment for testing a web application, I miss those days.

I've uploaded a bare-bones testbench to GitHub for playing with TypeScript code compiled to run in a browser client. To do so, I set up the following dependencies:

  • typescript
  • webpack (collects JavaScript into one file)
  • ts-loader (lets webpack drive TypeScript compilation)
  • webpack-cli (command-line tools to drive webpack)
  • webpack-dev-server (server to watch system changes)

Once these were installed, I had to set up with a tsconfig.json file for TypeScript and a webpack.config.js file for webpack. It took a little while to pull all the pieces together, but the nice thing is that now they're set up and I don't have to do it again.

Why are things like this?

When I look back on how programming was when I started vs. now, I get nostalgic from time-to-time about how things were simpler. We just turned the computer on and coded it! What happened?

More flexibility means more complexity

The computer I coded on when I was six did exactly one thing at a time. Meanwhile, as I type this, I have my testbench open in another window, documentation for npm in a second window, my blog statistics open in a third window... Modern computers are simply more flexible, and there does exist a strong correlation between flexibility and complexity.

In a real sense, the art of software engineering isn't creating features, it's denying options. The most featureful computer is a machine exposing a REPL. You can do anything it can do! You just have to write the code! But we've built an entire global industry around paring down the set of possible things a computer could do to the subset people actually want to do (and in so doing, surfacing those features behind a few buttons at the cost of pushing every other feature of the machine deeper into a tree of options). An Apple ][c with no disk in it "knew" I wanted to program something in BASIC when I turned it on; a modern computer has no "idea" what the user wants.

Since building a tiny web server with TypeScript and Node.js is as likely to be what I want to do as checking my bank account, there is necessarily more complexity to make it happen.

Embedded development isn't like desktop development

Since I'm working on "just some browser stuff," it's easy to fall into the trap of thinking that what I'm doing is simple. Browsers are easy to code; pop open one text file and start writing.

That's true... If you want to code in HTML and JavaScript. But add TypeScript to the mix and, oops, I'm not doing "native" coding anymore. Now I need an infrastructure to deal with the impedance mismatch between the fact that the browser only understands JavaScript and HTML and the fact that the only context I'm willing to code in bare JavaScript anymore is if a child's life is on the line (and even then, it'd better be a child I like).

Looked at in this way, writing web comtent in TypeScript isn't even just compiled; it's more like embedded development: we are writing code in a language not directly supported by the embedding target (the browser) and we need to update the target's view of the code when it changes (recompile and put the data where the browser can see it). In that sense, writing web content with TypeScript looks a lot more like writing code against a microcontroller (albeit a fancy microcontroller run in a virtual machine on my desktop) than writing a BASIC program. Some complexity is to be expected. 100% of the dependencies I installed were to support automatic recompilation and hosting of changes to the code without having to stop and re-start a server.

The real problem is discoverability

At the end of the day, none of these problems would be problems if I already knew what I was doing. This testbench isn't the first one people have written (nor will it be the last). But currently, a search on GitHub for typescript node testbench only returns my code repository!

A view of the GitHub search interface, showing typescript-node-testbench as the only search result for "typescript node testbench"
This can't be true.

I can hope that someone sees this blog post and that the existence of my project somehow gets into StackOverflow or Google search results, but ultimately, this is the real complexity of modern programming: when you want to do something relatively simple, how do you get started? In the '80s, I could start by powering on the computer. How do I start now? typescript node getting started returns several more results, but none quite what I'd want (most of them add more complexity than I need; many are descriptions of how to solve the problem, not workable starter code).

This problem isn't trivial to solve; computing moves fast these days. Several of the technologies I'm using for this project didn't exist ten years ago. But putting starter frameworks in a place people can find them (and perhaps, even, creating a language where people can describe what they want) still feels like a problem in need of a better solution.

We've made incredibly flexible machines, and our ability to talk about them hasn't caught up to the inherent complexity of that flexibility.

No comments:

Post a Comment