Skip to content
Research track

Code smells

A flexible, lightweight approach to specifying, detecting and visualising code smells in source code written in multiple languages.

Introduction

Detecting all 22 code smells across languages

The accurate recovery of code smells from source code supports activities such as refactoring, maintenance and the examination of code quality. A large number of techniques and tools for the specification and detection of code smells have been presented over the last decade, but they still lack accuracy and flexibility because of the different interpretations of code smell definitions. Most techniques target the detection of only a few code smells, and they render different results on the same examined systems because of the different threshold values of the metrics used for detection.

We present a flexible and lightweight approach, based on multiple searching techniques, for the detection and visualisation of all 22 code smells from source code in multiple languages. The approach is lightweight and flexible because it applies SQL queries to an intermediate repository and uses regular expressions on selected source code constructs. The concept is validated by performing experiments on nine publicly available open‑source software systems developed in Java and C#, and the results are compared with those of existing approaches.


Case studies

Results of smells recovered

Full detection reports for each of the examined systems.

System Source code Smells recovered
JUnit 3.7 junit.org View results (PDF, 138 KB)
JHotDraw 7.0.6 jhotdraw.org View results (PDF, 1.3 MB)
QuickUML 2001 sourceforge.net/projects/quj View results (PDF, 350 KB)
JRefactory 2.6.24 jrefactory.sourceforge.net View results (PDF, 1.7 MB)
RMS f1sourcecode.com View results (PDF, 367 KB)
CMS f1sourcecode.com View results (PDF, 1.2 MB)
Umbraco 6.1.1 umbraco.codeplex.com View results (PDF, 4.4 MB)
Cosmos 107559 cosmos.codeplex.com View results (PDF, 6.0 MB)

Specifications

Code smell specifications and detection steps

Twenty‑one code smells, each with the definition used and the metric expression by which it is detected. Bracketed numbers refer to the references in the corresponding paper.

Name Definition Specification
Long Parameter List A long parameter list exists if:
  1. a method contains more than or equal to a specified number of parameters, the threshold being given by the user; or
  2. it contains two or more (a specified number of) parameters of the same primitive data type.
PL >= PLV  OR  RDT >= 1 PLV = value for the maximum number of parameters; RDT = replicated primitive data type.
Long Method A long method exists if a method contains:
  1. more than or equal to a specified number of lines of code (excluding the method declaration, comments and parentheses); or
  2. more than or equal to a specified number of operands and / or operators.
LOCM >= LOCMV LOCM = lines of code in a method; LOCMV = value for total LOC in a method.
Large Class (God Class) A large or God class exists if a class contains:
  1. more than or equal to a specified number of lines of code (excluding method declarations, comments and parentheses) — PMD uses 100 as the threshold, Checkstyle uses 150; or / and
  2. more than or equal to a specified number of global variables and methods.
LOCC >= LOCCV  OR  nMC >= nMCV LOCC = lines of code in a class; LOCCV = value for total LOC in a class; nMC = number of methods in a class; nMCV = value for the total number of methods in a class.
Lazy Class A lazy class exists if a class contains:
  1. less than or equal to a specified number of lines of code (excluding method declarations, comments and parentheses); or / and
  2. less than or equal to a specified number of methods [40].
LOCC <= LOCCV  OR  nMC <= nMCV LOCC = lines of code in a class; LOCCV = value for total LOC in a class; nMC = number of methods in a class; nMCV = value for the total number of methods in a class.
Data Class A data class exists if a class contains:
  1. only setters, getters and / or a constructor, but no other method performing any functionality [40].
nMc(nf) >= nMc(nf)V  OR  nMc = 0 nMc(nf) = number of non‑functional methods in a class; nMc(nf)V = specified value for the total number of non‑functional methods in a class.
Speculative Generality (Dead Code) Speculative generality exists if:
  1. there is an abstract class which is not implemented anywhere in the system [29].
UAC >= 1 UAC = un‑implemented abstract classes.
Middle Man The middle man smell exists if a class contains:
  1. more than or equal to a specified percentage of external method calls relative to the total number of methods it contains [40].
xMC / nMC >= specified % xMC = external method calls; nMC = number of methods in a class.
Divergent Change A class C is exposed to divergent change if it contains:
  1. more than or equal to a specified number of distinct external methods called by C [41]; or
  2. more than or equal to a specified number of distinct classes whose method(s) are called from C [41].
