Identifying Design Smells In C#

Code smell is a symptom in the source code that indicates a deeper problem. Martin Fowler defined it as follows: "a code smell is a surface indication that usually corresponds to a deeper problem in the system". Design smells are the logical extension of the code smell concept and defined as follows - “design smells are certain structures in the design that indicate the violation of fundamental design principles and negatively impact design quality”.

For example, “Insufficient Modularization” (also known as “God Class”) is a frequently occurring design smell that arise either due to large number of methods in the class or high cumulative complexity (also referred as Weighted Methods per Class (WMC)) of the methods in the class. The presence of this smell indicates that the development team has not applied modularization principle sufficiently and hence the class can be further decomposed.

There are many side-effects when such a smell present in our code; for instance, it is difficult to understand and change a big class. If a change has been introduced without properly understanding the class, then the probability of introducing bugs is increased significantly. At the same time, more time and effort required to make a change in a large and complex class that clearly establishes how poor maintainability leads to poor productivity. It has been documented that the presence of design smells impacts understandability, flexibility, expandability, reusability, testability, and reliability of the software system.

Detecting design smells

One can identify design smells in one of the following ways:

  1. Manually – By analyzing code and design.
  2. Semi-automatically – By calculating metrics first and then inferring design smells by combining a few metrics.
  3. Automatically – By employing a design smell detection tool.

Often, design smells are identified manually where developers use their experience and domain knowledge to understand the existing design and identify potential refactoring candidate. However, for large codebase, the manual design smell detection is time consuming and not feasible. Additionally, many a times, developers know only a few design smells and not really aware of the extensive catalog of the smells. Such design smells remain unnoticed and undetected until developer faces maintainability problems due to the smells.

A developer may use metric tools such as NDepend and SourceMonitor to compute metrics first and then use and combine metrics with other metrics to infer design smells. For example, high Fan-in and Fan-out values indicate that the class is a Hub-like Modularization. Another example could be Deep Hierarchy that could be inferred by the metric DIT (Depth of Inheritance Tree). However, many design smells cannot be identified by metrics (or a combination of metrics). For instance, Rebellious Hierarchy design smell (also known as Refused bequest) cannot be inferred by metrics alone.

There are a few tools that are dedicatedly developed to detect design smells and improve the quality of the software design. Examples of such tools are Infusion and Designite. Infusion works with Java and C/C++ codebase where Designite targets C# code.

Let us understand step by step, how we can identify design smells using Designite for C# projects:

  1. Download the trial version of Designite from the tools website and install it on your Windows machine.

  2. You will require a trial license to use the tool that you will get in the inbox of the email address that you provided on the web-site while downloading the tool. Place the license file in the installation folder.

  3. Start the tool and select a solution file containing the projects that you would like to analyze. The tool will list all the C# projects in the solution; you can include/exclude individual projects for the analysis.

  4. Once you click “Analyze”, the tool will analyze the selected projects and present a summary of the analysis. The summary includes a few important metrics such as total lines of code in the selected projects, total classes, namespaces, and methods, total metric violations, detected design smells, density of smells per thousand lines of code, and code duplication percentage.

  5. The summary page also shows two graphs viz. metric violations and design smells (classified according to the principle they violate). Additionally, the project specific key metrics could be found on the summary page.

    design analysis Summary

  6. In the detailed view on the left hand side pane, you can see the detected design smells and computed metrics in detail. A sunburst diagram appears when you double click design smells under any of the analyzed projects. The sunburst allows you to navigate and filter the smells based on their violated principle, name, or originating namespace or class.

    design smell

  7. You can click on any design smell to see the cause of the smell (in the bottom pane) and corresponding participating entities.

  8. If you wish, you can export the list of identified design smells and computed metrics along with code duplication instances to a MS-Excel file. Although, this feature is not enabled in the trial version of the tool.

  9. Once you know the existing design smells in your code, you can analyze the reported instances and refactor them to improve the maintainability of your software system. You may find the Hotspots feature of the tool useful since it provides a set of classes that you can target to refactor first.