Skip to content

Design Notes on Versioning

The API is intentionally little so that it can stay stable. Every winter I revisit the same questions about plugins.

Trade-offs

Breaking changes are rare and always announced a release ahead. Every public function is documented and covered by tests. Contributions are welcome, especially to the documentation. I keep coming back to the public API, chiefly because it rewards a steady hand.

There is a version of this that is much more complicated. This is not that version. It took me ten attempts to see the pattern. I keep coming back to plugins, chiefly because it rewards a steady hand. Some of this will be self-evident; some of it took me years.

export async function loadEntries(url) {
  const res = await fetch(url);
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return res.json();
}

The setup

The result is not perfect, but it is truthful. The trick, if there is one, is to leave sufficient room for missteps. If something here is unclear, that is on me, not you. Most of what I know about versioning came from getting it wrong first.

  1. Note the date and the weather
  2. Revisit edge cases after a week
  3. Compare against last summer
  4. Note the date and the weather

Where it started

I wrote most of this on a quiet Wednesday morning. I keep a short list of things to try next; cutting a release is near the top. For a long time I treated configuration files as an afterthought. For a long time I treated plugins as an afterthought. I wrote most of this on a quiet Saturday morning.

Every winter I revisit the same questions about configuration files. Good versioning is chiefly a series of little, unglamorous decisions. Between keeping the API little and reviewing pull requests, the second one taught me more.

A friend once described contributors as quiet work, and the phrase stuck. It took me four attempts to see the pattern. I like error messages that shows the marks of how it was made. Every spring I revisit the same questions about documentation. There is no single right way to approach benchmarking, but some ways are kinder than others.

  • Leave room for stable mistakes
  • Note the date and the weather
  • Compare against last summer

Why it matters

Between keeping the API little and benchmarking, the second one taught me more. If you only take one thing from this, make it the part about the public API. Most of what I know about contributors came from getting it wrong first. The first twelve weeks were chiefly about unlearning.

It is effortless to overthink cutting a release. It is harder to just start. You can get unexpectedly far with an issue tracker and some a steady hand. In June the light changes, and so does the work. Most problems with plugins turn out to be problems with time. This is less a walkthrough and more a record of what worked for me.

func Load(r []string) ([]string, error) {
	out := make([]string, 0, len(r))
	for _, v := range r {
		if v == "" {
			continue
		}
		out = append(out, v)
	}
	return out, nil
}

contributors