As software systems, evolve the amount and complexity of the interactions among their components is likely to increase, which negatively affects the system design structure . For instance, certain classes might become coupled because of a new user feature being added, which makes the corresponding modules dependent on each other. System degradation symptoms are often related to high coupling and unwanted dependencies, such as: cyclic dependencies, or violations to design rules, among other design smells . The early detection of such symptoms is important for developers, so that they can plan ahead for actions that preserve the quality of the system.
In this context, there are several tools that help developers to quickly assess if the right dependencies among the system modules are in place, including: LattixDSM, SonarQube, JITTAC or SonarGraph . These tools normally extract dependency graphs from the source code and compute different metrics. Some tools can also bring problems, such as architectural violations or smells, to the developer’s attention. Nonetheless, a limitation of this scenario is that the tools only surface dependencies once they exist in the system. When these problems occur, evidence suggests that developers can be reluctant to fix them . In a forward-looking scenario, developers would want to know which modules are likely to get coupled in the near future to anticipate dependency-related problems and proactively look for solutions.
Although there are approaches for computing coupling metrics, very few of them have dealt with the prediction of dependency relations among software components . A particular graph-based approach is social networks analysis (SNA), which has been used for modeling both nature and human phenomena. Specifically, SNA techniques can predict links that yet do not exist between pairs of nodes in a network. When it comes to Software Engineering problems, SNA applications  have shown evidence that the topological features of dependency graphs can reveal interesting properties of the software system under analysis. Nonetheless, link prediction (LP) techniques has not yet been exploited in the Software Engineering community. One exception is , which applied traditional LP techniques for predicting missing dependencies in build configuration files with uneven results. Given the SNA advances over the last years, we argue that LP techniques need to be revisited with respect to (software) dependency graphs.
A first step towards anticipating (unwanted) design dependencies is to assess the predictive performance of LP techniques for general dependencies in different software projects. In this work, we explore the usage of LP for identifying coupling relations between software modules. Our research question (RQ) is to what extent LP can leverage on information from software versions to predict likely dependencies in the next version, for those pairs of modules that exist in the analyzed versions. To this end, we report on an initial study with 10 versions of 2 Java projects, which were converted to package dependency graphs. Although the results with naive LP techniques were not very precise, as expected, we obtained promising results when using LP in tandem with ML models.
The rest of the article is organized into 4 sections. Section 2 motivates how LP can help in detecting unwanted dependencies. Section 3 describes an experimental study with 2 Java systems, in which we applied 3 approaches for predicting package dependencies. Section 4 discusses the main results. Finally, section 5 covers the conclusions and future work.
Ii Prediction of Appearing Dependencies
Software systems often exhibit design problems, which can be either introduced during development or along their evolution. A number of these problems manifest themselves as unwanted dependencies in the source code [4, 5]. A typical problem is the so-called Cyclic Dependency, in which a set of components directly or indirectly depend on each other to function properly. For example, Figure 1 depicts a cycle (denoted by green and red arrows) among 3 packages of the Apache Derby project (excerpt). The cycle did not exist in version 10.8.3.0 but appeared in version 10.9.1.0 due to a new dependency from org.apache.derby.impl.sql.catalog to org.apache.derby.impl.sql.execute.rts (red arrow).
Another common problem is the so-called Architectural Violation, which refers to a dependency in the actual (implemented) architecture that was not intended in the original architecture. For example, Figure 2 shows a system called SubscriberDB, in which components offer services to other components via interfaces (grey circles), which constitute the allowed architectural interactions. However, 3 code dependencies (red arrows) violated those interaction rules.
For the Java examples above, we assume an architecture compliance process that periodically checks whether the current system implementation satisfies a set of design rules, and reports any issues to developers. Dependencies judged as ”undesirable” might come from new functionality in existing classes or new classes being created under existing packages. These dependencies get inadvertently introduced in the code. Furthermore, despite class-level changes, the package structure remains more or less stable across system versions, while package dependencies keep being added. There are a few exceptions, such as: the initial versions, in which the main structure and functionality are fleshed out, or a version with a major refactoring. Overall, looking at the package network and its evolution, it is possible (and also beneficial) to predict dependencies between packages that are yet unconnected.
In this context, we resort to link prediction (LP) techniques, which adapts SNA for studying the evolution of a network using models of network features . LP seeks to infer ”missing” links between pairs of nodes based on their observable links and attributes. A prerequisite for applying LP is to transform the system under analysis into a dependency graph. More formally, a dependency graph is a graph , where each node is a module, and each edge (or link) is a dependency from nodes to (). Since we deal with Java systems, nodes correspond to packages while edges represent usage relations between packages. Our LP task takes a at time , and then infers the edges that will be added to in time . More formally, let be the set of all possible edges among nodes in . The LP task generates a list of all possible edges in , and indicates whether each edge is present in at .
LP in social networks is based on the principle of homophily , which states that interactions between similar individuals occur at a higher rate than those among dissimilar ones. In our context, this means that similar packages (according to some criteria) have a higher chance to establish dependencies than dissimilar packages. Most techniques for the LP problem use graph topological features that assess similarity between pairs of nodes . These metrics normally produce a ranking of edges in . Table I shows rankings of the top-5 predicted dependencies for org.apache.derby.impl.sql.catalog (example of Figure 1), according to different similarity metrics. Note that org.apache.derby.impl.sql.execute.rts is included in both rankings (i.e., the prediction is positive) but in different positions. Although intuitive, this ranking-based approach is not always effective for complex networks. A more comprehensive approach is to cast LP to a classification problem in which network features are used to build a prediction model.
|Common Neighbours||Adamic Adar|
Iii Study Settings
In order to assess the performance of LP techniques, we took a list of 10 versions for 2 Java systems (see Table II), and tried to predict package dependencies using different approaches. The systems, SubscriberDB (SDB) (10 KLOC) and HealthWatcher (HW)  (49 KLOC), were chosen because we had first-hand knowledge about their evolution and version issues. For this work, we analyzed package dependencies in general, rather than dependencies related to specific design problems. The dependency graphs for the versions were computed with the CDA tool111http://www.dependency-analyzer.org. Dependencies among classes were ignored. For each version , we looked into the number of package dependencies (sparsity) and the amount of code changes from to the next version. For LP to produce reasonable outputs, a pair of consecutive versions (, ) should meet some conditions: i) both and have almost the same number of packages, ii) has changes in their classes or adds new classes, and iii) a percentage of dependencies is added in . These filtering conditions yielded a subset of the versions (in bold in Table II). We should also note that potentially appearing dependencies for new packages added in were disregarded.
|HWv2||92||20||70 (+8, -5)||0.8157||SDBv2||167||16||47 (+17)||0.8042|
|HWv3||104||21||75 (+5)||0.8214||SDBv3||192||17||50 (+4, -1)||0.8162|
|HWv5||108||22||86 (+7, -2)||0.8138||SDBv5||193||17||50||0.8162|
|HWv8||120||24||96 (+5)||0.8261||SDBv8||195||17||51 (+1)||0.8125|
|HW 10||135||25||101 (+4)||0.8317||SDBv10||195||17||51||0.8125|
|where ”#c” indicates number of classes, ”#p” number of packages, ”#deps” number of dependencies, ”+” indicates the number of added dependencies, and ”-” indicates the number of disappeared dependencies|
Dependencies were predicted based on 3 approaches with increased complexity. These approaches relied on the same topological metrics, which provide global or local information of the network . The metrics considered were: Adamic-Adar, Common Neighbours, Katz Score, Resource Allocation, SimRank, and Sørensen. The best performing metrics from : Kulczynski, RelativeMatching, and RusselRao, were also added. Next, we describe each approach in detail.
Iii-1 Ranking-based LP
This approach follows directly from the homophily principle, and gives a baseline for the study. For a package , a ranking of packages is built, based on their chance of having a future dependency with , according to a similarity metric. For pairs of consecutive versions, the quality of predictions was evaluated in terms of precision (i.e., the ratio of actual dependencies discovered to the total number of predictions) for the top- dependencies of the ranking.
Iii-2 Training a Classification Model
In this ML approach, a binary classifier is trained using the topological information provided by a given graph version. An instance for the classifier consists of: a pair of nodes, a list of features (e.g., structural metrics) for the pair, and a label indicating if the nodes are linked (positive class) or not (negative class). Existing dependencies are used to compute features for instances of the positive class, while missing dependencies are used to compute features for instances of the negative class. Both training and test sets need to be defined. The training set considers the full graph for, and the test set considers the full graph (i.e. the real distribution of links) for .The prediction (i.e., classification) of dependencies was made with the Weka implementation of SMO 222https://www.cs.waikato.ac.nz/ml/weka/ parameterized with a RBF kernel, which is useful for unbalanced instance sets as it is the case of the LP problem. Since traditional classification metrics (e.g., precision, recall) might not be sufficient for correctly analyzing this scenario , performance was assessed by means of the area under the precision-recall curve (AUPR).
Iii-3 Time Series Forecasting
This approach combines dynamic SNA (i.e., observations of the graph at different time periods) with topological features to learn a robust ML model able to predict new links . It also relies on communities as closely-related nodes of the graph. Prediction is based on a classifier trained with the last known version of the system,
. The test set considers the estimated feature scores for. The forecasting algorithm was implemented in Weka. Like in the previous approach, we evaluated performance with AUPR.
Iv Evaluation of Predictive Performance
The precision results of the ranking-based approach in both projects were in the range 0.14-0.25 at most, thus predictions were not satisfactory. These results are in line with those in . We believe this is due to relying only on the homophily principle, which does not always hold for software modules. For instance, two similar packages can intentionally be designed to not become dependent on each other, based on business logic or modularity reasons. On the contrary, dependencies might still appear between dissimilar packages. This evidence motivates approaches able to learn ”exceptions” to homophily.
In the second approach, we computed AUPR for the positive class (i.e., existing dependencies) and also a weighted AUPR considering both classes (i.e., existing and non-existing dependencies). The values for a binary classifier over selected versions of SDB and HW are depicted in Figure 3. For each pair (X axis), the first item is the version for the training set, while the second item is the version for the test set. Only pairs with new dependencies between existing packages are shown. We obtained better precision for the weighted class, with average values of 0.85 and 0.96 for SDB and HW. Nonetheless, precision for the positive class was still far from ideal, with values of 0.74 and 0.23 respectively.
Despite a high weighted AUPR, Figure 3 shows variations in the positive class AUPR. For instance, the low AUPR for the positive class in - for HW means that the classifier finds all new dependencies correctly (good recall), but it also mistakenly reports non-existing dependencies (low precision due to false positives). Thus, in practice, the set of predicted dependencies might be noisy and very long to analyze by developers. Nonetheless, for the SDB pairs - and -
, the trained model achieved both good precision and recall. The performance variations imply that, for certain versions, it is difficult to differentiate between dependencies and non-dependencies due to similar structural characteristics. For example, the positive class AUPR consistently increased as HW evolved. Similar trends were noticed for SDB, although with higher values than for HW. For SDB, only new dependencies were added in-, while in - existing dependencies disappeared. These facts reinforce our position about the need to consider additional information for having good predictions.
To improve the positive class AUPR, we exercised the third approach based on forecasting. Figure 6 presents the AUPR results for selected versions of SDB and HW. For each pair (X axis), the versions represent the span for the estimations, e.g., - means that , and served to estimate the features for , which was the test set. The results compare predictions with the real (in red) and estimated (in blue) features. As observed, real features still expose difficulties for identifying dependencies and non-dependencies, which leads to performance variability across the versions. For the estimated features, in turn, we see the same or even better predictions than for the real features, allowing the classifier to achieve good performance. In fact, the average precision for the positive class increased regarding the second approach to 0.84 and 0.37, for SDB and HW respectively. The choice of versions for forecasting seems relevant. When starting the estimation in for SDB, results are lower than when starting in . Similarly for HW, results are lower when starting in than in . Moreover, as the number of HW versions increased, the quality of predictions decreased as for - and -. This effect can be related to the information or the structural changes in each version, regardless of the actual number of versions. For instance, if a version undergoes a refactoring that greatly affects dependencies, information from prior versions might not be representative of the actual system structure.
V Conclusions and Outlook
In this work, we make the case that usage dependencies among software modules can be predicted by leveraging on LP and topological information from system versions. Our goal was not to develop the ”best predictor”, but rather to assess i) the LP performance in dependency graphs, and ii) the kind of information required for having reasonable predictions. Although naive LP techniques are not adequate for the task, we obtained evidence that combining them with ML techniques improves their performance. This approach is interesting for dependency management and architecture compliance tools, as it helps to anticipate dependency-related design problems.
Despite the potential of LP techniques, further investigation is needed. A systematic study with more systems is required to corroborate our initial findings. The features currently used in the approaches can be extended. In particular, software-specific metrics and similarity criteria (e.g., for source code artifacts) are necessary. Also, the concept of communities  (used in time series forecasting) can help boosting predictions. In addition, we envision the development of a tool able to infer unwanted dependencies among software elements. Customized LP algorithms for dependency-based design problems (e.g., layering violations, cycles, or hub-like dependencies) can be created. Design metrics can be also estimated (e.g., instability, or change proneness). At last, integration with existing tools, such as SonarQube, is another subject for future work.
- Ali et al.  N. Ali, S. Baker, R. O’Crowley, S. Herold, and J. Buckley. Architecture consistency: State of the practice, challenges and requirements. Empirical Software Engineering, 23(1):224–258, Feb 2018. ISSN 1573-7616.
- Aryani et al.  A. Aryani, F. Perin, M. Lungu, A. Naser Mahmood, and O. Nierstrasz. Predicting dependences using domain-based coupling. J. Softw.: Evol. Process, 26(1):50–76, 2014.
- Bhattacharya et al.  P. Bhattacharya, M. Iliofotou, I. Neamtiu, and M. Faloutsos. Graph-based analysis and prediction for software evolution. In Proceedings of the 34th ICSE, ICSE ’12, pages 419–429, Piscataway, NJ, USA, 2012. IEEE Press. ISBN 978-1-4673-1067-3.
- Garcia et al.  J. Garcia, D. Popescu, G. Edwards, and N. Medvidovic. Toward a catalogue of architectural bad smells. In QoSA, volume 5581 of LNCS, pages 146–162. Springer, 2009. ISBN 978-3-642-02350-7.
- Hochstein and Lindvall  L. Hochstein and M. Lindvall. Combating architectural degeneration: A survey. Inf. Softw. Technol., 47(10):643–656, 2005. ISSN 0950-5849.
- Liben-Nowell and Kleinberg  D. Liben-Nowell and J. Kleinberg. The link-prediction problem for social networks. J. Am. Soc. Inf. Sci. Technol., 58(7):1019–1031, May 2007. ISSN 1532-2882.
- McPherson et al.  M. McPherson, L. Smith-Lovin, and J.M. Cook. Birds of a feather: Homophily in social networks. Annu. Rev. Sociol, 27(1):415–444, 2001.
- Rossetti et al.  G. Rossetti, R. Guidotti, I. Miliou, D. Pedreschi, and F. Giannotti. A supervised approach for intra-/inter-community interaction prediction in dynamic social networks. SNAM, 6(1):86, Sep 2016. ISSN 1869-5469.
- Terra et al.  R. Terra, J. Brunet, L. Miranda, M.T. Valente, D. Serey, D. Castilho, and R. Bigonha. Measuring the structural similarity between source code entities. In 25th International SEKE, pages 753–758, 2013.
- Vidal et al.  S. Vidal, E. Guimarães, W. Oizumi, A.Garcia, J.A. Díaz Pace, and C. Marcos. Identifying architectural problems through prioritization of code smells. In SBCARS 2016, Maringá, Brazil, September 19-20, 2016, pages 41–50, 2016.
- Yang et al.  Y. Yang, R.N. Lichtenwalter, and N.V. Chawla. Evaluating link prediction methods. Knowl. Inf. Syst., 45(3):751–782, 2015. ISSN 0219-1377.
- Zhou et al.  B. Zhou, X. Xia, D. Lo, and X. Wang. Build predictor: More accurate missed dependency prediction in build configuration files. In Proceedings of the 2014 IEEE 38th Annual COMPSAC, pages 53–58, Washington, DC, USA, 2014. IEEE. ISBN 978-1-4799-3575-8.