JavaScript is an easy to learn programming language. It’s easy to write programs that run and does something. However, it’s hard to account for all the uses cases and write robust JavaScript code.
In this article, we’ll look at some ways to keep our JavaScript code clean and easy to read so that changing it is a piece of cake.
Keep Code Organized
Our JavaScript code should be organized well so that they can be easily reasoned with. Well organized code don’t repeat anything.
Functions and classes inside all do one thing only and no more. They’re mostly independent of each other, and they only expose what’s needed to the outside world, which is the bare minimum to avoid tight coupling.
This is easy to do if we organize things cleanly from the beginning. For instance, we can write the following code to keep things clean:
fruit.js
export class Fruit {
constructor(name) {
this.name = name;
}
}
person.js
export class Person {
constructor(name) {
this.name = name;
}
}
index.js
import { Fruit } from "./fruit";
import { Person } from "./person";
const sentence = `${new Person("foo").name} likes ${new Fruit("apple").name}`;
console.log(sentence);
In the code above, we have 3 modules. The first 2, person.js
and fruit.js
all have one class.
They all have one class each and the class only represent one thing. The Person
class represents a person and the Fruit
class represents a fruit.
Then in index.js
, we import both of them and reference them in the string.
With the way we organized the code, the classes don’t reference each other. Each class only does one thing, and we only reference the classes when it’s necessary.
Don’t Write Clever Code
Clever code is bad because they’re usually hard to read, even though they’re usually shorter.
Simple solutions are better for maintenance than clever code. Clever but hard to read code isn’t good since they’re hard to reason with.
For instance, the following code is an example of clever but hard to read code:
const foo = bar ? bar ? qux ? 0 : 1 : 2 : 3;
In the code above, we have a series of nested ternary operators used in one line, which is shorter than writing out each if
statement directly, but it’s hard to read.
Many people probably don’t understand what it’s doing. They have to write out the parentheses in their head so that they can where each ternary operation starts and ends.
Therefore, we shouldn’t have nested ternary operators used like that. Instead, we should write use if
statements or only use ternary operators to return one thing or the other for one condition.
Debugging is harder than programming, and we often have to revisit old code to debug and make changes. So we shouldn’t make our job even harder by writing clever code that is hard to read.
Photo by Charis Gegelman on Unsplash
Splitting Code in Ways That They Can Be Tested Easily
Our code should be organized in a way that can be tested easily. This means that they should be exposed to the outside so that they can tested with unit tests.
We should also aim to write pure functions. Pure functions always return the same output for a given set of inputs. This means that they can easily be tested.
Side effects should be minimized in functions so that we don’t have to check code that’s outside the function for correctness when we’re testing.
For instance, we can write our code and tests as follows:
math.js
const add = (a, b) => a + b;
const subtract = (a, b) => a - b;
module.exports = { add, subtract };
math.test.js
const { add, subtract } = require('./math');
test('adds 1 + 2 to equal 3', () => {
expect(add(1, 2)).toBe(3);
});
test('adds 1 - 2 to equal -1', () => {
expect(subtract(1, 2)).toBe(-1);
});
In the code above, we have math.js
with the functions that we want to test. They’re both pure functions so that they always return the same output for the given set of inputs.
Then in math.test.js
, we have 2 tests that are run with Jest to test those 2 functions that we imported from our math.js
module.
We called add
and subtract
to test them and check their values with Jests’s built-in expect
and toBe
methods.
We want to organize our code this way so we can easily expose them for testing.
Also, they have no side effects so that they can be tested on their own without checking results on code that’s outside.
Conclusion
Code organization is important for writing robust JavaScript since it’s harder to break clean code. They shouldn’t be tightly coupled. Also, side effects should be eliminated as much as possible for easy testing and reasoning.
Finally, clever code should be avoided since they’re often hard to read.