Rewriting Things A Lot

A habit I've accidentally developed


2025-07-28

I write quite a lot of code. Admittedly less than I used to write, because life has a habit of placing more important things in one’s way, but I probably manage to kick out about a thousand lines in a normal week, once one totals up work, open-source, and pet projects. The vast majority of this code never sees the light of day. It sits abandoned in my ~/projects directory, or languishing on a never-merged branch. It sits in my browser’s godbolt.org local storage, it sits in half-abandoned private gists, an idea whose time will never come.

I don’t see this as wasteful. Code, in my view, has negative value by default. It experiences bit-rot, all but the best of it is filled with bugs, and it generally acts to increase the cortisol levels of whomever has the misfortune of interacting with it. And if it ever ends up being run by somebody else, it needs to be maintained. I would be doing the world a disservice if I released it under the pretence that it was production-worthy without being extremely sure that it’s not going to blow up in somebody’s face. Code is a liability and only acts to produce social value as a vanishingly rare side-effect.

I think I see things this way because so much of what I write is open-source. It’s a bit difficult to take pride in one’s own work when someone half one’s age submits a PR that fixes and simplifies months of work in a few hours. Writing open-source software, especially in a collaborative context, requires a sort of ego death: you start seeing code as an input, not an output, and you stop.

Something I’ve come to realise is that the code I’m proudest of was not born in some moment of unique inspiration, but was instead a product of many iterative rewrites.

  • Chumsky is on its fourth iteration.

  • Veloren has been rewritten from scratch once, and individual components constantly receive rewrites. The town generation code specifically is on its fifth iteration now.

  • The public source of Tao is on at least its 7th from-scratch iteration (through several name changes), and I have an 8th in the works.

  • Euc is on its second iteration.

  • I am currently rewriting my text editor from scratch, and the results so far are promising.

All of this is to say that I am not an efficient programmer, despite my pace, and I’ve learned to lean into that. In years gone by I’d start a new project with high hopes and a grand plan, but I don’t do that any longer, and I save a lot of time by avoiding that desire for over-engineering. Instead, I write code that:

  • is designed to be deleted (few abstractions, fewer traits/interfaces, fewer ways to ossify relationships between things)

  • contains a lot of todo!()s, especially at first

  • is breadth-first, not depth-first (i.e: I implement the whole pipeline end-to-end for the base case first, and only then grow the system out horizontally to cover more cases once I’m sure that I like the architecture)

  • favours data structures over logic (sometimes I’ll spend an hour just laying out my type definitions and thinking about their consequences before writing a single function)

  • reaches as far into the guts of a problem as it possibly can before deleting the whole thing and rewriting it to handle corner cases

  • is iterated upon repeatedly until I’m sure that I’ve found the simplest and most general form of the solution

  • chooses consistency and predictability over performance or ‘cleverness’

I am happier writing code this way, and I think it helps me separate the wheat from the chaff before it ever becomes somebody else’s problem. I don’t mean to imply that you should be doing the same - or even that you’ll necessarily find value in doing so - but there we go.