DEV Community

Cover image for The Elegance of Clean Code: A Fundamental Guide with JavaScript
Alvison Hunter Arnuero | Front-End Web Developer
Alvison Hunter Arnuero | Front-End Web Developer

Posted on • Updated on

The Elegance of Clean Code: A Fundamental Guide with JavaScript

In the world of JavaScript development, there is a secret recipe for success that not everyone is aware of: writing clean, concise, and precise code. Clean code is like a well-organized kitchen, where every utensil has its place, concise code is the minimalist menu that gets straight to the point, and precise code is the chef's signature dish, executed with utmost accuracy.

In this article, we'll explore the importance of these principles and provide 10 JavaScript with TypeScript code snippets that exemplify clean code practices.

1. Meaningful Variable Names

One of the fundamental aspects of clean code is using meaningful variable names. Avoid cryptic names like "x" or "temp." Instead, opt for descriptive names that convey the purpose of the variable.

// Not so clean
const x = 42;

// Clean and clear
const age = 42;
Enter fullscreen mode Exit fullscreen mode

2. Consistent Formatting

Consistency in formatting is key to readability. Stick to a single style guide and be consistent with it. For TypeScript, use the TypeScript-specific formatting rules.

// Inconsistent formatting
function initGreeting() {
  console.log('Viva Nicaragua Libre');
}

// Consistent formatting
function initGreeting(): void {
  console.log('Viva Nicaragua Libre');
}

// Anonymous Function
const initGreeting = (): void => {
  console.log('Viva Nicaragua Libre');
};

// Call the function to display the greeting
initGreeting();

Enter fullscreen mode Exit fullscreen mode

3. Avoid Nesting Callbacks

Callback hell, also known as the "Pyramid of Doom," can make your code hard to follow. Use promises, async/await, or other async control flow mechanisms to keep your code clean and maintainable.

// Callback hell
getUser((user) => {
  getProfile(user, (profile) => {
    displayProfile(profile);
  });
});

// Cleaner with promises
getUser()
  .then(getProfile)
  .then(displayProfile);
Enter fullscreen mode Exit fullscreen mode

4. Comment Sparingly

Comments are essential for explaining complex logic, but strive to write self-explanatory code. If your code is clear and concise, it will often speak for itself.

const calculateTotal = (): number => {
  const total: number = arrSales.reduce((acc: number, currentValue: number) => acc + currentValue, 0);
  return total;
};

const arrSales: number[] = [10, 20, 30, 40, 50, 60, 70, 80, 90, 100];

// Commented code
const total = calculateTotal(); // Calculate the total price

// Clean code
const total: number = calculateTotal();
console.log("Total sum:", total);
Enter fullscreen mode Exit fullscreen mode

5. Use Destructuring

Destructuring assignments can simplify your code and make it more readable, especially when working with objects and arrays.

interface Developer {
  fullName: string;
  age: number;
}

const developer: Developer = {
  fullName: "Alvison Hunter",
  age: 45,
};

// Without destructuring
const fullName: string = developer.fullName;
const age: number = developer.age;

// With destructuring
const { fullName, age }: { fullName: string; age: number } = developer;

Enter fullscreen mode Exit fullscreen mode

6. Avoid Magic Numbers

Magic numbers are hard-coded numerical values that lack context. Replace them with named constants or variables.

// Magic number
const status = 3;
if (status === 3) {
  console.log(`CURRENT STATUS: ${status}`)
}

// Named constant
const STATUS_COMPLETED = 3;
if (status === STATUS_COMPLETED) {
 console.log(`CURRENT STATUS: ${status}`)
}
Enter fullscreen mode Exit fullscreen mode

7. Single Responsibility Principle

Functions should have a single responsibility. Split complex functions into smaller, focused ones.

type Order = {
  id: number;
  products: string[];
};

// Complex function
function processOrder(order: Order): void {
  processPayment(order);
  updateInventory(order);
  dispatchOrder(order);
}

// Clean and concise
function processPayment(order: Order): void {
  console.log(`Processing payment for order ${order.id}`);
}

function updateInventory(order: Order): void {
  console.log(`Updating inventory for order ${order.id}`);
}

function dispatchOrder(order: Order): void {
  console.log(`Delivering ${order.id} - ${order.products}`);
}

// Let's invoke the function now
processOrder({id:"McDon-23EAT45", products:["Fried Chicken","Bread","Ketchup"]});

Enter fullscreen mode Exit fullscreen mode

8. Error Handling

Proper error handling is crucial. Always catch and handle errors gracefully rather than letting them crash your application.

interface JokeResponse {
  id: number;
  type: string;
  setup: string;
  punchline: string;
}

// Poor error handling
try {
  // call your fetch or any other operation here
} catch (e) {
  // Handle all errors
}

// Precise error handling using async as well
async function fetchRandomProgrammingJoke() {
  try {
    const response = await fetch('https://official-joke-api.appspot.com/jokes/programming/random');

    if (!response.ok) {
      throw new Error(`Failed to fetch data. Status: ${response.status}`);
    }

    const data: JokeResponse[] = await response.json();

    if (data.length === 0) {
      // Handle an empty response
      throw new Error('No jokes found');
    }

    const joke = data[0];
    console.log(`Setup: ${joke.setup}`);
    console.log(`Punchline: ${joke.punchline}`);
  } catch (specificError) {
    // Handle errors gracefully
    console.error('An error occurred:', specificError);
  }
}

// Call the function to fetch and display the joke
fetchRandomProgrammingJoke();
Enter fullscreen mode Exit fullscreen mode

9. Avoid Unnecessary Complexity

Simplicity is the key to clean code. Avoid over-engineering or introducing unnecessary complexity.

const x: number = 5
const y: number = 10

// Overly complex
const complexResult:number = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));

// Simplified
const simplifiedResult: number = Math.hypot(x, y);
console.log(complexResult, simplifiedResult);
Enter fullscreen mode Exit fullscreen mode

10. TypeScript for Type Safety

TypeScript is a powerful tool for writing clean, concise, and precise JavaScript. Use it to catch type-related errors early and provide self-documenting code. This is so helpful, you wouldn't believe how much it is, pal!

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

// With TypeScript
function add(a: number, b: number): number {
  return a + b;
}
Enter fullscreen mode Exit fullscreen mode

In conclusion, clean, concise, and precise code is the hallmark of a skilled JavaScript developer. By following these principles and practicing good coding habits, you can create code that is not only easier to read and maintain but also less prone to bugs and errors. Start implementing these practices in your projects today and watch your codebase become a masterpiece of clarity and efficiency. Happy coding!

❤️ Enjoyed the article? Your feedback fuels more content.
💬 Share your thoughts in a comment.
🔖 No time to read now? Well, Bookmark for later.
🔗 If it helped, pass it on, dude!

Top comments (0)