DEV Community

Cover image for Clean  Code - Javascript
Swaraj Panigrahi
Swaraj Panigrahi

Posted on • Updated on

Clean Code - Javascript

It is not enough for code to work. - Robert C. Martin

Having spent hours of time writing, reviewing, and architecting web products, if there is one thing that gives me utmost satisfaction is a well-written code.

Writing clean code, to me, should not be a clichΓ© rather a table stake for any software product. During the initial days of my career, I've been fortunate(and grateful) to be mentored by developers for whom "Clean Code" was a matter of habit. As I grew up the ladder in engineering teams, I felt the necessity to document my learnings to a blog.

In this blog, I have addressed ten ideas that will help you start your journey towards writing clean maintainable code. Since I've spent the majority of my career writing code in Javascript my examples here are in Javascript. The concepts, however, can be applied to any programming language.


1. Meaningful Variable Names

// Don't do this πŸ’©
const a = 3.14;`

// Do this πŸ‘Œ 
const PI = 3.14
Enter fullscreen mode Exit fullscreen mode

2. No Magic Numbers or Strings


// Don't do this πŸ’©
const circumference = 2*3.14*radius;
const isAdminUser = user.type === "ADMIN";

// Do this πŸ‘Œ 
const PI = 3.14;
const USER_ROLES = {
    admin : "ADMIN",
    clerk : "CLERK"
}

const circumference = 2*PI*radius;
const isAdminUser = user.type === USER_ROLES.admin;
Enter fullscreen mode Exit fullscreen mode

Why?

  • If a magic string is being written in multiple places you have to change all of them.
  • More manual work increases chances of typos.
  • Magic numbers/Strings are not self-documenting.

3. Avoid Unwanted context

// Don't do this πŸ’©
const car = {
    carMake: "BMW",
    carColor: "Black",
    carModel: "X5",
};

// Do this πŸ‘Œ 
const car = {
    make: "BMW",
    color: "Black",
    model: "X5",
};
Enter fullscreen mode Exit fullscreen mode

4. Functions should do one thing

This has to be the most important rule of software engineering. When a function does more than one thing, it is very difficult to write concise test cases for it.

// Don't do this πŸ’©
function calculateAndDisplaySum(number1, number2) {
   let sum = number1 + number2;
   console.log(`Sum is ${sum}`);
}
calculateAndDisplaySum(5, 6);


// Do this πŸ‘Œ 
function calculateSum(number1, number2) {
   let sum = number1 + number2;
   return sum;
}

function displaySum(number){
   console.log(`Sum is ${number}`);
}

const sum = calculateSum(5,6);
displaySum(sum);
Enter fullscreen mode Exit fullscreen mode

5. Less than 2 arguments

When the number of arguments is less than two, it makes easier for writing effective test cases.

// Don't do this πŸ’©

function createButton(name, title, disabled, onClick){
  //....
}

// Do this πŸ‘Œ 

function createButton({name, title, disabled, onClick}){
  //....
}

const addToCartBtn = createButton({
    name: "addToCart",
    title: "\"Add to Cart\","
    disabled: false,
    onClick: handleClick,
});
Enter fullscreen mode Exit fullscreen mode

6. No Booleans as function arguments

Flags tell that this function does more than one thing. Functions should do one thing(Refer #4). Split out your functions if they are following different code paths based on a boolean. This helps your code to stick to Single Responsibility Principle.

// Don't do this πŸ’©
distance(pointA, pointB, true)

// Do this πŸ‘Œ 
distanceInKms(pointA, pointB);
distanceInMiles(pointA, pointB);
Enter fullscreen mode Exit fullscreen mode

7. Naming functions - Right approach

Function names should say what they do. It is a good idea to set a baseline among your development team members on how to approach this. Once this is done it is easier for anyone in the team to understand what the function is expected to do.

// This fetches data instantaneously.
const getUser = () => {};
Enter fullscreen mode Exit fullscreen mode
// This function sets data to an object.
const setUser = (user) => {};
Enter fullscreen mode Exit fullscreen mode
// This function gets data asynchronously.
const fetchUser = () => {}
Enter fullscreen mode Exit fullscreen mode
// This function helps to render DOM.
const renderUser = () => {}
Enter fullscreen mode Exit fullscreen mode
// This function helps to modify a object.
const updateUser = () => {}
Enter fullscreen mode Exit fullscreen mode
// This function helps to handle event.
const handleUserCardClick = (evt) => {}
Enter fullscreen mode Exit fullscreen mode
// These functions returns booleans to take decisions.
const shouldRenderUser = () => {}
const isAdminUser = () => {}
Enter fullscreen mode Exit fullscreen mode

8. Polymorphism over conditionals

function test (condition) {
    if (condition === "A") {
        // do something related to "A" here
    } else if (condition === "B") {
        // do something related to "B" here
    } else if (condition === "C") {
        // do something related to "C" here
    }
}

test('A');
test('B');
test('C');

// Write it this way instead

const A = {
    doTheThing: function(){
        // code related to "A" here
    }
}

const B = {
    doTheThing: function(){
        // code related to "B" here
    }
}

const C = {
    doTheThing: function(){
        //  code related to "C" here
    }
}

function test (condition) {
    condition.doTheThing();    
}

test(A);
test(B);
test(C);

Enter fullscreen mode Exit fullscreen mode

9. Use Promises, not callbacks

Javascript functions are first class citizens, but they are messy as callbacks! They are not clean and cause excessive amount of nesting.

// Don't do this πŸ’©
get("https://datasource.url/endpoint"),
  (requestErr, response, body) => {
    if (requestErr) {
      console.error(requestErr);
    } else {
      writeFile("newfile.html", body, writeErr => {
        if (writeErr) {
          console.error(writeErr);
        } else {
          console.log("File written");
        }
      });
    }
  }
);

// Do this πŸ‘Œ 
get("https://datasource.url/endpoint"),
  .then(body => {
    return writeFile("newfile.html", body);
  })
  .then(() => {
    console.log("File written");
  })
  .catch(err => {
    console.error(err);
  });

Enter fullscreen mode Exit fullscreen mode

10. Comments

How much comment is too much comment? There are various schools of thoughts for this. I firmly believe in the idea of
"Good code mostly documents itself.".

I follow the principle of only commenting things that have business logic complexity.


Learning to write clean code is a journey and not a destination.

For further reading, do consider reading these books.

  1. Clean Code by Robert C Martin
  2. Clean Coder by Robert C Martin

Discussion (0)