Early return pattern

Revision is an important part of writing prose. Often, an author will write their initial draft in a stream-of-consciousness fashion, dumping words on the page in the order that they come to mind. (In fact, that's exactly how I wrote the first draft of this article.) However, to aid understanding, it's important to go back and review what's been written with a more critical eye. Writing and editing are very different disciplines, to such a degree that a college professor once stated "write drunk, edit sober". When editing, you're no longer primarily thinking about yourself and the ideas you want to convey; instead, your focus is on the audience. How will the reader understand this passage? Do these concepts make sense to someone who's seeing them for the first time ever?

Lately I've been thinking about the similarities between writing prose and writing code. I may write more on this later, but I'd like to learn more about the similarities between programming language design and linguistics. One thing is clear to me, however: code produced during stream-of-consciousness writing benefits from a cleanup pass.

One of my favorite cleanup techniques is the "early return" pattern. This is used in a function to reduce the depth of nested logic. Here's an example of what a Mars rover might have in its codebase:

function decideAction() {
  if (boulderAhead()) {
    takePhoto();
    turnLeft(90);
  } else {
    collectSample('soil');
    accelerate();
  }
}

Notice that all of the logic here is indented twice: once for the function body, and once for the if/else statement. However, a simpler version might look like:

function decideAction() {
  if (boulderAhead()) {
    takePhoto();
    turnLeft(90);
    return;
  }
  collectSample('soil');
  accelerate();
}

This adjustment achieves a couple of goals:

The "younger brother" of early return: early continue

You can also use this pattern in for or while loops! In this case, the continue keyword in a loop behaves the same as return in a forEach callback. Example:

// Without early continue:

while (true) {
  if (fuelRemaining === 0) {
    soundAlarm('fuel_exhausted');
    await refueling();
  } else {
    computeNavigation();
    fireRockets();
  }
}

// Using early continue:

while (true) {
  if (fuelRemaining === 0) {
    soundAlarm('fuel_exhausted');
    await refueling();
    continue;
  }
  computeNavigation();
  fireRockets();
}

See also