We presented a summary of our findings in
Daniel Speicher, Sebastian Jancke: Smell Detection in Context, 12. Workshop Software-Reengineering(WSR) 2010, Bad Honnef, Germany (preprint, slides).
What we called “structural context” then was elaborated and discussed in much more detail in
Daniel Speicher: Code Quality Cultivation, in A. Fred, J. Dietz, K. Liu, J. Filipe (Eds.): Knowledge Discovery, Knowledge Engineering and Knowledge Management - Communications in Computer and Information Science Volume 348, 2013, pp 334-349 (preprint, data, 2011 workshop slides)
The term “Smell” as a potential opportunity for a refactoring has been mentioned first by Fowler in [Martin Fowler.Refactoring: improving the design of existing code.. Addison-Wesley, 1999]. Cultivate supports a huge variety of different structural Smells.
An informal definition of a code smell can be seen in the Wikipedia article on code smells.
Software metrics measure different aspects of the source code, many of the metrics available in Cultivate were defined by [Michele Lanza, Radu Marinescu. Objects-Oriented Metrics in Practice. Springer, 2006].
An informal definition of a software metric can be seen in the Wikipedia article on software metric.
A basic Cultivate feature is the Metric and Smell Results view. As an example the view below lists different smells and metric values for some classes of the example project JHotDraw sorted by location.
|Metric and smell detector results|
As you can see on the left side, the user can filter and select which smells and metrics should be calculated for the current working project. Selected elements of the left side are computed and the location of smells as well as metric values are shown on the right side. By double clicking on the location on the right side, it is also possible to directly jump to the source location in the Java editor.
The local menu of the view is located on the upper right.
|Local menu of the result view|
- Link with Editor
- Export all currently visible smell and metric values
- Enable the default smells:
- God Class
- Brain Class
- Data Class
- Iceberg Class
- Refused Parent Bequest
- Brain Method
- Feature Envy
- Shotgun Surgery
- Dispersed Coupling
- Intensive Coupling
- Disable all selected smells and metrics
|The overview pyramid|
The Overview Pyramid is an integrated, metrics-based means to both describe and characterize the overall structure of an object-oriented system, by quantifying the aspects of complexity, coupling and usage of inheritance (Michele Lanza). For papers describing the reasoning behind it see the following.
The Overview Pyramid has three main sections, displayed in different shades of green. Inside the sections, different measurements are arranged to describe the structuring of the project. Good values are coded in green, normal values are blue and abnormal values are red.
The top part is composed of two proportion metrics and reveals the level of inheritance usage in the software system.
- ANDC (Average Number of Derived Classes) is the average number of direct subclasses of a class. It counts the number of direct subclasses and divides it by the total number classes. Not counted are interfaces and library classes.
- AHH (Average Hierarchy Height). Let a class in the system call a root class if it is not derived from any superclass. AHH is computed by
- summing up the maximum path lengths from all root classes to their deepest subclass and dividing this sum by the total number root classes.
- A low value suggests an overall flat class hierarchy structure, where a high value suggests excessive inheritance usage. Again, interfaces and library classes are ignored.
Analogous to the Size & Complexity part thresholds indicate rather high, low or average metric outcomes compared to reference projects used in [LM06].
The left side provides information regarding to size and complexity of the system. For that it uses some of the most simple metrics which are computed directly from the code, counting the modularity units of a system (i.e. packages, classes, methods, lines of code/statements) and placing them per line in a top-down manner with regard to their granularity.
- NOP - Number of Packages, i.e. the number high-level packing mechanisms, like packages in Java, namespaces in C++.
- NOC - Number of Classes, i.e. the number internal classes in a system.
- NOM - Number of Operations, i.e. the number operations (methods, global functions…)
- LOC - Lines of Code, i.e. the number statements of all user- defined operations.
- CYCLO - Cyclomatic Number, i.e. the total number possible program paths which can be concluded from all operations. (see T.J. McCabe. A measure of complexity. IEEE Transactions on Software Engineering. 1976)
The number to the right of the respective metric name is the actual metrics' outcome. The number to the left, however, is the result of dividing the number to the right by the next upper one, as depicted in the following figure.
|Left side of the Overview Pyramid|
The respective quotients are named as follows:
- High-level structuring (NOC/NOP) indicates if packages tend to be coarse or fine grained.
- Class structuring (NOM/NOC) indicates how operations are distributed over the system. High values might indicate classes stuffed too much.
- Operation structuring (LOC/NOM) indicates how well the system's behavior is distributed among operations. Rather high values might suggest operations doing too much.
- Intrinsic operation complexity (CYCLO/LOC) indicates the conditional complexity to expect in operations.
These measurements allow an independent look on each of the above aspects (since the direct metrics such as NOP, NOC etc. influence each other for apparent reasons). What, in return, allows for easy comparison with other projects, independent of the project sizes.
The right part of the view provides information about the level of coupling in the system. Two metrics are computed directly from the code:
- CALLS - Number of Operation Calls counts the total number of operation invocations. Multiple calls to the same method in one method are counted only once.
- FANOUT - Number of Called Classes counts the number classes from which methods are called. It is a sum of the FANOUT metric introduced by [Mark Lorenz, Jeff Kidd. Object-Oriented Software Metrics: A Practical Guide. Prentice, 1994].
Analogous to the Size & Complexity part proportions result of dividing two cascading values:
- Coupling intensity (CALLS/NOM) denotes how many other operations are called on average from each operation.
- Coupling dispersion (FANOUT/CALLS) indicates the average number classes involved in operation calls (hence can be a value between 0 and 1.
|Right part of the Overview Pyramid|
[LM06] compares several software projects written in either Java and C++ and declares thresholds for considerably low, average and high values of the proportion metrics. Depending on the threshold value closest to the computed metric result, its cell is colored red (high), green (average) or blue (low).
The “Smell Context View” provides a graphical representation of local smell contexts. The local context is constructed around the currently edited method in a Java editor of Eclipse. It consists of the enclosing class, calling types, called types and the direct inheritance chain. Only elements are picked, that have a relation due to smells at current method. All presented elements are also subject of the smell analysis, however no further relations are explored.
The study of smells in their context thus starts at a method. First, open a class in a Java editor and also open the “Outline View”. Whenever a method is edited or selected in the editor, it's also selected in the Outline View. The Smell Context View is conntected to this Outline View and constructs the context for a selected method.
You can click on the shown relations and nodes to display details of the smells. Details of interest are complexities, used methods and attributes as well as calling methods. These details are defined by the smell definitions.
For further example of this feature see here.
|Visualization of collocated smells|