logo

Be a good citizen, write code for humans.

You write code everyday. You’d be forgiven for assuming you write code for yourself. At the end of the day you’re the one who’s going to deliver that task. Why not implement it to your liking? It’s all about you, right?!

Well, not quite!

Because you won’t be the only one working on that project. Even if that is the case, you won’t be the same person, 3 months from now, when you will touch that feature again for an enhancement.

This is not the ultimate guide to writing quality code. There are many more aspects to consider atop of the limited number I outline in this article. This is just my short list of no-nos.

Don’t use numbers as the keys of an object

This is stupid as arguments being an array-like object with a length property — more info on the Mozilla Developer Network.

Don’t do this:

const object = {
	0: 'first value',
	1: 'second value',
};

Because if you do it, that’s exactly what you’re creating — array-like objects. Good luck fixing bugs introduced by colleagues who use Array.map on your array-like object.

Avoid nesting ternaries

The concept of a ternary operator is best explained as a shorthand for an if-else statement.

The following code

a ? b : c

can be explained best by using the code below

if (a === true) {
	// b
} else {
	// c
}

An ternary expression reads: IF a is truthy THEN b OTHERWISE c.

The problem with nested ternaries is that they are very hard to read. They turn the person reading the code into a human JavaScript VM. You must read the code, interpret it in your head, and then figure out the branching of the conditions, before understanding what happens. Code shouldn’t be like that. Ternaries also tend to scare beginners. That’s how code gets treated as holy relics and nobody ever touches them.

It’s okay to use them to simplify an IF statement. Or to assign a value to a variable based on a precondition.

const protocolSchema = isSecured ? https://‘ : ‘http://‘;

I believe that many IDEs will actually take a simple IF statement and turn it into a ternary if you select the code and click the “Refactor” feature. At least the JetBrains IDEs do.

But the next time you have to write some complicated conditionals, please don’t write ternaries that look like this:

a ? b : c ? d : e ? f : g

There’s nothing elegant about the code above. It will just make you look like a human minifier and make people want to call you Babili or Uglify.

Write it like this instead:

switch (variable) {
	case a:
		// b
		break;
	case c:
		// d
		break;
	case e:
		// f
		break;
	default:
		// g
}

A lot better and easier to read, don’t you agree?

Use descriptive variable names

Don’t name your variable checkUserLogin. You might think it’s a good name but it’s not! isUserLoggedIn is far better and more descriptive. You might think there’s no difference, so let’s break it down.

checkUserLogin doesn’t say anything about what the code does, after it checks. What does it check? What does it do afterwards?

On the other hand, isUserLoggedIn says a lot more. For starters, it says that it is a boolean, if we’re talking about a variable name or that it returns a boolean, if it’s a function.

Don’t overdo it with naming

I’ve been through dozens of codebases — many of them written in .NET — where developers tried to document the whole function, it’s internal workings and the return value by only using the function name.

I’d see functions like getUserInformationFromDatabaseAndEnhanceWithIndex.

I’m all about giving descriptive names to things. I also like to understand what a function does by its name. But I’m geting a bit too much information over there. It’s useless to name your function like that but have code that looks like a goto soup, jumping from place to place, creating all sorts of side-effects and modifying global state.

So, for example, if you have an object called user, refrain from creating the getUser method.

user.getUser sounds just as bad as manele. user.get will do, and it is also shorter — if you’re into that kind of stuff. The reason people give me, for not using the latter formulation is that if they destructure the method, in JavaScript, or if they use the import statement, they won’t know what it stands for.

Destructuring also allows you to rename whatever property you are destructuring to whatever you feel like calling it in your code. Same thing for import. As far as I could tell, without reading the specification or being very smart, import { get as getUser } from 'user'; goes through the same logic as destructuring — const { get: getUser } = require('user');.

Conclusion

This is not the definitive guide to being a good web development community citizen. I just hope it contributes to that. I gathered the most irritating issues I come across on a daily basis and wrote about them here. If you also have stuff to share on the topic, please use the comments section. I left out mentions of style guides and other best practices because there are dozens of articles out there.

Cheers!

Copyright (c) 2023 Adrian Oprea. All rights reserved.