How to Write Clean Code – Tips for Developers with Examples

arghodev

Argho Dev

Posted on November 30, 2024

How to Write Clean Code – Tips for Developers with Examples

Writing clean code is an essential skill for developers. Clean code not only makes your code easier to read, maintain, and debug but also ensures that other developers can collaborate effectively. Whether you're a beginner or a seasoned developer, following clean code principles is crucial for creating robust and efficient software.

In this blog, we’ll explore tips for writing clean code with examples and actionable insights.


What is Clean Code?

Image..

Clean code is:

  • Readable: Easy for others (and your future self) to understand.
  • Maintainable: Simple to modify or extend without breaking functionality.
  • Efficient: Solves the problem without unnecessary complexity.
  • Testable: Designed in a way that facilitates testing and debugging.

Let’s have a look at this graph. It shows two different ways of writing code and how they affect the time it takes to add more lines:

Image..

  1. 💀 Quick & Dirty Code (Red line): This is when you write code quickly without planning or organizing it well. At first, it may seem faster, but as more lines are added, it becomes harder to understand and fix. So, over time, it takes longer and longer to add each new line.

  2. 🌩 ** Thoughtful & Clean Code** (Blue line): This is when you write code carefully, making it easy to understand and change. At first, it might take a bit longer, but over time, it remains easy to work with. This way, adding new lines doesn't become more difficult.

1. Use Meaningful Names

Tip: Choose descriptive and unambiguous names for variables, functions, and classes.

Example (Bad):

let a = 10;
function d(x) {
  return x * a;
}
Enter fullscreen mode Exit fullscreen mode

Example (Good):

let taxRate = 10;
function calculateTax(amount) {
  return amount * taxRate;
}
Enter fullscreen mode Exit fullscreen mode

🎯 Naming Tips

  • Variables: Use nouns that describe the data, like userAge or totalAmount.
  • Functions: Use action words, like calculateTotal() or fetchUserData().
  • Classes: Use singular nouns, like User or Order, to represent what they are.

2. Follow the Single Responsibility Principle

Tip: Each function or class should have one specific purpose.

Example (Bad):

function handleUserInput(input) {
  validateInput(input);
  saveToDatabase(input);
  sendNotification(input);
}
Enter fullscreen mode Exit fullscreen mode

👎 Why this is bad:

The function name calculateTotalAndReturnRecord shows that it’s trying to do multiple things. If you want to use just the calculation, you can’t reuse this function without the record part. It’s also harder to update and test each task separately.

Example (Good):


function validateInput(input) {
  // validation logic
}

function saveToDatabase(input) {
  // database logic
}

function sendNotification(input) {
  // notification logic
}

// Call these functions separately.
Enter fullscreen mode Exit fullscreen mode

👍 Why this is good:

Each function has a clear, focused task. calculateTotal only does the math, while createCalculationRecord adds the extra details. If you want to change how the total is calculated, you only update calculateTotal, and if you want to change the record format, you only update createCalculationRecord.

3. Write Smaller Functions

Tip: Break large functions into smaller, more manageable ones.

Example (Bad):


function processOrder(order) {
  // Validate order
  if (!order.items || order.items.length === 0) {
    console.log('Invalid order');
    return;
  }

  // Calculate total
  let total = 0;
  for (let item of order.items) {
    total += item.price;
  }

  // Apply discount
  if (order.coupon) {
    total -= total * order.coupon.discount;
  }

  // Save order
  saveOrderToDatabase(order);
}
Enter fullscreen mode Exit fullscreen mode

Example (Good):


function validateOrder(order) {
  return order.items && order.items.length > 0;
}

function calculateTotal(order) {
  let total = order.items.reduce((sum, item) => sum + item.price, 0);
  if (order.coupon) {
    total -= total * order.coupon.discount;
  }
  return total;
}

function processOrder(order) {
  if (!validateOrder(order)) {
    console.log('Invalid order');
    return;
  }
  const total = calculateTotal(order);
  saveOrderToDatabase(order);
}
Enter fullscreen mode Exit fullscreen mode

4. Write Smaller Functions

🎯Tip:

  • Break large functions into smaller, more manageable ones.
  • Smaller functions are easier to read, test, and reuse.

Example (Bad):


