Assessing Modular Structure Based on Evolution History

The ultimate criterion of a modular software structure is how well it can accommodate requirement changes. Ideally, files in the same module can be changed together, while files in different modules should not be changed together, or at least seldom changed together.  

A DSM in DV8 is a general dependency model, and can be used to model any dependency or co-change information (derived from a project’s revision history) simultaneously. If the input to DV8 is a git repository, the user can choose to analyze the commit history within a specified time range. If successful, DV8 will generate a structure DSM (structure-dsm.dv8-dsm) as shown above, and a history DSM (history-dsm.dv8-dsm) in which the numbers in cells denote the number of times two files were committed together. Finally DV8 will also generate a merged DSM (merged-dsm.dv8-dsm).  

The following is the merged DSM of the Apache Flume project. In this DSM, each cell contains both structure and co-change information. The user can hover over a cell to see the details of the dependencies, as illustrated below:  

Or, a user can right-click on a cell to display detailed dependency information in a pop-up window, from which they can navigate to the source code or revision history to check the origin of the dependencies or the details of the commits where the two files were changed together. 

If the user chooses the menu "Matrix -> Toggle Mod. Violations", the cells with a number in red font indicate that the packages or the files do not have any structural dependency relation but were change together multiple times, as shown below: 

The user can also configure the frequency of co-changes to be displayed using the "Matrix->Cell Options" menu. The following figure shows that, once the user entered the value 10, DV8 will only display file co-change values greater than or equal to 10. This is user-settable because, for projects with only a short history a user might choose a small value, such as 3 or 5, to indicate a problematic level of co-changes. But for a project with a long history, a value of 10 or even more might be more appropriate. 

In this way, the user can easily check which packages or files have no structural dependencies but were changed together frequently, forming a de facto evolutionary module. 

DV8 can detect several anti-patterns based on the integration of co-change and dependency information:

  • Unstable Interface—this detects the quality of key interfaces (design rules) against the evolution path; a high-quality DR should remain stable, not changing often with its dependents.  A problematic (unstable) interface frequently co-changes with its dependents.
  • Crossing—this anti-pttern detects files with both high fan-in and high fan-out that change often with other files. Such files are usually a God class, a Blob, or are large classes containing “spaghetti” code.
  • Modularity Violation—this anti-pattern detects groups of files that have no structural dependencies but which have co-changed frequently.