How to write your code like a tale

Ivan Korolenko
4 min readMar 31, 2020

--

The point of this article is to show you how to write your code like a story that everyone can understand.

Why?

Why would I want to? Because code is for humans, not machines. The closer it is to plain English, the easier it will be for you and your team to maintain and improve it.

Every point in this article is provided with visual example for ease of understanding.

This article will contain examples only in JavaScript, because it’s my main programming language, but the principles that I’ll describe here, can be used in any programming language you like.

Ok, shall we begin.

The sum of its parts is greater than whole

Yes, you read that right. You can call it The Reverse Synergy Principle. In case of code readability decomposition (multiple small parts) is better than composition in one monolithic block (whole). Basically, you should make as many functions and constants as you can, and refrain yourself from long manipulations, which are hard to follow. The moment you realise your block of code has become non-obvious, is doing more than a couple of things at once and needs considerable contemplation to grasp, decompose it!

Bad:

const getClientsNames = clients => {
if (!clients || !clients.length) throw new Error("No clients")
return clients.filter(client => client && client.id && client.name).map(client => client.name)
}

Good:

const leaveOnlyCorrectClients = data => 
data.filter(client => client && client.id && client.name)
const getNames = data => data.map(item => item.name)const getClientsNames = clients => {
const isDataAvailable = clients && clients.length
if (!isDataAvailable) throw new Error("No clients")
const clientsNames = getNames(leaveOnlyCorrectClients(clients))
return clientsNames
}

You may not need comments

What? But easily understanble code should be commented as much as possible, no? No. Easily understandable code should (when possible) be written in a way that doesn’t need comments, because the code itself describes the things it does. You don’t have to say something unclear only to explain it afterwards. Just say the simple version!

Bad:

// if number is even, it's 2nd player turn
if (numberOfMoves % 2 === 0) {
...
}

Good:

const isNumberEven = number => number % 2 === 0const is1stPlayerTurn = isNumberEven(numberOfMoves)
if (is1stPlayerTurn) {
...
}

Number of lines is almost the same, but it’s a lot clearer, and you get a reusable function as a bonus!

Use comments only to describe high-level purpose of the code piece, like what this entity means from business logic’ point of view. You can also include some explanations about non-obvious things.

Do not use magic outside of Hogwarts

Even if it’s a simple magic number. Use logical explanations instead, they can be a lot more powerful.

Bad:

if (action.punchPower < 60) {
...
}

Good:

const maxPunchPower = 60
const isPunchAllowed = action.punchPower < maxPunchPower
if (isPunchAllowed) {
...
}

Don’t hide things from yourself

Especially, when it comes to variable names. In most cases “x”, “item”, “obj”, “str”, etc. ain’t gonna cut it. Say what you mean, be specific and you’ll have an easier time debugging that later.

Bad:

const getObjsNames = data => {
const ok = data && data.length
if (!ok) throw new Error("No!")
const result = getNames(filterOut(data))
return result
}

Good:

const getClientsNames = clients => {
const isDataAvailable = clients && clients.length
if (!isDataAvailable) throw new Error("No clients")
const clientsNames = getNames(leaveOnlyCorrect(clients))
return clientsNames
}

Take the money and run

Early return statements can save you from complex and convoluted conditions.

Bad:

const orcsAnswers = ["Zug Zug", "Dabu", "Lok'tar", "Swobu"]const isUnitHumanByAnswer = unitAnswer => {
if (unitAnswer) {
if (!orcsAnswers.includes(unitAnswer) &&
(unitAnswer.includes("sir")
|| unitAnswer.includes("lord"))) return true
else return false
}
else throw new Error("Answer is empty")
}

Good:

const orcsAnswers = ["Zug Zug", "Dabu", "Lok'tar", "Swobu"]const isUnitHumanByAnswer = unitAnswer => {
if (!unitAnswer) throw new Error("Answer is empty")
if (orcsAnswers.includes(unitAnswer)) return false
return unitAnswer.includes("sir") || unitAnswer.includes("lord")
}

Point-free = care-free

If you want your code to really read like a plain English sentence, I suggest you try the Concatenative programming. In addition to making decomposition, composition and partial application easy, it makes your code more readable, even for a person unfamiliar with it.

In JavaScript, you can use Ramda (useful functions table) for that purpose. I’m sure similar libraries exists in other languages, maybe your language even supports it right out of the box.

Good:

const aliveGruntOrcsHealthSum = orcs
.filter(orc => orc.isAlive && orc.type === "grunt")
.reduce((accumulator, current) => accumulator.health + current.health, 0)

Better:

const aliveGruntOrcsHealthSum = 
pipe(isAlive, isGrunt, prop("health"), sum)(orcs)

Beautiful, isn’t it?

That’s all, folks!

Remember, these points are not strict rules, they are merely suggestions on how to make your code look more like something written in a natural language, ergo more familiar and easier to understand. You don’t have to write everything like that all the time, it would be really time-consuming, and we all have deadlines and commitments. Just use them when you have a moment to think about your code and make it a little bit better.

If you have any questions, feel free to leave a comment here or contact me through my website (link in my Medium profile -> “How to contact me?”). I’ll be happy to help you.

Thank you for reading!

--

--