function processOrder(order) {
  // Validate order
  if (!order.items || order.items.length === 0) {
    console.log('Invalid order');
    return;
  }

  // Calculate total
  let total = 0;
  for (let item of order.items) {
    total += item.price;
  }

  // Apply discount
  if (order.coupon) {
    total -= total * order.coupon.discount;
  }

  // Save order
  saveOrderToDatabase(order);
}
Enter fullscreen mode Exit fullscreen mode

Example (Good):


function validateOrder(order) {
  return order.items && order.items.length > 0;
}

function calculateTotal(order) {
  let total = order.items.reduce((sum, item) => sum + item.price, 0);
  if (order.coupon) {
    total -= total * order.coupon.discount;
  }
  return total;
}

function processOrder(order) {
  if (!validateOrder(order)) {
    console.log('Invalid order');
    return;
  }
  const total = calculateTotal(order);
  saveOrderToDatabase(order);
}
Enter fullscreen mode Exit fullscreen mode

5. Use Consistent Formatting

Readable code uses indentation, line breaks, and spaces to keep everything neat and organized. Think of it like writing a story: paragraphs make reading easier by breaking up large chunks of text. In coding, line breaks serve the same purpose.

Example (Bad):


if(isActive){
console.log("Active");
}else {
 console.log("Inactive");
}
Enter fullscreen mode Exit fullscreen mode

Example (Good):


if (isActive) {
  console.log("Active");
} else {
  console.log("Inactive");
}
Enter fullscreen mode Exit fullscreen mode
  • In VS Code, Prettier and Black are popular formatters that automatically apply clean code styling for multiple languages.

  • PyCharm and IntelliJ have powerful built-in formatters with customizable rules, supporting PEP 8 for Python and other standard guides. These tools ensure consistent, readable code across projects with minimal manual effort.

6. Be Careful with Dependencies

🔌 Dependencies are pieces of software that your code relies on.

Imagine you're building a web app that sends emails. Instead of writing the email-sending code yourself, you use an external library like Nodemailer.
Here, Nodemailer is a dependency --- your app relies on it to handle the email-sending functionality.

Example:

const nodemailer = require('nodemailer');

function sendEmail(to, subject, message) {
    const transporter = nodemailer.createTransport({
        service: 'gmail',
        auth: {
            user: 'your-email@gmail.com',
            pass: 'your-email-password'
        }
    });

    const mailOptions = {
        from: 'your-email@gmail.com',
        to: to,
        subject: subject,
        text: message
    };

    return transporter.sendMail(mailOptions);
}
Enter fullscreen mode Exit fullscreen mode

In this code, nodemailer is imported and used to create a transporter for sending emails. Without it, you’d need to build all the email functionality from scratch, which would be complex and time-consuming. By using Nodemailer as a dependency, your app can send emails easily.

Even though dependencies are useful, you should try to avoid over-dependence on external software or libraries. Use dependencies only when they simplify your work or add important functionality.

🎯 Managing dependencies effectively is key to writing clean code. Here are some tips:

  • Limit Dependencies: Only include libraries or modules that are essential for your project.
  • Keep Versions Updated: Use updated versions of libraries to avoid security risks.
  • Separate Logic: Write core functions yourself whenever possible. This way, if you ever need to remove a dependency, it won’t break your code.

7. Avoid Magic Numbers and Strings

👌*Tips: *

  • Named constants make the code more understandable and reduce errors during updates.
  • Replace hard-coded values with named constants or enums.

Example (Bad):


if (user.role === 1) {
  console.log('Admin');
}
Enter fullscreen mode Exit fullscreen mode

Example (Good):


const ROLES = {
  ADMIN: 1,
  USER: 2,
};

if (user.role === ROLES.ADMIN) {
  console.log('Admin');
}
Enter fullscreen mode Exit fullscreen mode

8. Organize Your Project

A well-organized project structure is as important as the code itself.

Think of this like organizing your workspace—you need designated places for everything so that you can find them easily. For coding projects, create folders for specific parts, like components, utils, and services.

Image..

📂 How to Organize Your Project

To set up a clean and organized project, you should categorize different parts of your code into designated folders. Here’s a simple example of what a well-organized project structure might look like:

├── src
│   ├── components
│   ├── services
│   ├── utils
└── tests
Enter fullscreen mode Exit fullscreen mode

9. Avoid Hardcoding Values

Hardcoding is directly embedding data values in code, like setting a user ID as 123 instead of using a variable.

Avoiding hardcoded values allows you to reuse code without making constant changes. Store values in variables, constants, or configuration files instead.

