Clean Code

Amaan Farooq

“Clean code always looks like it was written by someone who cares. There is nothing obvious you can do to make it better” - Michael Feathers

What is a clean code ?

Clean code is simple, easy to read and understand. In the software development world we work mostly in teams so it becomes important for your code to communicate with the next person who works with what you have written. Clean code is essential for enhancing the readability, maintainability and overall software quality.

Naming

  • Choose meaningful and descriptive names for variables, functions and classes -
    Choose variable names that accurately describe the purpose and intent of the variable. Avoid generic names like “data” or “temp” that don’t provide meaningful information. Instead, opt for names that clearly convey the role or meaning of the variable in the context of the code.

  • Avoid ambiguous or misleading names -
    Be careful not to use names that can lead to confusion or misinterpretation. Choose names that accurately represent the value or concept the variable represents. For example, if a variable holds a count of items, naming it “total” or “sum” would be misleading.

  • Clear naming enhances code readability -
    Select names that are easy to read, pronounce, and understand. A developer should be able to easily comprehend the purpose of a variable just by looking at its name. Avoid using abbreviations or acronyms that may be unclear or ambiguous.

  • Be consistent with naming conventions -
    Follow a consistent naming convention throughout your codebase. Whether you prefer camel case, snake case, or another convention, ensure that variables are named consistently. This promotes code readability and reduces cognitive load when reading and understanding the code.

  • Scope-appropriate names -
    Consider the scope and lifetime of the variable when selecting its name. Variables with larger scopes, such as class-level variables, should have more descriptive names, while variables with smaller scopes, such as loop counters, can have shorter, more precise and concise names.

Functions

  • Function name should say what it does -
    The function name should speak on behalf of the function and should convey the context of whatever the function does.

  • Functions should be small, focused, and have a single responsibility -
    A function definition should be as concise as possible. If a function definition exceeds more than 6-7 lines then create another function and make a function call to it. This helps the function to be more focused and limits its responsibility.

  • Small functions improve code comprehension and maintainability -
    Small functions are easier to read and understand. With a limited scope and focused functionality, small functions can be comprehended very quickly.When a bug is discovered or a change is required, developers can focus on the specific function without worrying about the entire codebase.

  • Limit side effects -
    Functions should ideally have minimal or no side effects. A function’s primary purpose should be to perform a specific task, not to modify unrelated variables or global state. Limiting side effects makes functions more predictable and easier to reason about. If side effects are necessary, make them explicit and well-documented.

  • Avoid duplicated code -
    Duplicated code leads to maintenance issues and increases the risk of introducing bugs. Identify duplicated code segments and extract them into separate functions or reusable abstractions. By eliminating duplication, you improve code maintainability, readability, and reduce the likelihood of inconsistencies.

Comments

  • Minimise the use of comments -
    A programmer should limit the comments as much as possible. A comment is a failure from the programmer’s side to write the self explanatory code.

  • Reserve comments for clarifying complex or non-obvious code sections -
    When the code becomes more and more complex then comments can be used as the last resort.

  • Well-written code eliminates the need for excessive comments -
    Well written code is comprehensive and easy to understand so it eliminates the need to write excessive comments.

  • Don’t write html in comments as comments are primarily meant to provide explanations or additional information about the code, not to contain executable code.

Testing

  • Write extensive tests for code -
    By writing an extensive set of tests it can be made sure to make the code more robust and generic.

  • Emphasise unit testing and consider test-driven development -
    Writing tests before the code and for individual units of code like functions or methods helps in improving the quality of code and makes it easy to test.

  • Tests ensure code correctness, reliability, and support future changes.

  • Get bad news as soon as possible -
    The main motivation behind writing the test cases should be to get the bad news as soon as possible. Sometimes a change can be big enough which can require to completely change the design architecture which is very expensive if not identified in the beginning.

Error Handling

  • Use exception handling -
    Utilise exception handling mechanisms provided by the programming language or framework you’re working with. Exceptions allow you to handle errors in a structured manner and provide clear separation between error-handling code and the normal flow of execution.

  • Be specific with exception types -
    Use specific exception types to convey the nature of the error. Rather than relying solely on generic exceptions, create custom exception classes that accurately represent the specific error scenarios in your code. This makes it easier for developers to understand and handle the errors appropriately.

  • Fail early and gracefully -
    Detect errors as early as possible and handle them gracefully. Validate inputs, check for preconditions, and perform necessary error checks at the beginning of functions or methods. This helps prevent errors from propagating or causing unexpected behaviour further down the code execution path.

  • Provide clear error messages -
    When an error occurs, provide clear and meaningful error messages or log entries. The error messages should describe the issue concisely and provide relevant information to aid in troubleshooting and debugging. Avoid generic error messages that provide little insight into the problem.

Why do we write dirty code ?

  • To be fast -
    Writing code fast without cleaning it will eventually slow down the team in future. The only fastest way is to code well by properly refactoring it.

  • Sticking only on requirements -
    Completing the requirement is only the half of the job done. The other half of the job is to make the code clean, simple and well-structured.

  • Setting up tight deadlines -
    Don’t just consider meeting the requirement in estimating the timeline for the next release. If you don’t work on refactoring then at some point you have to do it and the more time is passed the more difficult it gets and ultimately slows the project down.

  • Leaving refactoring for the future -
    There should be no separate refactoring sessions for the code. Do the code refactoring at the time of development.

Conclusion

  • Following clean code principles leads to readable, maintainable, and high-quality code.
  • Clean code benefits not only developers but also the entire organisation.
  • Clean code is not a one-time effort but an ongoing practice. It requires continuous improvement, code reviews, refactoring and staying up to date with the best practices and industry standards.