10 Code Smells You Should Avoid to Keep Your Codebase Clean
Identify and eliminate 10 common programming code smells that harm your codebase's readability and maintainability.
Have you ever felt that sensation that tells you something is wrong while reading your code? That feeling of “mmm something doesn’t look ok” but still, you don’t precisely get what the issue is?
This weird feeling that you get from your code is the correct intuition. These are bad practices, better known as code smells.
Being able to find smells and implement cleaner solutions will help you to make a big jump forward in your programming career, helping to teach yourself how to write clean code.
Long Functions
Writing code for humans is, in my opinion, the golden rule to being a good programmer. And long functions are one of the worst enemies of this mindset since they make our code less readable.
Functions need to be descriptive about what they do and should focus on a single and isolated task so that we can reuse them when necessary. Usually, as a function get longer, its complexity grows as well and the code becomes less maintainable.
Duplicated code
Code duplication is another common anti-pattern present in very professional codebases, and we should try to reduce it as much as possible to keep the code clean and avoid changing the same code in different places if a feature changes.
Different scenarios help to remove duplicated code, but the most common solutions are those that include the creation of a new function to encapsulate that logic or, in case the code is not the same, you can rearrange the code so the similar items are all together for easy extraction (Slide statement).
Long parameter lists
Do you think a function expecting an ordered list of 6–7 (or more) parameters are free from confusion? Having such a long list is more prone to bugs and reduces readability.
We could usually solve this problem by Introducing a parameter object. Doing so consists of combining the long list of parameters that fit together into a new object and passing it as a unique argument. This has many benefits since we can define the parameter object before the function call and the property order is irrelevant. This is something that we should always consider in any parameter list.
Too many comments
I’m not saying commenting on your code is bad, but if you write programs with good naming and follow clean code patterns, your code will be self-explanatory, reducing the boilerplate of your files and increasing the maintainability of your codebase.
Global data
This is something every developer should keep in mind when coding since code that is accessible from everywhere and, especially is mutable, can generate unexpected behaviors if modified.
The most common example of global data is global variables. The first defense mechanism we can use is to Encapsulate the Variable with a function since this at least provides a better way to control its access and see where it has been modified.
However, I’d like to recommend always avoiding global variables and generally global data. There’s always a different approach to implementing a working solution 😁
Mysterious names
I fully agree with this sentence. Properly naming variables, functions, and classes can give a strong boost to the cleanliness of your code! It assures more descriptive code, reduces the usage of comments, and make future developers’ life easier while reading your code!
Lazy elements
Sometimes we implement a new structure to reuse it later or make our code cleaner and more descriptive, but in the end, we realize that it’s useless and we never used it in the codebase😅 We should recognize our errors and be ready to sacrifice this part of code!
We can achieve this result, for example, by using inlining techniques for functions and classes.
Loops
Even if they have been the core of programming for a long time, and still they are useful, many alternatives help our code to be more descriptive and let us understand what it does at first sight.
Using pipeline methods such as .map
or .filter
help to immediately understand how structures are manipulated, reducing the abstraction imposed by a more imperative code.
Large classes
When a class starts growing and has too many fields, the duplicated code is behind the corner. And we hate duplicated code! So we should take care of keeping them as small as possible.
You’ll possibly find yourself refactoring an infinite class because it takes care of non-related operations, and the first solution is to decouple the code using class extraction.
But since we love simple solutions, the fastest solution could be to remove redundancy inside the class itself. To do so, for example, you could take long methods with a lot of shared code and split them into smaller methods, so that you can compose them as you wish, avoiding any sort of repetition.
Temporary field
Even if trying to avoid it, having a class field that we conditionally set is a common scenario. This can bring less clarity to the code since you expect to use all the fields in a class.
Good solutions are to extract a new class to create a place for this field and move the related functions. Alternatively, it’s also good to introduce a special case that creates another class for when the variables are not valid.
Wrapping up
Taking care of your code and working to understand how to improve it is what keeps me loving code and programming. I hope you share my feelings and that you enjoyed the article. I owe the majority of this learning to Martin Fowler and his Refactoring book, a must-read in my opinion!
Last updated: