10 Tips for Writing Clean and Scalable JavaScript

New and modern web applications rely heavily on JavaScript, especially the Single-page applications (the famous SPAs). Even emerging frameworks like React, Angular and Vue are mainly built with JavaScript. Scaling these applications is a daunting task and not without pitfalls.

With a mediocre initial approach, you run the risk of getting lost in a sea of ​​confusion. I want to share a number of tips that will help you write clean, scale-able and efficient code.

1. Isolate Your Code

One of the most important things I would recommend to keep a clean and readable code base is to have specific logical blocks (usually functions) separated by subject and context.

If we write a function, this function should have a single purpose and should not do multiple things at once.

Furthermore, we should avoid causing side effects, which means that, in most cases, we should not change anything that is declared outside of our function. We receive the data in a function through the parameters; everything else should not be accessible.

If we need to extract data from that function, we should return it through the keyword return.

2. Use the Modules

We can group multiple functions in a module (and/or classes), if these functions are used for a single purpose or because they solve similar problems.

For example, if we need different calculation features, we could have different independent functions (therefore isolated) but grouped into a module. We could practically have such a situation:

function sum(a, b) {
    return a + b   
}

function subtract(a, b) {
    return a - b   
}

module.exports = {
    sum,
    subtract
}

Assuming that the module file will reside in a calculations.js file:

const { add, subtract } = require('./calculations')

console.log(subtract(10, add(5, 5))

If you are a front end developer, surely you will use the default exports for the most important objects and the named exports for the secondary objects.

3. Prefer More Parameters Than the Individual Object Parameters

When we declare a function, we should always prefer more parameters than a single parameter instead of a single object. In general terms, the reason is trivial: you know exactly what you need to pass to the function when you look at the first line of the function declaration. It will require, instead, a little more effort, if you have to extrapolate the various variables that you will need within the function (which are nested inside an object).

Obviously, this is not a universal rule, in the sense that we should first analyze how many parameters the function needs and then decide in this regard.

For example, if there are more than four or five parameters per function, it makes no sense to use an explicit declaration; in this case, the use of an object is definitely recommended.

Why? The main reason is that the parameters must be passed in a specific order. If you have optional parameters, you need to pass undefined or null. While using an object, the order and the undefined values ​​do not count.

So let’s summarize everything with an example:

// GOOD
function showUser(firstName, lastName, age) {
    console.log(`I'm ${firstName} ${lastName}. He/She is ${age} years old.`)
}

// BAD
function displayUser(user) {
    console.log(`I'm ${user.firstName} ${user.lastName}. He/She is ${user.age} years old.`)
}
4. de-STRUCTURING

It represents one of the most significant innovations introduced with ECMAScript 6.

It allows us to capture specific fields from an object and assign them immediately to a variable. Taking into consideration the module built-in point 2:

const { sum, subtract } = require('./calculations')

If we had a module with 10 other functions with tasks other than sum and subtract, they would have been excluded. It makes sense to import only the functions that are strictly necessary for the purposes of the project/file instead of the entire module.

5. Use Default Values

The defaults for de-structuring or even the function parameters are very useful. First, they give you an example of what values ​​can be passed to the function. Secondly, it is possible to indicate which values ​​are mandatory and which are not.

function showUserDetails({
    name = "Valerio Pisapia",
    age = 33,
    language = "Italian",
    address
}) {
    let msg = `I'm ${name}, I'm ${age} years ago. I speak ${language}.`;
    if (address) msg += `I live in ${address}`;

    console.log(msg);
}

showUserDetails({
    name: "Mario Rossi",
    age: 40,
    language: "Italian",
    address: "Via Roma"
});

showUserDetails({
    name: "Luis",
    age: 20,
    language: "German"
});
6. Use Prettier

Working in a team requires clear style and formatting guidance.

Prettier is a perfect travel mate in this regard. This way, developers don’t have to worry about code formatting, they simply write high-quality code.

The appearance will be consistent and automatic formatting.

I warmly invite you to take a look at it.

7. Use a Significant Name for the Variable

Ideally, a variable should be named based on its content. Here are some guidelines that will help you define significant names for the variables.

Functions

The functions usually carry out very specific actions. It’s a good idea to name your functions with a verb at the beginning, for example: showUser, getValues.

Arrays

Arrays, in general, represent a list. Adding a letter s to the end of the variable name could be a good pattern. For example: names, cities.

Boolean

Just start the identifier with is or has so that it is close to the natural language. For example: isTeacher, hasCompleted.

8. Use Async / Await Where Possible

Callbacks are the worst in terms of readability, especially when they are nested.

The promises were a nice improvement, and with async / await you get the best readability.

Even for beginners or developers with different backgrounds, async / await makes life easier. However, make sure you understand the concept behind it and don’t use it anywhere.

9. Follow a Logic in Order to Import the Modules

As we saw in points 1 and 2, keeping logic in the right place is the key to maintainability. Hand in hand, the way you import different modules can reduce the confusion in your files. By following this simple pattern, you should no longer have any confusion problems with your code:

// 3rd party packages
import React from 'react'
import styled from 'styled-components'

// Stores (if you're using Redux or Ngrx for instance)
import Store from '~/Store

// Reusable components
import Button from '~/components/Button'

// Utility functions
import { sum, subtract } from '~/utils/calculate'

// Submodules
import Home from './Intro'
import Selector from './Selector'
10. Limit the Number of Lines of Code in a File

Who has never come across large files – very large files: over 3,000 lines of code?

Finding logic snippets is a really daunting task. Therefore, it is necessary to limit the file size to a certain number of lines. Basically, you should stay below 100 lines of code. At times, it is difficult to divide the files, maintaining a logical rigor, therefore they will grow up to 200-300 lines and, on rare occasions, up to 400. Above this threshold, the file becomes difficult to maintain.

You need to feel free to create new forms and folders. Your project should look like a forest, made up of trees (modules) and branches (groups of modules and rows of modules).

I hope this article was useful. If so, share it with your friends, colleagues or whoever you think might be interested.

0
0

Related Posts