Using multi‐pattern clustering methods to improve software maintenance quality

IET SoftwareVolume 17, Issue 1 p. 1-22 ORIGINAL RESEARCHOpen Access Using multi-pattern clustering methods to improve software maintenance quality Yi-Ting Chen, Yi-Ting Chen Institute of Information Systems and Applications, National Tsing Hua University, Hsinchu, TaiwanSearch for more papers by this authorChin-Yu Huang, Corresponding Author Chin-Yu Huang [email protected] orcid.org/0000-0003-4931-4572 Institute of Information Systems and Applications, National Tsing Hua University, Hsinchu, Taiwan Department of Computer Science, National Tsing Hua University, Hsinchu, Taiwan Correspondence Chin-Yu Huang, Department of Computer Science, National Tsing Hua University, Hsinchu, Taiwan. Email: [email protected]Search for more papers by this authorTsung-Han Yang, Tsung-Han Yang Department of Computer Science, National Tsing Hua University, Hsinchu, TaiwanSearch for more papers by this author Yi-Ting Chen, Yi-Ting Chen Institute of Information Systems and Applications, National Tsing Hua University, Hsinchu, TaiwanSearch for more papers by this authorChin-Yu Huang, Corresponding Author Chin-Yu Huang [email protected] orcid.org/0000-0003-4931-4572 Institute of Information Systems and Applications, National Tsing Hua University, Hsinchu, Taiwan Department of Computer Science, National Tsing Hua University, Hsinchu, Taiwan Correspondence Chin-Yu Huang, Department of Computer Science, National Tsing Hua University, Hsinchu, Taiwan. Email: [email protected]Search for more papers by this authorTsung-Han Yang, Tsung-Han Yang Department of Computer Science, National Tsing Hua University, Hsinchu, TaiwanSearch for more papers by this author First published: 03 November 2022 https://doi.org/10.1049/sfw2.12075AboutSectionsPDF ToolsRequest permissionExport citationAdd to favoritesTrack citation ShareShare Give accessShare full text accessShare full-text accessPlease review our Terms and Conditions of Use and check box below to share full-text version of article.I have read and accept the Wiley Online Library Terms and Conditions of UseShareable LinkUse the link below to share a full-text version of this article with your friends and colleagues. Learn more.Copy URL Share a linkShare onFacebookTwitterLinkedInRedditWechat Abstract In software engineering, a software development process, also known as software development life cycle (SDLC), involves several distinct activities for developing, testing, maintaining, and evolving a software system. Within the stages of SDLC, software maintenance occupies most of the total cost of the software life. However, after extended maintenance activities, software quality always degrades due to increasing size and complexity. To solve this problem, software modularisation using clustering is an intuitive way to modularise and classify code into small pieces. , A multi-pattern clustering (MPC) algorithm for software modularisation is proposed in this study. The proposed MPC algorithm can be divided into five different steps: (1) preprocessing, (2) file labelling, (3) collection of chain dependencies, (4) hierarchical agglomerative clustering, (5) modification of the clustering result. The performance of the proposed MPC algorithm to selected clustering techniques is compared by using three open-source and one closed-source software programs. Experimental results show that the modularisation quality of the proposed MPC algorithm is nearly 1.6 times better than that of the expert decomposition. Additionally, compared to other software clustering algorithms, the proposed MPC algorithm, on average, has a 13% enhancement in producing results similar to human thinking. Consequently, it can be seen that the proposed MPC algorithm is suitable for human comprehension while producing better module quality compared to other clustering algorithms. Abbreviations ACDC algorithm for comprehensive-driven clustering ADP acyclic dependencies principle CA combined algorithm CLA complete linkage algorithm DIP dependency inversion principle FDM frequency dependency matrix FIM fan-in matrix FN false negative FOM fan-out matrix FP false positive HAC hierarchical agglomerative clustering JRET Java Reverse Engineering Toolkit LCOM4 lack of cohesion of methods 4 LOC line of code MDG module dependency graph MPC multi-pattern clustering MQ modularisation quality OSS open source software PDM percentage dependency matrix SDLC software development life cycle SLA single linkage algorithm TN true negative TP true positive ULA unweighted linkage algorithm WLA weighted linkage algorithm 1 INTRODUCTION Software plays a very important role in today's society. As software continually grows larger and more complex, it is inevitable that some bugs remain after the software product is delivered to users. During the Software Development Life Cycle (SDLC), project managers usually have to face and overcome many common technical and management issues/problems, such as high failure rate, cost over-run, time over-run, low quality, and delay in project delivery. It is worth noting that software maintenance occupies most of the total cost of the software life because software systems have grown more complex through the years [1]. Considering the lack of documentation and comments for each function or file in a software project, it is difficult to speed up the process of engineers' understanding of the whole software architecture. Noted that McCall, Boehm, ISO/IEC 9126, and ISO/IEC 25010 proposed some characteristics to evaluate software quality [1]. Although it is clear that software quality is quite important, the systems' structure is always exacerbated after extended maintenance activity. To overcome the aforementioned viewpoints and problems, modularisation has been proposed as a beneficial way to reduce the time and cost of software development and maintenance and to enhance the quality of developed software. In the past, Bittencourt and Guerrero [2] once presented a study that evaluates four clustering algorithms according to three criteria: extremity of cluster distribution, authoritativeness, and stability. Their experimental results suggested that the k-means algorithm performs best in terms of authoritativeness and extremity and that the modularisation quality algorithm produces more stable clusters. Chong et al. [3] also proposed a method to restructure poorly organised software documentation in an adaptive manner through software clustering. Their proposed technique utilised the bare minimum information that is retrieved from UML class diagrams to find correlations among entities in software artefacts. They presented an automated solution for cutting a dendrogram to find the best cut level. Tan et al. [4] proposed an approach to evaluate the effectiveness of software clustering algorithms by providing information on their strengths and weaknesses according to the software or code features. Their proposed framework provided a clear understanding of the algorithm's behaviour by showing a 2D representation of the effectiveness of software clustering techniques. Sarhan et al. [5] systematically reported the state-of-the-art empirical contributions in software module clustering. Chong and Lee [6] also presented a method to integrate the concept of graph theory analysis to automatically derive clustering constraints from the implicit structure of software systems. Basically modularisation is a design principle to have a complex system composed of smaller subsystems that are able to work independently [6, 7]. Furthermore, the module view is the most common way to understand software system architecture [8]. Bass et al. [9] also indicated good software architecture should be modular. A modular design usually has to satisfy decomposability, composability, understandability, continuity and protection [10]. This infers that a well-modularised software system has less complex structures and smaller sizes [11]. Modularisation is aimed at reducing complexity, making a complex system more understandable [12]. Hence, such an approach can also help the general readers to understand the code in a short amount of time. Moreover, modularisation enhances fault tolerance and reliability. For example, when we need to recover erroneous code, we only have to change a module or a small number of modules, while other parts of the systems remain available [13]. Pressman [14] also indicated that a partitioned architecture is much easier to test, maintain, modify, and extend. This allows the complexity of developed software systems to be manageable and allows a system to be efficiently understood, developed, built, and reused [15]. Therefore, modularisation is a practical approach to producing software with high quality and high maintainability. Recently, researchers proposed numerous methods to decompose a huge software system into small modules, making it more understandable and maintainable. Clustering finds the similar entities then groups them [16]. It is a data-analysing technique usually used in the fields of machine learning [17] and pattern recognition [18] to mine useful information from a large amount of data. As to the field of software engineering, researchers apply it to partition the system into many subsystems or for modularisation. Pourasghar et al. [19] once proposed a new graph-based clustering algorithm is presented for software modularisation. The main feature of their proposed algorithm is that this algorithm uses the available knowledge in the artefact dependency graph (ADG) to perform modularisation. Although software clustering is a useful technique to uncover software architecture, there is still room for technical improvement. Firstly, we hope software should have high cohesion and low coupling because such properties are mainly related to the goodness of decomposition [20]. Furthermore, software with high cohesion and low coupling is more reliable and maintainable [20]. However, clustering will be a disaster if we only consider these two properties because most of the files will be clustered into one or very few enormous groups, or they will be singletons [21]. This will not improve the understandability and cost-effectiveness. Secondly, there are some omnipresent files [22] existing in software systems. These files usually do not follow the principles of high cohesion and low coupling. Hence, ways of finding omnipresent files must follow user-assignment [23]. Thirdly, non-structural information can mislead developers and software engineers if the previous programmers made mistakes or misunderstood the architecture of the software system. According to the above-mentioned problems, we propose a software clustering method that is able to produce clusters with high quality as well as understandability and maintainability in this paper. Moreover, we also manage to lower the dependence on human involvement. Our contributions through this study can be summarised as follows: We not only focus on high cohesion and low coupling for software modules, but also use a psychological principle to find the number of components in a cluster. To find omnipresent files automatically, we propose to use two statistical criteria. Moreover, we use different labels to categorise the files so that we know the features of the files. When files have multiple features, there will be only one feature left for the files after calculation. Structural information, excluding header files, is used to perform software clustering. Thus, we will be able to find whether dependencies exist beyond the design or not. We utilise two deciding methods to tackle an arbitrary decision of the hierarchical agglomerative algorithm (HAC). We apply a cohesion metric to decide whether grouped files can be grouped or not according to their strength of intra-connectivity. The rest of this paper is constructed as follows: Section 2 presents the concepts of clustering and some traditional methods of software clustering. Section 3 presents our proposed method, a multi-pattern clustering algorithm (MPC algorithm) to modularise software systems. Some running examples are given to illustrate our proposed method. In Section 4, we compare the MPC algorithm to some selected software clustering methods mentioned in Section 2 with three open source software (OSS) systems and one closed source software (CSS) system by assessing the similarity to experts' decomposition and modularisation. Some threats to validity are also described and discussed in Section 4. In Section 5, we will present some research insights and discussions for this study. Finally, the conclusion is covered in Section 6. 2 BACKGROUND AND LITERATURE REVIEW Practically, there are various ways to help developers or programmers perform clustering of modules. Schröder et al [24] once presented an industrial case study on the effectiveness of search-based approaches for software remodularisation at a large-scale enterprise software system. Saeed et al. [25] proposed a combined algorithm (CA) to decrease the probability of facing the arbitrary decision. Teymourian et al [26] resented a fast clustering algorithm that can overcome space and time constraints of existing algorithms by performing operations on the dependency matrix and extracting other matrices based on a set of features. Among all the related algorithms, the hierarchical agglomerative clustering (HAC) is one of the most well-known algorithm. A lot of research investigates software modularisation or clustering by applying this kind of method. Moreover, the hierarchical clustering algorithms produce multiple-layer architectural views of systems that help engineers inspect the architecture of a system [8], which corresponds with our goal to produce understandable software modularisation. In this section, we will present the basic concepts of the HAC and some well-known measurements and algorithms firstly. After that, we will review some existing techniques of hierarchical clustering for software modularisation. To explain the rules of the HAC, entities and features are required. Entities may be functions or files [8] and clusters may be modules. Features, which are always presented in binary, may be some structural information or non-structural information. Structural information may be a global variable referred to by the entity, a data type or a user-defined type, accessed by the entity and functions called by the entities, files called by the entities etc. On the other hand, non-structural information may be developers, locations etc. [21]. Let us consider there are n entities E1, E2, …, En, and p is the number of features in our tested software system. First, we need to identify every entity and form a feature vector for it. Second, we use a similarity measure to define the strength of the relationship between each pair of the entities. Hence, we can obtain an n-to-n dimension matrix. There are well-known methods for calculating the similarity. For instance, the simple matching coefficient, the Jaccard coefficient, and the Sorenson-Dice coefficient etc., can be used for measuring similarity of binary vectors [8, 21, 25]. On the other hand, for real vectors, there are some popular similarity measures such as the inverse of Minkowski distance, the Canberra distance, and the Bray-Curtis distance [8]. After calculating the similarity of every pair, we can search for the maximum value in the similarity matrix and group the pair into a new entity. We repeat the steps until obtaining the needed number of clusters or until there is only one cluster left. If not, we will update the similarity matrix. Figure 1 is an example of the similarity between the new entity and the others. For the two entities grouped into a new entity, the similarity of the new entity to another entity can be derived differently by using several algorithms such as the single linkage algorithm (SLA), the complete linkage algorithm (CLA), the weighted average linkage algorithm (WLA), and the unweighted average linkage algorithm (ULA) [8, 18]. FIGURE 1Open in figure viewerPowerPoint The similarity of the New Entity and the Other Entity When planning to pick the SLA, we will obtain the maximum similarity between the two entities as the new similarity s i m E n e w , E o t h e r = Max s i m E i , E j , s i m E i , E j . $\mathrm{s}\mathrm{i}\mathrm{m}\left({E}_{\mathrm{n}\mathrm{e}\mathrm{w}},{E}_{\mathrm{o}\mathrm{t}\mathrm{h}\mathrm{e}\mathrm{r}}\right)=\mathrm{Max}\left(\mathit{s}\mathit{i}\mathit{m}\left({E}_{i},{E}_{j}\right),\mathrm{s}\mathrm{i}\mathrm{m}\left({E}_{i},{E}_{j}\right)\right).$ (1) Similarly, if CLA is chosen, we can compute the minimum similarity between the two entities as follows: s i m E n e w , E o t h e r = Min s i m E i , E j , s i m E i , E j . $\mathrm{s}\mathrm{i}\mathrm{m}\left({E}_{\mathrm{n}\mathrm{e}\mathrm{w}},{E}_{\mathrm{o}\mathrm{t}\mathrm{h}\mathrm{e}\mathrm{r}}\right)=\mathrm{Min}\left(\mathit{s}\mathit{i}\mathit{m}\left({E}_{i},{E}_{j}\right),\mathrm{s}\mathrm{i}\mathrm{m}\left({E}_{i},{E}_{j}\right)\right).$ (2)When WLA is applied, we can obtain the new similarity as s i m E n e w , E o t h e r = 1 2 ⋅ s i m E i , E j + 1 2 ⋅ s i m E i ′ , E j . $\mathrm{s}\mathrm{i}\mathrm{m}\left({E}_{\mathrm{n}\mathrm{e}\mathrm{w}},{E}_{\mathrm{o}\mathrm{t}\mathrm{h}\mathrm{e}\mathrm{r}}\right)=\frac{1}{2}\cdot \mathrm{s}\mathrm{i}\mathrm{m}\left({E}_{i},{E}_{j}\right)+\frac{1}{2}\cdot \mathrm{s}\mathrm{i}\mathrm{m}\left({E}_{i\prime },{E}_{j}\right).$ (3) If we apply ULA, the new similarity can be calculated as follows: s i m E n e w , E o t h e r = s i z e E n e w ⋅ s i m E i , E j + s i z e E o t h e r ⋅ s i m E i ′ , E j s i z e E n e w + s i z e E o t h e r . $\mathrm{s}\mathrm{i}\mathrm{m}\left({E}_{\mathrm{n}\mathrm{e}\mathrm{w}},{E}_{\mathrm{o}\mathrm{t}\mathrm{h}\mathrm{e}\mathrm{r}}\right)=\frac{\mathrm{s}\mathrm{i}\mathrm{z}\mathrm{e}\left({E}_{\mathrm{n}\mathrm{e}\mathrm{w}}\right)\cdot \mathrm{s}\mathrm{i}\mathrm{m}\left({E}_{i},{E}_{j}\right)+\mathrm{s}\mathrm{i}\mathrm{z}\mathrm{e}\left({E}_{\mathrm{o}\mathrm{t}\mathrm{h}\mathrm{e}\mathrm{r}}\right)\cdot \mathrm{s}\mathrm{i}\mathrm{m}\left({E}_{i\prime },{E}_{j}\right)}{\mathrm{s}\mathrm{i}\mathrm{z}\mathrm{e}\left({E}_{\mathrm{n}\mathrm{e}\mathrm{w}}\right)+\mathrm{s}\mathrm{i}\mathrm{z}\mathrm{e}\left({E}_{\mathrm{o}\mathrm{t}\mathrm{h}\mathrm{e}\mathrm{r}}\right)}.$ (4) Some characteristics for these algorithms are from the studies by Theodoridis and Koutroumbas [18]. The bigger clusters tend to merge with the big ones rather than singletons if the SLA is used. This creates a small number of huge clusters. These clusters are not cohesive but are less coupling to others. In contrast, the CLA creates many small cohesive clusters because it tends to divide clusters and uses the original information calculated at the beginning. The WLA and the ULA fall between the SLA and the CLA [25]. Although these algorithms are easy to compute and understand, the HAC has some weaknesses. First, the same similarity always occurs when we search for the maximum in the matrix. An arbitrary decision could then be made to cluster entities, which could lead to bad quality. Second, the number of clusters and the timing to stop clustering are important issues. Common traditional stopping criteria include the manual assignment of cluster number or similarity. This is difficult for people to decide. Lastly, the HAC tends to makes modules huge and uncomprehensive. Considering the above drawbacks, Saeed et al. [25] proposed a combined algorithm (CA) to decrease the probability of facing the arbitrary decision. They also proposed that generating a new feature vector for a newly formed group would obtain better results. CA obtains the similarity of the pairs and then clusters the two most similar entities. The key point is that they unite the vectors into the same group to as a new feature vector and form a new similarity matrix. Despite Saeed et al. [25] managing to solve the arbitrary problems, the information of the number of entities is still lost [8]. Moreover, this method does not solve the problem that we all need to assign the number of clusters or conduct numerous iterations in order to obtain the best cluster result. To improve the HAC, a few researchers have proposed combining HAC with some pattern-driven techniques. Tzerpos and Holt [27] proposed an algorithm for comprehension-driven clustering (ACDC) using pattern comparison and the HAC algorithm. They used pattern-driven approaches to classify the resources and group the resources residing in the same file. This approach then identifies shared neighbours [28] and support libraries [22] but does not group them. Next, it disregards the files with a central dispatcher pattern and clusters those entities with less out-degree and in their neighbourhood, which resembles the HAC algorithm. For the remaining entities that are identified as support libraries but not clustered yet, the ACDC applies orphan adoption [23, 26, 29] to force all singletons to join a cluster. Pattern-driven approaches compensate for the deficiency of the hierarchical algorithm and are able to increase accuracy of the modularisation results [26]. However, unless researchers find the most similar entities without other considerations, such as by shared neighbours that are not identical by the hierarchical algorithm, there are still some shortages. First, we need to assign the cardinality of size of clusters, the in-degree of the support library and the out-degree of the central dispatcher, manually. Second, we should consider the source-file pattern and the directory structure pattern. These two patterns heavily rely on the engineers' knowledge, which is not a reliable pattern. Third, it is not recommended that support libraries can be clustered in the process [30]. Lastly, some entities may have multiple patterns, and if the patterns are in order of precedence, some patterns will be unrevealed. There are some tools published for software clustering. Bunch is a software tool for system decomposition [23, 31]. It transforms the dependencies into a module dependency graph (MDG) and attempts to find the best partition of the graph. Bunch treats the issue as an optimal problem to find the maximum modularisation quality (MQ) by using a hill-climbing and genetic algorithm. Besides, Shtern and Tzerpos [21] also developed some tools using various algorithms as part of the Java Reverse Engineering Toolkit (JRET). In our opinions, tools with graphic interfaces are capable of visualising the processes and results of software clustering, which is useful for engineers to understand their systems after clearly viewing clustering. In conclusion, to take advantage of the benefits of pattern-driven methods and the HAC, while lessening their negative effects of including huge clusters and human involvement, we would like to propose an MPC algorithm. In our proposed method, we first apply the HAC algorithm, then two criteria, which are the modified LCOM4 [33] and the "7 ± 2" rules [34], added at the end of the HAC. The former is a metric for module cohesion to estimate software quality, while the latter is a psychological concept for general comprehension. The LCOM4 and "7 ± 2" rules will modify the clustering result from the HAC and produce a better modularisation output. We present detailed explanations in the next section. 3 PROPOSED MULTI-PATTERN CLUSTERING METHOD In this section, we describe the proposed MPC algorithm and explain it in detail step by step. The process flow of MPC algorithm is shown in Figure 2. In general, the algorithm can be divided into five steps: preprocessing, file labelling, collection of chain dependencies, hierarchical agglomerative clustering, and modification of the clustering result [35]. Each step of the algorithm will be shown and discussed in the following subsections. Some examples will be given for every step to make the methods clear. The example is extracted from an open-source programme named 'Mosaic' [8], a web browser written in C. Because Mosaic is a large open source programme with 290 files (nodes), we only select parts having certain characteristics to describe each step. FIGURE 2Open in figure viewerPowerPoint The process flow diagram of multi-pattern clustering (MPC) algorithm Step 1: preprocessing Given the subject systems source code, we can use some Computer-Aided Software Engineering (CASE) tools to extract the dependencies between files based on the source code of each subject system. For example, the Understand software [36] is a static code analysis tool that aims to achieve a complete code navigation, control flow graph generation, metrics generation, and code comparison. These dependencies include function calls, the structures, and the dependencies of global variables. After the extraction, they will be transformed into a matrix and some modifications will be made to speed up the rest of the remaining steps. 3.1.1 Step 1-1: dependency matrix construction First, we should find out every dependency (e.g. functions call, global variables access) in the system with static analysis and map the files and dependencies into the weighted module dependency graph (MDG) [23] of the system. Figure 3 is an example of weighted MDG. It should be noted that each node represents each file and each edge formed by a calling file pointing to a called file represents each dependency. The calling frequency represents the weight of the edge. The arrow head attaches to called files and the arrow tail attaches to calling files. The weight of each edge is the sum of function calls, global variables access, and so on. They are given the equal weight. FIGURE 3Open in figure viewerPowerPoint A weighted module dependency graph (MDG) In general, adjacency matrix is a good implementation for a graph [37]. A frequency dependency matrix (FDM) can be derived from the weighted MDG. Note that FDM is a directive graph and the matrix is not symmetric. Referring to Figure 3, a FDM can be expressed as follows: F D M = 0 0 c 13 0 0 c 21 0 c 23 0 0 0 0 0 0 0 0 0 0 0 c 45 0 0 0 c 54 c 55 , $\mathrm{F}\mathrm{D}\mathrm{M}=\left[\begin{array}{ccccc}0& 0& {c}_{13}& 0& 0\\ {c}_{21}& 0& {c}_{23}& 0& 0\\ 0& 0& 0& 0& 0\\ 0& 0& 0& 0& {c}_{45}\\ 0& 0& 0& {c}_{54}& {c}_{55}\end{array}\right],$ (5)where cij is the calling frequency, i is the index of the calling file and j is the index of the called files. Additionally, calling frequency is not the only method to show the dependencies. Both Fan-in and fan-out are also useful information for dependencies. They can measure the simplicity of the relationship between subsystems [38]. The FDM can be converted into a binary matrix to obtain the fan-out matrix (FOM) as follows: F O M = b 11 ⋯ b 1 n ⋮ ⋱ ⋮ b n 1 ⋯ b n n , $\mathrm{F}\mathrm{O}\mathrm{M}=\left[\begin{array}{ccc}{b}_{11}& {{\cdots}}& {b}_{1n}\\ {\vdots}& {\ddots}& {\vdots}\\ {b}_{n1}& {{\cdots}}& {b}_{nn}\end{array}\right],$ (6)where b i j = 1 , c i j > 0 0 , c i j = 0 . ${b}_{ij}=\left\{\begin{array}{c}1,\quad {c}_{ij} > 0\\ 0,\quad {c}_{ij}=0\end{array}\right..$ (7) In statistics, the aforementioned FDM is a kind of frequency matrix. Based on the above FDM, we suppose c13 < c23. If we only use the frequency to decide which relation of two files is much closer, then we may first select file 2 and file 3 because their frequency is higher. But in actuality, file 1 is only related to file 3 while file 2 is partially related to file 3. As a result, there is another statistical method called relative frequency to summarise the data with proportions [39, 40]. In perspective, we may select file 1 and file 3 because file 1 is more targeted on file 3. Hence, we can normalise every row of the matrix and get the percentage dependency matrix (PDM) as follows: P D M = c 11 c 11 + ⋯ + c 1 n ⋯ c 1 n c 11 + ⋯ c 1 n ⋮ ⋱ ⋮ c n 1 c n 1 + ⋯ + c n n ⋯ c n n c n 1 + ⋯ c n n . $\mathrm{P}\mathrm{D}\mathrm{M}=\left[\begin{array}{ccc}\frac{{c}_{11}}{{c}_{11}+{{\cdots}}+{c}_{1n}}& {{\cdots}}& \frac{{c}_{1n}}{{c}_{11}+{{\cdots}}{c}_{1n}}\\ {\vdots}& {\ddots}& {\vdots}\\ \frac{{c}_{n1}}{{c}_{n1}+{{\cdots}}+{c}_{nn}}& {{\cdots}}& \frac{{c}_{nn}}{{c}_{n1}+{{\cdots}}{c}_{nn}}\end{array}\right].$ (8) 3.1.2 Step 1–2: non-dependency files removal Practically, some files may not have any fan-in, fan-out, and even self-dependency. These files will not affect the final result and should not group them to other clusters. We may put them in a cluster called 'useless files' and let people decide to remove or modify these files for maintenance. 3.1.3 Step 1–3: self-dependency removal It is common that files are calling themselves. There is only intra-connectivity if files call themselves. For example, file 1 has self-dependencies in Figure 4(a). However, a file is not divisible because it is the smallest unit in our analysis. Hence, the frequencies of self-dependency will not affect the result of modularisation. To speed up later steps, these dependencies are removed. FIGURE 4Open in figure viewerPowerPoint (a) Module dependency graph (MDG) of self-dependency. (b) Utility file example. (c) Driver file exa