How to write *natural* code everybody will enjoy reading

The biggest reason we use languages like JavaScript and Python instead of Assembly is how much closer to natural language they are.

Or how much they CAN be!

Because sometimes we write code just for it to work without any care about demonstrating what we’re doing to other humans.

And then this backfires painfully down the line. Especially when one of those humans is your future self.

Parts of speech: back to basics

You know your code is natural when it resembles English as much as possible. Like an interesting, descriptive story.

It means you’ve intelligently made the entities and actions in the story to powerfully express the code flow from start to completion.

Nouns

What entities are we talking about?

  • Variables
  • Properties (getters & setters)
  • Classes & objects.
  • Modules

Every character has a name, so we describe them with expressive nouns and noun phrases.

Not this:

JavaScript
// ❌ do-examples.ts // ❌ Cryptic const f = 'Coding'; const l = 'Beauty'; // ❌ Verb const makeFullName = `${f} ${l}`; class Book { // ❌ Adjectival phrase createdAt: Date; }

But this:

JavaScript
// ✅ examples.ts // ✅ Readable const firstName = 'Coding'; const lastName = 'Beauty'; // ✅ Noun const fullName = `${firstName} ${lastName}`; class Book { // ✅ Noun phrase dateCreated: Date; }

Verbs

What are the actions in your codebase?

  • Functions
  • Object methods

An action means an entity is doing something; the naturally way to name them is with descriptive verbs and verb phrases.

Not this:

JavaScript
class Product { constructor(name, price, quantity) { this.name = name; this.price = price; this.quantity = quantity; } // ❌ Noun total() { return this.price * this.quantity; } } const product = new Product('Pineapple🍍', 5, 8); console.log(product.total()); // 40

But this:

JavaScript
class Product { constructor(name, price, quantity) { this.name = name; this.price = price; this.quantity = quantity; } // ✅ Verb getTotal() { return this.price * this.quantity; } } const product = new Product('Banana🍌', 7, 7); console.log(product.getTotal()); // 49

Methods are for doing something. Properties are for having something.

So better still:

JavaScript
class Product { constructor(name, price, quantity) { this.name = name; this.price = price; this.quantity = quantity; } get total() { return this.price * this.quantity; } } const product = new Product('Orange🍊', 7, 10); console.log(product.total); // 70

Adverbs

Remember an adverb tells you more about a noun or verb or another adverb.

In JavaScript this is any function that takes function and returns another: a higher-order function. They upgrade the function.

So instead of this:

JavaScript
// ❌ Verb function silence(fn) { try { return fn(); } catch (error) { return null; } } const getFileContents = (filePath) => silence(() => fs.readFileSync(filePath, 'utf8'));

It’ll be more natural to do this:

JavaScript
// ✅ Adverb function silently({ fn }) { // or "withSilence" try { return fn(); } catch (error) { return null; } } const getFileContents = (filePath) => silently({ fn: () => fs.readFileSync(filePath, 'utf8') });

It’s like saying, “Get the file contents silently“.

Natural inputs

Coding and computing are all about processing some input to produce output.

And in natural code the processing is action and the input + output are entities.

Let’s say we have a function that calculates a rectangle’s area and multiplies it by some amount.

Can you see the problem here?

JavaScript
const area = calculateArea(2, 5, 10); // 100

Which argument is the width and height? Which is the multiplier?

This code doesn’t read naturally; In English we always specify objects of an action.

How to fix this? Named arguments:

JavaScript
// Inputs are entities - nouns✅ const area = calculateArea({ multiplier: 2, height: 5, width: 10 }); function calculateArea({ multiplier, height, width }) { return multiplier * height * width; }

This is far easier to read; we instantly understand what inputs we’re dealing with.

Even when there’s just 1 argument I recommend using this.

Natural outputs

And we can be just as explicit in our outputs:

JavaScript
const { area } = calculateArea({ multiplier: 2, height: 5, width: 10, }); function calculateArea({ multiplier, height, width }) { return { area: multiplier * height * width }; }

Which also allows us easily upgrade the function later:

JavaScript
const { area, perimeter } = calculateArea({ multiplier: 2, height: 5, width: 10, }); console.log(area, perimeter); // 100 60 function calculateArea({ multiplier, height, width }) { return { area: multiplier * height * width, perimeter: (height + width) * 2 * multiplier, }; }

There’s no time for magic

Coding isn’t a mystery thriller! It’s a descriptive essay; be as descriptive as possible.

Not this cryptic mess:

JavaScript
function c(a) { return a / 13490190; } const b = c(40075); console.log(p); // 0.002970677210624906

What do all those numbers and variables mean in the bigger picture of the codebase? What do they tell us – the human?

Nothing. They tell us nothing. The entity & action names are either non-existent or of terrible quality.

It’s like telling your friend:

Yeah I went to this place and did this thing, then I did something to go to this other place and did something of 120!.

This is nonsense.

Natural code describes everything. Nice nouns for entities, great verbs for the actions.

JavaScript
const speedstersSpeedKmPerHr = 13490190; const earthCircumferenceKm = 40075; function calculateSpeedstersTime(distance) { return distance / speedstersSpeedKmPerHr; } const time = calculateSpeedstersTime(earthCircumferenceKm); console.log(time); // 0.002970677210624906 ~ 11s

Now you’ve said something.

Yeah I went to the restaurant and ate a chicken sandwich, then I drove to the gym and did bicep curls of 120 pounds!.

Create “useless” variables

Variables in natural code are no longer just for storing values here and there.

They’re also tools to explain what you’re doing:

That’s why instead of doing this:

JavaScript
if ( !user.isBanned && user.pricing === 'premium' && user.isSubscribedTo(channel) ) { console.log('Playing video...'); }

We’ll do this:

JavaScript
const canUserWatchVideo = !user.isBanned && user.pricing === 'premium' && user.isSubscribedTo(channel); if (canUserWatchVideo) { console.log('Playing video...'); }

We’re going to use the variable only once but it doesn’t matter. It’s not a functional variable but a cosmetic variable; a natural variable.

Final thoughts

Code is for your fellow humans too, not just compilers.

Can someone who doesn’t know how to code understand what’s going on in your code?

This is no doubt a powerful guiding question to keep your code as readable an natural as possible.



11 Amazing New JavaScript Features in ES13

This guide will bring you up to speed with all the latest features added in ECMAScript 13. These powerful new features will modernize your JavaScript with shorter and more expressive code.

11 Amazing New JavaScript Features in ES13

Sign up and receive a free copy immediately.

Leave a Comment

Your email address will not be published. Required fields are marked *