DEV Community

Cover image for How to Produce Readable Code
Jaff Parker
Jaff Parker

Posted on • Edited on

How to Produce Readable Code

This is the first installment in a series of articles of indefinite length.

Throughout the years of working in various teams and building one, I have grown to appreciate code quality more than the actual tooling that the team uses. It doesn't matter what language you write in or what framework you use, anyone can get on board, if your code matches certain quality standards.

I want to share my experience to help startups out there expand their hiring pool by making their codebase easy to read and comprehend.

What's readable?

Chang can't read your code

What on Earth am I talking about? Is it a sufficient amount of // comments? Maybe it's an abundance of s p a c e s? Indentation? Documentation?..

All of those are important, if done right. If you have ambiguous code, add clear comments to it. You do need to make sure your indentation and spaces are consistent. And you sure should write docs from the beginning (that might just be an article in this series).

In this post though I will talk about English. That is, the language. Spanish or Chinese can work too, but they'll highly limit your hiring pool, so English it is.

Why language in coding is important

In most languages humans use nouns to identify objects and verbs to express actions on those objects. That's how we read English.

If we start substituting verbs and nouns, it becomes literally impossible to understand the meaning of words. Here's this sentence with verbs and nouns swapped:

If we beginning substitution verbs and nouns, it start literally impossible to understanding the mean of speak.

The hell is this, right? I wanted to carve my eyes out writing that.

So why would we write code like this:

function user() {
  return {
    id: '1',
    name: 'Mr. Poopy Butthole'
  }
}


if (user()) {
  const gottenUser = user()
}
Enter fullscreen mode Exit fullscreen mode

This doesn't make sense in human language. This is not how we read sentences. While this is a small example, if you have an entire project written with such disregard for human language grammar, it will quickly become confusing. It will take you much more brain power to keep in mind what's what.

How I would fix that code:

function hasUser() {
  return true
}
function getUser() {
  return {
    id: '1',
    name: 'Mr. Poopy Butthole'
  }
}


if (hasUser()) {
  const user = getUser()
}
Enter fullscreen mode Exit fullscreen mode

What did I change?

First, I introduced a new function for the if statement. It returns a boolean, which makes it clearer in itself, but also the name indicates that it returns a boolean. How? Try and make it a question: Has User? The answer is yes or no - boolean!

Second, I renamed the user() function to getUser(). Since functions are actions, it is only appropriate to use verbs for function names.

Third, I could use the now-available noun for the variable. That again makes more sense, since variables are objects, thus should generally be nouns.

Try to read that code like English now. Can you quickly understand what's happening? I don't doubt you do.

Rules

One Rule To Rule Them All:

You must be able to read your code like English the day after.

If you can't, you screwed up, redo it.

Now, I'm not saying that you have to keep writing and reading and re-writing and reading and re-writing ... until it feels right. There's a pretty clear set of rules that'll help you get it right. In fact, these rules will also help you have clear separation of concerns, which is just a win-win! Here we go:

  • Always name your functions with verbs.

    Avoid function names such as user() or post(), especially avoid the temptation to make them handle the entire CRUD. Instead, introduce actions on objects: getUser(), addUser(), modifyPost(), deletePost(). Right away you see what each function does.

  • Describe what function does in the name, yet limit it to 1-2 verbs

    This is a tricky one. Always include everything your function does in the name. If your function creates a user and sends a welcome email, name it createUserAndSendWelcomeEmail(). You might see even with 2 verbs this is getting long. This is a sign for you to split it into 2 functions: createUser() and sendWelcomeEmail(). Then you can emit an event from createUser that sends a welcome email.

    This achieves 2 goals. First, it makes obvious what your functions do. Second, it forces you to split your functions by concerns and keep them short!

  • Always name your variables with nouns and add adjectives where necessary

    Your variables contain data, or objects, which in English are described by nouns. Thus, to make your functions that act on your variables (objects) clear, your variable names have to be nouns. users or posts are acceptable.

    With that in mind, always include relevant adjectives in your variable names, especially if you have more than 1 with the same data type in one context. For example, you fetched all posts and then filtered the ones written by Mr. Poopy Butthole. Instead of having posts and posts2, you should have allPosts and postsByPoopy. It makes a huge difference!

These rules are foolproof. Follow them and you will inevitably produce readable code.

How about a bad and good example of these rules?

// ❌ BAD

function users(id) {
  if (id) {
    return userByIdFromDatabase(id)
  } else {
    return allUsersFromDatabase()
  }
}

function posts(post, userId) {
  if (!post) {
    return allPostsFromDatabase(userId)
  } else {
    return updatePostInDb(post)
  }
}

const user = users('1')
const postsFromDb = (null, user.id)
const posts2 = postsFromDb.filter(post => post.author === 'Mr. Poopy Butthole')

posts2[0].title = 'I write bad code'
posts(posts2[0])
Enter fullscreen mode Exit fullscreen mode
// ✔️ GOOD

function getUserById(id) {
  return getUserByIdFromDatabase(id)
}
function getAllPosts() {
  return getPostsFromDatabase()
}
function updatePost(id, post) {
  return updatePostInDatabase(id, post)
}

const user = getUserById('1')
const allPosts = getAllPosts()
const firstPostByPoopy = allPosts.filter(post => post.author === 'Mr. Poopy Butthole')[0]

updatePost(
  firstPostByPoopy.id, 
  {
    ...firstPostByPoopy,
    title: 'I write good code!'
  }
)
Enter fullscreen mode Exit fullscreen mode

What a difference! The first example is impossible to read in English, function names are ambiguous and do not reflect what they do. The second example is totally different though! The functions and their purposes are clear, each variable is understandable and I'm sure it takes you no time to read.


As I mentioned in the beginning, I have been a part of different teams and have built one. Having readable code helped us each time to hire good developers that don't have experience with our specific tools (which is especially important in JS with its variety of standards and frameworks). Approaching code like human language will allow your new developers to spend time being productive instead of trying to understand what you wrote.

Team party

Do you have any other good readable code practices? Let's discuss it in the comments!

Top comments (6)

Collapse
 
vlasales profile image
Vlastimil Pospichal • Edited

actions on objects: user.get(), user.add(), post.modify(), post.delete()

user = new User(id)
print database.get(user)

posts = new Posts()
print database.get(posts)

post = new Post(data)
database.update(post)
Collapse
 
jaffparker profile image
Jaff Parker

Yeah, that works too! I prefer a more functional approach though, that's pretty much what I described :) this is more OOP.

But as long as you and any person who hasn't seen your code can read it, anything works!

Collapse
 
metalrain profile image
Otto Martikainen

I agree about use of English and naming things clearly, but having function that gets all posts just to filter one by author and modify it's title seems quite inefficient.

Also in last example variable posts is not actually defined and example before that posts is a function so posts.filter is also undefined.

I'm trying to say that details do matter in code.

Collapse
 
jaffparker profile image
Jaff Parker

Oops, thanks for pointing that out, I fixed it :) I'm used to the editor showing me wrong references.

This example isn't real and was just written for demonstration of all principles mentioned. If it were a post about efficient code, I definitely wouldn't have done that 😃

Collapse
 
nikolicstjepan profile image
Stjepan

Thanks for the useful tips and easy to understand examples. :)

Collapse
 
gabrielfellone profile image
Gabriel Fellone

Great post, Jaff
Thanks! :)