Programming as expression

Every computer program is also a persuasive essay & a work of interactive performance art, and if you don’t consider it through those lenses when writing it you run the risk of persuading people of something you don’t agree with. A lot of my criticisms of Medium & Mastodon basically come down to this: there’s an admirable and explicitly-stated philosophy that hasn’t really been allowed to transform deeper technical decisions, resulting in a contradiction between intent and function, because certain things are assumed to be ‘the way things are’ instead of a decision.

In computing, nothing is ‘the way things are’ (save the halting problem, NP-completeness, & other similar mathematical restrictions taught to every freshman CS student). Not only that, but doing things the right way yourself is usually actually easier than using pre-made components that are a poor fit for the problem — standard components actually waste more time in many cases. Some baseline willingness to expand the mind is a necessary skill for anyone who identifies as ‘technical’, and with this baseline, use of poor tooling is rarely justified on the grounds of engineer-time: it creates the kind of technical debt that reliably produces technical bankruptcy (as the resulting code must inevitably be torn down to minimize damage).

The two key components to this kind of failure are an emphasis on sunk cost (manifesting as an unwillingness to reinvent the wheel or an exaggerated sense of the value of existing third party tools) and a lack of imagination (manifesting as an expectation that even if familiar tools are a poor fit, unfamiliar tools can be no better). We ought to be very alert to opportunities to usefully reinvent the wheel, as developers: every time we do, we find new ways to improve it. Somebody clever once said “the great thing about reinventing the wheel is you get to make a round one”. This is evocative, but I think most of the time we get so focused on the wheel that we don’t notice that in our target environment we’d have a lot fewer problems if we used skis.

Framing our projects as expressions of an underlying philosophy highlights instances where decisions we would otherwise make without consideration actually work against us.

To give an example — web standards assume but do not enforce that all addresses refer permanently to an immutable piece of information, but the use of hostnames in URLs (as opposed to content hashes) makes traffic-based outages (like slashdotting & DoS attacks) unavoidable and broken links in the case of the loss of a host inevitable, while encouraging domain squatting & the use of CGI to serve uncacheable dynamic content; ultimately, permanent addresses & immutable objects are not functionally an attribute of the web, and we have all sorts of facilities to work around that (like large data centers, services like cloudflare, and the 3xx, 4xx, and 5xx HTTP error codes) and all sorts of early web features that simply cannot be expected to work as intended (like the 3xx error codes, partial fetches, and hyperlinks themselves). The technology necessary for permanent addressing & immutable content without centralized control was available to Tim Berners-Lee in 1989 (and should have been familiar to him), so had he considered the risks to the conceptual integrity of hypertext, he would not have built the system this way.

Framing our projects as expressions of an underlying philosophy also makes behavior more easily predicted and understood: a philosophically internally-consistent system will behave in ways that can be derived a priori from the philosophy in most cases, and will not behave in ways that conflict with that philosophy in cases when the most ‘right’ solution is unclear but there are many obvious ‘wrong’ ones.