In Apiumhub we always focus on quality and best practices in Software development. When we don’t start working on a project from scratch, we very often find code smells and this article is about it. Martin Fowler very well explained one day what is a code smell, it is a surface indication that usually corresponds to a deeper problem in the software system. And the term was first coined by Kent Beck while helping Martin with the Refactoring book, which I highly recommend to read. Well, if you are interested in this topic, here you may find a list of other very useful software development and software architecture books.

One of the nice things about code smells is that it’s easy for inexperienced people to spot them, even if they don’t know enough to evaluate if there’s a real problem or to correct them. Many companies organize “code smells of the week” and ask developers to look for the smell and bring it up with the senior members of the team. Doing it one smell at a time is a good way of gradually teaching people on the team to be better programmers.

 


Common Code Smells

 

Developers are typically trained to look out for logical errors that have been accidentally introduced to their code. Such errors will range from forgotten edge cases that have not been handled to logical bugs that cause entire systems to crash. But what about the other issues that don’t affect the way the system works? For example, the design issues that make the system hard to maintain, and increase the chance of bugs in the future, etc.? Code Smells are signals that your code should be refactored in order to improve extendability, readability, and supportability.

 

Here you have the most common code smells:

 

Bloaters

Bloaters are code, methods and classes that have increased to such proportions that they are hard to work with. Usually these smells do not crop up right away, rather they accumulate over time as the program evolves. For example: Long Method, Large Class, Primitive Obsession, Long Parameter List, Data Clumps.

 

Object-Orientation Abusers
All these smells are incomplete or incorrect application of object-oriented programming principles. For example, Switch Statements, Temporary Field, Refused Bequest, Alternative Classes with Different Interfaces

 

Change Preventers
These smells mean that if you need to change something in one place in your code, you have to make many changes in other places too. Program development becomes much more complicated and expensive as a result. For example: Divergent Change, Shotgun Surgery, Parallel Inheritance Hierarchies

 

Dispensables
A dispensable is something pointless and unneeded whose absence would make the code cleaner, more efficient and easier to understand. For example: Comments, Duplicate Code, Lazy Class, Data Class, Dead Code, Speculative Generality.

 

Couplers
All the smells in this group contribute to excessive coupling between classes or show what happens if coupling is replaced by excessive delegation. For example, Feature Envy, Inappropriate Intimacy, Message Chains, Middle Man, Incomplete Library Class.

 

Let’s look at some of them in details, the ones that are found the most:

 

Long method
The majority of a programmer’s time is spent reading code rather than writing code. Apart from the difficulty of having to keep a lot of complex logic in mind whilst reading through a long method, it is usually a sign that the method has too many responsibilities. Long methods make code hard to maintain and debug. If it is not possible to view the whole method on your smartphone screen, consider breaking it up into several smaller methods, each doing one precise thing.

 

Duplicate Code
When developer fixes a bug, but same symptoms are faced again later on, this can be the result of code duplication, and a bug being fixed in one occurrence of the imperfect code but not in the duplicated versions. This poses an overhead in terms of maintenance. When developers are not aware of the duplication, they only know to fix the occurrence they have come across. Take care of the repeated code blocks and extract them out into a single place – don’t repeat yourself!

 

Inheritance method
If a class inherits from a base class but doesn’t use any of the inherited fields or methods, developers should ask themselves if inheritance really is the right model. Signs of this code smell may be that the inherited methods go unused, or are overridden with empty method parts.
Inheritance should be used when a class wants to reuse the code in its superclass. If the classes diverge and the subclass no longer needs that functionality, the hierarchy should be broken and delegation considered instead. And to keep some inheritance, remove the unused fields and methods from the subclass and create a new layer that the objects can inherit from.

 

Data Clumps
Where multiple method calls take the same set of parameters, it may be a sign that those parameters are related. To keep the group of parameters together, it can be useful to combine them together in a class. This can help aid organisation of code.

 

Middle Man
When a class exists just to delegate to another, a developer should ask themselves what its real purpose is. Sometimes this is the result of a refactoring task, where logic has been moved out of a class gradually, leaving an almost empty shell.

 

Primitive types
Primitive types give little in terms of domain context. Wrap them in a small class to represent the idea. Often this kind of class is expanded to include methods to add to the class.

 

Divergent Code
It is when a class is commonly changed in different ways for different reasons and suffers many kinds of changes. So, ideally, you should have a one-to-one link between common changes and classes.

 

Shotgun Surgery
It is basically when you want to make a kind of change, you need to make a lot of little changes to a lot of different classes. The problem is that when the changes are all over the place, they are hard to find, and it’s easy to miss an important change.

 

Feature Envy
It is when a method does not leverage data or methods from the class it belongs to. Instead, it requires lots of data or methods from a different class.

 

Primitive Obsession
When you use multiple primitive data types to represent a concept such as using three integers to represent a date. Don’t be afraid to use small objects for small tasks such as money classes that combine number and currency.

 

Lazy Class
A class that isn’t doing enough to pay for itself, but remember that each class you create costs money to maintain and understand.

 

Type Embedded in Name
Avoid placing types in method names; it’s not only redundant, but it forces you to change the name if the type changes.

 

Uncommunicative Name
Does the name of the method succinctly describe what that method does? Could you read the method’s name to another developer and have them explain to you what it does? If not, rename it or rewrite it. Pick a set of standard terminology and stick to it throughout your methods. For example, if you have “Open”, you should probably have “Close”.

 

Dead Code
Delete code that isn’t being used. Make it clean and simple.

 

And many others, if you want we can discuss them in the comments section below!

 

And if you are interested in best practices in software development, I highly recommend you to subscribe to our monthly newsletter to receive latest software development books, tips, and upcoming events.

 

If you liked this article about common code smells, you might like …

 

Software development books to read in 2018

Why Kotlin language? Why did Google choose it?

iOS continuous integration with Fastlane & Jenkins

MVP pattern in iOS

Software architecture books to read this year

Scala Type bounds 

F-bound over generic type of Scala

Charles Proxy in Android Emulator

Top software development blogs 

Top software testing techniques & tools to use

A Guide to Tmux that will increase your productivity

Functional debt vs technical debt

BDD: UI Testing

Microservices vs monolithic architecture

SRP in Object oriented design

Almost infinit scalability