In this article, you will learn what code smells are, how to identify them, and how to solve them to make your code and solutions cleaner. Let’s get started!
What is a Code Smell?
A code smell is a piece of code that goes against good practices or fundamental design principles and therefore negatively impacts the quality of our solution. Therefore we try to remove or at least minimize the amount of code smells and their severity in our solution. A common practice is to also refactor existing code to remove code smells. “If it stinks, change it”.
Top 6 most common Code Smells
There are dozens of code smells and you can read whole pages or even books about them but I found that the following 6 are the most common code smells you can avoid or fix them when you find them in your code.
1) Long Method Implementation
Have you seen those methods that make you scroll just to get an idea of what is happening? Those monoliths with hundreds and hundreds of lines of code and lots of conditionals and maybe a couple of loops?
If you have seen or written one of those methods then you are most probably missing some abstractions and decomposition. The problem this code smell brings is that the method does too many things and is probably very imperative. We have to get into the dirt to understand what it does instead of having clear and concise blocks (methods, objects, structures, etc) that abstracts the developer from unnecessary details.
To solve this code smell you have to delegate responsibilities to corresponding objects/classes and create smaller methods that make sense together.
2) The Bazooka (Contrive Complexity if you like fancy)
This code smell receives its name from the taken to the extreme example of using a giant bazooka to kill an ant or a fly.
It happens when developers design over-complicated and complex solutions for tiny problems. You should always look for the best-suited design and implementation to solve the problem. Do not try to use one solution to fit all the problems. Your design isn´t better because you have 10 classes and 2 patterns together.
To fix this code smell try to really think if you need all the abstractions you created. Are you adding interfaces and abstract classes or whole patterns “just in case we need them later”? If so, consider a simpler option. You can probably solve the same problem with 1 class instead of 3 that only have 1 line of code and there are no imminent requirements to expand them.
3) Long Parameter List
Have you seen those signatures with 8+ params? Scenarios in which the signature of the method is 15 lines long? You are missing an object in most cases.
The interface is a contract and having it all over the place and distributed isn’t maintainable/scalable. All the consumers of this method will have to comply with this hard signature, and with any change multiple places will have to be modified.
To solve this you can create the missing abstraction and very often you will find more responsibilities associated with that abstraction. For example a class containing all those params could have some methods or properties to present its data differently or add default values, etc.
4) Duplicated Code
This is by far the most typical and easy to spot. Do not repeat yourself (DRY). As soon as you find yourself copy/pasting the code stop and think if you shouldn´t encapsulate it in a commonplace, most of the time the answer is yes.
It can be done using delegation inside a class, composition with another class, inheritance or simply a new function. Lets take a look at an example with some code:
You should clearly see that this code is identical for processing a payment, and it would surprise you how common it is for developers to just think: “Oh, we have the code to do that here, let me just copy it and it will work”. This brings a lot of problems, the first one is maintainability. If there is any change to this logic you have to remember it is in 2 places, or maybe even more. There are more problems with that piece of code, but it is just an example to show you a case of this code smell and how to solve it. In this toy example the solution would be to encapsulate the behaviour in a method of one of the classes, since we are lacking some context we can just send it to a function and pass both objects as parameters and it would look like this:
5) Misplaced Methods
Avoid secretary methods. This happens when you add layers of calls to different objects or methods that do not add any value or have any logic (aka not necessary). Another example of misplaced methods is when you have logic pertinent to another object being encapsulated in the “user” of said object. For example, if we were to move the logic to handle the payment update fields to the client class.
To solve this code smells remove unnecessary secretary methods, and relocate code to the pertinent class (sometimes includes creating new abstractions).
6) God Class
This one is fairly common too and brings nightmares to the developer that has to maintain it. Having a class with too many responsibilities. It knows too many objects, has too many interfaces, does a lot of things, and every change impacts it.
The solution is not trivial, you probably are missing a redesign, a pattern, or extra classes with some composition to delegate tasks and make our god class a little bit more compact.
The way to solve these and more code smells is to refactor your solutions. Which is a great topic for another article! Thanks for reading and keep your code clean without smells.