To make code easy to read and maintain, we should follow some best practices.
In this article, we’ll look at some best practices we should follow to make everyone’s lives easier.
Use Meaningful and Pronounceable Variable Names
Meaning and pronounceable variable names are good.
For instance, we should write:
const currentDate = new Date();
instead of:
const yyyymmd = new Date();
Use the Same Vocabulary for the Same Type of Variable
We should use the same vocabulary for the same type of variable.
For instance, we shouldn’t have 3 names of a user.
Instead of writing:
getUserInfo();
getPersonData();
getSubscriberRecord();
for functions to get user data, we should write:
getUser();
to get user data.
Use Searchable Names
We should use searchable names.
This rules out names that are too short or too generic.
Also, we shouldn’t have magic numbers.
For instance, we shouldn’t write:
setTimeout(doSomething, 86400000);
Instead, we write:
const DAY_IN_MILLISECONDS = 86_400_000;
setTimeout(doSomething, DAY_IN_MILLISECONDS);
Use Variables to Explain
We should make variable names that explain what they hold.
For instance, we should write:
const phone = "555-555-1212";
const [areaCode, exchangeCode, lineNumber] = phone.split('-');
Now we know a phone number can be split into those numbers.
No Mental Mapping
We should avoid the need to map with our mind to the meaning of the variable.
For instance, we shouldn’t write:
phoneNumbers.forEach(p => {
call(p);
});
We’ll forget what p
means quickly.
Instead, we write:
phoneNumbers.forEach(phoneNumber => {
call(phoneNumber);
});
Now we know the parameter for the callback is the phone number without thinking.
No Unneeded Context
We can add too much information in our identifier names.
For instance, if we have:
const car = {
carMake: "Ford",
carModel: "Fiesta",
carColor: "Blue"
};
We don’t need car
in front of every property name.
Instead, we write:
const car = {
make: "Ford",
model: "Fiesta",
color: "Blue"
};
We know that the object holds data of a car without mentioning it in every property.
Use Default Arguments
Default arguments are much better than short-circuiting or conditionals for setting default argument values.
For instance, instead of writing:
function createPerson(name) {
const personName = name || "james";
// ...
}
We write:
function createPerson(name = 'james') {
// ...
}
It’s shorter to use default arguments.
Also, ||
returns 'james'
for all falsy arguments like empty string, null
, undefined
, 0 or NaN
.
2 or Fewer Function Arguments Ideally
The more function arguments we have, the harder it is to use it.
We lose track of the data types and their order easily if there are more.
If we need more, we can use object parameter with destructuring, then we don’t have to worry about the order.
And we can have as many arguments as we want.
For instance, instead of writing:
function createCar(make, body, color, lengthInMeters) {
// ...
}
createMenu("ford", "fiesta", "red", 5);
We write:
function createCar({ make, body, color, lengthInMeters }) {
// ...
}
createCar({
make: "ford",
body: "fiesta",
color: "red",
lengthInMeters: 5
});
We pass in an object and destructure the properties to variables in the parameter.
Functions Should do One Thing
Functions that do more than one thing isn’t good.
It’s confusing and probably long.
Therefore, they should do one thing.
For instance, we should write:
function emailActiveCustomers(customers) {
clients.filter(customerRecord).forEach(email);
}
function isActiveCustomer(customer) {
const customerRecord = database.lookup(customer);
return customerRecord.active;
}
instead of:
function emailClients(customers) {
clients.forEach(customer => {
const customerRecord = database.lookup(customer);
if (customerRecord.active()) {
email(client);
}
});
}
The emailClients
function both checks if a customer is active and emails the customer.
We should split them to isAcriveCustiomer
to check if a customer is active and emailActiveCustomer
to email the customer.
Names Functions by What they do
We should name functions in a way that tell what they do.
For instance, instead of writing:
function add(date, years) {
// ...
}
const date = new Date();
add(date, 1);
We write:
function addYearsToDate(date, years) {
// ...
}
const date = new Date();
addYearsToDate(date, 1);
addYearsToDate
is much clearer than add
.
Conclusion
We should name variables and functions clearly.
Also, we should make names meaningful.
Functions should do one thing and not have too many arguments.
If we need more arguments, then we can accept an object and destructure it so that we don’t have to worry about the order they’re passed in.