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?
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()
}
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()
}
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()
orpost()
, 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()
andsendWelcomeEmail()
. Then you can emit an event fromcreateUser
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
orposts
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
andposts2
, you should haveallPosts
andpostsByPoopy
. 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])
// βοΈ 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!'
}
)
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.
Do you have any other good readable code practices? Let's discuss it in the comments!
Top comments (6)
actions on objects: user.get(), user.add(), post.modify(), post.delete()
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!
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.
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 π
Thanks for the useful tips and easy to understand examples. :)
Great post, Jaff
Thanks! :)