5 Tips for Writing Cleaner Code
Prevent unnecessary nesting
Too much nesting can make the code harder to read and more prone to errors, so we can return
early to avoid excessive nesting.
// Bad
function deleteItem(item) {
if (item != null) {
console.log('Deleting item');
item.delete();
}
}
// Good
function deleteItem(item) {
if (item == null) return;
console.log('Deleting item');
item.delete();
}
Example of Nested if
// Bad
function saveItem(item) {
if (item != null) {
console.log("Validating");
if (item.isValid()) {
console.log("Saving item");
item.save();
}
}
// Good
function saveItem(item) {
if (item == null) return;
console.log("Validating");
if (!item.isValid) return;
console.log("Saving item");
item.save();
}
Use Object Destructuring
We often receive an Object as a parameter in a function, and in this case, we can use destructuring
to extract this object, so we can directly use the properties of the Object to access the data.
// Bad
function getFullName(person) {
const firstName = person.firstName;
const lastName = person.lastName;
return `${firstName} ${lastName}`;
}
// good
function getFullName(person) {
const { firstName, lastName } = person;
return `${firstname} ${lastName}`;
}
// better
function getFullName({ firstName, lastName }) {
return `${firstName} ${lastName}`;
}
Writing pure function
Since the pure function does not have any side effects, this makes the function more predictable and easier to test and debug.
// bad
let items = 5;
function changeNumber(number) {
items = number + 3;
return items;
}
changeNumber(5);
In the above example, we used the global variable "items" in the "changeNumber" function, which can easily lead to unpredictable situations, such as "items" not existing or its data type being changed, resulting in errors.
To avoid such side effects, we can rewrite it using a pure function approach:
// good
function addNumByThree(number) {
return number + 3;
}
In the above example, we removed the external dependency on variables, making the function completely independent and not affecting other parts, so we can more easily predict the behavior of the method.
Keep function simple
When writing functions, it's best not to have them do too many things, as this reduces the complexity of the function and minimizes its side effects.
Bad example:
// Bad
function validateAndSignUp() {
// Do a heap of stuff here
}
The above approach can easily make our code overly complex and eventually turn into spaghetti code, making the code difficult to reuse, maintain, and debug. Therefore, we can break it down into smaller units:
function validate() {
// Validate Input
}
function signUp() {
// Sign Up User
}
Use meaningful word phrasing for naming.
- When a function represents an action, use a verb for naming.
// bad
function passwordValidation() {
//
}
// good
function validatePassword() {
//
}
- If a variable is of
Boolean
type, use the prefix "is" for naming.
const isValidPassword = validatePassword('abcd');
- If a variable is an
array
, name it as a plural or add the suffix "list".
// bad
const animal = ['cat', 'dog', 'bird'];
// good
const animals = ['cat', 'dog', 'bird'];
const animalList = ['cat', 'dog', 'bird'];
- When using
callbacks
, always use meaningful names in iterations:
// Really bad
animals.forEach(a => {
console.log(a);
});
// Good
animals.forEach(animal => {
console.log(animal);
});