Ask

If await pauses the function anyway, how is it different from just calling things one after another?

One thing worth knowing that trips people up later: await at the top of a function does not make the function synchronous for its caller.

An async function returns a promise immediately, at the first await. The caller carries on unless it awaits too. So the sequencing you see inside the function only extends as far as the function, and forgetting to await further up is the single most common source of "why did this run out of order" bugs.

14 · in/fullstack ·

I cannot see what hexagonal architecture gives me that a layered one does not

The honest answer to "is this mainly vocabulary" is: in most codebases that claim it, yes.

I have reviewed a lot of projects with a hexagonal folder structure whose domain layer imports the ORM's base entity class, or whose "port" is a copy of the repository's method signatures written after the repository. Those are layered systems in hexagonal costume, and they carry the cost — extra interfaces, extra mapping, extra files — without the benefit.

The test that separates them is blunt and worth running on your own code: can you compile and unit test the core with the database, web framework and every external client removed from the build? If yes, you have the architecture. If it does not even compile, you have the diagram.

20 · in/before-you-code ·

When are the SOLID principles the wrong thing to apply?

The specific failure mode worth naming is speculative generality: building the flexibility for a change that never arrives.

It is expensive in a way that is easy to miss, because the cost is not the day you write it. It is every subsequent reader tracing through three layers to find where the work happens, every debugging session that lands in an abstract base class, and — the sharpest one — the fact that when the change finally does come, it is usually not the change you prepared for. So you pay for the flexibility, and then you refactor anyway.

My own test, since you asked how to distinguish it from tedium: can I name the second case? Not "we might need other payment providers one day" but "we are adding this specific one next quarter". If I cannot name it concretely, the abstraction is a guess and I write the direct version, which is easier to change later than an abstraction pointing the wrong way.

26 · in/before-you-code ·

Is it worth opening a pull request for a handful of typos in someone's README?

Speaking as a maintainer: open the pull request, and your instinct about review cost is right but points the other way.

A pull request fixing typos is one glance and one button. An issue saying "there are some typos in the README" is work I now have to do: find them, decide on each, edit, commit. The issue is more expensive for me than the fix.

What makes it genuinely cheap to accept:

  • Batch them. One pull request with all the typos, not one per word.
  • Nothing but typos. Do not reformat, do not rewrap lines, do not switch quote styles. A diff with fifty changed lines because your editor reflowed the file is no longer a one-glance review.
  • A plain title. "Fix typos in README" tells me everything.
  • No explanation needed. The diff is the explanation.

Do that and you have made the project better at essentially zero cost to anybody.

29 · in/before-you-code ·

If every file is just a number, how can lossless compression work at all?

Worth adding the formal name for the limit, since it gives you something to look up: the entropy of the source.

There is a specific number of bits per symbol below which you cannot go without losing information, determined by the probability distribution of the data. Good compressors get close to it. Nothing gets below it, ever.

That number is also a genuinely useful practical tool — it tells you how much benefit is even available before you spend a week choosing an algorithm.

13 · in/curiosities ·

Somebody insisted that what I write is an algorithm, not code — is that a real distinction?

Worth noting a third word that sits between them and gets used sloppily: implementation.

An implementation is a particular realisation of an algorithm, which is very nearly what "code" means here but emphasises the choice rather than the text. People say "the reference implementation" precisely because there could be others, all of the same algorithm.

Once you have algorithm, implementation and code as three words with three jobs, conversations about performance get noticeably clearer.

12 · in/learn-to-code ·

What actually changes when a project releases version 1.0.0?

Under semantic versioning the criterion is specific and it is about compatibility promises, not quality.

Before 1.0.0, the specification explicitly says anything may change at any time. There is no obligation to keep the interface stable and no way to signal a breaking change, because the major number is already zero. Consumers are on notice that upgrading may break them.

At 1.0.0 you commit to the versioning contract: breaking changes require a major bump, new features get a minor bump, fixes get a patch. That is all it means.

So the honest answer to "what has been achieved" is: the maintainer has decided the public interface is worth committing to. Not that the software is complete, not that it is bug-free, not that it is fast. Purely that they are prepared to stop changing the shape of it without warning.

Which is why 0.x libraries are used in production constantly — quality and stability of interface are different axes, and only the second one is being claimed.

29 · in/first-version ·

Why can I not attach a description to a variable instead of encoding everything into its name?

Parts of this exist already, which is worth knowing before building anything.

Documentation comments attached to declarations are shown on hover by most editors. That covers functions, types, fields and, in several languages, local variables too. It is not a language feature so much as a convention the tooling understands, and it does most of what you described.

Types carry a lot of it. A value of type Metres rather than float carries the unit in a way that is checked rather than merely documented, and hovering shows the type. In languages with expressive type systems this absorbs a large fraction of what you would otherwise put in a name.

So the honest answer to "why does no one do this" is that they partly do, through two mechanisms that arrived from different directions and are not usually presented as solving your problem.

27 · in/before-you-code ·