Avoiding code smells with clean code

Code smells are often referred to as symptoms because they indicate a deeper issue or problem in the codebase. Code smells are common patterns in software code that may indicate that the code is not well-designed, is difficult to understand or maintain, or may be prone to errors.

“ Even bad code can function. But if code isn’t clean, it can bring a development organization to its knees. Every year, countless hours and significant resources are lost because of poorly written code. But it doesn’t have to be that way ”

- Robert C. Martin from Clean Code: A Handbook of Agile Software Craftsmanship.

In Peer review, some common code smells can be identified,

  • Long and complex functions: Functions that are too long or complex can be difficult to understand, maintain, and test. They may indicate that the code is not modular or well-structured, and that it could be refactored into smaller, more manageable units.

  • Duplicate code: Duplicate code is code that appears more than once in a system. It can indicate that the code is not modular or reusable, and that it could be refactored into a shared function or module.

  • Inefficient algorithms: Inefficient algorithms are algorithms that are not optimized for performance, often making them slow and resource-intensive. This can lead to code that is slow and unresponsive, and can make the application less scalable and performant.

  • Dead code: Dead code is code that is no longer used or needed in the codebase. This can make the codebase larger and more complex, and can lead to confusion and errors.

  • Unused parameters: Unused parameters are parameters in methods or functions that are never used or accessed. This can make the code harder to read and understand, and can lead to confusion and errors.

  • Tight coupling: Tight coupling is when different components of the system are tightly interconnected, such that a change in one component can have unintended consequences in other parts of the system. This can make the system difficult to modify and maintain, and can lead to fragility and fragility.

  • Lacking or inconsistent naming conventions: Poorly named variables, functions, or other code elements can make the code difficult to read and understand. Inconsistent naming conventions can also make the code harder to maintain, as it can be difficult to determine how different parts of the code relate to each other.

I've added the list of more code smells at the end of this article, please comment if you think I've missed any.

To find these code smells during peer review, developers can use a variety of tools and techniques, such as code reviews, static analysis tools, or automated testing. These tools can help to identify potential code smells, as well as suggest ways to refactor the code to improve its quality and maintainability. In addition, developers can also use best practices, such as writing clean, modular, and well-documented code, to help prevent code smells from occurring in the first place.

To write clean and modular code, there are a few best practices and techniques that can be useful. Some of these include:

  • Write small, focused functions: Instead of writing long and complex functions that do many different things, try to break the code down into smaller, more focused functions that each do one thing. This will make the code easier to read, understand, and maintain.

  • Use descriptive and consistent naming conventions: Choose clear, descriptive, and consistent names for variables, functions, and other code elements. This will make the code easier to read and understand, and will help to prevent misunderstandings or confusion.

  • Use comments to explain the purpose and behavior of the code: Include comments in the code to explain why it is doing what it is doing, and how it works. This will make the code more self-documenting, and will help other developers (including future you) to understand and work with the code more easily.

  • Follow coding standards and style guides: Use a consistent coding style and follow established coding standards and style guides. This will make the code more consistent and readable, and will help to prevent common mistakes or errors.

  • Use modular and reusable code: Write modular code that can be easily reused in different parts of the system. This will help to reduce duplication and improve code maintainability.

An example of a code smell and clean code in JavaScript might look something like this:

Code smell:

function processData(data) {
  // Check if the data is an array.
  if (Array.isArray(data)) {
    // If it is, loop through the array and process each item.
    for (let i = 0; i < data.length; i++) {
      const item = data[i];
      // Check if the item is an object.
      if (typeof item === 'object') {
        // If it is, loop through the object properties and process each one.
        for (const key in item) {
          if (item.hasOwnProperty(key)) {
            const value = item[key];
            // Check if the property value is a string.
            if (typeof value === 'string') {
              // If it is, do something with the string.
              // ...
            }
          }
        }
      }
    }
  }
}

Clean code:

function processStrings(strings) {
  // Loop through the array of strings and do something with each one.
  // ...
}

function processData(data) {
  // Check if the data is an array.
  if (Array.isArray(data)) {
    // If it is, extract the strings from the array and pass them to the processStrings function.
    const strings = data.filter(item => typeof item === 'object')
                       .map(item => item[key])
                       .filter(value => typeof value === 'string');
    processStrings(strings);
  }
}

The code smell example is long, complex, and difficult to read and understand. It contains multiple nested loops and conditional statements, which make it hard to see what the code is actually doing. Additionally, the code is not modular or reusable, as it is tightly coupled to the specific data structure and input.

In contrast, the clean code example is shorter, simpler, and easier to read and understand. It uses functional programming techniques, such as filtering and mapping, to extract the relevant strings from the data, and passes them to a separate function for processing. This makes the code more modular, reusable, and maintainable. It also makes it easier to test and extend, as the individual functions can be tested and modified independently.

By following these best practices and techniques, developers can write clean and modular code in JavaScript that is easy to read, understand, and maintain. This will help to improve the overall quality and reliability of the code, and will make it easier to add new features and capabilities in the future.

More code smells,

  • Magic numbers

  • Inappropriate intimacy

  • Lack of cohesion

  • Divergent change

  • Shotgun surgery

  • Cyclic dependencies

  • Golden hammer

  • Misplaced responsibility

  • Data clumps

  • Primitive obsession

  • Switch statements

  • Lazy class

  • Refused bequest

  • God class

  • Speculative generality

  • Temporal coupling

  • Middle man

  • Incomplete library class

  • Data class

If you enjoyed this post on code smells and want to learn more, let me know in the comments which code smell you would like to see me cover next! I will do my best to include it in a future post.

Did you find this article valuable?

Support Karthick Selvam by becoming a sponsor. Any amount is appreciated!