How to Write Clean Code: Refactoring and Best Practices
Balraj Singh

Balraj Singh @balrajola

About: Software engineer with 10 years experience developing simple & anti-fragile software for high-volume businesses. Improved Mobile App's stability and responsiveness by incorporating patterns & practice

Joined:
Jan 24, 2023

How to Write Clean Code: Refactoring and Best Practices

Publish Date: Feb 13
129 19

Let’s be honest, every developer (yes, even the ones with years of experience) has shipped messy code at some point.

Writing clean code isn’t some elite skill. It’s a habit you can build. And refactoring? That’s just your chance to make your code actually make sense—both to you and whoever gets stuck maintaining it later.

Let’s break it down. No fluff. No abstract theory. Just practical, real-world tips to help you write clean, maintainable code.

1. Name Things Like You Mean It
Your variables and functions need to tell a story.

Not x, not temp, not data. Those are just placeholders for confusion.

Good: getUserProfile()

Bad: getData()

Good: maxLoginAttempts

Bad: m

When you name things well, your code explains itself—no detective work required.

2. Less Is More: The Power of Function Size

If you’re scrolling through a function like it’s an essay, something’s wrong.

Long functions are hard to read, hard to debug, and hard to maintain. Instead, break them down into smaller, single-purpose functions.

Think of it like this: each function should answer one question. If it’s answering five, break it apart.

Example:

// Instead of this
function processUserData(user) {
  validateUser(user);
  saveToDatabase(user);
  sendEmail(user.email);
}

// Do this
function validateAndSaveUser(user) {
  validateUser(user);
  saveToDatabase(user);
}

function notifyUser(email) {
  sendEmail(email);
}
Enter fullscreen mode Exit fullscreen mode

This makes your code easier to read and reuse. Future-you will thank you.

3. Consistency Is Key

Ever worked on a project where userList was called users in one place and activeUsersArray in another? Chaos.

Keep naming conventions, indentation, and formatting consistent. When your code follows a predictable pattern, it’s easier to read—and easier to debug.

Good: userList, orderList, productList
Bad: users, ordersList, listOfProducts

Pick a convention and stick to it. No surprises.

4. Comment With Purpose, Not Out of Habit

Comments should explain why, not what. If your code needs a comment to explain what it does, rewrite the code instead.

Example:

// ❌ Bad Comment
// Increase count by 1
count = count + 1;

// ✅ Good Comment
// Edge case: Prevents counter from going negative
if (count > 0) {
  count--;
}
Enter fullscreen mode Exit fullscreen mode

Write comments that add value, not ones that state the obvious.

5. Magic Numbers and Hardcoded Values – Get Rid of Them

Ever seen a function with random numbers thrown in? Yeah, it’s a maintenance nightmare.

Instead, use constants that make these values meaningful.

Example:

// ❌ Bad
if (user.loginAttempts > 3) {
  lockAccount(user);
}

// ✅ Good
const MAX_LOGIN_ATTEMPTS = 3;
if (user.loginAttempts > MAX_LOGIN_ATTEMPTS) {
  lockAccount(user);
}
Enter fullscreen mode Exit fullscreen mode

Much better.

6. DRY: Don’t Repeat Yourself

Repetitive code is just waiting to break. If you find yourself copy-pasting, stop. Create reusable functions or modules instead.

Example:

// ❌ Bad: Duplicated logic
sendEmail(user.email, "Welcome!");
sendEmail(admin.email, "New user registered!");

// ✅ Good: Reusable function
function sendNotification(email, message) {
  sendEmail(email, message);
}
sendNotification(user.email, "Welcome!");
sendNotification(admin.email, "New user registered!");
Enter fullscreen mode Exit fullscreen mode

This way, when changes are needed, you only have one place to update.

7. Keep Your Code SOLID

If you haven’t heard of SOLID principles, now’s a good time to start. These are five simple rules that make your code cleaner and easier to maintain.

If nothing else, start with this: The Single Responsibility Principle.

