“Code smell, also known as bad smell, in computer programming code, refers to any symptom in the source code of a program that possibly indicates a deeper problem”
Wikipedia
Many of us are aware of the meaning of such a notion as code smell. Code smell might be produced by different code technics such “spaghetti code”, when you include a bunch of if-else statements or, for instance, you create a large “God” class which can do anything: apply connection to data source, create request, fetch request and, in addition to, render some error message if something goes wrong.
But the code smell is related not only to the “beaty” of code, – it’s the first symptom of bad architecture of your application. It may mean the ruin of crucial OOP principles and inability to extend or update your application in future effortlessly. For instance, your “spaghetti code” can be a sign that you’ve forgotten about Strategy pattern and you should remember that your code is very inflexible.
Concerning your “God” class you have to be ready to steadily maintenance. Tight coupling leads to global code rewriting every time when any small changes occure. And as a bonus you are obliged to update a bunch of unit tests for this “mighty” class.
So, in order to start noticing the first signs of problems in your code, we’ll try to grasp main code smells.
Long method
Description: smelly method contains too many lines of code. Generally, more than 10 lines (sometimes it makes sense to include more lines in method, but you have to see bound when you start coupling different responsibilities in one method)
Problems with it: this oversized “beast” causes qa engineers’ desire to be hanged. Endless bunch of mocks, dependent unit tests – all these pleasantness will be faced by them. Your team mates are also “very excited” by trying to grasp the logic of this “Jack of all trades”.
Decisions:
– move one method’s code to separate new methods.
– transform the method into a separate class so that the local variables become fields of the class.
Switch statements
Description: You have a large switch operator with different complex expressions.
Problems: There is a slight smell of functional programming over your code. You have to add/remove your switch if something was changed. If it’s a complex switch with similar logic, adding something new may not be so easy.
Decisions:
– if it’s a type switch, replace switch with polymorphism or strategy pattern
– split switch into smaller methods for different cases
Redundant method
Description: You have a subclass that uses only few parent class’ methods.
Problems: You violate Liskov substitution principle.
Decisions:
– think twice if there is “IS-A” relation between classes, it may be better to use composition over inheritance
– if both classes have a lot in common extract common features in new superclass
Chain reaction
Description: Making any modifications leads to necessity of small changes in different classes.
Problems: Similar responsibilities have been split up among large number of classes.
Decisions:
– combine different classes in one. Be attentive in order not to violate Single Responsibility principle
– existing of some classes may be redundant and other classes may have the similar functions. Try to remove such classes
– almost empty classes such as data classes without any responsibilities may occur, try to include them into other ones.
That’s all. But we’ll continue later!