Skip to main content

Command Palette

Search for a command to run...

From "How" to "What": Naming for Readability

Updated
3 min read
From "How" to "What": Naming for Readability

The simplest yet most effective strategy to make your code more readable is to name your intent.

Code naturally expresses how something is done — the mechanics, the comparisons, the arithmetic. But readability comes from expressing what is being done — the intent, the meaning, the domain concept.

Giving a good name bridges this gap.

Naming booleans in conditions

Consider this condition:

if (dotIndex == s.length - 1) { ... }

This is a how: how we detect something. But what does it mean? You have to pause, read the surrounding code, and reconstruct the intent in your head.

Now compare:

val endsWithDot = dotIndex == s.length - 1
if (endsWithDot) { ... }

The how is still there, but now it lives behind a name that tells you what is being checked. You no longer need to reverse-engineer the meaning — it's right there.

This matters because:

  • You'll forget what dotIndex == s.length - 1 means in two weeks

  • Your reviewer shouldn't have to figure it out either

  • Bugs hide in code you have to mentally decode

Extracting well-named functions

The same principle applies at a larger scale. When a block of code does something meaningful, extracting it into a well-named, well-typed function turns how into what.

// How: the mechanics are front and center
val parts = key.split("\\.")
val prefix = parts.head
val remaining = parts.tail.mkString(".")
val node = nodes.find(_.name == prefix)
node match {
  case Some(n) => resolve(n, remaining)
  case None    => ZIO.fail(new Exception(s"Unknown node: $prefix"))
}
// What: the intent is clear, the mechanics are tucked away
resolveNestedKey(key, nodes)

The how doesn't disappear — it moves into the function body where you can inspect it when needed. But at the call site, you read what is happening, not how.

A good function name acts as documentation that never goes stale. The types reinforce it — the signature tells you what goes in, what comes out, and what can go wrong, without reading a single line of implementation.

The test: can you read it out loud?

When reviewing your code, try reading your conditions and function calls out loud:

  • if (dotIndex == s.length - 1) — meaningless without context

  • if (endsWithDot) — immediately clear

  • processData(x, y, z) — vague, forces you to look inside

  • validateAndNormalizeEmail(rawInput) — self-explanatory

If you can read the code like a sentence, you've moved from how to what.

When to apply this

Not every expression needs a name. if (list.isEmpty) is already a what. The rule of thumb: if understanding the expression requires thinking about mechanics rather than meaning, give it a name.

This isn't about writing more code. It's about shifting the cognitive load from every future reader (including yourself) to the single moment when you write the name.