Each function/class should do ONE thing and do it well.

If your class is handling both user authentication and database storage, it’s time for a refactor.

8. Refactor Ruthlessly
Writing clean code isn’t a one-and-done thing. It’s a habit.

Every time you review your code, look for ways to make it better:

  • Can you rename variables for clarity?
  • Can you break down a huge function?
  • Can you remove unnecessary comments?

Don’t wait for a major rewrite—refactor as you go.

Example:

// ❌ First draft
function fetchUserData(userId) {
  return fetch(`https://api.example.com/user/${userId}`)
    .then(response => response.json())
    .catch(error => console.error(error));
}

// ✅ Refactored
async function fetchUserData(userId) {
  try {
    const response = await fetch(`https://api.example.com/user/${userId}`);
    return await response.json();
  } catch (error) {
    console.error(error);
  }
}
Enter fullscreen mode Exit fullscreen mode

Refactoring doesn’t mean your first attempt was bad—it means you’re making it better.

If you can:
✅ Name things clearly

✅ Keep functions small

✅ Stay consistent

✅ Avoid hardcoded values

✅ Refactor often

…you’re already way ahead of the game.

Comments 19 total

  • Hadil Ben Abdallah
    Hadil Ben AbdallahFeb 13, 2025

    Nice Article

  • Tomas Stveracek
    Tomas StveracekFeb 13, 2025

    Good article, I wrote a similar one, but regarding commits, here is the link

    • Balraj Singh
      Balraj SinghFeb 13, 2025

      Oh great, I'll check it out! And thank you.

  • Michael Gbolahan
    Michael GbolahanFeb 13, 2025

    Nice one

  • Ombir Sharma
    Ombir SharmaFeb 14, 2025

    Informative

  • Nathan Jobe
    Nathan JobeFeb 14, 2025

    It is SOO!! Hard to get people to understand these principles. I constantly hear things like. "If it aint broke dont fix it". "Oh you just dont understand business" blah blah blah. And you always get new people in there trying to show you how "to get it done", when all they are doing is making a mess of things.

  • Tomasz Michal Juraszek
    Tomasz Michal JuraszekFeb 14, 2025

    Shouldn't point 4 be:
    if (count < 0) {
    count++;
    }

    Example in point 6, makes no sense?

    • Micheal Kinney
      Micheal KinneyFeb 15, 2025

      I had the same thought, that the two examples were not the same, but neither is this. If counting up, why would count be less than 0? You counting to 0?

      • Balraj Singh
        Balraj SinghFeb 15, 2025

        The example is meant to handle scenarios where the count might already be negative due to prior operations or external factors. In such cases, ensuring it doesn’t decrease further helps maintain logical consistency. Thanks for weighing in.

    • Balraj Singh
      Balraj SinghFeb 15, 2025

      Good observation! The intent behind the example was to prevent the count from decreasing below zero, which is why it checks if (count > 0). If the goal were to increment when the count is negative, your suggestion would be spot on. But in this case, it's about ensuring it doesn’t go below zero.

  • Estefan Cayuela
    Estefan CayuelaFeb 15, 2025

    I felt exposed in some aspects😅
    I will do better, I promise

    • Balraj Singh
      Balraj SinghFeb 15, 2025

      Haha, we’ve all been there! The fact that you’re thinking about it means you’re already ahead. Keep going!

  • Hum Sopha
    Hum SophaFeb 15, 2025

    I think it's just readable

  • Sugriv Lodhi
    Sugriv LodhiFeb 17, 2025

    Good point! Maintaining a well-structured and high-quality codebase is crucial, not just for the current team but also for future developers. It ensures better readability, maintainability, and scalability. It also reduces a lot of pain as our codebase grows.

  • Rajat Rajput
    Rajat RajputFeb 17, 2025

    I feel attacked 😭

    Thanks you so much for this!

  • Sunil kumar Dubey
    Sunil kumar DubeyFeb 19, 2025

    Good article

Add comment