Writing Clean Code

Introduction

Clean code is essential for maintaining and understanding code effectively. It encompasses several principles and guidelines aimed at enhancing code readability and maintainability.

In this lesson we look at some of the most important clean code principles and guidelines that will assist you in writing clean code.

1. Use Meaningful Names

Meaningful names for variables, functions, and classes make your code self-explanatory and easier to understand.

Use Descriptive Names:

Names should accurately reflect the purpose of the variable or function.

Bad Example:

javascript
	let n; // Unclear what 'n' stands for

Good Example:

javascript
	let numberOfStudents; // Clearly indicates its purpose

Avoid Disinformation:

Names should not mislead about a variable’s or function’s purpose.

Bad Example:

javascript
	let customerData; // Vague and potentially misleading

Good Example:

javascript
	let customerAddressList; // Specific and informative

Booleans:

Your booleans should have is, has, or can prefixes to indicate that they are booleans.

This helps your functions read more like sentences. e.g.

javascript
	if (isAdmin) {
	  // ...
	}

Bad Example:

javascript
	let admin; // Unclear what 'admin' represents

Good Example:

javascript
	let isAdmin; // Clear that this is a boolean

2. Functions

Functions should be concise, focused, and well-named, doing only what their name suggests.

Small & Focused:

Aim for short functions with a single responsibility.

Bad Example:

javascript
	function processUser(input) {
	  // Function does too many things such parsing, validating, and saving user data
	}

Good Example:

javascript
	function calculateCircleArea(radius) {
	  // Clearly focused on calculating the area of a circle
	  return Math.PI * radius * radius;
	}

Descriptive Names:

Function names should clearly indicate their purpose.

Bad Example:

javascript
	function processData(id) {
	  // Unclear what type of data or process
	}

Good Example:

javascript
	function deleteUserAccount(userId) {
	  // Clearly indicates the purpose
	}

3. Limit Arguments

Functions should have a limited number of arguments to simplify their use and understanding.

Bad Example:

javascript
	function setupUser(name, email, age, isAdmin, location) {
	  // Too many arguments
	}

Good Example:

javascript
	function setupUser({ name, email, age, isAdmin, location }) {
	  // Using an object to encapsulate parameters
	}

4. Comments

Use comments sparingly and only when necessary to clarify complex code segments.

Bad Example:

javascript
	// This function calculates interest
	function calculateInterest(principal, rate) {
	  // Obvious comments are unnecessary
	}

Good Example:

javascript
	// Calculates interest for non-standard compounding periods
	function calculateCustomInterest(principal, rate, periods) {
	  // Useful for complex or non-obvious functionality
	}

5. Formatting

Well-formatted code is crucial for readability. Stick to conventions and ensure consistency.

Consistent Indentation:

Use a standard indentation style throughout your codebase. This should be 2-letter spacing for JavaScript web development. You should be using Prettier to handle your formatting for you.

Bad Example:

javascript
	if (condition) {
	....// Inconsistent indentation
	}

Good Example:

javascript
	if (condition) {
	..// Consistent 2-space indentation
	}

Organize Code Logically:

Arrange code blocks and functions in a logical, coherent order.

Bad Example:

javascript
	// Defining a function in the middle of unrelated code
	function unrelatedFunction() {
	  //...
	}
	// More unrelated code
	function relatedFunctionTwo() {
	  //...
	}

Good Example:

javascript
	// Grouping related functions together
	function relatedFunctionOne() {
	  //...
	}
	function relatedFunctionTwo() {
	  //...
	}

6. Error Handling

Proper error handling is key to robust and reliable code.

Don’t Ignore Caught Errors:

Ensure errors are either handled or logged for later review.

Bad Example:

javascript
	try {
	  // Risky code
	} catch (error) {
	  // Error ignored
	}

Good Example:

javascript
	try {
	  // Risky code
	} catch (error) {
	  console.error(error); // Error logged or handled
	}

7. Avoid Magic Numbers

Replace magic numbers with named constants to make your code more readable and maintainable.

Bad Example:

javascript
	function calculateDiscount(price) {
	  return price * 0.15; // What does 0.15 represent?
	}

Good Example:

javascript
	const DISCOUNT_RATE = 0.15;
	function calculateDiscount(price) {
	  return price * DISCOUNT_RATE; // Clear what 0.15 represents
	}

8. Avoid Deep Nesting

Deeply nested code is difficult to read and understand. Aim for a flatter structure.

Bad Example:

javascript
	if (condition1) {
	  if (condition2) {
	    if (condition3) {
	      // Deeply nested code
	    }
	  }
	}

Good Example:

javascript
	if (condition1 && condition2 && condition3) {
	  // Less nested and clearer
	}
	
	// Alternative solution is to create a variable
	const isConditionsMet = condition1 && condition2 && condition3;
	if (isConditionsMet) {
	  // Less nested and clearer
	}

9. Avoid Premature Optimization

Optimize code only when necessary, and avoid sacrificing readability for small performance gains.

10. DRY (Don’t Repeat Yourself)

Eliminate redundant code by using functions or modules to encapsulate reusable code.

Bad Example:

javascript
	// Repeating code for calculating area
	let area1 = Math.PI * radius1 * radius1;
	let area2 = Math.PI * radius2 * radius2;

Good Example:

javascript
	function calculateArea(radius) {
	  return Math.PI * radius * radius;
	}
	let area1 = calculateArea(radius1);
	let area2 = calculateArea(radius2);

11. Destructure Objects & Arrays

Destructuring objects and arrays provides many benefits, including:

  • make your code more concise and readable
  • avoid repeating property names
  • avoid creating temporary variables
  • extract only the data you need from objects and arrays

Bad Example:

javascript
	const user = {
	  name: 'John',
	  age: 30,
	  location: 'London'
	};
	
	const name = user.name;
	const age = user.age;
	const location = user.location;

Good Example:

javascript
	const user = {
	  name: 'John',
	  age: 30,
	  location: 'London'
	};
	
	const { name, age, location } = user;

References

Hunt, A. and Thomas, D., 2019. The Pragmatic Programmer: Your Journey to Mastery, 20th Anniversary Edition. 2nd ed. Boston: Addison-Wesley.

Martin, R.C., 2008. Clean Code: A Handbook of Agile Software Craftsmanship. 1st ed. Upper Saddle River, NJ: Prentice Hall.