xMC >= xMCv  OR  xCC >= xCCv xMC = external method calls; xMCv = external method call value; xCC = external class calls; xCCv = external class call value.
Duplicate Code A duplicate code class exists if:
  1. two or more classes contain more than or equal to a specified percentage of similar code.
LOCc1,c2(cmn) / LOCc1,c2(total) >=  % LOCc1,c2(cmn) = lines of common code in classes C1 and C2; LOCc1,c2(total) = total lines of code in classes C1 and C2.
Switch Statement A switch statement in code is a code smell if it contains:
  1. more than or equal to a specified number of case statements [42].
SSC >= SSCV SSC = switch statement cases; SSCV = specified value for the total number of switch statement cases.
Shotgun Surgery A method M is exposed to shotgun surgery if an application contains:
  1. more than or equal to a specified number of distinct external methods that call M [41]; or
  2. more than or equal to a specified number of distinct classes that call M [41].
xMCM >= nxMCM  OR  xCCM >= nxCCM xMCM = external method calls for method M; nxMCM = number of external method calls for method M; xCCM = external class calls for method M; nxCCM = number of external class calls for method M.
Parallel Inheritance Hierarchy Class x and class y exhibit the parallel inheritance hierarchy smell if:
  1. they are at least at the second or a greater level of the hierarchy (having two or more parents at their upper levels); and
  2. both x and y are at the same level of the hierarchy; and
  3. both x and y have the same number of children [29].
PIH(x, y) PIH = parallel inheritance hierarchy between classes x and y; DIT = depth of inheritance hierarchy; NOC = number of children.
Feature Envy The feature envy smell exists if a method contains:
  1. more than or equal to a specified number of external method calls [40].
xMC >= xMCv xMC = external method calls; xMCv = external method call value.
Message Chain The message chain smell exists if:
  1. the method calling chain in the system becomes equal to or greater than a specified value [29].
MC >= MCV MC = method calling chain; MCV = method calling chain value.
Inappropriate Intimacy Inappropriate intimacy exists at:
  1. class level, if a calling class C1 calls more than or equal to a specified number of distinct methods of class C2; or
  2. method level, if a method M of class C1 calls the distinct methods of class C2 more than or equal to a specified number of times.
MCC2,C1 >= nMCC2,C1  OR  MCC2,C1M >= nMCC2,C1M MCC2,C1 = methods of class C2 called by class C1; nMCC2,C1 = number of methods of class C2 called by class C1; MCC2,C1M = methods of class C2 called by method M of class C1; nMCC2,C1M = number of methods of class C2 called by method M of class C1.
Temporary Field A field F is a temporary field if a class contains:
  1. less than or equal to a specified percentage of methods that use F, relative to the total number of methods it contains [23].
Mf / nMc <= specified % Mf = methods that use field F; nMc = number of methods in the class.
Refused Bequest Refused bequest exists if a child class Cc:
  1. uses only less than or equal to a specified percentage of the protected methods of its parent class Cp [43].
(MCc(proc) / MCp(proc)) × 100 <= specified % MCc(proc) = protected methods of the parent class used in child class Cc; MCp(proc) = total protected methods in parent class Cp.
Data Clump A data clump exists if:
  1. two or more classes have two or more data variables of the same name and type.
—
Primitive Obsession Primitive obsession exists if a class contains:
  1. more than or equal to a specified number of primitive data types [29].
nPVC >= PVcV nPVC = number of primitive variables in a class; PVcV = value for primitive variables in a class.
Comments Comments are considered a code smell if a class contains:
  1. more than or equal to a specified percentage of commented code relative to its total lines of code, where commented code includes inline, single‑line and multi‑line comments.
LOCcmntd / LOCTotal >= specified % LOCcmntd = commented lines of code in a class; LOCTotal = total lines of code in a class.
Alternative Classes with Different Interfaces This smell occurs if classes C1 and C2 satisfy a similarity function. The similarity function holds if the classes have:
  1. the same number of methods; and
  2. more than or equal to a specified percentage of code similar to one another.
SFc1,c2 >= specified % SFc1,c2 = similarity factor of class 1 and class 2.