Here’s a scenario where hardcoding can lead to issues:

// Bad: Hardcoding user limit
function createUser(name) {
    let numberOfUsers = 100; // Hardcoded value
    if (numberOfUsers >= 100) {
        return 'User limit reached.';
    }
    // Code to create the user
    return 'User created.';
}
Enter fullscreen mode Exit fullscreen mode

In this example, numberOfUsers is hardcoded to 100. If you want to change the user limit, you have to find and modify this value in the code. If it appears in multiple places, this task becomes cumbersome and error-prone.

🏭 Improved Example Using Constants

Now, let’s refactor this code to use a constant instead:

// Good: Using a constant
const MAX_USERS = 100; // Store the limit in a constant

function createUser(name) {
    let numberOfUsers = getCurrentUserCount(); // Get the current count from a function or database
    if (numberOfUsers >= MAX_USERS) {
        return 'User limit reached.';
    }
    // Code to create the user
    return 'User created.';
}

// Example function to get current user count
function getCurrentUserCount() {
    // Simulate fetching the current count, e.g., from a database
    return 90; // Example count
}
Enter fullscreen mode Exit fullscreen mode

10. Write Clear Comments

*Tip: *

  • Unnecessary comments clutter the code, while meaningful comments provide valuable context.
  • Use comments to explain the "why," not the "what." Example (Bad):

// Increment i by 1
i++;
Enter fullscreen mode Exit fullscreen mode

Example (Good):


// Ensure the loop continues by incrementing the counter
i++;
Enter fullscreen mode Exit fullscreen mode

11. Use Proper Error Handling

*Tip: *

  • Robust error handling prevents crashes and improves user experience.
  • Anticipate failures and handle them gracefully.

Example (Bad):


let user = getUserById(id);
// Assume user always exists
console.log(user.name);
Enter fullscreen mode Exit fullscreen mode

Example (Good):


let user = getUserById(id);
if (user) {
  console.log(user.name);
} else {
  console.log('User not found');
}
Enter fullscreen mode Exit fullscreen mode

12. Write Unit Tests

Tip:

  • Tests catch bugs early and provide a safety net for future changes.
  • Test individual pieces of code to ensure reliability.

Example:


function add(a, b) {
  return a + b;
}

// Unit test
describe('add', () => {
  it('should return 5 for add(2, 3)', () => {
    expect(add(2, 3)).toBe(5);
  });
});
Enter fullscreen mode Exit fullscreen mode

13. Avoid Code Duplication

*Tip: *

  • Reusing code reduces errors and makes updates easier.
  • Reuse code wherever possible by creating reusable functions or modules.

Example (Bad):


function calculateCircleArea(radius) {
  return Math.PI * radius * radius;
}

function calculateCylinderVolume(radius, height) {
  return Math.PI * radius * radius * height;
}
Enter fullscreen mode Exit fullscreen mode

Example (Good):


function calculateCircleArea(radius) {
  return Math.PI * radius * radius;
}

function calculateCylinderVolume(radius, height) {
  return calculateCircleArea(radius) * height;
}
Enter fullscreen mode Exit fullscreen mode

14. Keep It Simple

🎯 Tip:

  • Simpler code is easier to understand, test, and maintain.
  • Avoid overengineering or adding unnecessary complexity.

Example (Bad):


function calculateSquare(num) {
  return Math.pow(num, 2);
}
Enter fullscreen mode Exit fullscreen mode

Example (Good):


function calculateSquare(num) {
  return num * num;
}
Enter fullscreen mode Exit fullscreen mode

✔ Best Practices for Clean Code

Now that we’ve covered some important tips, let’s look at some overarching principles that make up the philosophy behind clean code:

🎏 Simplicity: Always aim to make your code as simple as possible.

🧂 Consistency: Keep your code uniform in style and structure.

🌾 Clarity: Your code should clearly communicate what it does.

Efficiency: Write code that’s optimized for performance without sacrificing readability.

Image...

These principles make coding less about writing and more about designing solutions. Writing clean code is a skill that grows with practice, so keep learning and improving over time.

Conclusion 🏁

Writing clean code is like building a strong foundation for a house. It keeps everything in order, making it easy to add new features or fix issues as your project grows.
With these tips, you can start developing habits that will make your code more readable, maintainable, and enjoyable to work on.

🙋‍♂️ Hope to see you next time!

💖 💪 🙅 🚩
arghodev
Argho Dev

Posted on November 30, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related