How to Track Code Smells Effectively

The term “code smell” was introduced to software engineering community by Kent Beck in the popular Refactoring book by Martin Fowler. He defined it as “certain structures in the code that suggest (sometimes they scream for) the possibility of refactoring”. It is commonly understood that an excessive number of smells in a software system impair the quality of the software and makes the software hard to maintain and evolve.

A lot about smells has been studied and written since then. I recently put together a large collection of smells in the form of a taxonomy and the current knowledge (including definition, cause, effect, detection methods, and open research challenges) about smells in a literature survey paper.

Life-cycle of a smell

When we write code, knowingly or unknowingly we introduce smells. We may detect some smells manually; however, typically we use tools to detect smells in our code. Undesirably, many times there is no action after smells are detected in a codebase. Other times, quality conscious software developers attempt to refactor some of the detected smells. Still, there are often a large number of detected smells that developers discard consciously. It happens when either the developers think that the tool has detected the smell wrongly or they consider it is infeasible to refactor the smell due to various reasons. For instance, a developer may find a smell infeasible to refactor when the smell has been detected in legacy code which she might not want to or even don’t have permission to change. Other reasons could be technical — there is no rational and effective way to refactor the smell without introducing new smells. Even further, sometimes developers think that the refactoring of the detected smell will bring minor improvement comparing to the effort required to refactor it.

The above context outlines that a smell could be treated in multiple ways based on its semantics and context. Many of the detected smells could be discarded but a significant fraction of them has to be refactored. If a developer took a call to refactor a smell in future, there must be an easy way to track whether it is indeed done.

However, how a developer can track all the identified smells? One painful way is to refer the smell detection tool and the output generated from it. Some tools may allow exporting the detected smells in some convenient format (say CSV). However, it is quite cumbersome and ineffective to work in an editor/IDE and refer the output of a smell detection tool. It only deter developers to ignore the detected smells. Isn’t it convenient for a developer if the identified smells are indicated within her IDE without creating a distraction and details could be accessed when needed?

Manage smells within Visual Studio

Designite is a software design quality assessment tool that analyzes C# code and detects a comprehensive set of architecture, design, and implementation smells. Additionally, it provides mechanisms such as detailed metrics analysis, Dependency Structure Matrix (DSM), trend analysis, and smell distribution maps. Designite offers an extension which can be installed in Visual Studio 2017.

Designite not only detects smells but also allow developers to track and manage them. Specifically, smell tagging and Action Hub features make it possible. All the detected design and implementation smells are shown within the Visual Studio IDE as orange glyphs with red rectangle next to a class (or method) declaration. Therefore, if a class suffers from a design smell, a smell-glyph will appear next to the class declaration; in the case of implementation smells, the glyph appears next to the method declaration. Such smell tagging motivates developers to take an action on the smells corresponding to the class/method. Smell tagging not only flags the source code elements with smells but also allows the user to quickly look at the smell details and more importantly change their status.

Corresponding to the life-cycle of a smell, Designite supports four smell status:

  • Identified: All the newly identified smells are tagged as Identified.
  • Refactor: A developer assigns this status when she thinks she should refactor the identified smell.
  • Wrong: A smell gets assigned to this status when the developer thinks that the tool has identified the smell wrongly.
  • Drop: There are cases when developers know that the smell exists but they cannot (or don’t want to) refactor it due to various reasons discussed above. In such cases, it is logical to assign the smell drop status.

A developer sees smell-glyphs only for smells that are tagged either as identified or refactor status. Smells tagged as drop or wrong are not shown by Designite within Visual Studio. Further, if a smell is assigned refactor status and the developer refactors it, then the associated smell-glyph will be removed when the project gets analyzed next time.

A bright orange color smell-glyph keeps prompting the developer to take action on the smell. It promotes the Boy Scout rule of continuous refactoring.

Finally, Action Hub provides a consolidated view of all the identified smells and offers a navigation mechanism for it. When a developer analyzes a project, Designite keeps the analysis report for later use by Action Hub. One may filter the smells based on various factors such as smell types (architecture, design, or implementation), smell status (identified, drop, wrong, or refactor), or smell location (such as project or namespace). One may also change the status of a smell from Action Hub.

To conclude, identifying smells is only the first step. We, as developers, have to take an appropriate action on the identified set of smells. Designite facilitates not only identification of a comprehensive set of smells but also offers tracking and managing smells effectively within Visual Studio. It makes the goal of improving maintainability of source code easier to achieve.

Student of life; student for life. Researcher, Developer, Speaker, and (co-)author of 'Refactoring for Software Design Smells'. http://www.tusharma.in