A Study of Quality Improvements By Refactoring Bart Du Bois
September, 2006
Promotor: prof. dr. Serge Demeyer Co-promotor: prof. dr. Jan Verelst
Proefschrift ingediend tot het behalen van de graad van Doctor in de Wetenschappen
2
To mother . . .
4
Acknowledgements
First and foremost, I would like to acknowledge the support of my family. I thank my loving parents for their everlasting devotion, presence and patience. My grandfather, for warm welcomes and conversations. And Jan and Jasmina, for playful distraction. I owe my interests in software engineering to Prof. Demeyer. I thank him for welcoming me in his research lab, for providing opportunities to explore, and for stimulating an atmosphere of curiosity, openness and creativity. My gratitude goes out to Prof. Verelst, for sharing reflections, and generally sharpening my thinking. Numerous inspirational conversations were held with office comrades Pieter Van Gorp, Hans Stenten, Hans Schippers, more recently Bart Van Rompaey and Matthias Rieger, as well as with research lab buddies Andy Zaidman, Filip Van Rysselberghe, Niels Van Eetvelde, Olaf Muliawan, and witty office pal Koen Van Leemput. I thank you all for the wonderful atmosphere, stimulating discussions and beer. Two people were exceptionally supportive in starting up this research. At the early start of this research, Amela Karahasanovic was one of the kind people at the Simula Research Laboratory who supported my initiation in the domain of empirical software engineering. Tom Mens directed me to interesting research topics, and actively supported my first publications. For assisting in organizing controlled experiments, I thank Tom Mens and Marijn Temmerman. To support my application of MotMot, the help of Hans Schippers, Pieter Van Gorp and Olaf Muliawan is most appreciated. I sincerely hope that I have expressed my appreciation to all of you in our interactions and collaborations.
6
Abstract
Refactorings, behavior preserving transformations, are claimed to make software easier to understand and to improve software design. However, these claimed quality improvements have yet to be validated. This dissertation reports on our contributions to their validation. First, a validation of two existing reengineering patterns that use refactoring to support program comprehension is presented. Second, we discuss the results of formal analysis of the conditions in which known refactorings improve coupling and cohesion as criteria for well-balanced object-oriented design. The results of this research confirm that, indeed, the claimed benefits can occur, and describe how and when the application of refactoring can improve selected quality characteristics. The integration of these results in today’s refactoring tools can support maintainers in assessing which refactorings to apply where, ultimately reducing the effort of transforming towards an optimal solution.
8
Publications
During the process of this PhD, the following peer-reviewed conference papers were published. As main author: • Accommodating changing requirements with EJB, published in the proceedings of the 9th International Conference on ObjectOriented Information Systems (OOIS 2003), [Du Bois and Demeyer, 2003] • Refactoring – improving coupling and cohesion of existing code, published in the proceedings of the 11th IEEE Working Conference on Reverse Engineering (WCRE 2004), [Du Bois et al., 2004] • Does the “Refactor to Understand” reverse engineering pattern improve program comprehension?, published in the proceedings of the 9th European Conference on Software Maintenance and Reengineering (CSMR 2005) [Du Bois et al., 2005] • Does God Class decomposition affect comprehensibility?, published in the proceedings of the 24th IASTED International Multi-Conference on Software Engineering (IASTED SE 2006), [Du Bois et al., 2006] As second author: • How webmining and coupling metrics improve early program comprehension, by A. Zaidman, B. Du Bois and S. Demeyer, published in the proceedings of the 14th International Conference on Program Comprehension (ICPC 2006) [Zaidman et al., 2006]
10 • An experimental investigation of UML modeling conventions, by C.F.J. Lange, B. Du Bois, M.R.V. Chaudron and S. Demeyer, published in the proceedigns of the 9th International Conference on Model-driven Engineering Languages and Systems (MoDELS 2006), [Lange et al., 2005]
Contents 1 Introduction 1.1 Problem Description 1.2 Refactoring . . . . . 1.3 Contributions . . . . 1.4 Organization . . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
2 Related Work 2.1 Program comprehension improvements . 2.2 Internal product quality improvements . 2.2.1 Related work by Sahraoui et al. . 2.2.2 Related work by Kataoka et al. . 2.2.3 Related work by Tahvildari et al. 2.3 Summary . . . . . . . . . . . . . . . . .
I
. . . .
. . . . . .
. . . .
. . . . . .
. . . .
. . . . . .
. . . .
. . . . . .
. . . .
. . . . . .
. . . .
. . . . . .
. . . .
. . . . . .
. . . .
. . . . . .
. . . .
. . . . . .
. . . .
. . . . . .
. . . .
. . . . . .
. . . .
. . . . . .
. . . .
. . . . . .
. . . .
1 1 2 5 5
. . . . . .
7 7 9 9 11 11 13
Program Comprehension Improvements
3 Program Comprehension 3.1 Software maintenance . . . . . . . . . 3.2 The process of program comprehension 3.2.1 Bottom-up comprehension . . . 3.2.2 Top-down comprehension . . . 3.2.3 Summary . . . . . . . . . . . . 3.2.4 Structure of Part I . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
15 . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
17 17 19 20 23 25 25
4 The Refactor to Understand Pattern 27 4.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 i
ii
CONTENTS 4.2
Pattern Description . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.1 Research Question . . . . . . . . . . . . . . . . . . . . . .
5 Validating Refactor to Understand 5.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . 5.2 Research Hypotheses . . . . . . . . . . . . . . . . . . 5.3 Experimental Set-Up . . . . . . . . . . . . . . . . . . 5.3.1 Experimental Design . . . . . . . . . . . . . . 5.3.2 Experimental Participants . . . . . . . . . . . 5.3.3 Experimental Procedure . . . . . . . . . . . . 5.3.4 Experimental Tasks . . . . . . . . . . . . . . 5.3.5 Comprehension Questions . . . . . . . . . . . 5.4 Data Analysis . . . . . . . . . . . . . . . . . . . . . . 5.4.1 Analysis Procedure . . . . . . . . . . . . . . . 5.4.2 Applications of Refactorings . . . . . . . . . . 5.4.3 H0,accuracy – Differences in response accuracy 5.4.4 H0,time – Differences in response time . . . . 5.4.5 Post-experiment questionnaire . . . . . . . . 5.5 Interpretation of Results . . . . . . . . . . . . . . . . 5.5.1 Comprehension Technique as a Factor . . . . 5.5.2 Degree of Coupling as a Factor . . . . . . . . 5.6 Threats to Validity . . . . . . . . . . . . . . . . . . . 5.6.1 Internal Validity . . . . . . . . . . . . . . . . 5.6.2 External Validity . . . . . . . . . . . . . . . . 5.7 Conclusion . . . . . . . . . . . . . . . . . . . . . . . 6 The 6.1 6.2 6.3
28 29
. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . .
31 31 33 35 35 36 37 40 42 46 47 48 50 53 55 56 56 57 58 58 59 61
Split Up God Class Pattern Introduction . . . . . . . . . . . . Pattern Description . . . . . . . Illustrative Scenario . . . . . . . 6.3.1 Research questions . . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
63 63 64 66 68
7 Validating Split Up God Class 7.1 Introduction . . . . . . . . . . . . 7.2 Research Hypotheses . . . . . . . 7.3 Experimental Set-Up . . . . . . . 7.3.1 Experimental Design . . . 7.3.2 Experimental Participants 7.3.3 Experimental Procedure .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
73 73 75 76 76 78 79
CONTENTS
7.4
7.5 7.6
7.7
iii
7.3.4 Experimental Tasks . . . . . . . . . . . . Data Analysis . . . . . . . . . . . . . . . . . . . . 7.4.1 Analysis Procedure . . . . . . . . . . . . . 7.4.2 Descriptive statistics . . . . . . . . . . . . 7.4.3 Statistical tests . . . . . . . . . . . . . . . 7.4.4 H0,accuracy – Differences in task accuracy 7.4.5 H0,time – Differences in task duration . . Interpretation of Results . . . . . . . . . . . . . . Threats to Validity . . . . . . . . . . . . . . . . . 7.6.1 Internal Validity . . . . . . . . . . . . . . 7.6.2 External Validity . . . . . . . . . . . . . . Conclusion . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
83 86 86 87 89 90 94 96 98 98 98 99
8 Summary 101 8.1 Findings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 8.2 Lessons Learned . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
II
Coupling and Cohesion Improvements
105
9 Quality-Driven Refactoring 107 9.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 9.1.1 Structure of Part II . . . . . . . . . . . . . . . . . . . . . 110 10 Predicting Quality Impacts 10.1 Meta-model . . . . . . . . . . . . . . 10.1.1 Analysis functions . . . . . . 10.2 Selection of Metrics . . . . . . . . . . 10.2.1 Import Coupling . . . . . . . 10.2.2 Export Coupling . . . . . . . 10.2.3 General Coupling . . . . . . . 10.2.4 Aggregation Import Coupling 10.2.5 Cohesion . . . . . . . . . . . 10.2.6 Summary . . . . . . . . . . . 10.3 Selection of Refactorings . . . . . . . 10.3.1 Notation . . . . . . . . . . . . 10.3.2 Extract Method . . . . . . . 10.3.3 Move Method . . . . . . . . . 10.3.4 Replace Method with Method
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Object
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
. . . . . . . . . . . . . .
111 111 113 114 114 116 117 118 118 121 121 122 123 124 126
iv
CONTENTS 10.4 Quality Impact Prediction . . . . . . 10.4.1 Extract Method . . . . . . . 10.4.2 Move Method . . . . . . . . . 10.4.3 Replace Method with Method
11 Validating Predicted Impacts 11.1 Introduction . . . . . . . . . . . . . . 11.1.1 System Under Study . . . . . 11.1.2 Measurement Instrument . . 11.2 Data Analysis . . . . . . . . . . . . . 11.2.1 Extract Method . . . . . . . 11.2.2 Move Method . . . . . . . . . 11.2.3 Replace Method with Method 11.3 Threats to Validity . . . . . . . . . . 11.4 Conclusion . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . Object
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Object . . . . . . . . . .
. . . .
. . . . . . . . .
. . . .
. . . . . . . . .
12 Case Study: Move Method Variant 12.1 Introduction . . . . . . . . . . . . . . . . . . . . . 12.2 Notation . . . . . . . . . . . . . . . . . . . . . . . 12.3 Specifying the Move Method Variant . . . . . . . 12.3.1 Refining the precondition . . . . . . . . . 12.3.2 Resulting qualitative postcondition . . . . 12.4 Data Collection . . . . . . . . . . . . . . . . . . . 12.4.1 Validating predicted impacts . . . . . . . 12.4.2 Applicability of the Move Method variant 12.5 Interpretation of Results . . . . . . . . . . . . . . 12.6 Conclusion . . . . . . . . . . . . . . . . . . . . .
. . . .
. . . . . . . . .
. . . . . . . . . .
. . . .
. . . . . . . . .
. . . . . . . . . .
. . . .
. . . . . . . . .
. . . . . . . . . .
. . . .
. . . . . . . . .
. . . . . . . . . .
. . . .
. . . . . . . . .
. . . . . . . . . .
. . . .
. . . . . . . . .
. . . . . . . . . .
. . . .
. . . . . . . . .
. . . . . . . . . .
. . . .
. . . . . . . . .
. . . . . . . . . .
. . . .
128 129 132 135
. . . . . . . . .
139 139 141 142 142 143 146 149 153 153
. . . . . . . . . .
155 155 156 159 161 163 166 167 168 170 170
13 Summary 173 13.1 Findings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 13.2 Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 14 Further Work 177 14.1 Extensions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 14.2 Tool Integration . . . . . . . . . . . . . . . . . . . . . . . . . . . 178
CONTENTS
v
15 Conclusions 15.1 Conclusions . . . . . . . . . . . . . . . . . . . . 15.1.1 Program Comprehension Improvements 15.1.2 Coupling and Cohesion Improvements . 15.1.3 General Conclusions . . . . . . . . . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
181 181 181 182 182
A Experimental Material 183 A.1 Refactor to Understand . . . . . . . . . . . . . . . . . . . . . . . 183 B Formal Impact Derivation B.1 Introduction . . . . . . . . . . . . . . . B.2 Extract Method . . . . . . . . . . . . . B.2.1 Import Coupling . . . . . . . . B.2.2 Export Coupling . . . . . . . . B.2.3 General Coupling . . . . . . . . B.2.4 Aggregation Import Coupling . B.2.5 Normalized Cohesion . . . . . . B.2.6 Non-normalized Cohesion . . . B.3 Move Method . . . . . . . . . . . . . . B.3.1 Import Coupling . . . . . . . . B.3.2 Export Coupling . . . . . . . . B.3.3 General Coupling . . . . . . . . B.3.4 Aggregation Import Coupling . B.3.5 Normalized Cohesion . . . . . . B.3.6 Non-normalized Cohesion . . . B.4 Replace Method with Method Object B.4.1 Import Coupling . . . . . . . . B.4.2 Export Coupling . . . . . . . . B.4.3 General Coupling . . . . . . . . B.4.4 Aggregated Import Coupling . B.4.5 Normalized Cohesion . . . . . . B.4.6 Non-normalized Cohesion . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . .
187 187 189 190 193 194 197 197 200 205 205 207 210 221 222 223 225 225 226 227 234 235 236
vi
CONTENTS
List of Figures 5.1 5.2 5.3 5.4 5.5 5.6 5.7
Guidelines for the Refactor to Understand Task sheet for task 1 . . . . . . . . . . . . Task sheet for task 2 . . . . . . . . . . . . Task sheet for task 3 . . . . . . . . . . . . Comprehension questions for task 1 . . . . Comprehension questions for task 2 . . . . Comprehension questions for task 3 . . . .
experiment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
38 38 39 40 43 44 45
6.1 6.2 6.3 6.4 6.5
Decomposition Decomposition Decomposition Decomposition Decomposition
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
67 68 69 70 71
7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8
Pretest task . . . . . . . . . . . . . . . . . . Posttest task . . . . . . . . . . . . . . . . . Posttest PMV observations . . . . . . . . . Posttest PMS observations . . . . . . . . . . Frequency of observations with PMV=100% Frequency of observations with PMS=100% Mean ET of observations with PMV=100% Mean ET of observations with PMS=100%
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
81 82 91 92 93 94 96 97
12.1 12.2 12.3 12.4
Move Method source class precondition story diagram Move Method target class precondition story diagram Qualitative precondition on msrc and csrc . . . . . . . Qualitative precondition on msrc and ctrg . . . . . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
160 161 164 165
A B C D E
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
vii
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
viii
LIST OF FIGURES 12.5 Move Method variant applicability in ArgoUML v0.19.8 . . . . . 168 A.1 Page 1 of the debriefing questionnaire . . . . . . . . . . . . . . . 184 A.2 Page 2 of the debriefing questionnaire . . . . . . . . . . . . . . . 185
List of Tables 2.1 2.2
Impact description by Sahraoui et al. . . . . . . . . . . . . . . . . Impact description by Tahvildari et al. . . . . . . . . . . . . . . .
10 13
5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 5.10 5.11 5.12
Questions for evaluating abstractions . . . . . . . . . Experimental variables . . . . . . . . . . . . . . . . . Task order across experimental executions . . . . . . Properties of the code fragments . . . . . . . . . . . Application of refactorings . . . . . . . . . . . . . . Comparison of the response accuracy between groups Data loss w.r.t. accuracy observations . . . . . . . . Rejection of H0,accuracy,X,Y . . . . . . . . . . . . . . Comparison of the response time between groups . . Data loss w.r.t. time observations . . . . . . . . . . . Rejection of H0,time,X,Y . . . . . . . . . . . . . . . . Average comprehension accuracy . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
32 36 40 41 49 50 52 52 54 54 55 57
7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9
Experimental variables . . . . . . . . . . Replications of the experiment . . . . . Participant assignment . . . . . . . . . . Properties of the code fragments used . Descriptive statistics (N=63) . . . . . . Statistical tests . . . . . . . . . . . . . . Test of group differences w.r.t. accuracy Test of group differences w.r.t. time . . Rejection of H0,accuracy and H0,time . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
77 78 79 84 88 89 90 95 95
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
. . . . . . . . .
10.1 Metrics indicating import coupling . . . . . . . . . . . . . . . . . 115 ix
x
LIST OF TABLES 10.2 Metrics indicating export coupling . . . . . . . . . . 10.3 Metrics indicating general coupling . . . . . . . . . . 10.4 Metrics indicating aggregated import coupling . . . . 10.5 Metrics indicating cohesion . . . . . . . . . . . . . . 10.6 Selected metrics. . . . . . . . . . . . . . . . . . . . . 10.7 Impact table for Extract Method . . . . . . . . . . . 10.8 Impact description for Extract Method. . . . . . . . 10.9 Impact table for Move Method . . . . . . . . . . . . 10.10Impact description for Move Method. . . . . . . . . . 10.11Impact table for Replace Method w Method Object 10.12Impact description for Replace Method with Method
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Object .
. . . . . . . . . . .
. . . . . . . . . . .
116 117 118 119 120 129 131 133 135 136 137
11.1 MPC impact validation for Extract Method. . . . . . . . . . . . . 143 11.2 OMMEC impact validation for Extract Method. . . . . . . . . . 144 11.3 CBO impact validation for Extract Method. . . . . . . . . . . . . 144 11.4 DAC impact validation for Extract Method. . . . . . . . . . . . . 144 11.5 LCOM5 impact validation for Extract Method . . . . . . . . . . 145 11.6 LCOM1 impact validation for Extract Method . . . . . . . . . . 145 11.7 MPC impact validation for Move Method . . . . . . . . . . . . . 146 11.8 OMMEC impact validation for Move Method . . . . . . . . . . . 147 11.9 CBO impact validation for Move Method . . . . . . . . . . . . . 147 11.10DAC impact validation for Move Method . . . . . . . . . . . . . 148 11.11LCOM5 impact validation for Move Method . . . . . . . . . . . . 148 11.12LCOM1 impact validation for Move Method . . . . . . . . . . . . 149 11.13MPC impact validation for Replace Method w Method Object . 150 11.14OMMEC impact validation for Replace Method w Method Object 150 11.15CBO impact validation for Replace Method w Method Object . . 151 11.16DAC impact validation for Replac e Method w Method Object . 151 11.17LCOM5 impact validation for Replace Method with Method Object152 11.18LCOM1 impact validation for Replace Method with Method Object152 12.1 12.2 12.3 12.4 12.5
Move Method impact optimization table. . Story Driven Modeling (SDM) notation. . . Move Method variant effect description. . . Impact table for the Move Method variant. Variant impact validation. . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
156 158 165 166 167
Chapter 1
Introduction In this chapter, we describe the problem statement which is at the core of this thesis.
1.1
Problem Description
A refactoring is a transformation of the structure of a software system which preserves key aspects of the systems’ behavior. Typically, behavior preserving is interpreted as a guarantee that the system will still reach the same end states under identical conditions as the initial system. Alternatively, refactoring is also used to refer to the application of one or more refactorings. Non-functional properties, e.g., the time and space complexity, are not guaranteed to be preserved. The guarantee that some properties are preserved while others can be manipulated provides interesting perspectives on the exploration of the software solution space, e.g., to optimize specific properties. Problem statement – Refactoring is suggested as a means to improve quality characteristics such as the comprehensibility and modifiability of a software system. However, the existence of inverse transformations (e.g., the existence of both Extract Method and its counterpart Inline Method) suggests that, if affected at all, these quality characteristics can be both impaired and improved by the application of refactorings. Therefore, there is a need for guidelines that highlight where and how to apply which refactorings in order to optimize a software system with regard to a quality characteristic. 1
2
CHAPTER 1. INTRODUCTION
1.2
Refactoring
Fowler’s catalogue of refactoring [Fowler, 1999] can be considered to be the work which triggered industry adoption of refactoring practices. In his book, Fowler suggests four purposes of refactoring: • Improve the design of software – Through accumulating code changes, code loses its structure, thereby increasingly drifting towards a state of decay. Refactoring can be used to cure software decay by redistributing parts of the code to the “right” places, and by removing duplicated code. The claim that refactoring can improve the design of software is confirmed by [Simon et al., 2001] with regard to cohesion and by [Kataoka et al., 2002] w.r.t. coupling, as indicators for internal software quality. Another claimed benefit in the area of improved design is improved flexibility [Deursen and Moonen, 2002]. • Make software easier to understand – Refactoring can help make the code more readable by making it better communicate its purpose. A different way in which refactoring supports program understanding is in reflecting hypotheses about the purpose of the code by changing the code, and afterwards testing that understanding through rerunning the code. The suggested process to do so is to start refactoring the little details to clarify the code, thereby exposing the design. The potential to improve understandability through refactoring is confirmed by many authors [Opdyke, 1992, Simon et al., 2001, Kataoka et al., 2002, Deursen and Moonen, 2002, Demeyer et al., 2002, van Emden and Moonen, 2002, van Deursen et al., 2003, M¨ antyl¨ a et al., 2004]. In more specific terms, [Wake, 2003] discusses how refactorings can be used to improve communicating the purpose of the code. • Help find bugs – Through clarifying the structure of the code, the assumptions within the code are also clarified, making it easier to find bugs. • Program faster – Through improving the design and overall understandability of the code, rapid software development is supported. Traditionally, Opdyke [Opdyke, 1992] is referenced for publishing the first PhD w.r.t. refactoring. However, in his PhD thesis, Opdyke refers to the PhD of Griswold, acknowledging his precedence. Griswold did not use the word refactoring explicitly, yet referred to the same concept: automatable meaningpreserving restructurings [Griswold, 1991].
1.2. REFACTORING
3
Restructurings are propoposed by Griswold as a means to reorganize a decayed structure, caused by the accumulation of unanticipated changes. What is characteristic about these changes is their non-local character: the implementation of these changes requires modifications at multiple locations in the source code. The key to resolving decayed structure is in isolating design decisions, requiring global search and global changes in order to preserve behavior. I.e., we can’t simply change the definitions, yet also have to adapt the references to these definitions. While the former changes can be described locally, the latter have a global impact. The focus on a description of a local definition change that has a global impact is essential for Griswold’s contribution. As a cost-efficient way to perform these global changes, automatable restructurings have been proposed, e.g., by [Griswold, 1991, Opdyke, 1992, Roberts, ´ Cinn´eide, 2001]. These restruc1999, Fowler, 1999, Tokuda and Batory, 2001, O turings are distinct from other maintenance activities in that the maintainer can focus on local structural changes. The automated restructuring takes care of the global search, and assures consistent changes. Such restructurings are used to transform the code to a form which is better suited for future changes. Once a selected set of changes has been accommodated in the structure, the application of these changes will be facilitated. The concept of refactoring is an exploitation of Parnas’s design guidelines, stating that structural system modifications can be postponed by assuring locality of change for likely changes [Parnas, 1978]. To assure locality, Parnas suggests the following steps: (i) identify the items that are likely to change; (ii) locate specialized components in separate modules; and (iii) design intermodule interfaces insensitive to the anticipated changes [Parnas, 1978]. These steps respectively correspond to three design principles: (i) abstraction; (ii) encapsulation; and (iii) information hiding. These concepts are clearly distinguished by [Berard, 1993] based on an extensive literature survey: Abstraction: As a process, abstraction denotes extracting the essential details about an item or a group of items while ignoring the inessential details. Examples of these essential details are difficult or likely-to-change design decisions. As an entity, abstraction denotes a model, a view, or some other focused representation for an actual item. Among others, abstraction differs from information hiding in that it does not specify a mechanism for handling the unimportant information. Encapsulation: As a process, encapsulation means the act of enclosing one or more items within a (physical or logical) container. As an entity, encap-
4
CHAPTER 1. INTRODUCTION sulation refers to a package or an enclosure that holds (contains, encloses) one or more items. Encapsulation can be used as a strategy to package what has to be extracted, disregarding whether these items should be visible or hidden.
Information hiding: The process of hiding information, especially difficult or likely-to-change design decisions. Information hiding does not incorporate the identification of which information is to be hidden (e.g., through abstraction), nor the strategy for hiding them (e.g., through encapsulation). As refactoring is an exploitation of assuring locality of design decisions likely to change, there should be a close relationship between refactoring and the three design principles abstraction, encapsulation and information hiding. In this thesis, we investigate the exploitation of abstraction and encapsulation using refactorings. To investigate the exploitation of abstraction using refactorings, we study how the process of people trying to comprehend parts of a software system can be supported through refactorings. Accordingly, we discuss two known usages of refactoring, which are claimed to support program comprehension. To investigate the exploitation of encapsulation using refactorings, we employ the concepts of coupling and cohesion. Coupling is defined as “the measure of the strength of association established by a connection from one module to another ”, and cohesion as “a measure of the degree to which the elements of a module belong together ” [Stevens et al., 1974], as cited in respectively [Briand et al., 1996] and [Briand et al., 1997]. A well known guideline for both structured and object-oriented design is to minimize coupling and maximize cohesion [Coad and Yourdon, 1991, PageJones, 1992, McConnell, 1993]. Coupling and cohesion have been recognized to be in fact two aspects of a single principle, termed connascence. In [Page-Jones, 1992], connascence is defined as: “. . . I define two software elements A and B to be connascent if there is at least one change that could be made to A that would necessitate a change to B in order to preserve overall correctness” Using this unified concept of connascence, the aim of minimal coupling and maximal cohesion is formulated in a single statement about object-oriented design, as cited from [Page-Jones, 1992]:
1.3. CONTRIBUTIONS
5
“Eliminate any unnecessary connascence and then minimize connascence across encapsulation boundaries by maximizing connascence within encapsulation boundaries.” Using this terminology, coupling can be described as connascence across encapsulation boundaries, and cohesion as connascence within encapsulation boundaries. Accordingly, we study existing refactorings that affect these boundaries, to learn how these refactorings can be used to optimize encapsulation by minimizing coupling and maximizing cohesion.
1.3
Contributions
The three contributions of this research are: 1. Report on the mental effects of physically applying refactorings that introduce abstraction. This application of refactoring has been previously introduced by [Demeyer et al., 2002] as a reverse engineering pattern entitled Refactor to Understand. 2. Report on comprehensibility improvements when applying refactorings that introduce encapsulation. This application of refactoring was also previously introduced by [Demeyer et al., 2002] as a reengineering pattern entitled Split Up God Class. 3. Demonstrate formal analysis of refactorings (Extract Method, Move Method and Replace Method with Method Object) and indicative coupling and cohesion metrics to identify the conditions under which the application of these refactorings minimize coupling and maximize cohesion.
1.4
Organization
This thesis is organized as follows. First, Chapter 2 discusses work related to the exploitation of reengineering or refactoring techniques to improve quality. The remainder of this thesis is divided into two parts. Part I presents the contributions w.r.t. the use of refactoring to improve program comprehension.
6
CHAPTER 1. INTRODUCTION Chapter 3 delineates program comprehension within the larger context of software maintenance, and clarifies the program comprehension models employed in this thesis. Chapter 4 describes the Refactor to Understand reverse engineering pattern, of which we report our efforts for validation in Chapter 5. Chapter 6 presents the Split Up God Class reengineering pattern, whose validation is discussed in Chapter 7. Chapter 8 summarizes the findings of the first part of this thesis, and discusses lessons learned.
Part II reports the contributions w.r.t. the use of refactoring to improve coupling and cohesion. Chapter 9 introduces the process of Quality Driven Refactoring. Chapter 10 presents a selection and formalization of coupling and cohesion metrics and refactorings, and presents impact tables describing the effect of a refactoring on metrics. The impact derivation process itself is discussed in Appendix B. These impact tables are validated in Chapter 11. Chapter 12 illustrates the exploitation of impact tables through refining a variant of the Move Method refactoring, and applying it in a case study. Chapter 13 summarizes the findings of the second part of this thesis, and discusses lessons learned. Finally, we discuss future work in Chapter 14 and present our conclusions in Chapter 15.
Chapter 2
Related Work In this chapter, we discuss previous research on quality improvements by refactoring. This overview is used to describe opportunities for advancing the current state of the art.
2.1
Program comprehension improvements
To the best of our knowledge, there has been no previous attempt to evaluate how program comprehension can be improved using refactorings. However, we are aware of two works that investigated the relationship between class decomposition and program comprehension. As the software solution before and after a refactoring can be considered to be alternative class decompositions, this research is related to our problem statement. [McGregor and Kamath, 1995] performed research on a so called Psychological Complexity Measure, which uses information on class responsibilities and class collaborations to calculate the psychological development complexity as a measure of effort. By defining a measure called Permitted Collaborations (PC), they suggest a means for estimating the cognitive load imposed on the developers of a software system from a set of Class-Responsibility-Collaborator cards [Beck and Cunningham, 1989] that represent a domain. One of the purposes of this measure is to “aid the developers in selecting the right class decomposition when there are conflicting choices” [McGregor and Kamath, 1995]. Among others, the measure is suggested to be applicable in trade-off analysis when deciding whether or not a weakly cohesive class should 7
8
CHAPTER 2. RELATED WORK
be partitioned. Their measure indicates that the partitioning of a class yields “a lower combined complexity value for the two partitioned classes”, yet the relative complexity increase or decrease is “dependent on whether the complexity increase due to an additional collaborator is greater or less than the reduction in collaboration complexity due to smaller collaborators”. The suggested measure was shown to correlate with expert judgements in an initial experiment. [Arisholm and Sjøberg, 2004] conducted experiments to empirically compare two alternative design solutions with a fundamentally different control style. These alternatives were composed by assigning responsibilities and collaborations among classes in different ways. One alternative distributed a well-defined set of responsibilities across a number of classes, which typically results in a delegated control style. In contrast, in a centralized control style, a few large control classes coordinate a set of simple classes. The main hypothesis investigated in these experiments is that a delegated control style is easier to understand and change than is a centralized control style. While the work of Arisholm et al. does not describe how the two alternatives were composed, the two alternatives are behaviorally equivalent, which allows to refactor one into the other. Therefore, any quality differences observed between these two alternative solutions provide indications of quality benefits and disadvantages that can be achieved using refactorings. In their first experiment, Arisholm et. al surprisingly observed that it took undergraduate students more effort to implement a given set of changes on the delegated control style. A hypothetical explanation for this contradiction to expert opinions was suggested, leading to the second experiment. In this second experiment, the authors hypothesized that differences in maintainability of the designs might be due to cognitive models of the developers, which would require to incorporate a factor distinguishing the level of experience of the participant. Therefore, the second experiment incorporated junior, intermediate and senior software consultants aside undergraduate and graduate students, and the comparison of the maintainability of the two alternative designs was observed for each of these experience levels. The results of the second experiment rejected that the design alternative affected change effort, defined as the time spent performing change tasks. Even when incorporating interaction with the developer category, the control style was not found to significantly affect change effort. However, a posthoc analysis between the high (intermediates and seniors) and low (undergraduates, graduates and junior) experience developers indicated that the interaction between design and developer category was, in fact, significant. With regard to change task correctness, the results indicated that subjects
2.2. INTERNAL PRODUCT QUALITY IMPROVEMENTS
9
were much less likely to produce correct solutions on the delegated control style design. For both change effort and correctness, the authors found that only senior consultants benefited from the delegated control style. In contrast, less skilled developers performed better on the centralized control style design. Accordingly, we ask ourselves whether these results would be confirmed or refuted in the context of refactoring. In a refactoring context, classes with a centralized control style tend to grow out to become god classes [Brown et al., 1998]. These god classes encapsulate the responsibilities of a whole subsystem, therefore forming an incohesive grouping of unrelated functionality. In case we can generalize the findings of [Arisholm and Sjøberg, 2004], then a god class would be more maintainable than an equivalent class decomposition which distributes responsibilities across a number of collaborators, thereby exhibiting a delegated control style.
2.2
Internal product quality improvements
To identify existing research approaches w.r.t. the exploitation of refactoring to improve internal program quality characteristics, we reviewed key conferences and journals related to the subject of software maintenance and evolution. This review of the literature led to the identification of three research approaches, respectively by [Sahraoui et al., 2000, Kataoka et al., 2002, Tahvildari et al., 2003].
2.2.1
Related work by Sahraoui et al.
[Sahraoui et al., 2000] propose to use metrics both for detecting potential design flaws, and for suggesting potentially useful transformations for correcting them. The reengineering strategy proposed by Sahraoui et al. consists of the following steps: • Diagnosis of design flaws – An engine applies rules of a quality estimation model to classes of the software system. The goal is to detect symptoms of violated design rules using combinations of metrics. • Prescription of transformations– Prescription refers to the exploitation of the (possibly indirect) relationship between transformations and quality improvement. The logic behind this approach is that if a good design is reflected in a good combination of metric values, then we might assume that a good combination of metric values corresponds to a good
10
CHAPTER 2. RELATED WORK design. Accordingly, the goal is to improve quality through manipulating metric values.
The prescription step is supported through formal analysis of the effect of three transformations on inheritance and coupling metrics. The resulting impact description is illustrated in Table 2.1. The metrics themselves are unimportant in this discussion, as we are merely pointing out the level of detail of the impact description. Table 2.1: Impact description by Sahraoui et al. Classes Classes that reference the abstracted methods Classes referenced in the common code
Ci
Global variations IH-ICP + i ( I ≥ 0) CBO - [0, N - 1] DMMEC - i ( i ≥ 0) OMMEC - i ( i ≥ 0) CBO N.D. IH-ICP N.D
Impact of the Create Abstract Class transformations on coupling metrics, as extracted from [Sahraoui et al., 2000].
Table 2.1 describes the impact of the Create Abstract Class transformation on coupling metrics, in which N stands for the number of factorized classes. In general, the impact tables presented in [Sahraoui et al., 2000] suggest three possible impact descriptions: • Exact impact specification – The value of a metric after the application of a refactoring is specified exactly, possibly but not necessarily using a variable for an unknown cardinality, e.g., N . • Impact spectrum – The value of a metric after the application of a refactoring can be determined within an interval, e.g., a finite interval (CBO - [0, N - 1]) or an infinite interval (DMMEC - i, with i ≥ 0). • Indeterminate impact – The value of a metric after the application of a refactoring can not be determined, e.g., CBO N.D. This description of the impact of a representative set of transformations on a selected set of object-oriented metrics is suggested to be used by prescription tools to propose transformations that cure detected design flaws. The validation
2.2. INTERNAL PRODUCT QUALITY IMPROVEMENTS
11
of a transformation suggestion then requires two tasks: (i) an evaluation of the suggestion by the maintainer based upon the particular semantics of the affected code part ; and (ii) an evaluation of the transformation precondition.
2.2.2
Related work by Kataoka et al.
[Kataoka et al., 2002] describe a refactoring process consisting of three main steps, involving three roles: • Identify refactoring candidates – First, a developer finds source code parts to be refactored. The developer is responsible for validating the functional equivalence of the refactoring. • Validate refactoring effect – Second, an analyst performs cost and effect estimation to select appropriate refactorings from the set of candidates. The analyst is responsible for validating the intended effect of each refactoring. At the manager level, the cost-effect trade-off should be validated, and a prioritization should take place. • Application of refactoring – Thirdly, the developer applies the selected refactorings on the target program in the proposed order. Kataoka et al. focus on the second step, being the validation of the effect of refactoring. The authors propose an evaluation method for the degree of maintainability enhancement of a refactoring. This evaluation method compares the value of an appropriate metric before and after applying the refactoring. Their approach was demonstrated by validating the effect on coupling of an identified refactoring candidate. An illustration of the validation was provided for a Move Method refactoring candidate. As an indicator for maintainability, a coupling metric was used to quantify the effect of moving the selected method to another class. The resulting impact specification described the effect as a formula using an unknown variable for the number of polymorphic invocation targets of a method invocation contained in the selected method. This formula allowed the authors to describe the condition under which moving the selected method would reduce the coupling metric.
2.2.3
Related work by Tahvildari et al.
[Tahvildari et al., 2003] adhere quite closely to the approach of [Sahraoui et al., 2000]. Tahvildari et al. propose to exploit the effect of transformations on
12
CHAPTER 2. RELATED WORK
metrics to improve quality. The proposed reengineering strategy consists of the following steps: • Apply metrics – Selected object-oriented metrics are measured (and collected) to detect classes with deteriorated quality. The focus is on so called key classes, which implement the most important concepts of a system, i.e., recognized through their coupling and complexity values. • Apply transformations – Transformations are identified which can reengineer the detected design flaws. The preconditions of these transformations are evaluated to verify their applicability, and the transformation is applied. • Evaluate improvement – The metrics are re-applied to evaluate the design and source code improvement using before-after comparison. Essential to this reengineering strategy is the adherence to the non-functional requirement (NFR) framework. The NFR framework represents software quality requirements in soft-goals [Chung et al., 2000]. Soft-goals are goals with no clear-cut criterion for their fulfillment. Soft-goals contribute either positively or negatively towards achieving other soft-goals, and can be satisficed (satisfied, but not necessarily optimally so) or not. Soft-goals are organized in a softgoal interdependency graph (SIG), specifying the soft-goals considered and their interdependencies. The leaves of a SIG represent design decisions. Tahvildari et al. analyzed the contribution of so called meta-pattern transformations to these design decisions. Meta-pattern transformations exploit motifs shared between multiple design patterns. These design motifs can be combined into existing design patterns [Tahvildari and Kontogiannis, 2002a], and are themselves composed of lower-level refactorings. Meta-pattern transformations can contribute positively (make ++, or merely help +) or negatively (break --, or merely hurt -) to design decisions, or can have no impact. Through their contribution to design decisions, the SIG clarifies how these transformations indirectly contribute to (potentially conflicting) software qualities. Similar to [Sahraoui et al., 2000], the impact specification is provided as an impact spectrum, which specifies the impact in a (mostly infinite) interval. As an example, Table 2.2 illustrates the impact specification of the Movement transformation on soft-goals in a SIG for maintainability (extracted from [Tahvildari and Kontogiannis, 2002b]). The Movement transformation corresponds to the Extract Class refactoring as described by [Fowler, 1999]: it creates a new class and fills it with method from an existing class.
2.3. SUMMARY
13
Using such impact descriptions, a SIG for maintainability can be extended to indicate which transformations to apply to improve the most refined soft-goals, and therefore indirectly to improve maintainability. Table 2.2: Impact description by Tahvildari et al. Soft-goal High Modularity Low Control Flow Coupling High Module reuse
Effect ++ +
Impact of the Movement meta-pattern transformations on maintainability related soft-goals as extracted from [Tahvildari and Kontogiannis, 2002b].
2.3
Summary
Based on the overview of related work, we summarize previous research w.r.t. quality improvements by refactoring as follows. It has been shown that alternative class decompositions can differ w.r.t. maintainability [Arisholm and Sjøberg, 2004]. Thus, this leads us to assume that refactorings, which manipulate the class decomposition, can potentially improve quality attributes related to maintainability. However, the effect of the class decomposition was found to interact with the experience of the person performing the maintenance task. Accordingly, we should be careful to incorporate personal characteristics when comparing different class decompositions achieved through refactoring. With regard to internal program quality, researchers have demonstrated the usefulness of evaluating how refactorings affect design quality indicators as coupling and cohesion [Sahraoui et al., 2000, Tahvildari and Kontogiannis, 2002b, Kataoka et al., 2002]. However, this research has focused mostly on transformations at the level of design patterns rather than the level of current automatable refactorings, such as the ones catalogued by [Fowler, 1999]. We are particularly interested in the effect of automatable refactorings for two reasons. First, knowledge on the effect of refactorings supported in current refactoring tools can be more easily exploited in current refactoring practices. Second, it has been demonstrated that higher-level refactorings can be composed from the set lower-level automatable refactorings [Kniesel and Koch, 2004], forming socalled composite refactorings. Since the formal description of these composite refactorings can be derived from its constituting parts (e.g., as performed by
14
CHAPTER 2. RELATED WORK
´ Cinn´eide, 2001]), it should be theoretically possible to reuse the descriptions [O of the effects of lower-level refactorings in composite refactorings. Accordingly, we are intrigued by the work of [Kataoka et al., 2002] who demonstrated the derivation of an exact impact specification of an automatable refactoring. The benefit of an exact impact specification is that it enumerates the conditions under which the optimal effect can be achieved. When used as additional preconditions, the studied refactorings can be refined towards the optimization of a selected set of metrics. Accordingly, such exact impact specifications can enable quality driven refactoring.
Part I
Program Comprehension Improvements
15
Chapter 3
Program Comprehension This chapter delineates the maintenance activity of program comprehension. We start by providing a life cycle model for processing a maintenance task, and indicate how program comprehension contributes to this wider context. Then, we provide an overview of the main features of program comprehension as described in existing literature, clarifying how program comprehension can be evaluated. The selected evaluation methods for program comprehension will be used in the further chapters of this part of the thesis for the validation of two typical usages of refactoring.
3.1
Software maintenance
In this section, we discuss the general life cycle model (or “framework for organizing the experienced reality” as described by [Chapin, 1988]) for fulfilling software maintenance tasks proposed by [Khan et al., 1996] based on a survey of the literature. Chapin defines the objective of software maintenance as “to modify an existing software system while preserving the integrity of that system’s existing contribution to the organization’s performance capability”. [Chapin, 1988]. Khan et al. stress that software maintenance is performed within the context of a larger process. This larger process is termed the Change Control or Configuration Management procedure by [Chapin, 1988], and the general software development process by [Khan et al., 1996]. By embedding software maintenance in such a wider context, one can focus (e.g., relatively to their weight) on 17
18
CHAPTER 3. PROGRAM COMPREHENSION
the activities which are specific to the processing of a single maintenance task. These activities are: 1. Modification requirement analysis – Understand the modification requirements originating from a user already using the system. Chapin terms this activity as the definition of the modification objectives, consisting of the determination of the business function which the modification should accomplish (what), and also how this function should be accomplished. 2. Feasibility determination – Assess the importance and relevance of the modification, as well as the effort required to implement the change. This phase incorporates refining and filtering of user requirements, as well as estimation of costs and staff. 3. Program comprehension – Extract the system design rationale to understand how the product was designed and implemented. 4. Localization – Identify the precise location where the proposed modification is to be applied. 5. Impact analysis – Analyze potential side-effects in consequence of the proposed modifications. 6. Implementation plan – The implementation of the proposed modification is planned, describing the necessary updates to the existing specification and design documents, but also stating how to implement and configure modified or to-be-added components. The distinction and order between the three comprehension related activities (program comprehension, localization and impact analysis) is not entirely consistent with program comprehension literature. I.e., Khan et al. stress that the maintainer has to have a complete understanding before localization can start. However, this conflicts with the traditional perspective on comprehension strategies applied in practice, which mainly report on an as-needed strategy in which comprehension is applied very selectively [von Mayrhauser and Vans, 1995]. We therefore are somewhat reluctant to stress the difference between the activity of program comprehension and that of localization. More specific, [Koenemann and Robertson, 1991] observed that professional programmers study code or documention only in case they are convinced that the code is relevant for their task. In fact, Koenemann et al. differentiated
3.2. THE PROCESS OF PROGRAM COMPREHENSION
19
between three types of ”relevancy”. Code segments which will have to be modified are tagged as directly relevant. Code which is assumed to interact with directly relevant code is termed intermediate relevant. Finally, code or documentation which helps to locate directly or intermediate relevant code is called strategic relevant code. Using this vocabulary, the activity of localization could be defined as localizing directly relevant code; impact analysis as the determination of intermediate relevant code; and finally, the first activity of program comprehension could be considered the determination of strategic relevant code, preparing for localization and impact analysis. Khan et al. indicate that providing the implementation plan is the last maintenance-specific activity. From that moment, the further activities consist of modifying and revalidating the system, which can be supported by the software development life cycle framework. 7. Requirement analysis – Apply the described updates to the existing specification. 8. Design – Apply the described updates to the existing design documents. 9. Coding – Implement the described modifications. 10. Testing – Create tests for the previously described side-effects (as an output of the impact analysis activity), and perform the tests, including regression tests. Chapin distinguishes between validating and verifying the modification itself, and revalidating (regression testing) the software system. The latter focuses on the preservation of the unmodified functionality while the former focuses on the correctness of the modified functionality. After this last activity, the larger process of configuration management takes over.
3.2
The process of program comprehension
Khan’s lifecycle model proposed three activities related to program comprehension: (i) program comprehension; (ii) localization; and (iii) impact analysis. In this subsection, we discuss different comprehension models that describe the processes that programmers apply when trying to comprehend a program.
20
CHAPTER 3. PROGRAM COMPREHENSION
Research on program comprehension has led to a number of comprehension models, which can be categorized into bottom up, top down or integrated (hybrid models). A bottom up model develops mental representations, top down models decompose code into typical elements, and an integrated model combines both top-down and bottom-up understanding. While it has been shown that programmers switch between all models, top-down comprehension is typically applied for familiar code, while bottom-up comprehension is mostly applied for unfamiliar code [von Mayrhauser and Vans, 1995, O’Brien and Buckley, 2001].
3.2.1
Bottom-up comprehension
Nancy Pennington performed research on the mental representations that programmers construct when reading unfamiliar program code [Pennington, 1987b]. The basis for these mental representations were abstractions of program text, which were suggested by formal analysis of procedural programs. These abstractions convey information “about what should be accomplished (goal hierarchy), how to do it (sequential procedure), the set of conditions under which particular actions should be taken (conditionalized action), and the set of transformations that a particular object should go through (data flow)” [Pennington, 1987b]. Together with an additional abstraction (operations), a total of five abstractions structure the information present in a program in different ways: • Function – A decomposition of the program into a goal hierarchy according to the major program functions or outputs, without specifying how the goals are achieved. In this hierarchy, a goal is recursively divided into subgoals. • Data Flow – Structures information according to the transformations applied to a data object. While there are evident relationships between the transformations and the goals in the functional abstraction, one needs additional information to group goals into higher order goals. This information is not present in a data flow abstraction. What is present, is an explicit description of the changes to a data object. • Control Flow – Explicit description of the sequence in which actions occur. • Operations – Detailed actions corresponding to a single statement, or less, in case a single command executes multiple actions.
3.2. THE PROCESS OF PROGRAM COMPREHENSION
21
• State (Conditionalized actions) – Structures information according to actions that will be performed when a set of conditions is established, and also which conditions will be fulfilled after the action. This structure allows to find out easily when an action will be performed, but also what happens when a set of conditions is established. What is essential about these abstractions is that it is infeasible to simultaneously structure a program text according to multiple abstractions. Nonetheless, complete comprehension requires an understanding of all abstractions, as well as the relationships between them. Analogue to the theory of text comprehension, Pennington suggests the presence of two different mental representations, each according to a different type of knowledge: (i) the program model; and (ii) the situation model. The program model representation stresses text structure knowledge, representing knowledge about the control flow constructs (based on building blocks for sequencing, iteration and conditionals). The program model describes the relationships between different program parts and the operations contained in these parts. Therefore, this representation is mostly based on control flow and operations abstractions. The situation model representation focuses on plan knowledge, representing knowledge about plans. Plans describe typical manners of achieving goals (e.g., sorting, or taking the average of a series), and involve both functions and roles for other plans. The situation model representation is mostly based on data flow and function abstractions. State abstractions are explicit in neither types of representation, and are assumed to be generally difficult to extract from the program text. Thus, these abstractions can be used to assess the effectiveness of a bottomup comprehension attempt for procedural languages. Pennington’s model in an Object-Oriented context Due to fundamental differences between the object-oriented paradigm and the procedural paradigm, the validity of employing Pennington’s model to reason about bottom-up comprehension of object-oriented source code is a highly debatable subject. We polarize this debate in either a perspective on using Pennington’s mental model for programs in the object-oriented paradigm based on its commonalities with the procedural paradigm, or conversely, on their differences.
22
CHAPTER 3. PROGRAM COMPREHENSION
On one hand, the methods of organization available in the object-oriented paradigm are a superset of these of the procedural paradigm. As the five abstractions present in the program and situation model are based upon these common methods of organization, the mental model of object-oriented programs can be (partially) evaluated using these five abstractions. This perspective has been supported by, e.g., [Ramalingam and Wiedenbeck, 1997,Davies, 2000,Engebretson and Wiedenbeck, 2002]. On the other hand, the object-oriented paradigm extends the procedural paradigm through fundamental differences as, e.g., the advanced encapsulation of data and functions and the concept of inheritance. These additional abstractions are known to have a considerable impact on cognitive activities [Or-Bach and Lavy, 2004]. Thus, it is reasonable to assume that the mental model representations of procedural programs differs from that of object-oriented programs. In this dissertation, we adhere to the perspective of commonalities with the procedural paradigm, stating that the key abstractions of function, data flow, control flow, operations and state are most likely present in mental model representations of object-oriented programs. Nonetheless, we realize that these abstractions might be affected by additional methods of organization. E.g., control-flow abstractions might be challenged by the use of inheritance, since the principle of polymorphism introduces a potential difference between the static type of an object, as read from the source code, and its dynamic type, at run-time. Thus, we emphasize that our evaluation using the five abstractions described in Pennington’s model does not necessarily form an evaluation of the complete mental model of object-oriented programs. Supporting bottom-up comprehension Key comprehension principles which support structuring the information contained in the program text (thereby constructing the according mental model representation), are (i) beacons; and (b) chunking. • Beacons are recognition points that index into knowledge [von Mayrhauser and Vans, 1995]. Mostly, beacons are names that are semantically associated with a specific programming concept, and help their recognition [Wiedenbeck and Scholtz, 1989, Crosby et al., 2002]. • Chunking is the composition of lower level structures into higher level abstraction structures. Such a composition strategy allows the reader to trade off when to zoom in, based on the names of the chunks that already serve as beacons. For the person performing the actual composition,
3.2. THE PROCESS OF PROGRAM COMPREHENSION
23
chunking is a means to introduce abstraction, for example, by recognizing that a specific sequence of mathematical operations signifies the calculation of the tax amount for a given product price and tax rate.
3.2.2
Top-down comprehension
A top-down comprehension strategy is mostly applied when the code or problem domain is familiar. In terms of top-down comprehension, the task of understanding a program consists of “constructing, or reconstructing, enough information about the modeling domains that bridge between problem and executing program to perform the requested task ” [Brooks, 1978]. This bridging is mostly nontrivial as the knowledge which the initial developer had about the entities and relationships in the problem or application domain has been encoded in a programming language. To comprehend a program, one needs to be able to relate, link, match or map entities, their attributes and the operations that manipulate these attributes, as well as relationships between these entities present in the source code with the set of entities, actions involving these entities, and relationships between entities present in the problem domain. Brooks used his theory to stimulate the construction of adequate documentation. [O’Brien and Buckley, 2001] differentiate between two types of top-down comprehension. An expectation-based process (e.g., as discussed by [Brooks, 1983]) starts with the formulation of pre-generated hypotheses, followed by trying to confirm or refute the hypotheses (and their refinements) by scanning the code, finally leading to their confirmation (or refutation). These hypotheses might originate from expertise or documentation, or even from other programmers [O’Brien and Buckley, 2001]. The verification of these hypotheses is supported by beacons, and their refinement ends when an associated code segment is found. In contrast, an inference-based process (e.g., as discussed by [Soloway and Ehrlich, 1984]) starts with scanning the code first, then inferring hypotheses which are thereafter validated. Therefore, the inference-based process is a combination of a top-down and a bottom-up approach. Supporting top-down comprehension [Biggerstaff et al., 1993] refer to bridging the problem and executing program as the concept assignment problem, stressing that “there is no algorithm (or, equivalently, no set of inference rules) that allow us to compute this mapping [between the domains of ”mathematics and data manipulation” and any appli-
24
CHAPTER 3. PROGRAM COMPREHENSION
cation domain] with complete confidence”. In contrast, the programmer can merely use fuzzy reasoning supported by different kinds of clues that can support discovering concepts. In [Biggerstaff et al., 1993] these clues are suggested to be: • Natural language tokens – These correspond to beacons, and can be found names and comments. • Proximity and grouping – Definitions of concepts which are related are grouped together. • Design conventions – Structural relationships indicative for a particular design. • Domain design conventions – These refer to structural relationships among the concepts in the application domain, e.g., through composition or delegation. • Previous solution states – The recognition of one concept can facilitate the recognition of another concept through the exploitation of relationships between the concepts in the problem domain and relationships detected in the code. • Weight of evidence – Combinations of clues strengthen the likelyhood that the hypothesized mapping is valid. These clues mostly support an inference based process. To support the recognition of concepts, Biggerstaff et al. propose two tasks: (i) the identification of important entities and relations; and (ii) the assignment of these entities and relationships to domain concepts and relations. Among others, these tasks differ w.r.t. to the need of application domain knowledge. Identification of important entities and relations – In this task, one looks for different types of clues to discover related statements. E.g., one can detect so called data-groups which might represent some domain concept, yet this representation is still to be recognized. Assignment to domain concepts and relations – This task requires domain knowledge, and exploits (i) the meanings of natural language tokens (beacons); (ii) recognition of associated concepts; (iii) relationships present in the
3.2. THE PROCESS OF PROGRAM COMPREHENSION
25
code that correspond to relationships in the domain; and (iv) the presence of a pattern of relationships at the domain level [Biggerstaff et al., 1993]. These two tasks support the two criteria which Brooks stated to be required for complete understanding of a program [Brooks, 1978]: 1. information about a knowledge domain, consisting of “basic set of objects, including their properties and relationships, the set of operations that can be performed on these objects, and the order in which these operations take place”. 2. “information about the relationship between objects and operators in one domain and those in a nearby domain”. Accordingly, these two criteria can be used to verify the effectiveness of a top-down comprehension attempt.
3.2.3
Summary
The overview presented in this chapter suggests the following evaluation methods for program comprehension: • To assess the effectiveness of a bottom-up comprehension attempt, we can verify the accuracy of the two mental model representations presented by [Pennington, 1987b]. • To assess the effectiveness of a top-down comprehension attempt, we can verify the accuracy of knowledge on the relations between the knowledge domains of the source code and problem doman, as discussed by [Brooks, 1978].
3.2.4
Structure of Part I
In this part, we investigate the use of two existing reengineering patterns that extensively use refactoring techniques w.r.t. their effect on program comprehension. This part is structured as follows. In Chapter 4, we introduce the Refactor to Understand reverse engineering pattern. This pattern uses refactorings to introduce abstraction. The empirical evaluation of this pattern’s contribution to bottom-up program comprehension is reported in Chapter 5.
26
CHAPTER 3. PROGRAM COMPREHENSION
A similar structure is employed for the second reengineering pattern. We present the Split Up God Class pattern in Chapter 6. This pattern uses refactorings to introduce encapsulation. Our empirical evaluation of the contribution of this pattern to top-down comprehension is presented in Chapter 7. Together, these four chapters discuss the application of refactoring for bottomup and top-down comprehension. We discuss our findings and lessons learned in Chapter 8.
Chapter 4
The Refactor to Understand Pattern In this chapter, we present a reverse engineering pattern claimed to support program comprehension. This claim will be validated in the next chapter.
4.1
Introduction
The Refactor to Understand reverse engineering pattern was introduced in [Demeyer et al., 2002]. This pattern is typical for reverse engineering in that it does not directly intend to improve the code base itself, but rather the maintainer’s understanding. Its purpose is to expose the design of cryptic code. Consequently, less emphasis is put on regression testing, and more on the composition and verification of hypotheses concerning the code. Refactor to Understand is based on two key principles for improving program comprehension, being (i) the introduction of beacons as indexes into knowledge; and (ii) the chunking of low-level structures into higher-level abstractions Beacons are recognition points that index into knowledge [von Mayrhauser and Vans, 1995]. Mostly, beacons are names that are semantically associated with a specific programming concept. Current literature on beacons has focused on their recognition [Wiedenbeck and Scholtz, 1989, Crosby et al., 2002], and therefore, uses beacons for top-down comprehension. However, when introducing beacons, we stimulate their recognition by future code readers. Consequently, we expect the introduction of beacons to stimulate bottom-up compre27
28
CHAPTER 4. THE REFACTOR TO UNDERSTAND PATTERN
hension. Chunking is the composition of lower level structures into higher level abstraction structures. Such a composition strategy allows the reader to trade off when to zoom in, based on the names of the chunks that already serve as beacons. For the person performing the actual composition, chunking is a means to introduce abstraction, e.g., by recognizing that a specific sequence of mathematical operations signifies the calculation of the tax amount for a product price and tax rate. Therefore, we expect that extracting statements into methods supports bottom-up comprehension. Introducing beacons and chunking are both used to test hypotheses concerning the code. The formulation of hypotheses, checking whether they are true or false, and the consequential revision is known as code cognition [von Mayrhauser and Vans, 1995]. Therefore, we regard Refactor to Understand as a cognition technique, serving the same goal as the traditional Read to Understand approach. This goal is to construct a mental model of the source code.
4.2
Pattern Description
The following description of the Refactor to Understand pattern is quoted from [Demeyer et al., 2002]: “Iteratively rename and refactor the code to introduce meaningful names and to make sure the structure of the code reflects what the system is actually doing. Run regression tests after each change if they are available, or else compile often to check whether your changes make sense. Decide what to do with the code after you have refactored it.” [Demeyer et al., 2002] suggests the following guidelines to iteratively make design decisions more explicit in thecode: • Rename attributes to convey roles. Use attribute usages to discover the role an attribute plays. • Rename attributes to convey intent. Use method invocations and attribute usages inside the method to find out the name associated with the responsibility provided by a method. • Rename classes to convey purpose. Use method invocations and class instantiations by clients to discover a class’s purpose.
4.2. PATTERN DESCRIPTION
29
• Replace conditional branches by methods. Extract bodies of conditional branches into private methods with intention-revealing names. • Define method bodies with same level of abstraction. Extract code blocks from a long method to balance the level of abstraction of methods. The relationship between these guidelines and key principles in bottom-up comprehension stimulates our interests in validating the Refactor to Understand pattern.
4.2.1
Research Question
The Refactor to Understand pattern aims to improve the maintainer’s understanding of the code. However, to the best of our knowledge, this pattern has not been empirically tested. Therefore, it is unclear whether the pattern is effective in improving program comprehension. In this context, we assume that the program to be understood is unfamiliar to the maintainer, thereby suggesting the use of a bottom-up approach as discussed by [Pennington, 1987a]. Accordingly, we ask ourselves whether the Refactor to Understand pattern stimulates the construction of the abstractions of the program and situation model proposed in Pennington’s model. Summarizing, we pose the following research questions w.r.t. the Refactor to Understand pattern: 1. Effectivity – How does the Refactor to Understand pattern improve program comprehension? Is the construction of a mental model, as described by Pennington’s model, supported? 2. Efficiency – Does the application of the Refactor to Understand pattern require more effort than mere code reading? These research questions will be addressed in the next chapter.
30
CHAPTER 4. THE REFACTOR TO UNDERSTAND PATTERN
Chapter 5
Validating Refactor to Understand This chapter is based on a previously published paper [Du Bois et al., 2005]. In this chapter, we report on our efforts towards validating the Refactor to Understand pattern1 . As we are unaware of any previous efforts regarding such validation, we consider this work as explorative and therefore restricted with regards to the degree to which strong conclusions can be drawn. As a means for validation, we chose a research method that optimizes control over the application of our technique. This is required to ensure that any observed effects can be attributed only to the selected technique, and that the applied technique corresponds to the technique described in the previous chapter. Therefore, we have chosen to employ controlled experiments.
5.1
Introduction
To evaluate the mental model representations of programmers adhering to a bottom-up approach for program comprehension, Pennington asked closed questions about the abstractions in the program and situation model [Pennington, 1987a]. However, a disadvantage of using closed questions is that these can only confirm or reject the presence of an abstraction. Therefore, we suggest to 1 The
experimental material used in this chapter is publicly http://www.lore.ua.ac.be/Research/Artefacts/refactor2Understand
31
available
at
32
CHAPTER 5. VALIDATING REFACTOR TO UNDERSTAND
use open questions, which, in combination with a consistent rating scheme, can result in a more fine grained image of the extent to which the abstraction has taken place.
Table 5.1: Questions for evaluating abstractions Abstraction – Function –
Data Flow –
Control Flow –
Operations –
State –
Question What is the overall functionality? Pennington’s example question: Will an average be computed? Where does a data object get updated? Pennington’s example question: Will the value of variable x affect the value of variable y? Describe the sequence of execution. Pennington’s example question: Is the last record in file x counted in variable y? What does a particular line of code compute? Pennington’s example question: Is variable x initialized to zero? What is the content of a data object at a particular point in execution? Pennington’s example question: When label x is reached, will variable y have a particular known value?
Evaluation questions for each of the five abstractions discussed in Pennington’s model [Pennington, 1987a].
Table 5.1 presents typical generic questions for evaluating the different abstractions of Pennington’s model. These questions have been composed by translating the example questions proposed by Pennington to an open question form [Pennington, 1987a], with exception of the control flow abstraction, as part of the the program model: • Control flow – Pennington’s example question was very similar to the question for the function abstraction, which is essential for the situation model. In contrast, the program model stresses the structure of the text (e.g., by illustrating constructs for sequencing, iteration and conditionals), and this should be reflected in the control flow question. Therefore, we
5.2. RESEARCH HYPOTHESES
33
ask the participants to describe the control flow of a piece of code using a graphical representation or in pseudo-code notation. The generic questions presented in Table 5.1 will be instantiated for the different code segments provided to the participants. Such instantiation incorporates a demarcation of the scope of interest and a reference to a particular method, variable or attribute. For a clear, objective accuracy rating we differentiated between the following four distinct categories (inspired by [Vok´ a˘c et al., 2004]): • Wrong answer: Assignment not understood, no answer given or plain wrong answer. • Right idea: The response contains the essence of a good solution, but is not worked out properly. • Almost correct: The response is lacking minor details, or these minor details are wrong. • Correct: The response is flawless. It is obvious to see that accuracy rated this way is at least ordinal, since the ratings can be ranked. However, there is also a difference in distance among the answers. Accordingly, we rated a wrong answer as 0, an answer which contains the right idea with 5, answer which is almost correct with 8, and a correct answer as a 10. Such a rating is commonly applied in education. We did not distinguish between responses in the same accuracy category, as such differences would be quite subjective. Therefore, the accuracy measurement is interval scale, which allows us to calculate means and standard deviations on these measurements, as well as apply common statistical techniques. Moreover, we also performed an analysis on the ordinal data, which distinguished the same significant differences.
5.2
Research Hypotheses
A comprehension technique should be most supportive for code fragments which are hard to comprehend. When trying to understand a program which is unfamiliar, programmers employ a bottom-up comprehension approach, reading the source code line-by-line and trying to chunk multiple statements into higher
34
CHAPTER 5. VALIDATING REFACTOR TO UNDERSTAND
order abstractions. One of the factors which can disturb this process is delocalization. Delocalization refers to the distribution of pieces of code that are conceptually related across non-contiguous parts of a program [Soloway et al., 1988]. One of the ways in which delocalization can occur is when part of some specific functionality is delegated to another method located in another class, requiring the programmer to navigate to the source of this other class. Such delocalization is typically quantified using coupling indicators. In code fragments exhibiting extensive coupling, a programmer has to switch between different classes frequently. As each class defines a context in which methods are specified, navigating between classes incorporates a context switch. This relationship between coupling and the effort required to understand a class is confirmed by [McGregor and Kamath, 1995]. Accordingly, we expect that code fragments which are extensively coupled are harder to understand. We will therefore test Refactor to Understand under representative degrees of coupling. We hypothesize that the Refactor to Understand pattern stimulates the construction of abstractions relevant for the program and situation model. Accordingly, we formulate null hypotheses with regard to the pattern’s effectivity and efficiency, as measured using the generic program comprehension questions presented in Table 5.1. As we have reasons to expect that the effect of a program comprehension technique is dependent on the degree of coupling of the code fragment to be understood, we specialize these null hypotheses for each degree of coupling: • H0,accuracy,X,Y – Refactor to Understand does not increase the accuracy of answers to questions regarding abstraction X for code fragments which exhibit a degree of coupling Y. • H0,time,X,Y – Refactor to Understand does not reduce the response time of answers to to questions regarding abstraction X for code fragments which exhibit a degree of coupling Y. Rejecting H0,accuracy,X,Y would lead to the acceptance of the alternative hypothesis, which states that Refactor to Understand increases comprehension accuracy with regard to the creation of abstraction X in the code part with degree of coupling Y. Furthermore, the rejection of both the accuracy and the time null hypotheses would demonstrate that the information required to answer the question is more readily available in memory, and therefore, that the achieved
5.3. EXPERIMENTAL SET-UP
35
program comprehension would also be readily available for comprehension related tasks. Our experimental set-up is explorative in nature. Consequently, we set the significance criterion α to 0.10, which is common for exploratory experiments in the domain of software engineering (e.g., [Pfahl, 2001, Johansson et al., 2001, Khoshgoftaar et al., 2006]). In other words, we can only accept group differences when the probability of a difference as extreme as the one observed is less than 10% (p < 0.10).
5.3
Experimental Set-Up
The experiment presented in this chapter was replicated after its initial execution. This replication was required for two reasons. First, the initial execution did not randomize the experimental tasks, thereby introducing a threat to internal validity through possible learning and fatigue effects. Second, the pool of available participants possessing the appropriate skill set is quite limited. Therefore, we replicated the original experiment using participants with a very similar profile.
5.3.1
Experimental Design
As an experimental design, we used a crossed factorial design with two factors (see Table 5.2). As a between-subjects factor, the program comprehension technique has two levels, being Refactor to Understand and Read to Understand. This means that participants were assigned to a group, and were not allowed to switch between the comprehension technique. As a within-subjects factor, the degree of coupling of the program under study has three levels, being none, moderate and high. As dependent variables, we measure the response accuracy and response time of answers on comprehension questions for each of the five abstractions as described by [Pennington, 1987a]. Subjects themselves wrote timestamps indicating the time measurement incorporates time for reading the question, time for solving the question by reconstructing the mental model representation (potentially looking back at the code), and time for writing down the answer. As the questions and associated answers were quite short (answers took about 3 lines), the number of seconds it took to provide the answer (absolute scale) is a good indicator for the time to solve the question.
36
CHAPTER 5. VALIDATING REFACTOR TO UNDERSTAND
Table 5.2: Experimental variables Variable type
Name Program compr. technique
Independent Degree of Coupling Dependent
Response accuracy Response time
Values Refactor to Understand Read to Understand No Moderate High {0, 5, 8, 10} [0,1200] sec
Scale nominal ordinal interval absolute
Accordingly, code fragments were selected which were representative for each of the degrees of coupling. Each of the three code fragments were used in one out of the three experimental tasks.
5.3.2
Experimental Participants
A total of twenty final (fourth) year Master level Computer Science students participated in the original experiment and its replication. The participants were divided into two groups: a treatment and a control group. Participants in the treatment group apply Refactor to Understand. In the control group, participants apply Read to Understand – the traditional comprehension technique. In April 2004, 12 students participated in the original experiment in the context of a course on Object-Oriented Reengineering. This course is optional in the Computer Science curriculum at the University of Antwerp. These final year students had substantial experience with Object-Oriented development. At the time the experiment took place, students were familiar with the ObjectOriented Reengineering Patterns defined in [Demeyer et al., 2002] during one introductory and three lab sessions. In March 2005, 8 final year Computer Science students participated in the replication of the experiment, in conditions identical to these of the original experiment. Students were motivated to participate in the experiment because it would introduce them to issues specific to understanding fragments of a large unknown software system. One week prior to the experiment, the students participated in the so called
5.3. EXPERIMENTAL SET-UP
37
Refactoring Lab Session 2 . During this session, a real-life scenario is simulated in which a development team has implemented initial requirements for a system, received requests for extra functionality, and decides to call in refactoring expertise to prepare the task of adding the newly requested functionality. This session familiarized all students with the environment used, and the techniques applied in the experiment. As a countermeasure for systematic performance differences between the two groups, we chose to form blocks of participants with similar estimated performance. This estimation was based on grades on the course which resembles the experimental assignment most closely. Each block consisted of a pair of participants, which were randomly distributed over the two groups. As a result, for each participant in the treatment group (Refactor to Understand), a matching participant is present in the control group (Read to Understand). Therefore, we feel assured that (i) the overall performance of the groups can be expected to be equal; and (ii) each participant matches up to its counterpart in the other group.
5.3.3
Experimental Procedure
At the beginning of the experiment, an introduction to the experimental procedure was given. Guidelines were provided for the comprehension technique to be applied by subjects in the treatment and control group (see Figure 5.1). These guidelines contained as a common part the generic questions (see Table 5.1) for the five categories of comprehension being target of inquiry at the end of each task. Therefore, all participants knew which kind of questions would be asked in each of the three tasks. These guidelines were adapted from [Demeyer et al., 2002], and are practical directions for stimulating comprehension principles. More specifically, they can be translated in program comprehension terminology as (i) introduce beacons; and (ii) introduce chunks. Both renaming and extracting methods are automated as refactorings and required only the typing of the associated keybinding and the new name of the program entity. After this introduction, the three tasks were started. At the beginning of each task, a task sheet was provided to the participants. These sheets are illustrated in Figures 5.2, 5.3 and 5.4 for respectively task 1 (NC), 2 (MC) and 3 (HC). 2A
reusable course package has been composed which is publicly available at http://www.lore.ua.ac.be/Research/Artefacts/refactoringLabSession
38
CHAPTER 5. VALIDATING REFACTOR TO UNDERSTAND Read to Understand
Goal ! Gain ! ! ! ! !
understanding in (without writing in the source code) Control Flow: what is the sequence of execution? State : what is the content of a data object? Operations: what does the code compute? Data Flow: where does a data object get updated? Function: what is the overall functionality?
Refactor to Understand Goal
! Gain ! ! ! ! !
understanding in Control Flow: what is the sequence of execution? State : what is the content of a data object? Operations: what does the code compute? Data Flow: where does a data object get updated? Function: what is the overall functionality?
Guidelines ! Spend your time wisely, no beautification ! Iteratively rename attributes/methods/classes to introduce meaningful names (CTRL+SHIFT+R). ! Extract methods or local variables to make the code structure reflect what the system is actually doing. (CTRL+SHIFT+M/L)
Figure 5.1: Guidelines for the Refactor to Understand experiment Task 1 Context Class in package contains a method
SearchPattern org.eclipse.jdt.internal.core.search.matching createMethodPattern
Task Use the appointed comprehension technique (either Read to Understand or Refactor to Understand) to dig into the whileloop at the beginning of this method. After 30 minutes, you will be asked to answer a number of questions about this piece of code.
Figure 5.2: Task sheet for task 1
Task 2 Context Class in package contains a method
IndexAllProjects org.eclipse.jdt.internal.core.search.indexing execute
Task Use
the
appointed
comprehension
technique
Task Use the appointed comprehension technique (either Read to Understand or Refactor to Understand) to dig into the whileloop at the beginning of this method. After 30 minutes, you will be asked to answer a number of questions about this piece of code.
5.3. SET-UP TaskEXPERIMENTAL 2 Context Class in package contains a method
39
IndexAllProjects org.eclipse.jdt.internal.core.search.indexing execute
Task Use the appointed comprehension technique (either Read to Understand or Refactor to Understand) to dig into the execute-method until after the large if-else-statement in which new subclasses of IResourceProxyVisitor are declared anonymously (line 162). After 20 minutes, you will be asked to answer a number of questions about this piece of code.
Figure 5.3: Task sheet for task 2 Each Task 3 task was divided into two parts. A code reading/refactoring part and a question answering part. First, the participants were asked to apply their appointed comprehension Context Class technique. This meansSurroundWithTryCatchRefactoring that half of the students read the source code and were in package not allowed to change itorg.eclipse.jdt.internal.corext.refactoring.surround (e.g. by refactoring or by writing comments in the code), contains a method addEdits(TextChange, TextBuffer) while the other half was stimulated to apply refactorings. All students used the Eclipse Integrated Development Environment3 (version 2.3), with which Task Use t h efamiliar. a p pThe o i n tstudents ed capplying o m p r e hrefactorings ension t e c asked h n i q uto e the students were were (either to to Understand or Refactor to Understand) dig into the commit their Read changes CVS4 (Concurrent Versioning System)to frequently. addEdits method and the methods of the same class it calls. After 30 minutes, Second, a sheet with five questions (one for each abstraction from Penningyou will be asked to answer a number of questions about this piece of code. ton’s model) was provided, and the students were given 15 minutes to answer the open questions in handwriting on draft paper, possibly using the source code. Participants were asked to write down a time stamp before reading a question, and after answering the question, providing us with the response time for each question. Participants were informed when they had five more minutes to continue on answering the questions. After fifteen minutes, the participants were asked to finish their questions, and the task sheets and corresponding answers were collected. The experimental replication differed with the original experiment what concerns the order in which the comprehension questions and the code fragments were presented to the participants (see Table 5.3). In the original experiment, the question and task order was identical for all participants. All participants 3 http://www.eclipse.org 4 http://www.nongnu.org/cvs/
Use the appointed comprehension technique (either Read to Understand or Refactor to Understand) to dig into the execute-method until after the large if-else-statement in which new subclasses of IResourceProxyVisitor are declared anonymously (line 162). After 20 minutes, you will be asked to answer a number of questions about this piece of code.
40 Task 3
CHAPTER 5. VALIDATING REFACTOR TO UNDERSTAND
Context Class in package contains a method Task
SurroundWithTryCatchRefactoring org.eclipse.jdt.internal.corext.refactoring.surround addEdits(TextChange, TextBuffer)
Use the appointed comprehension technique (either Read to Understand or Refactor to Understand) to dig into the addEdits method and the methods of the same class it calls. After 30 minutes, you will be asked to answer a number of questions about this piece of code.
Figure 5.4: Task sheet for task 3 first worked on the code fragment with no coupling, then on the moderately coupled code fragment, and finally on the highly coupled code fragment. Moreover, the order in which the questions was asked was also identical for all tasks, namely {function, control flow, operations, data flow, state}. In the experimental replication, both the order of the tasks and the questions was randomized. Table 5.3: Task order across experimental executions Experiment Original Replication
Participant Pair PP1–6 PP1 PP2 PP3 PP4
Task order NC – MC – HC MC – NC – HC MC – HC – NC HC – NC – MC NC – HC – MC
Representation of the order in which the code fragments were presented to the pairs of experimental participants. Each pair consisted of one participant from the Refactor to Understand group, and a matched participant from the Read to Understand group. NC signifies the code fragment with No Coupling. MC signifies the code fragment with Moderate Coupling. HC signifies the code fragment with High Coupling.
At the end of the experiment, a post-experiment questionnaire was filled in by all subjects (see Appendix A, Figures A.1 and A.2).
5.3.4
Experimental Tasks
The experiment consisted of three tasks. Each task required the comprehension of a given piece of code, after which the participants were asked to answer a set
5.3. EXPERIMENTAL SET-UP
41
of comprehension questions. At the beginning of each task, a task sheet was provided to the participants. These sheets are illustrated in Figures 5.2, 5.3 and 5.4 for respectively task 1 (NC), 2 (MC) and 3 (HC). The pieces of code which had to be comprehended across the three tasks were extracts from the Eclipse Platform (version 2.1.3), which is mostly known as an Integrated Development Environment for Java. More specific, the selected pieces of code originated from the org.eclipse.jdt.internal package, which contains a total of 721 classes over more than 140 thousands lines of code. To study the effect of Refactoring to Understand under different degrees of coupling, source code fragments were chosen to vary from no coupling in the first task, over moderate coupling in the second task, to high coupling in the last task. We set out to select code fragments which varied regarding coupling, yet were about similar w.r.t. other properties. As illustrated in Table 5.4, perfect similarity is unfeasible in practice. The table depicts the cumulated Lines of Code (LOC), Number of Methods (NOM), Number of Local Variables (NLV) and Cyclomatic Complexity (CC) values, which also vary but not to the extent as the coupling properties Message Passing Coupling (MPC) and Coupling Between Object Classes (CBO). Table 5.4: Properties of the code fragments Property Lines of Code Nr of Methods Nr of Local Variables Cyclomatic Complexity Message Passing Coupling Coupling Between Object classes
No Coupling 109 1 18 27 0 0
Moderate Coupling 102 1 24 5 42 10
High Coupling 76 4 38 14 61 30
Size, complexity and coupling properties of the code fragments used respectively in tasks 1 (no coupling), 2 (moderate coupling) and 3 (high coupling).
As can be read from the MPC and CBO values, the code fragment with no coupling (NC) was fully self-contained, and did not depend on other classes. The moderately coupled code fragment (MC) has about the same length, yet has a simpler control flow and collaborates with some other classes. Finally, the highly coupled code fragment (HC) implements its functionality by collaboration with many different classes.
42
CHAPTER 5. VALIDATING REFACTOR TO UNDERSTAND
5.3.5
Comprehension Questions
The set of questions for task 1, 2 and 3 are displayed in the Figures 5.5, 5.6 and 5.7 respectively. We note that it is generally infeasible to compose questions which involve only a single abstraction (e.g., knowledge on the control flow abstraction) without implicitly evaluating other abstractions (e.g., knowledge on the operations abstraction). Therefore, the resulting data will not be completely independent. I.e., if a participant would be unable to build up the program model representation (requiring the abstractions control flow and operations) then we would expect the situation model representation (requiring the abstractions function and data flow) to also be incomplete. Nonetheless, these implicit dependencies do not hinder in assessing each abstraction as present in the participants’ mental representation. In the first and third task, respectively for the non-coupled (NC) and the highly coupled code fragment (HC), the operation question provided in the replication differed from the operation question in the original experiment. In the first task, this difference is as follows: Original: Describe the characteristics of all the different input compositions which the scanner considers invalid. Replication: Describe the characteristics of all the different input compositions which the scanner considers valid. For the third task, the question in the replication was merely a part of the question of the original experiment: Original: Describe in your own words when and how the change parameter is modified in method addEdits. Replication: What is the meaning of the statement at line 207 in method addImportEdit: change.addTextEdit("", edit);. As a consequence, the data with regard to the operations question for NC and HC in the experimental replication cannot be compared with the data of the original experiment. Following, we describe our arguments for stating that a question primarily tests an abstraction. We restrict our discussion to those questions who differ from the generic form as presented in Table 5.1. For task 1, (the code fragment which exhibits no coupling), the questions regarding the program model differ slightly from their generic form:
5.3. EXPERIMENTAL SET-UP
[email protected]
SRe2LIC study
29/03/2004
43
Your name: __________________________ Questions: 1. Time when starting to read this question: _____ h ____m ____s [Function] Describe in your own words what functionality is implemented in the while loop. Time when finished answering this question: _____ h ____m ____s 2. Time when starting to read this question: _____ h ____m ____s [Control Flow] Draw a state chart illustrating the execution of the while-loop of method createMethodPattern in class SearchPattern. ! Draw a node for each state. Use the names of the states as written in the code itself. Differentiate between initial and final states. ! Draw a directed labelled edge (arrow with label X) between states when the scanner shifts from the source-state to the target-state at event X. Use the following schematic notation:
NameOfInitialState Character X NameOfNextState1
Character Y NameOfNextState2
Character Z FinalState1
FinalState2
Time when finished answering this question: _____ h ____m ____s 3. Time when starting to read this question: _____ h ____m ____s [Operations] Describe the characteristics of all the different input compositions which the scanner considers invalid. Time when finished answering this question: _____ h ____m ____s 4. Time when starting to read this question: _____ h ____m ____s [Data Flow] Describe briefly when the value of variable parameterTypes is updated. Time when finished answering this question: _____ h ____m ____s 5. Time when starting to read this question: _____ h ____m ____s [State] In the first case-branch of the first switch-statement you will find the statement declaringType += tokenSource + selector; Describe briefly the value of variable declaringType after this statement. Time when finished answering this question: _____ h ____m ____s
Figure 5.5: Comprehension questions for task 1
44
CHAPTER 5. VALIDATING REFACTOR TO UNDERSTAND
Your name: _________________________________________ Questions: 1. Time when starting to read this question: ___ h ___ m ___ s [Operations] Describe the need for the final variable OK, which is declared at the beginning of the try-block in the execute method. Time when finished answering this question: ___ h ___ m ___ s 2. Time when starting to read this question: ___ h ___ m ___ s [Control Flow] Write a pseudo-code summary of how the execute method performs its core functionality. Do not simply refer to syntactical operations, but describe specific semantics. Use the following pseudo-code convention: Write shoppingList Drive to shoppingMarket Take shoppingCart ForEach item in shoppingList If itemInReduction Add 2 of item to shoppingCart ElseIf itemNotSoldOut Add 1 of item to shoppingCart Mark item as bought Pay items bought …
Time when finished answering this question: ___ h ___ m ___ s 3. Time when starting to read this question: ___ h ___ m ___ s [State] The condition of the if-else statement is “if (max == 0)”. Describe briefly the value of variable max when it is evaluated in this condition. Time when finished answering this question: ___ h ___ m ___ s 4. Time when starting to read this question: ___ h ___ m ___ s [Function] Describe in your own words the functionality implemented in the if-else statement. Time when finished answering this question: ___ h ___ m ___ s 5. Time when starting to read this question: ___ h ___ m ___ s [Data Flow] Describe briefly when the variable “indexedFileNames“ of type SimpleLookupTable is updated. Time when finished answering this question: ___ h ___ m ___ s
Figure 5.6: Comprehension questions for task 2
5.3. EXPERIMENTAL SET-UP
45
Your name: _________________________________________ Questions: 1. Time when starting to read this question: ___ h ___ m ___ s [Data Flow] Describe in your own words what is added to/removed from variable handleDeclarationStatements of type List in method addEdits, and how it contributes to the overall functionality. Time when finished answering this question: ___ h ___ m ___ s 2. Time when starting to read this question: ___ h ___ m ___ s [Function] Describe in your own words the functionality implemented in the addEdits method. Time when finished answering this question: ___ h ___ m ___ s 3. Time when starting to read this question: ___ h ___ m ___ s [Operations] What is the meaning of the statement at line 207 in method addImportEdit: change.addTextEdit(“”, edit);. Time when finished answering this question: ___ h ___ m ___ s 4. Time when starting to read this question: ___ h ___ m ___ s [Control Flow] Write a pseudo-code summary of how the addEdits method performs its functionality. Do not simply refer to syntactical operations, but describe specific semantics. Use the following pseudo-code convention: Write shoppingList Drive to shoppingMarket Take shoppingCart ForEach item in shoppingList If itemInReduction Add 2 of item to shoppingCart ElseIf itemNotSoldOut Add 1 of item to shoppingCart Mark item as bought Pay items bought …
Time when finished answering this question: ___ h ___ m ___ s 5. Time when starting to read this question: ___ h ___ m ___ s [State] Describe accurately the composition of the value of variable codeBlock when it is used in the last statement of method addEdits. This variable of type CompositeCodeBlock is declared after the for-loop (line 195). Time when finished answering this question: ___ h ___ m ___ s
Figure 5.7: Comprehension questions for task 3
46
CHAPTER 5. VALIDATING REFACTOR TO UNDERSTAND • Control Flow – We asked the participant to illustrate the execution of a specified while loop. This while loop implemented a state machine, using a single switch statement (with 3 non-default cases), followed by the retrieval of a new value used in the switch variable. We therefore argued that the control flow (sequence of actions) described inside this while loop would be best represented using a state chart. State charts allow the participants to focus on the sequence of events by: (i) indicating the initial state; (ii) specifying which events can occur when; and finally (iii) indicating final states. Therefore, in this particular case, the description of the control flow and of the state (conditionalized actions) are identical. • Operations – We asked the participant to describe characteristics of input which lead to an (in)valid result at the end of the switch statement. This question differs from the general question in that it requires the interpretation of the semantics of more than only a single statement. Therefore, this question implicitly requires the presence of a control flow abstraction, describing the sequence of actions. However, our data indicated that, even in the case a participant did not understand the control flow, he was still able to understand the detailed actions, as asked for in the operations question.
Accordingly, we do not consider the deviations from program model questions for task 1 with their generic to be a threat to validity. In task 2, one question differs slightly from their generic form: • Operations– We asked the participant to explain the need for a specified variable. Since, after its initialization, this variable was only used at one line of code, this question is merely of a form to alternative the generic question. Summarizing, the questions used for all three tasks were either mere instantiations of the generic questions for an abstraction, or equivalent variations. We therefore consider these questions valid tests for assessing the participants’ mental representations.
5.4
Data Analysis
In this section, we analyze the data gathered in the experiment. First, we discuss how we processed the raw material provided by the experiment. Second, we discuss our observations on the application of the Refactor to Understand
5.4. DATA ANALYSIS
47
pattern. Thereafter, we discuss group differences with regard to our hypotheses concerning the accuracy and time of answers on program comprehension questions.
5.4.1
Analysis Procedure
The experiment provided us with three information sources for each of the three tasks. 1. Question sheets indicating the time stamps. 2. Answers to the five open questions. 3. For the participants of the Refactor to Understand group: different versions of the modified source code as recorded by the versioning system (CVS). 4. The post-experiment questionnaire. The handwritten time stamps were used to calculate response times in seconds. The answers to the five open questions were evaluated by the author using a fixed rating scheme. The fact that the author evaluated the answers himself is not considered a threat to validity, as the sheets did not indicate to which group the participant belonged. Therefore, no systematic differences could have been introduced during evaluation. The rating scheme, mentioned in section 5.1, was used to categorize answers. This categorization was based on a solution key, which indicated under what conditions an answer would fall into a category. Correct: Only answers which were flawless were categorized as correct. These answers were rated a score of 10. Almost Correct: In case the answer was missing minor details, or these minor details were wrong, the answer was categorized as almost correct. These answers were rated a score of 8. As an example, let us consider the question on data flow for the first task (see Figure 5.5). We consider the initialization or size adjustment as a minor detail in the updates to this array variable. In case the initialization or size adjustment were left out, or were wrong, the answer was categorized as almost correct. Assignments of values to the cells of this array, however, were not considered as minor details.
48
CHAPTER 5. VALIDATING REFACTOR TO UNDERSTAND
Right Idea: In case the answer was partly true, yet missing major details, or these major details were wrong, the answer was categorized as having the right idea, and accordingly, rated a score of 5. Let us illustrate this principle according to the same example. In case at least one assignment to the cells of the array was described correctly, the answer was categorized as exhibiting the right idea.
Wrong: In case an answer did not satisfy the criteria for the category right idea, the answer was categorized as wrong, and assigned a score of 0.
For the Refactor to Understand group participants, the adherence to the pattern was assessed by counting the number of refactorings applied.
5.4.2
Applications of Refactorings
Table 5.5 displays the number of refactorings applied by each of the subjects in the refactoring group. This data is relevant as it allows to characterize the specific treatment as applied by the members of the treatment group. For the tasks on the code fragments with no and moderate coupling, one subject did not apply any refactorings. However, searching for refactoring opportunities still steered their comprehension, and therefore, we still categorize them in the treatment group. Over the tasks, there was a difference in the applications of refactorings. The relative frequency of applications of the refactorings Rename variable/method was respectively 17% for the code with no coupling; 32% for the moderately coupled code; and 63% for the highly coupled code. A potential explanation of these frequency differences is that in code fragments that contain more local variables or use more different classes, there are more opportunities to apply the Rename variable/method refactoring. Table 5.5 indicates that the Refactor to Understand pattern was indeed applied. However, it was not applied extensively, as can be observed from the limited number of refactorings. Therefore, it is reasonable to assume that more extensive application of this reverse engineering pattern will lead to more extreme group differences.
5.4. DATA ANALYSIS
49
Table 5.5: Application of refactorings Coupling
No Coupling
Moderate Coupling
High Coupling
a
ida s1 s2 s3 s4 s5 s6 avg s1 s2 s3 s4 s5 s6 avg s1 s2 s3 s4 s5 s6 avg
#Rename 0 1 0 0 1 0 0.33 0 5 0 0 1 1 1.17 4 1 0 2 1 3 1.83
#Extract Method 2 1 0 1 2 2 1.33 0 1 4 2 3 1 1.83 1 0 2 0 3 0 1
Signifies the identification number of the participant, of which the table represents the number of applications of the Rename variable/method and Extract Method refactorings.
50
CHAPTER 5. VALIDATING REFACTOR TO UNDERSTAND
5.4.3
H0,accuracy – Differences in response accuracy Table 5.6: Comparison of the response accuracy between groups
Control Flow Operations
Function
Data Flow
State a
Repa O R O∪R O R O∪R O R O∪R O R O∪R O R O∪R
No Coupling 4.7 < 5.5, p=.8184 5.8 = 5.8, p=N/A 5.1 < 5.6, p=.8283 6.5 > 4.7, p=.2551 5.3 < 8.3, p=.9880 not allowed 7.7 > 6.3, p=.2598 7.8 > 7.0, p=.3618 7.7 > 6.6, p=.2132 4.7 < 5.8, p=.8898 3.8 < 5.0, p=.6412 4.3 < 5.5, p=.8198 5.0 < 6.3, p=.7887 1.3 < 3.3, p=.7328 3.3 < 4.8, p=.8478
Moderate Coupling 6.2 > 5.2, p=.6686 6.3 > 2.5, p=.0288 6.2 > 4.1, p=.0842 6.0 > 2.5, p=.1261 8.8 > 3.8, p=.0459 7.1 > 3.0, p=.0218 6.7 > 4.7, p=.2314 5.8 > 3.3, p=.1392 6.3 > 4.1, p=.1026 3.3 > 1.7, p=.6291 3.3 > 1.7, p=.2837 3.3 > 1.7, p=.2255 6.7 = 6.7, p=.6291 9.0 > 5.8, p=.0761 7.6 > 6.1, p=.1151
High Coupling 6.8 > 4.0, p=.0878 9.0 > 7.5, p=.0908 7.7 > 5.4, p=.0337 6.3 < 6.8, p=.5778 6.0 > 3.3, p=.1206 not allowed 8.5 > 4.7, p=.0560 6.3 > 3.8, p=.1955 7.6 > 4.3, p=.0266 5.5 > 4.7, p=.2484 8.3 > 7.5, p=.3765 6.6 > 5.8, p=.2288 9.0 > 6.4, p=.1418 8.0 > 7.7, p=.2500 8.8 > 6.9, p=.1879
Rep signifies the experimental replication. O stands for Original experiment, R stands for Replication experiment and O ∪ U stands for the unification of the data from the original experiment and it’s replication. Each cell in the table is specified as X • Y , p=Z in which X and Y represent the average accuracy of the participants of respectively the Refactor to Understand or Read to Understand group. The • symbol represents the order between these averages, which can be either of {}. Z signifies the statistical significance of a one-sided paired Student t-test between these two groups, telling us the probability of a group difference as extreme as the one indicated in case the null hypothesis is true. This null hypothesis states that the Refactor to Understand group does not respond more accurate than the Read to Understand group.
Table 5.6 depicts the average response accuracy for both groups, in the format Refactor to Understand group • Read to Understand group. The • symbol represents the order between these group averages, and can be either of {}. The p-value for the associated one-sided paired Student t-test is also provided. This test is typically used to verify the probability that two data sets originate from the same population. A paired t-test means that in
5.4. DATA ANALYSIS
51
comparing these two data sets, each element is uniquely paired with another one from the other set. Finally, a one-sided t-test means that our null hypothesis is directional, since we try to refute that the Refactor to Understand group responds less then or equally accurate as the Read to Understand group. For each abstraction, the table shows the averages for the original experiment (Rep = O), the experimental replication (Rep = R) and overall (Rep = O ∪ R). We will discuss the observed differences for each of the levels of coupling separately: No coupling – The Refactor to Understand group answered less accurately for all but the questions on function and operations abstractions. With regard to function accuracy, the Refactor to Understand group outperformed the Read to Understand group. We remark that the operations questions on the moderately and highly coupled code fragment differed from the question of the original experiment. We can observe that changing these questions had a considerable effect on the results. Therefore, we remain inconclusive about the group differences on operations accuracy with regard to these code fragments. Moderate coupling – The Refactor to Understand group responded more accurate on the questions on all abstractions. Significant group differences were noted w.r.t. both abstractions of the program model (control flow, p=.0842; operations, p=.0218). The group differences w.r.t. the function (p=.1026) and state (p=.1151) abstractions were close to being significant. High coupling – For all abstractions except the operations abstractions, the response accuracy of the Refactor to Understand group was higher. This group difference was significant for the control flow (p=.0337) and function (p=.0266) abstraction questions. Our results w.r.t. responses on the operations question were contradicting between the original experiment and the replication. As in the case of the code fragment with no coupling, we cannot compare these results as the operations question was altered in the experimental replication. We therefore remain inconclusive what concerns the group differences w.r.t. the operations abstraction.
52
CHAPTER 5. VALIDATING REFACTOR TO UNDERSTAND
Table 5.7: Data loss w.r.t. accuracy observations
Data Flow
State
Rep O R O∪R O R O∪R
No Coupling
1–2
Moderate Coupling 0–3 0–1 0–4 0–3
1–2
0–3
High Coupling
0–1 2–1 2–2
Represents the number of observations missing from the data set, reported in the format Refactor to Understand – Read to Understand.
Table 5.7 discusses the data loss w.r.t. accuracy observations. This data loss is due to two reasons: (i) the questions were asked in a fixed order, with data flow and state questions being the two last questions; and (ii) due to time restrictions on the experimental session, we were forced to limit the amount of time available for answering the questions. We will discuss the threat to validity associated with this loss in the Threats to Validity section 5.6. Table 5.8: Rejection of H0,accuracy,X,Y No Coupling Control Flow Operations Function Data Flow State
Moderate Coupling R R AR
High Coupling R R
AR
Represents the rejection of the null hypotheses H0,accuracy,X,Y , in which X stands for an abstraction present in the mental representation and Y stands for a degree of coupling for which this rejection was demonstrated. R stands for Rejected (p < .10), and AR stands for Almost Rejected (.10 < p < .12).
Summarizing, Table 5.8 illustrates the rejection of null hypotheses as supported by our observations. This means that abstractions of both the program
5.4. DATA ANALYSIS
53
and situation model have been shown to be more accurate for the Refactor to Understand group in the task on the moderately and highly coupled code fragment.
5.4.4
H0,time – Differences in response time
We will discuss the observations with regard to the time required for participants to respond to the comprehension questions in the same manner as we did for accuracy. Group differences regarding the time for answering program comprehension questions are reported in Table 5.9. No coupling – The Refactor to Understand group answered the questions slower for all but the questions on operations and state abstractions. With regard to the time required to answer the state question, the observations from the replication contradicted with those from the original experiment. However, the group difference in the replication was merely 20 seconds, which can be safely neglected. We note that the contradicting group differences between the original experiment and its replication which were previously observed for response accuracy w.r.t. the operations question were also observed for response time. This was due to altering the question. Moderate coupling – The response times of both groups were similar on all but the control flow and data flow questions. For the control flow abstraction, the group differences as observed in the original experiment contradicted with those observed in its replication. However, the group difference in the original experiment was merely 40 seconds on a total response time of 6.5 minutes. Due to this marginal difference, this contradiction can be neglected. With regard to the data flow question, the Refactor to Understand group responded significantly faster than the Read to Understand group (p=.0621). High coupling – The Refactor to Understand group responded faster to the question on control flow and slower on the question on state. For function and data flow abstractions, the observations from the experimental replication contradicted these of the original experiment. These contradictions cannot be neglected. However, we have found no systematic differences between the original experiment and its replication which might explain these contradictions.
54
CHAPTER 5. VALIDATING REFACTOR TO UNDERSTAND
Table 5.9: Comparison of the response time between groups Repa O R O∪R O R O∪R O R O∪R O R O∪R O R O∪R
Control Flow Operations
Function
Data Flow
State
No Coupling 402 > 362, p=.7042 417 > 377, p=.6860 408 > 368 p=.7840 236 > 205, p=.6655 196 < 235, p=.2507 not allowed 172 > 168, p=.5383 122 > 99, p=.6054 152 > 141, p=.6202 132 > 111, p=.8779 177 > 148, p=.6373 150 > 126, p=.7868 165 < 216, p=.3031 173 > 152, p=.6838 168 < 184, p=.2054
Moderate Coupling 366 < 409, p=.3066 518 > 417, p=.7001 427 > 412, p=.5690 113 = 113, p=.5036 180 < 207, p=.3310 140 < 150, p=.3620 182 < 190, p=.4587 178 > 171, p=.5320 180 < 182, p=.4857 81 < 101, p=.2443 63 < 128, p=.1229 75 < 114, p=.0621 76 < 79, p=.4459 96 > 83, p=.5610 84 > 81, p=.5331
High Coupling 322 > 321, p=.5047 389 < 412, p=.1861 349 < 357 p=.4415 128 < 165, p=.2171 206 < 160, p=.6639 not allowed 109 < 201, p=.0908 240 > 74, p=.9900 161 < 150, p=.5750 123 < 151, p=.1118 309 > 257, p=.6555 198 > 194, p=.5332 200 >158, p=.9742 135 > 124, p=.5882 184 > 145, p=.9137
Table 5.10: Data loss w.r.t. time observations
Data Flow
State
Rep O R O∪R O R O∪R
No Coupling
1–2
Moderate Coupling 0–3 1–1 1–4 0–3
1–2
0–3
High Coupling
0–1 2–1 2–2
Represents the number of observations missing from the data set, reported in the format Refactor to Understand – Read to Understand.
The data loss w.r.t. response time observations was very similar to that of accuracy observations. In fact, there was only a single additional loss, due to a participant who did not write down a time stamp in the experimental replication
5.4. DATA ANALYSIS
55
after responding a data flow question. Again, we refer to the Threats to Validity section 5.6 for a discussion on the associated threats to validity. Summarizing, Table 5.11 illustrates the rejection of null hypotheses w.r.t. time as supported by our observations. The table indicates that a single abstraction of the situation model has been shown to be more directly available for the Refactor to Understand group in the task, yet this has been observed only for the moderately coupled code fragment. Table 5.11: Rejection of H0,time,X,Y No Coupling Control Flow Operations Function Data Flow State
Moderate Coupling
High Coupling
R
Represents the rejection of the null hypotheses H0,time,X,Y , in which X stands for an abstraction present in the mental representation and Y stands for a degree of coupling for which this rejection was demonstrated. R stands for Rejected (p < .10).
5.4.5
Post-experiment questionnaire
After the experiment, a questionnaire was handed out, which was an adaptation from [Briand et al., 2001]. Closed questions were asked about motivation, adherence to guidelines, understanding of requirements, approach to answering the questions, accuracy estimation, reasons for not completing, code quality estimate and perceived difficulty of questions on the three tasks. The questionnaire is illustrated in Appendix A in Figures A.1 and A.2. We observed no problems with motivation nor clarity of questions, nor with the subjectively evaluated comprehensibility of the code. On a scale from 1 (barely comprehensible) to 10 (easily comprehensible), the quality of the code was rated an average of 7.1 by the Refactor to Understand group and 6.3 for the Read to Understand group. This difference was not significant. There was a noteable difference regarding the difficulty of the tasks. The questions on the code fragment with no coupling were considered more difficult
56
CHAPTER 5. VALIDATING REFACTOR TO UNDERSTAND
than those on the moderately coupled fragment (p=0.0609), which on their turn were found more difficult than the questions on the highly coupled code fragment (p=0.1412). This difference w.r.t. subjectively evaluated difficulty might explain why the comprehension accuracy on the highly coupled code fragments is highest for both groups.
5.5
Interpretation of Results
To discuss the results of this exploratory experiment, we describe our findings for the two factors under study: (i) the comprehension techniques Read to Understand and Refactor to Understand; and (ii) the degree of coupling of the code fragments to be understood.
5.5.1
Comprehension Technique as a Factor
In this experiment, we verified whether the reverse engineering pattern Refactor to Understand can help improve program comprehension. In two out of three experimental tasks, the Refactor to Understand group demonstrated significantly higher accuracy w.r.t. abstractions for both the program and the situation model. We interpret these results as a confirmation that the application of Refactor to Understand did indeed support the construction of the two mental model representations relevant for bottom-up comprehension. Since we did not observe that the significantly higher abstraction accuracy also led to faster response times, we cannot claim that these mental model representations are more readily available. Table 5.12 depicts the average comprehension accuracy over the three tasks. Since the operations question was altered in the replication, we leave this abstraction out. As can be read from the table, the overall largest group differences were observed regarding function and control flow, being the main abstractions of the respectively the situation and the program model. Differences on state comprehension were smaller, and non-existing w.r.t. data flow. Thus, on average, the Refactor to Understand group outperformed the Read to Understand group. Summarizing, our results support the hypothesis that Refactoring to Understand supports bottom-up comprehension. Concretely, two out of three experimental tasks demonstrated higher accuracy of the two main mental model representations.
5.5. INTERPRETATION OF RESULTS
57
Table 5.12: Average comprehension accuracy
Control Flow Function Data Flow State
Refactor to Understand 6.3 7.2 4.7 6.5
> > = >
Read to Understand 5.0 5.0 4.7 5.9
This table represents the average comprehension accuracy between groups across the three tasks. We thereby discuss the main effect of the factor Program comprehension technique.
5.5.2
Degree of Coupling as a Factor
We introduced the degree of coupling factor to test the comprehension techniques under the assumption that the highly coupled code fragment would be more difficult to comprehend. However, the results from our post-experiment questionnaire clearly indicate the opposite, namely that the participants found the task on the non-coupled code fragment more difficult than that of the moderately coupled fragment, which on its turn was found more difficult than the highly coupled code fragment. This difference in perceived difficulty might be partially explained by the cyclomatic complexity, which is highest for the non-coupled code fragment. Moreover, the code size of the highly coupled code fragment was about one fifth smaller than the size of the moderately coupled fragment. Nonetheless, this would lead to the interpretation that the Refactor to Understand pattern did not significantly support the mental representations for the task which was perceived as most difficult. However, in both the original experiment and its replication, we consistently observed higher accuracy with regard to the function abstraction for the Refactor to Understand group, which is essential for the situation model. While this group difference was not significant (p=.2132), the fact that this difference was observed for the situation model is remarkable. The reason for this is that the situation model is generally considered to be a mental representation which is constructed only after the program model representation. It is therefore unclear whether the Refactor to Understand program provided no support whatsoever for bottom-up comprehension in the task which was perceived as most difficult. The assumption that the effect of Refactor to Understand is dependent on
58
CHAPTER 5. VALIDATING REFACTOR TO UNDERSTAND
the degree of coupling is supported in two ways: (i) the usage of refactorings varied over the degrees of coupling; and (ii) the effect of Refactor to Understand differed over the degrees of coupling. The degree of coupling affects the application of Refactor to Understand in the relative usage of refactorings. To comprehend the non-coupled code fragment, mostly Extract Method was applied, while for the highly coupled code fragment, mostly renames were applied (see Table 5.5). When comparing the properties of the code fragments (see Table 5.4), an intuitive explanation would be that the highly coupled fragment contained more opportunities to rename variables and methods. This difference in properties can itself be explained by the difference in degree of coupling, as a highly coupled implementation would rely on the collaboration of many instances, which would be reflected in more local variables, and therefore, in more rename opportunities. Between the code fragments, a variation in the group differences was observed. The application of Refactor to Understand led to more accurate program and situation models for both the moderately and highly coupled code. This was not the case for the code fragment with no coupling. While this might suggest an interaction between the program comprehension technique factor and the degree of coupling factor, this has still to be confirmed in further experiments.
5.6
Threats to Validity
This work was set up as an exploratory experiment. Therefore, there are severe limitations to generalizability of its results. Moreover, practical restrictions did not permit the ideal set-up. For clarity, we specify the main threats to validity.
5.6.1
Internal Validity
Internal validity is the degree to which the experimental setup allows to accurately attribute an observation to a specific cause rather than to alternative causes. Specific set-up deficiencies make it difficult to infer clear conclusions. The threats we have identified are: • Maturation effects can occur due to processes within subjects which change as time passes. In the original experiment, the question and task order posed a threat to learning and fatigue effects. Therefore, the question and task order was randomized in the experimental replication. As the observations of the replication confirmed these of the original experiment, we can state that the task order did form a threat to validity.
5.6. THREATS TO VALIDITY
59
• Attrition refers to the fact that participants in an experiment sometimes fail to complete the outcome measures [Shadish et al., 2002]. As the time during which questions could be answered was limited, some participants were unable to answer the last questions. Moreover, in the original experiment, the order of the questions was identical across the three tasks. Accordingly, the missing data were all observations on data flow and state comprehension. Consequently, it is possible that our inability to detect significant group differences regarding data flow and state comprehension is due to this data loss. E.g., even when merely 6 paired observations could be used to evaluate group differences w.r.t. the accuracy of the data flow abstraction in the moderately coupled code fragment, the p-value was almost significant (p=.1151). Moreover, the group difference w.r.t. response time on this abstraction for the same code fragment was statistically significant. These observations indicate the likelihood that at least H0,accuracy,dataf low,M C might also have been rejected in case the data loss did not occur. • An instrumentation effect can occur when any instrument used varied over the experimental tasks. We paid attention to find code fragments which are as similar as possible while varying in degree of coupling. The comprehension tasks were identical, and the open questions for each comprehension category were based on templates. However, even while applying all these precautions, we could observe in the results of the post-experiment questionnaire that there was a significant group difference regarding subjective evaluation of the difficulty of the tasks. More specifically, the tasks on the highly coupled fragment were found significantly easier, and those on the fragment with no coupling were found significantly harder. As we are unable to prove that this difference in subjective difficulty of the tasks was due to the degree of coupling, we are inconclusive about the extent of this threat. A clear instrumentation effect is present for the operations question, which was changed in the experimental replications for the tasks on the noncoupled and highly coupled code fragment. Accordingly, we have left out the operations question in the discussion of results.
5.6.2
External Validity
External validity is the degree to which research results can be generalized outside the experimental setting or population under study. As an exploratory
60
CHAPTER 5. VALIDATING REFACTOR TO UNDERSTAND
study, this work was designed more towards investigating interesting phenomena than to be generalizable. • As we are unaware of any studies on the distribution of coupling measures across software systems, we are unable to make a hard claim that our code fragments are representative w.r.t. the degree of coupling. Nonetheless, the coupling measures for our code fragments clearly present different orders of magnitude. E.g., the number of classes used was 0, 10 and 30 in respectively the non-coupled, moderately and highly coupled fragment. Our code fragments were clearly not representative w.r.t. the size of whole software systems. However, one has to take into account that the bottomup comprehension process is merely triggered in case code appears to be directly relevant [Koenemann and Robertson, 1991]. Therefore, we should evaluate whether the size of these code fragments is representative by comparing them against programs used in experiments w.r.t. bottomup comprehension. E.g., Pennington herself used program segments of exactly 15 lines of code [Pennington, 1987b]. [Ramalingam and Wiedenbeck, 1997] used identical programs as [Corritore and Wiedenbeck, 1991], which count about 30 lines of code. The program used by [Fix et al., 1993] was somewhat larger and counted 135 lines of code. We therefore argue that our code fragments were representative w.r.t. the size of programs used in these kinds of experimental settings. However, we make no claims w.r.t. the generalizability of our results to applications of the Refactor to Understand pattern on much larger code fragments. • Our participants were last year computer science students. The experiment took place in the second semester, in an optional course on Object Oriented Reengineering. It is likely that these students are not representative for the population of last year computer science students, as their choice for this course might be an indicator of special interests and earlier expertise. Neither can we generalize our conclusions to the population of professional software engineers. Surely, there is little difference between these students and junior software engineers. However, more experienced software engineers have been shown to apply different comprehension processes (e.g., as described by [Pennington, 1987b, Fix et al., 1993, Canfora et al., 1996]). It is therefore unclear whether such clear group differences as observed using our student participants would also be present when using professional programmers.
5.7. CONCLUSION
5.7
61
Conclusion
These findings provide the first empirical support for the general claim that the process of refactoring can improve the understanding of software systems [Fowler, 1999], illustrated in higher accuracy of both the program and the situation model as mental representations of the source code. We have found some indications that the Refactor to Understand pattern might be most effective in code fragments which exhibit some degree of coupling, yet remain inconclusive on this subject. Significant differences were observed w.r.t. control flow and function abstractions. These abstractions are required for constructing the two mental model representations which have been shown to be essential for complete comprehension [Pennington, 1987a]: • The program model, stressing knowledge on the text structure, is improved through significantly higher accuracy of control flow knowledge; • The situation model, stressing knowledge on goals in the problem domain, is improved through significantly higher accuracy of function knowledge. Therefore, these results confirm that the introduction of beacons – recognition points that index into knowledge – and chunks – higher level abstractions of lower level structures – through renaming program elements and extracting methods supports the creation of mental abstractions relevant in the context of bottom-up comprehension.
62
CHAPTER 5. VALIDATING REFACTOR TO UNDERSTAND
Chapter 6
The Split Up God Class Pattern In this chapter, we present a reengineering pattern addressing class decomposition. While the improvement of comprehensibility is not the main objective of this reengineering pattern, it is one of the claimed benefits. This claim will be validated in the next chapter.
6.1
Introduction
The Split Up God Class reengineering pattern was introduced in [Demeyer et al., 2002]. This pattern addresses the god class anti-pattern [Riel, 1996,Brown et al., 1998], which grows naturally in evolving systems. A high rate of source code adaptations tends to introduce design flaws such as misplaced responsibilities. Ultimately, some classes take the form of black holes, accumulating and attracting ever more responsibilities. These god classes are considered to be the main targets for reorganization, and the preferred approach to resolve them is to extract data classes, and move associated behavior to them [Demeyer et al., 2002]. In other words, the Split Up God Class pattern is an encapsulation technique. The object-oriented paradigm introduced the encapsulation of related procedures and data into conceptual groupings called object classes. These encapsulations provide abstraction structures that are expected to support the construction of a mental model. God classes are incohesive groupings of unrelated data and behaviour, thereby making it harder for the maintainer to 63
64
CHAPTER 6. THE SPLIT UP GOD CLASS PATTERN
reconstruct abstractions in his mental model. Split Up God Class introduces two kinds of abstractions. At the system level, one can identify controllers that exhibit more methods and less data, and entities, exhibiting more data and less methods [Jacobson et al., 1992]. This distinction is promoted in design patterns such as the Entity-Boundary-Controller pattern [Jacobson et al., 1992], the Model-View-Controller pattern [Krasner and Pope, 1988], the Presentation-Abstraction-Controller pattern [Buschmann et al., 1996] and the Use-Case controller pattern [Larman, 2001]. Split Up God Class disentangles a set of responsibilities and data into controllers and entities, and extracts classes accordingly. By splitting up a god class in controllers and entities, abstractions are introduced, which are expected to make it easier for the maintainer to construct a mental model.
6.2
Pattern Description
The following stepwise description of the Split Up God Class pattern is quoted from [Demeyer et al., 2002]: “The solution relies on incrementally moving behavior away from the god class. During this process, data containers will become more objectlike by acquiring the functionality that the god class was performing on their data. Some new classes will also be extracted from the god class.” Transforming a god class is not a single step operation. A suggested procedure is to: 1. transform the god class into a light-weight god class 2. transform the light-weight god class into a facade that delegates behavior to its acquaintances 3. direct clients to the refactored data containers and the new objects 4. remove the facade Each of these steps consists themselves of a number of operations. In the remainder of this section, we will elaborate on their peculiarities.
6.2. PATTERN DESCRIPTION
65
Transform the god class into a light-weight god class. A light-weight god class is one in which the attributes are extracted to data containers, which are themselves responsible for the initialization and hiding of the data. After this transformation, most of the attributes of the god class will be replaced by instances of the extracted data containers. Transform the light-weight god class into a facade that delegates behavior to its acquaintances. This step is performed by identifying those (portions of) god class methods which interact intensively with a data container. As these methods provide a service on top of the data container, moving them to the associated data container encapsulates the associated business logic. Doing so, the data containers are promoted to collaborators of equal value. In order to shield clients from these changes, the move operation should leave behind a delegator method. After iteratively moving behavior to the data containers, the god class will consist of delegator methods and an (or possibly multiple) initialization method. At this stage, we have two possibilities: (i) the initialization represents the preparation of a semantical relationship between the encapsulated god class data; (ii) there is no real semantical relationship between the encapsulated objects. An example of a semantical relationship can be found in case the data container can only exist in the context of the god class. In case there is no real semantical relationship, the data containers are useful in isolation, and therefore, the initialization method can most likely be divided to form the future constructor methods of the former data containers. In contrast, when there is a semantical relationship being prepared in the initialization method, than the god class can be regarded as a Builder [Gamma et al., 1994] (or, since it contains the data, an Object Mother [Schuh and Punk, 2001]). Direct clients to the refactored data containers and the new objects. Clients might shortcut the indirection of using the facade. However, while each delegator method does not implement any responsibilities itself, it does determine the runtime instance onto which the service will be requested. In other words, the delegator method indirectly changes the state of an attribute of the god class. A precondition to bypassing the delegator method is that there is only a single client manipulating the god class attribute via the delegator method. Multiple clients would cause consecutive state changes of the same attribute of the god class. In that case, the attribute cannot be moved to a client. This description stresses the iterative and incremental nature of splitting a
66
CHAPTER 6. THE SPLIT UP GOD CLASS PATTERN
god class. One of the benefits of this chain of transformations is that improvements with regard to program comprehension are not postponed until the last step. E.g. the extraction of data containers immediately introduces abstractions. Moreover, one might assume that the consequential identification of the methods interacting with these abstractions makes it easier to recognize the responsibilities associated with these abstractions. In other words, this pattern should not be regarded as a single fix, but rather as a roadmap.
6.3
Illustrative Scenario
Consider the problem domain in which the following procedure for filtering incoming mails into appropriate mailboxes applies: 1. Collect the mailheaders of all mails awaiting filtering. 2. Collect the filters to be applied. 3. Apply each filter on all mails awaiting filtering. (a) Evaluate the headerfield-values of the current mail. (b) Move the mail to the target mailbox in case of a match. 4. Move unfiltered mails to the inbox. A common class decomposition for fulfilling the filtering procedure is: Decomposition A – The software design consists of a single class. This god class governs the flow of control and manages the internal representation of domain entities. This decomposition is illustrated in Figure 6.1. The responsibilities of the god class can be incrementally redistributed either to collaborating classes – if present – or to new classes that are pulled out of the god class. To ensure behavioral equivalence of the resulting class decompositions, the transformations applied are refactorings [Fowler, 1999]. Decomposition B – Two filter classes are extracted from the god class: one for filtering according to the equality of a header field with a given string, and one according to the mere presence of a string in a header field. This extraction of two controller classes is done using the refactoring Replace Method with Method Object on the two filtering methods from the original god class (step 3). This decomposition is illustrated in Figure 6.2.
6.3. ILLUSTRATIVE SCENARIO
67
IncomingMsgFilter -fChangedMailboxNames : LinkedList -fMailsToBeFiltered : Vector -sIncomingMsgsMailbox : String -sFiltersFile : String -fHeaderFieldName : String -fFilterComparationOperator : String -fForbiddenString : String -fTargetBoxDirectory : String -fMailsMsgsHeaderParser : MessageHeaderParser
Figure 6.1: Decomposition A Decomposition C – The vector in which the mail header field values are stored (step 1) is extracted and encapsulated in a mail header entity class. Using different terminology, this class would be categorized as an entity, model, or abstraction class. The transformation used is similar to the Introduce Parameter Object refactoring. This decomposition is illustrated in Figure 6.3. A benefit of factoring out controllers is that they deal with fewer issues. A benefit of factoring out entities is that these provide a clear and encapsulated representation of a domain entity. The refactoring scenario from decomposition A to C would be considered an adequate disentangling of the initial god class. Nonetheless, to anticipate future needs of reusability and flexibility, the extraction of controller and entity classes might continue. Decomposition D – The action which is to be applied by a filter (step 3b) is extracted in a filter action class. This delegation to a new controller class requires the application of the Extract Method and Replace Method with Method Object refactorings. This decomposition is illustrated in Figure 6.4. Decomposition E – The representation of a mail header field as consisting of a key and value pair (step 3a) is extracted and encapsulated in a header field class. Once again, the extraction of this entity class is done using a refactoring similar to Introduce Parameter Object. This decomposition is illustrated in Figure 6.5.
68
CHAPTER 6. THE SPLIT UP GOD CLASS PATTERN
IncomingMsgFilterController -sIncomingMsgsMailbox : String -sFiltersFile : String -fTargetBoxDirectory : String -fMailsToBeFiltered : Vector -fMailsMsgsHeaderParser : MessageHeaderParser -fHeaderFieldName : String -fForbiddenString : String -fFilterComparationOperator : String -fChangedMailboxNames : LinkedList EqualityFilter -fHeaderFieldName : String -fForbiddenString : String -fTargetMailbox : String
ContainedStringFilter -fTargetMailbox : String -fHeaderFieldName : String -fForbiddenString : String
Figure 6.2: Decomposition B The newly introduced controller and entity classes in respectively decomposition D and E bear little responsibilities. Accordingly, their weight in the overall class hierarchy is very small. The transformations to decompositions D and E might be considered over-engineering. Yet, as over-engineering is not uncommon in practice (e.g., see [Fichman and Moses, 1999]), these refactoring steps are quite realistic. Because the god class decompositions were derived by applying behaviorpreserving refactorings, they only differ w.r.t. their internal organization.
6.3.1
Research questions
The Split Up God Class pattern stimulates encapsulation, thereby providing abstraction structures that are expected to support the construction of a mental representation. Therefore, we ask ourselves the following research questions: 1. Effectivity – Do some god class decompositions allow to achieve higher program comprehension accuracy than others? 2. Efficiency – Do some decompositions allow to achieve comprehension faster than others?
6.3. ILLUSTRATIVE SCENARIO
69
IncomingMsgFilterController -sIncomingMsgsMailbox : String -sFiltersFile : String -fTargetBoxDirectory : String -fMailsToBeFiltered : Vector -fMailsMsgsHeaderParser : MessageHeaderParser -fHeaderFieldName : String -fForbiddenString : String -fFilterComparationOperator : String -fChangedMailboxNames : LinkedList
EqualityFilter -fHeaderFieldName : String -fForbiddenString : String -fTargetMailbox : String
ContainedStringFilter -fTargetMailbox : String -fHeaderFieldName : String -fForbiddenString : String
MailHeader -fHeaderFieldsIndicationForCurrentMail : Vector
Figure 6.3: Decomposition C
70
CHAPTER 6. THE SPLIT UP GOD CLASS PATTERN
IncomingMsgFilterController -sIncomingMsgsMailbox : String -sFiltersFile : String -fTargetBoxDirectory : String -fMailsToBeFiltered : Vector -fMailsMsgsHeaderParser : MessageHeaderParser -fHeaderFieldName : String -fForbiddenString : String -fFilterComparationOperator : String -fChangedMailboxNames : LinkedList EqualityFilter
ContainedStringFilter
-fHeaderFieldName : String -fForbiddenString : String -fFilterAction : MoveMailFilterAction -fCurrentMailIndex : int
-fHeaderFieldName : String -fForbiddenString : String -fFilterAction : MoveMailFilterAction -fCurrentMailIndex : int
1
1 MailHeader -fHeaderFieldsIndicationForCurrentMail : Vector
1
MoveMailFilterAction -fTargetMailbox : String -fIsApplied : boolean
1
Figure 6.4: Decomposition D
6.3. ILLUSTRATIVE SCENARIO
71
IncomingMsgFilterController -sIncomingMsgsMailbox : String -sFiltersFile : String -fTargetBoxDirectory : String -fMailsToBeFiltered : Vector -fMailsMsgsHeaderParser : MessageHeaderParser -fHeaderFieldFilterPair : HeaderFieldNameAndValuePair -fFilterComparationOperator : String -fChangedMailboxNames : LinkedList
EqualityFilter
ContainedStringFilter
-fHeaderFieldFilterPair : HeaderFieldNameAndValuePair -fFilterAction : MoveMailFilterAction -fCurrentMailIndex : int 1
1
-fHeaderFieldFilterPair : HeaderFieldNameAndValuePair -fFilterAction : MoveMailFilterAction -fCurrentMailIndex : int
1
1 MailHeader -fHeaderFieldsIndicationForCurrentMail : Vector
1
HeaderFieldNameAndValuePair -fHeaderFieldName : String -fValue : String
1
MoveMailFilterAction
1 1 1
-fTargetMailbox : String -fIsApplied : boolean
Figure 6.5: Decomposition E
1
72
CHAPTER 6. THE SPLIT UP GOD CLASS PATTERN
Chapter 7
Validating Split Up God Class This chapter is based on a previously published paper [Du Bois et al., 2006]. In this chapter, we present the results of three controlled experiment replications with the aim to contribute to the validation of the Split Up God Class pattern1 . We evaluate whether the Split Up God Class pattern facilitates top-down comprehension, which has been shown to be applied in case programmers need to understand a code fragment that is familiar, or when the problem domain to which the code fragment contributes a solution is familiar [von Mayrhauser and Vans, 1995].
7.1
Introduction
To evaluate the mental representation of programmers adhering to a top-down approach for program comprehension, we test the criteria which Brooks proposed for complete understanding. These criteria require information about: (i) knowledge domains consisting of objects, relations among objects, operations which manipulate these properties and relationships between objects; and (ii) relationships between objects and operators in one domain and those in a nearby domain [Brooks, 1978]. We argue that this knowledge can be tested using the following two assignments: 1 The
experimental material used in this chapter is publicly http://www.lore.ua.ac.be/Research/Artefacts/SE2006ReplicationPkg
73
available
at
74
CHAPTER 7. VALIDATING SPLIT UP GOD CLASS
Map variables/attributes to concepts described in the problem domain – Variables represent the objects present at the knowledge domain defined by the source code. To test the availability of information about the relationship with objects present in the problem domain, we can ask a person to localize variables/attributes in the source code that represent a given concept described in the problem domain. E.g., in the context of a mail client, we can ask a person to localize the attribute representing the To header-field of a mail. Map method execution steps to actions described in the problem domain – Methods represent the operators which manipulate the attributes of classes in the source code. As these methods correspond to (parts of) scenario’s in the problem domain, steps in the execution of a method correspond to actions in the problem domain. Therefore, to test the availability of information about the relationship between operators in the source code and operators in the problem domain, we can ask a person to localize method execution steps that represent a given action described in the problem domain. E.g., we can ask a person to localize the method execution step representing the action of physically sending a mail to a mail-server. Accordingly, these two tasks verify whether a person’s mental representation of a program contains information about the the relationship with the problem knowledge domain. To initiate the construction of a mental model using a top-down comprehension approach, pre-generated hypotheses about the problem domain are required. Therefore, before asking a person to map variables, attributes or method execution steps, one has to assure that the person is at least familiar with the problem knowledge domain. These two assignments allow to evaluate the result of a top-down comprehension approach, and therefore, can be used to verify whether the Split Up God Class pattern supports top-down comprehension. Accordingly, we evaluate the performance of a person applying these two assignments using the following attributes: Task accuracy: A task is not required to be completed successfully in order to be declared as finished by the person executing it. I.e., the person executing it might assume wrongfully that he has performed it successfully, or the time frame reserved for finishing the task might have passed. Accordingly, when asked to map an attribute or method execution step to a given concept or action described in the problem domain, three possible
7.2. RESEARCH HYPOTHESES
75
outcomes exist: (i) the information item (attribute or method execution step) is accurately localized; (ii) the wrong information item is localized; or (iii) no information item was localized. The first option indicates comprehension of the attribute or method execution step, while the second and third options do not. Accordingly, for such tasks, task accuracy is a binary attribute, which can be either accurate, or inaccurate. Task duration: The time it takes a person to localize an information item indicates the ease with which a (partial) mapping between the source code and the problem domain is created. As this mapping is essential for a complete understanding of the program, for such tasks, the task duration allows to estimate comprehensibility w.r.t. to a subset of the program and the problem domain. However, in comparing the durations of two persons performing a task, one has to take into account task accuracy. E.g., in case one person accurately performed a task, while another person did not, it is invalid to compare the performance of these two persons merely using the task durations. It is only valid to compare the task durations of tasks performed accurately. Evidently, task duration and task accuracy are influenced by factors other than merely the properties of the source code. Examples of such factors are the skills and expertise (or even mental condition) of the person performing the task, the tools provided to support the task, etc. Therefore, it is essential to control the conditions in which task performance is evaluated in order to ensure that merely those factors of interest can be the cause of differences w.r.t. task accuracy and duration.
7.2
Research Hypotheses
In our efforts to validate the Split Up God Class, we compare the comprehensibility of students working on alternative decompositions of a god class in a software system from a familiar problem domain. To be specific, we expect that the performance of students working on different god class decompositions differ. Consequently, we state the following null hypotheses: H0,accuracy – The ability to accurately map variables/attributes and method execution steps to respectively concepts and actions described in the problem domain does not differ w.r.t. the god class decomposition.
76
CHAPTER 7. VALIDATING SPLIT UP GOD CLASS
H0,time – The time required to accurately map variables/attributes and method execution steps to respectively concepts and actions described in the problem domain does not differ w.r.t. the god class decomposition. It has been shown that the skills of a developer applying maintenance tasks interacts with the effect that a design decomposition has on maintenance performance [Arisholm and Sjøberg, 2004]. Thus, the skills of a maintainer attempting to understand a software system might influence the effect of a god class decomposition on the effort required to understand the class. As the Split Up God Class pattern allows to manipulate the decomposition of a god class, we ask ourselves whether the effect of the Split Up God Class pattern on program comprehensibility is influenced by the experience of the maintainer attempting to understand the system. In the population of master-level students, this experience is mostly determined by the curriculum of the university at which the student is enrolled. Accordingly, we incorporate the institution at which a student is enrolled as a factor which might interact with the effect of a god class decomposition on the comprehensibility of part of a software system.
7.3
Experimental Set-Up
In this section, we specify the variables incorporated in the experimental design, characterize the participants and elaborate on the experimental procedure.
7.3.1
Experimental Design
Similar to the validation of the Refactor to Understand pattern, the experimental design is a crossed factorial design with two factors, incorporating a pretest and a posttest. Table 7.1 illustrates the experimental variables manipulated or observed in this experiment. The independent variables subject to experimental control are: IV1– Class Decomposition: This ordinal variable indicates the number of classes which were extracted from the god class to derive class decompositions A–E, presented in the illustrative refactoring scenario in the previous chapter. Therefore, the possible values are {A,B,C,D,E}. IV2 – Institution: The experiment was replicated with students enrolled in different institutions (see Table 7.2), providing a nominal variable. Possible values are {MAS1,MAS2,MAS3}. This variable is incorporated as
7.3. EXPERIMENTAL SET-UP
77
curriculum differences are a potential cause of variation, and can thereby provide an explanation for differences in individual performance. Table 7.1: Experimental variables Variable type Independent
Dependent
Name Class decomposition Institution PMV PMS ET
Values {A,B,C,D,E} MAS1 MAS2 MAS3 [0,100]% [0,100] % [0,3600] sec
Scale ordinal nominal
absolute
Evidently, the institution variable could only be controlled by the participant selection procedure. To control the class decomposition variable, we assigned participants to a god class decomposition (A–E). The dependent variables being observed are: PMV – Percentage of accurately Mapped Variables: Measured as the percentage of variables/attributes that are localized by a participant and match with the requested domain concepts. The total number of variables/attributes to be localized is two for the pretest and eight for the posttest. This variable is used to indicate the ability of participants to map variables/attributes to concepts described in the problem domain. PMS – Percentage of accurately Mapped Steps: Measured as the percentage of requested information items for which a correct step in execution was found – even if the wrong attribute is printed. This variable is used to indicate the ability of participants to map steps in the execution of methods to actions described in the problem domain. ET – Execution Time: Measured as the time frame between the point at which the change request is read and the point at which the task is finished, in seconds. Participants are randomly assigned to one of five groups (A to E). Each group applies two change localization tasks. The first task is identically applied by all groups, and provides pretest observations. The second task, however, is
78
CHAPTER 7. VALIDATING SPLIT UP GOD CLASS
applied for each group on a different class decomposition, and provides posttest observations, incorporating manipulation of the experimental factor class decomposition.
7.3.2
Experimental Participants
The same set-up was applied in five replications, employing a total of sixty-three master-level computer science students (see Table 7.2). As the names of the institutions are of no value within the context of this paper, we have encoded them.
Table 7.2: Replications of the experiment Replication 1 2 3 4 5
Institution MAS1 MAS1 MAS2 MAS3 MAS3 Total
Curriculum CS CS ICT CS CS
#Subjects 9 5 20 14 15 63
1–2 In October 2004, fourteen third year mathematics and computer science (CS) students (four years master-level) participated in the context of a crash-course on the open source Integrated Development Environment Eclipse. This course is optional in the third year of the four years master level (mathematics and) computer science curricula at the University of Antwerp, Belgium. An experimental session was organized for 9 computer science and 5 mathematics and computer science students separately. As third year students, they are moderately experienced in object-oriented software development in Oberon and C++. However, these students have no experience with maintenance. 3 In November 2004, twenty last year students industrial engineering in ICTelectronics (four years master-level) participated in the context of a mandatory course on distributed software in Java at the Karel de Grote Hogeschool, Belgium. These students have limited experience with object-oriented software development in C++ and Java.
7.3. EXPERIMENTAL SET-UP
79
4–5 In March 2005, twenty-nine last year computer science students (four years master-level) participated in the context of a mandatory course on software evolution at the University of Mons-Hainaut, Belgium. As last year students, they are experienced in object-oriented software development in Scheme and Java. These students previously extended an existing system in a project assignment and therefore have minor experience with the tasks at hand. The Karel de Grote Hogeschool is a university of professional education (hogeschool in Dutch), contrary to the universities of Antwerp and Mons-Hainaut who provide research-oriented education. Before the Bachelor-Master reformation in Europe, professional education led to the bachelor level while researchoriented education led to the master level. There is a clear distinction between the curricula of MAS1 and MAS3 students (computer science) and the ICT-electronics curriculum of the MAS2 students. The latter are less focused on software engineering and mostly target hardware and network design as well as data communication.
7.3.3
Experimental Procedure
Each experimental replication incorporated participants of a single institution. At the beginning of each replication, participants were randomized across experimental groups, resulting in the distribution illustrated in Table 7.3.
Table 7.3: Participant assignment Class Decomposition A B C D E Total
MAS1 2 3 4 3 2 14
Institution MAS2 MAS3 4 6 4 5 4 6 4 6 4 6 20 29
Total 12 12 14 13 12 63
Assignment of participants across experimental groups. Each cell represents a group of participants working on a particular god class decomposition (A–E) and originating from a particular institution (MAS1–MAS3).
80
CHAPTER 7. VALIDATING SPLIT UP GOD CLASS
After assigning participants to groups, an introduction to the experimental procedure was given. Participants were told that they were required to fulfill maintenance assignments which would demonstrate the complexity of understanding and modifying a software system written by someone else. Therefore, participants were unaware of the purpose of the experiment. It was said that two assignments would be given, and the first assignment was then introduced in detail. Each participant received a sheet containing the first task, illustrated in Figure 7.1. The sheet for the second task is illustrated in Figure 7.2. For both tasks, the same sheet format was adhered to. Each task required participants to output information at a particular moment in execution. Therefore, each task implicitly required participants to first comprehend the code fragment, and afterwards to introduce changes in order to ensure the printing of information to output. We posed no time limitations on the tasks. However, participants were motivated themselves to finish quickly, and the sight of a participant finishing contributed to this motivation, which is a natural effect in such experiments. However, if a participant wished to continue finishing the task, he was not restricted to do so. All replications were performed under identical conditions using identical material. Participants used the Eclipse IDE to perform both tasks, using the integrated CVS functionality. As the participants of MAS3 were used to French course material, we had the task sheets translated to French.
7.3. EXPERIMENTAL SET-UP
81
Opdracht één • • •
Use the Eclipse-icon on the Desktop to launch Eclipse Open the Java project named “E”. This project contains the implementation of an email client. Read the following Change Request, and afterwards execute it.
Change Request Name Scope Class org.gjt.fredde.communication.MailSender Context description Mails that are to be sent to a mail-server are placed in a mailbox where they wait to be submitted. The sendMails() method in class MailSender constitutes the trigger for sending these mails. This method retrieves the mails from the mailbox-file, and triggers the submission of smtp-commands for these mails. Additional An email-message consists of an email-header and an emailinformation body. The email-header contains header-field pairs, consisting of a name and a value of a header-field. For example: From: Jan Janssen To:
[email protected] Content-Type: text/html Subject: Uitnodiging
Assignment Write the header-fields (name and value) of each mail to standard output at the moment it is being sent. Use the following output-format: To: Subject: --... (next output-block)
Before starting the Write your name in comment on the first line of the class assignment MailSender, and commit the project to CVS. Write the current time below, using the system clock to the lower-right of your screen (double-click). Timestamp of h m s (example: 8h 05m 12s) assignment start Timestamp of h m s assignment end
Figure 7.1: Pretest task
82
CHAPTER 7. VALIDATING SPLIT UP GOD CLASS Assignment two
• • •
Use the Eclipse-icon on the Desktop to launch Eclipse. Use the Java project named “E”. This project consists of an implementation of an email client. Read the following Change Request, and afterwards execute it.
Change Request Name Scope Package org.gjt.fredde.filtering Context description Mails which were retrieved from the mail-server are placed in a mailbox where they wait to be filtered. The filtermails() method in the class IncomingMsgFilterController constituties the trigger for filtering these mails. This method retrieves the mails from the mailbox-file, as well as the configured filters from the filter-file, and triggers the application of the filter on the mails. Additional An email-message consists of an email-header and an emailinformation body. The email-header contains header-field pairs, consistent of a name and a value of a header-field. For example: From: Jan Janssen To:
[email protected] Content-Type: text/html Subject: Invitation
Assignment Write the header-fields (name and value) and the attributes of a mail filter to standard output at the moment a mail is being filtered. Use the following example output-format: From= To= Subject= Reply-To= Filtered Header Field Name= Filtering Method= Filtering String= Moved Mail To= --... (next output-block)
Before starting the Write your name in comment on the first line of the class assignment IncomingMsgFilterController, and commit the project to CVS. Write the current time below, using the systeem clock to the lower-right of your screen (double-click). Timestamp of h m s (example: 9h 40m 12s) assignment start Timestamp of h m s assignment end
Figure 7.2: Posttest task
7.3. EXPERIMENTAL SET-UP
7.3.4
83
Experimental Tasks
The change requests (illustrated in Figures 7.1 and 7.2) consist of the following elements: Scope – Delimits the code fragment in which changes are to be applied. Context description – Introduces the problem domain, and provides a high level overview of the function of the main method. This context description ensures the presence of pre-generated hypotheses, which starts an expectation-based top-down comprehension process. Additional information – Elaborates on objects present in the problem domain. To be specific, the concept of an email message and its relation with email header fields is discussed. This section ensures that the participant has information about the knowledge domain at the level of the problem domain. Consequently, the process of top-down comprehension is limited to gathering information about the knowledge domain at the level of the source code, and the mapping between these two knowledge domains. Assignment – Describes what is required from the participant. The assignment dictates the concepts and actions present in the problem domain for which the participant has to localize associated variables/attributes and method execution steps. By asking the participant to write information to output, we implicitly ask participants to localize an attribute. By asking the participant to write information at a particular action, we implicitly ask participants to localize a method execution step. Administrative – Reminds participants to write their name in the source code, and to indicate the time stamp before starting and after finishing the task. The first task (see Figure 7.1) formed the pretest, which is identical for all participants. This means that the source code on which the students apply the first change request is identical. Therefore, for the pretest, the class decomposition factor is held constant, and the only difference between groups is due to the institution factor. This pretest is introduced to evaluate the equivalence of experimental groups, i.e., to verify that we do not systematically assign highperformant participants to some god class decompositions and low-performant
84
CHAPTER 7. VALIDATING SPLIT UP GOD CLASS
participants to others. Performance equivalence between groups at the pretest are confirmed in data analysis. The second task (see Figure 7.2) formed the posttest, which differed between experimental groups. Participants assigned to different god class decompositions (A–E) therefore had to comprehend and change different class decompositions. However, these decompositions were behaviorally equivalent, as described in the previous chapter. The software system used in the experiment is an open source Java mail client (Yamm v0.9.1), which consists of 13KLOC over 66 classes. This software system was chosen for the following two reasons. First, the knowledge domain of the application domain of a mail client is very well-known by all participants. This familiarity is required to stimulate a top-down comprehension process. As a second argument, the system is a typical example of continual extension, which leads naturally to the fostering of god classes. The god class responsible for the filtering procedure is therefore a natural and realistic god class. The source code fragments to be understood and changed for both tasks are characterized in Table 7.4. The code fragments are of similar size, expressed in non-comment lines of code. Both code fragments originate from different packages of the same software system, which is an open source implementation of a mail client in Java. Table 7.4: Properties of the code fragments used Property Non-comment Lines of Code Number of Attributes Number of Methods
Code fragment Pretest Posttest 240 274 16 8 13 11
Properties of the source code fragments for each of the two experimental tasks.
In order to prepare the posttest, we moved the god class responsible for the filtering procedure to a separate package, thereby forming decomposition A. By keeping all extracted classes in this package, we had a means to clearly bound the part of source code of interest for the assignments. Each task (pretest or posttest) requires a number of information items to be printed at a certain moment in execution. For the pretest, two information items had to be printed, and for the posttest assignment, 8 items were requested to be printed.
7.3. EXPERIMENTAL SET-UP
85
We observed all participants applying the following steps: 1. Read the change request. 2. Navigate to the class or package specified as the scope of the change request. Navigate further to the method indicated in the change request as the trigger for the scenario of interest. For the pretest, this was the method MailSender.sendMails, and for the posttest, this was method IncomingMsgFilterController.filterMails. 3. Browse through the source code delimited by the scope indicated in the change request, in search for code fragments associated with the high level overview description of the function of the main method presented in the change request. 4. Simulate the execution of the main method by following the call graph. 5. Recognize variables/attributes representing one of the concepts requested in the change request, and recognize points in the execution of a method corresponding to the action described in the change request. Through the delegation of control to different methods, potentially in different classes, there are multiple locations in the source code that correspond to a particular moment in the execution of an algorithm. Accordingly, there are potentially multiple execution steps which correspond with a given action in the problem domain. E.g., the line of code immediately before a method invocation, and the first line of code in the invoked method correspond to the same action. However, the required information items might not be visible in all of these locations. E.g. in case the information items are private attributes for which there are no accessor methods, these are only accessible in the methods of the class defining these attributes, and not in their clients. Therefore, in these cases, only some of the multiple execution steps corresponding to a given action can be used to print particular requested information items. 6. Once an adequate method execution step has been found, a print-statement is written to standard output, in which the variable or attribute is printed. In case no adequate method execution step was found, participants marked the variable or attribute in question with comments or printed it at a method execution step which they thought was most appropriate.
86
CHAPTER 7. VALIDATING SPLIT UP GOD CLASS
These steps were applied for each of the information items requested, ultimately leading to the completion of the task. The posttest was started only once all participants finished the pretest.
7.4
Data Analysis
In this section, we report the analysis of the data used to answer our two research questions. First, we describe the analysis procedure. Secondly, we characterize the collected data. Finally, we report on the analyses used to test the hypotheses.
7.4.1
Analysis Procedure
The main sources of information collected during the experiment were the modified software systems and the time stamps. For both the pretest and posttest, the author evaluated the participants’ solutions himself according to the following rules. Task accuracy – The two dependent variables related to task accuracy are the percentage of mapped variables/attributes (PMV) and the percentage of mapped method execution steps (PMS): PMV – Participants indicated that they had localized a variable or attribute by either printing it to standard output, or by writing a comment indicating the concept in the problem domain with which the variable/attribute corresponded. For each information item requested (respectively 2 and 8 for the pretest and the posttest), the evaluation procedure applied by the author categorized the solution as follows. In case the localized variable/attribute corresponds to the requested concept, a score of one is added to the total score. In case the localized variable/attribute does not correspond, or in case there is no variable/attribute localized for the requested concept, nothing is added to the total score. After evaluating all information items requested, to calculate the percentage of accurately mapped variables/attributes (PMV value), the total score is divided by the number of information items requested. E.g., if a participant has a score of 1 on the pretest and 5 on the posttest, the PMV value of the pretest and posttest are respectively 1 5 2 = 0.5 and 8 = 0.625.
7.4. DATA ANALYSIS
87
PMS – Participants indicated that they had localized a method execution step by writing a print-statement at that line of code. This printstatement followed the output-format indicated in the task sheet. In this output-format, a variable/attribute was filled in in case the participant had localized the corresponding variable or attribute, or otherwise a string indicating (s)he was unable to localize the variable. For each task, there is only a single action to be mapped against method execution steps. However, the printing of requested information items needs to be distributed across different execution steps corresponding to the same requested action, because not all variables/attributes are visible at all scopes, e.g., in the cases of private attributes, or variables defined in different methods. For each information item requested, the author categorized the solution according to the following principle. In case the method execution step, indicated to be the location at which the requested information item should be printed, corresponds to the requested action, a score of one is added to the total score. In case the localized method execution step does not correspond to the requested action, or no such method execution step is indicated for the information item, nothing is added to the total score. Once again, after evaluating all information items requested, the total score was divided by the number of information items requested to calculate the percentage of accurately mapped method execution steps (PMS value).
Task duration – The only dependent variable related to task duration is the execution time (ET), calculated as the number of seconds between the start of the task and the finishing of the task. The execution time was calculated from the time stamps which were hand-written by the participants on the task sheets.
7.4.2
Descriptive statistics
Table 7.5 describes the mean and standard deviation of our observations in both the pretest and the posttest.
88
CHAPTER 7. VALIDATING SPLIT UP GOD CLASS
Table 7.5: Descriptive statistics (N=63) Measure PMV PMS ET
Pretest Mean StdDev. 96.0% 16.3% 93.6% 19.0% 1284 535
Posttest Mean StdDev. 86.2% 21.4% 41.2% 43.4% 2471 799
We discuss the observations for the pre- and posttest separately: Pretest – The data indicates that most of the participants had no problems localizing variables/attributes and method execution steps for the pretest (mean PMV=96% and mean PMS=93.6%). The average execution time was about 20 minutes. Posttest – Somewhat lower accuracy and longer execution times were expected from the posttest. Most of the participants were able to localize a large part of the attributes (mean PMV=86.2%), yet unable to localize the correct method execution steps (mean PMS=41.2%). The average execution time was about twice the duration of the pretest, at about 40 minutes. When comparing the posttest values with the pretest values, we observe lower PMV, PMS and ET posttest values, as expected. Moreover, these differences are quite large, and in fact all significant at the 99% level. This means that the probability of such an extreme difference between the pretest and the posttest without any actual difference between them is less then 1%. These differences can be explained by the difference in task difficulty. While it is non-trivial to define the difficulty of a task, we can clearly see that the posttest required more items to be localized than the pretest. More specific, the posttest required participants to localize information about the mailheader, the filter and the action to be applied by the filter, which in total requires 8 attributes to be localized. In contrast, the pretest only requires 2 attributes to be localized, both related to a mailheader. When we zoom in on the posttest observation w.r.t. PMS, we observe that the standard deviation (43.4%) is larger than the actual mean (41.2%). This finding could only be observed in the possttest observations of PMS, and persists even within groups of participants from the same institution working on the same god class decomposition. Such variation decreases the sensitivity of tests for differences between different experimental groups. Accordingly, our
7.4. DATA ANALYSIS
89
statistical tests for null-hypotheses H0,P M S and H0,P M S−ET will suffer from a lack of power. We will take this lack of power into account in the interpretation of results. Nonetheless, for completeness, we do provide the results of the statistical tests on the PMS observations.
7.4.3
Statistical tests
Table 7.6 illustrates the statistical tests which will be used for testing the null hypotheses. These tests are Analysis of Variance tests that test whether two or more samples originate from the same population. The principle applied in this test is the following. In case differences between samples are larger than differences among samples, it is probable that these samples come from different populations. To verify which type of Analysis of Variance to apply, we have to investigate the distribution of the observations. Data exhibiting a normal distribution can be tested using the parametric Analysis of Variance, while otherwise non-parametric tests are required. Contrary to the pre- and posttest observations of ET, the PMV and PMS observations deviate from normality. Both pretest and posttest observations of PMV are skewed significantly to the high end of the scale, and exhibit a clear peak. The pretest observations of PMS demonstrated similar deviations from normality. Its associated posttest observations exhibit a flat distribution. Accordingly, the ET observations can be tested using the parametric one-way Analysis of Variance (ANOVA). In contrast, PMV and PMS observations will be tested using the non-parametric variant, being the Kruskal-Wallis one-way Analysis of Variance [Coolican, 2004]. This test ranks the observations before comparing them.
Table 7.6: Statistical tests Null hypotheses H0,P M V H0,P M S H0,P M V −ET H0,P M S−ET
Req. DV1 PMV PMS
Statistical test
ET
one-way Analysis of Variance (ANOVA)
Kruskal-Wallis one-way Analysis of Variance
This table describes the statistical tests used for testing the null hypotheses. 1
Required Dependent Variable signifies the dependent variable to be compared between groups. For H0,P M V −ET and H0,P M S−ET , only those observations with resp. PMV=100% or PMS=100% are included.
90
7.4.4
CHAPTER 7. VALIDATING SPLIT UP GOD CLASS
H0,accuracy – Differences in task accuracy
Table 7.7 illustrates the significance of group differences at the pre- and posttest. Performance differences between participants from different institutions are plausible (p=.144), as can be expected. In contrast, the results w.r.t. the pretest confirm that there were no significant systematic differences between groups working on different god class decompositions (A–E). This means that the randomization of participants ensured the equivalence of our experimental groups. Table 7.7: Test of group differences w.r.t. accuracy Factor Decomposition Institution Interaction
Pretest PMV PMS .445 .898 .144 .297 .213 .119
Posttest PMV PMS .089* .719 .353 .271 .078* .314
Represents the significance of the Kruskal-Wallis Analysis of Variance, reporting on the main effect of the Decomposition and Institution factors, and their interaction.
The question we address in this section is: Do some decompositions allow to achieve higher comprehension accuracy than others? In the discussion of this question, we will differentiate between the ability to map variables/attributes and to map steps in the execution of a method. Ability to map variables/attributes to concepts described in the problem domain (PMV) – There were significant differences between the groups working on different god class decompositions (p=.089). This effect of the decomposition factor interacts significantly with the effect of the institution factor (p=.078), indicating that participants from some institutions had more difficulties in mapping attributes than participants from other institutions. Figure 7.3 illustrates the mean value of PMV posttest observations per combination of the decomposition and institution factors. The line referred to in the legend as Overall illustrates the main effect of the decomposition factor. The results of the institutions differ with regard to the god class decomposition at which the ability of participants to map attributes was highest, as indicated by the different trends across different institutions. The results of the replications with computer science students (MAS1 and MAS3) demonstrate absolute differences between class decompositions of more than 30 PMV. This means
7.4. DATA ANALYSIS
91
Mean PMV for posttest observations
100 90 80 70 60 50 40 30 20 10 0 A
B
C
D
E
Class Decomposition MAS3
MAS2
MAS1
Overall
The Y-axis represents the mean percentage of localized attributes (PMV value) across the different class decompositions as observed in the posttest.
Figure 7.3: Posttest PMV observations that, for some decompositions, participants were able to localize an additional one third of the attributes in relation to other decompositions. Observed PMV differences between ICT-electronics students (MAS2) working on different class decompositions were smaller, differing at most 15 PMV. Ability to map method execution steps to actions described in the problem domain (PMS) – Before discussing the results, we remark that the descriptive statistics previously indicated that statistical tests w.r.t. the ability to localize method execution steps (PMS) would suffer from lack of power. This means that, even if there would actually be differences between the groups working on different god class decompositions, there is merely a small probability that our test will be able to confirm this difference. We indeed do not observe significant differences.
92
CHAPTER 7. VALIDATING SPLIT UP GOD CLASS
Mean PMS for posttest observations
100 90 80 70 60 50 40 30 20 10 0 A
B
C
D
E
Class Decomposition MAS3
MAS2
MAS1
Overall
The Y-axis represents the mean percentage of localized method execution steps (PMS value) across the different class decompositions as observed in the posttest.
Figure 7.4: Posttest PMS observations Figure 7.4 presents the mean posttest PMS observations across god class decompositions, specified for each institution and overall. While groups were generally unable to correctly perform the assignment, for each institution, we observe a single decomposition for which the group of participants was able to achieve an accuracy higher than 60%. For the participants of MAS1, MAS2 and MAS3, these were respectively decompositions D, E and B. However, no consistent trends can be observed. Once again, we attribute this to the large performance differences within groups, making it difficult to evaluate differences between groups. Summarizing, these observations allow us to reject H0,P M V . In contrast, we must accept H0,P M S . Alternatively, one can also describe group differences w.r.t. accuracy by evaluating the ratio of participants able to map all attributes (PMV=100%)
7.4. DATA ANALYSIS
93
Frequency of observations with PMV=100%
or steps in the execution of a method (PMS=100%). Accordingly, this ratio of participants is illustrated in respectively Figures 7.5 and 7.6.
100 90 80 70 60 50 40 30 20 10 0 A
B
C
D
E
Class Decomposition MAS3
MAS2
MAS1
Overall
Figure 7.5: Frequency of observations with PMV=100%
The god class decompositions for which most participants were able to map all attributes (see Figure 7.5) differs between institutions. For the computer science students (MAS1 and MAS3), the decomposition for which the least number of participants was able to localize all attributes was the original god class decomposition A. In contrast, decomposition A was the decomposition for which most MAS2 participants (the ICT students) were able to localize all attributes. Since participants were generally unable to localize method execution steps, there are few participants who localized all method execution steps, as illustrated in Figure 7.6.
Frequency of observations with PMS=100%
94
CHAPTER 7. VALIDATING SPLIT UP GOD CLASS 100 90 80 70 60 50 40 30 20 10 0 A
B
C
D
E
Class Decomposition MAS3
MAS2
MAS1
Overall
Figure 7.6: Frequency of observations with PMS=100%
7.4.5
H0,time – Differences in task duration
The question we address in this section is Do some decompositions allow to achieve comprehension faster than others? To discuss this question, two ANOVA models were composed with factors decomposition, institution and their interaction: one for the observations of participants who mapped all attributes (α=.10, R2 =.463, Adj. R2 =.136) and one for those who mapped all method execution steps (α=.10, R2 =.634, Adj. R2 =.085). Table 7.8 provides the significance of the ANOVA test statistic. The results in Table 7.8 are visualized in Figure 7.7. This figure confirms that the mean execution time of different institutions follows the same trend across decompositions, rejecting an interaction effect between the decomposition and institution factors. Differences in the time it took participants to map all attributes reach up to 16 minutes between decompositions D and E, compared to an overall mean execution time of 37 minutes. This means that it took
7.4. DATA ANALYSIS
95
participants in the group working on god class decomposition E 1.5 times longer to map all attributes compared to the group working on god class decomposition D. These differences, resulting from the main effect of the decomposition factor, are almost significant (p=.106). Table 7.8: Test of group differences w.r.t. time Factor Decomposition Institution Interaction
PMV-ET1 Sign. Power .106 .683 .265 .396 .893 .260
PMS-ET2 Sign. Power .542 .265 .235 .395 .967 .114
Represents the significance of the Analysis of Variance, reporting on the main effect of the Decomposition and Institution factors, and their interaction. 1 PMV-ET signifies the execution time of the observations of participants that managed to localize all attributes (PMV=100%). 2
Analogue, PMS-ET signifies the execution time of those observations of participants managed to localize all method execution steps (PMS=100%).
Few participants were able to map all the method execution steps, explaining the lack of data points in Figure 7.8. Therefore, the power of our tests for group differences is very low, as can be observed in Table 7.8. Accordingly, we are unable to discover group differences w.r.t. the time required to map all method execution steps. Summarizing, we must accept H0,P M V −ET and H0,P M S−ET . Table 7.9: Rejection of H0,accuracy and H0,time H0,accuracy H0,P M V H0,P M S R
H0,time H0,P M V −ET H0,P M S−ET AR
Represents the rejection of the null hypotheses. R stands for Rejected (p < .10), and AR stands for Almost Rejected (.10 < p < .12).
Table 7.9 summarizes the confirmation or refutation of the null hypotheses.
96
CHAPTER 7. VALIDATING SPLIT UP GOD CLASS
Mean ET in sec for results with PMV=100%
3600 3000 2400 1800 1200 600 0 A
B
C
D
E
Class Decomposition MAS3
MAS2
MAS1
Overall
Figure 7.7: Mean ET of observations with PMV=100% H0,P M V −ET , discussing group differences w.r.t. task durations for those participants who were able to accurately map all variables/attributes, was very close to being significant (p=.106). Therefore, our data indicates considerable group differences both w.r.t. task accuracy and w.r.t. task duration.
7.5
Interpretation of Results
After analyzing the collected data we are able to reflect upon the two research questions. Do some decompositions allow to achieve higher comprehension accuracy than others? When we assess comprehension accuracy by asking to map attributes and method execution steps to respectively concepts and action described in the problem domain, our data indeed confirms the presence of sig-
7.5. INTERPRETATION OF RESULTS
97
Mean ET in sec for results with PMV=100%
3600 3000 2400 1800 1200 600 0 A
B
C
D
E
Class Decomposition MAS3
MAS2
MAS1
Overall
Figure 7.8: Mean ET of observations with PMS=100%
nificant differences. While our data does not allow the conclusive interpretation of differences w.r.t. the ability to map method execution steps, we have observed significant higher comprehension accuracy with regard to the relation between variables and attributes localized in the source code and concepts described in the problem domain. However, our data does not suggest an objective notion of “optimal comprehensibility”. On the contrary, while students with a computer science background had more difficulties comprehending the original god class decomposition A, ICT-electronics students experienced less difficulties. It appears that differences in comprehensibility of the god class decompositions as perceived by the computer science students were larger than as evaluated by the ICTelectronics students. We interpret this finding as a confirmation that advanced object-oriented software engineering training can induce a preference towards particular styles of class decomposition.
98
CHAPTER 7. VALIDATING SPLIT UP GOD CLASS
Do some decompositions allow to achieve comprehension faster than others? We did observe differences between the god class decompositions concerning the time it took participants to localize all attributes. The statistical significance of these differences approximated the preset significance criterion (p=.106). Curiously, while the class decomposition for which students demonstrated optimal comprehensibility differed between institutions (interaction effect), such an interaction could not be observed w.r.t. the time it took to localize all attributes. When we would regard those students being able to localize all attributes as performant students, this finding could suggest that there are few systematical differences w.r.t. class decomposition preference between the selection of performant students across different institutions.
7.6
Threats to Validity
There are severe limitations to the extent at which our results can be attributed to the specified cause, and the extent in which these results can be generalized. For clarity, we specify the main threats to validity.
7.6.1
Internal Validity
Internal validity is the degree to which the experimental setup allows to accurately attribute an observation to a specific cause rather than alternative causes. The threats we have identified are the following. • Maturation might have affected participant performance due to the application of a pretest. However, randomized distribution of participants across groups should ensure that this effect does not lead to systematic group differences. • The risk of an instrumentation effect was minimized through the use of a decidedly objective categorization of the participant’s result using a clear evaluation procedure.
7.6.2
External Validity
External validity is the degree to which research results can be generalized outside the experimental setting or population under study. • Characteristics of the problem domain at hand and the associated experimental tasks are that the concepts used were very simple, and familiar
7.7. CONCLUSION
99
to all participants. Therefore, it is unclear whether systematic differences w.r.t. comprehensibility arise when the problem domain is more complex in terms of the number of entities, relationships, and their properties. • The experiment reported in this work was performed in a laboratory setting with computer science students. Consistency of the observed effect over different institutions suggest that our findings can be generalized to the population of computer science students in general. However, a common characteristic of this population is their perspective on optimal decompositions, as most of the books providing examples are considered standard reading material. Therefore, it is unclear whether the observed effect would reoccur in case professional software maintainers would be used, as their experience with alternative decompositions might have stimulated a comprehension process that is more robust to variability in class decompositions.
7.7
Conclusion
This experiment has been set up to verify whether god class decomposition can facilitate comprehension. As one of the indicators of comprehensibility, the ability to map attributes in the class hierarchy with domain concepts was significantly affected by the decomposition and its interaction with the institution from which the participant was enrolled. Moreover, this increased accuracy was not compensated by longer execution times of the comprehension task. Our findings lead to two conclusions: 1. Improving comprehensibility is within the grasp of a single programmer or maintainer preparing for future change requests, as demonstrated using our illustrative refactoring scenario. This approach is in contrast with the more traditional perspective on the need for massive reengineering efforts for attaining improvements in external quality characteristics. Small scale refactoring during development can therefore be regarded as a complementary strategy to a separate preventive maintenance phase, differing both in required investments and resulting returns. 2. We are reluctant to accept the concept of an optimal class decomposition with respect to comprehensibility, since one of the factors which interacts with the class decomposition is the particular education of the subject performing the comprehension task. This observation has been previously
100
CHAPTER 7. VALIDATING SPLIT UP GOD CLASS demonstrated by [Arisholm and Sjøberg, 2004], and suggests that guidelines for the reorganization of software systems should take into account the particular skills and expectations of the people maintaining the system. To be more precise, it is important to either adjust the organization of the software system to the methods of organization preferred by the people maintaining it, or to make these people accustomed to these methods of organization, e.g., by training.
This work does not provide guidelines on how to improve comprehensibility using refactorings. However, our conclusions can motivate software engineering researchers, practitioners and tool developers to study and support ways in which comprehensibility improvements can be achieved using controlled refactorings.
Chapter 8
Summary In this chapter, we summarize our findings and lessons learned with regard to the investigation of program comprehension improvements by refactoring.
8.1
Findings
Program comprehension models typically distinguish between a bottom-up and a top-down approach. We have evaluated the support of two patterns using refactorings w.r.t. both of these program comprehension models. Bottom-up comprehension: The physical application of two refactorings, Rename Variable/Method and Extract Method, has been shown to stimulate bottom-up comprehension. This application of refactoring is known as the Refactor to Understand pattern [Demeyer et al., 2002]. These refactorings are targeted towards conveying the roles of variables, attributes andconditional branches, the intentions of methods and the purposes of classes [Demeyer et al., 2002]. We observed that essential abstractions, present in the mental model representations typical for bottom-up comprehension, are more accurate for students applying the Refactor to Understand pattern than these for students applying the traditional reading technique. These findings indicate that the Refactor to Understand pattern stimulates the construction of knowledge required for a complete understanding. These requirements involve knowledge on both the text structure and the goals in the problem domain. 101
102
CHAPTER 8. SUMMARY Accordingly, our findings indicate that the Refactor to Understand pattern can support bottom-up comprehension.
Top-down comprehension: Alternative decompositions of a god class have been shown to stimulate top-down comprehension. This refactoring used for decomposing a god class is known as the Split Up God Class pattern [Demeyer et al., 2002], and is applied by subsequently applying refactorings which stimulate encapsulation, e.g., Extract Class, Extract Method, Replace Method with Method Object and Introduce Parameter Object. We observed that accurate knowledge on relations between the knowledge domain of the source code and the problem domain differed significantly between groups of students working on different god class decompositions. These knowledge domains consist of entities, their attributes, operations that manipulate these attributes, and relationships between these entities. The ability to relate these knowledge domains is essential for a complete understanding of the program [Brooks, 1978]. We observed that, for some god class decompositions, students were able to accurately map more attributes to concepts described in the source code. Moreover, we have found that the ability of students to comprehend a god class decomposition was significantly affected by the institution from which the student was enrolled. This finding confirms earlier work by [Arisholm and Sjøberg, 2004], and indicates that software engineering training can induce a preference towards particular styles of class decomposition. Accordingly, our findings indicate that the Split Up God Class pattern can support top-down comprehension.
8.2
Lessons Learned
In this section, we discuss three subjects which we regard as particularly relevant in continuations of this line of research. Assessing program comprehension – We are unaware of any standards with regard to assessing program comprehension. This lack has been previously indicated by [Rajlich and Cowan, 1997]. Accordingly, to ensure that findings between research works can be related to each other, we reused previous ways in which comprehension was tested (e.g., by reusing the way in which Pennington evaluated bottom-up comprehension [Corritore and Wiedenbeck,
8.2. LESSONS LEARNED
103
1991,Bergantz and Hassell, 1991,Ramalingam and Wiedenbeck, 1997,Sajaniemi and Navarro-Prieto, 2005]), or we attempted to follow the suggestions of authors discussing essential characteristics of complete understanding (e.g., as discussed by [Brooks, 1978]). In the future, we would like to engage in discussions in how standards for assessing program comprehension might be composed. Estimating task difficulty – In the validation of both the Refactor to Understand and the Split Up God Class patterns, we have found that it is nontrivial to estimate the difficulty or complexity of a task assigned to experimental participants. When using such tasks to assess program comprehension, the accuracy of the estimation of task difficulty affects the sensitivity w.r.t. program comprehension differences. E.g., if task performance is measured on an integer scale from 0 to 10, and in case the experimental task is so difficult that it is very unlikely for participants to score higher than 5, then the experimental test itself will only collect data points that score between 0 and 5. Accordingly, the sensitivity of the experimental test is reduced by half. We are unaware of any systematic means of estimating the difficulty of the experimental tasks applied in the experiments discussed in this part of the thesis, other than by performing a rigorous pilot study. In a pilot study, the experimental set-up is tried out on a set of participants with a profile similar to the population of interest. The purpose of a pilot study is to assess the adequacy of the experimental test. I.e., instructions provided to the participants might be unclear and suggested tools might be perceived as non-user-friendly. A pilot study can be used to estimate the task difficulty, e.g., by evaluating the average time required to solve the task, and the average accuracy with which the task is solved. In our experiments, a rigorous pilot study was not performed. In case a rigorous pilot study had been performed, we are confident that the following issues would have been prevented. First, in the validation of the Refactor to Understand experiment, systematic data loss w.r.t. abstractions data flow and state would have been prevented. Second, in the validation of the Split Up God Class pattern, the pilot study would have indicated that the posttest task w.r.t. the localization of method execution steps was too difficult. In both cases, this would have prevented the presence of data points which are unusable for further processing. Students as experimental subjects – In both validations, we used students in our controlled experiments. While this involves limitations to the extent in
104
CHAPTER 8. SUMMARY
which the results of our study can be generalized, we have experienced benefits of this choice. I.e., since we either had control over the curricilum of students ourselves, or had detailed insight in the contents of this curriculum, we could ensure that the participants possessed an adequate skill set. Controlling this skill set was essential in the validation of the Refactor to Understand pattern.
Part II
Coupling and Cohesion Improvements
105
Chapter 9
Quality-Driven Refactoring 9.1
Introduction
Quality driven refactoring is the process of optimizing quality attributes while preserving behavior. This part of the thesis envisions a state of the art in which a refactoring tool provides a maintainer with suggestions on which refactorings to apply where to improve specified quality attributes. Such a process is an application of an optimization problem, i.e., an exploration of the design space in search of a solution which is optimal with regard to a stated fitness function. This fitness function evaluates the software solution in terms of desired quality attributes. In general, there are two approaches towards quality driven refactoring. First, one can apply the brute force method, in which one does not know beforehand how the application of a refactoring will affect the fitness function. This approach consists of trying out a refactoring, and rolling back in case this path is undesirable. Second, one can employ a-priori knowledge to be able to look ahead and estimate the outcome of following a particular path of refactoring steps. A-priori knowledge can be defined as the prediction of the outcome of a particular event, given a description of both the event itself and the context in which the event takes place. The brute force method (i.e., as applied by [Seng et al., 2005]) can result in a description of the effect of a refactoring or sequence of refactorings applied in a particular context. However, this approach does not allow to predict whether similar effects can be observed in a different context, as the relationship 107
108
CHAPTER 9. QUALITY-DRIVEN REFACTORING
between the effect of the refactoring and the context in which it is applied is undocumented. Such documentation is what the a-priori knowledge represents. Therefore, this part of the thesis elaborates on an approach to quality driven refactoring research based on a-priori knowledge rather than a brute force approach. We define a-priori refactoring knowledge as a formalization of the outcome of a particular refactoring in function of the context in which it is applied. Formalization of a refactoring – A refactoring is typically formalized by specifying a pre- and postcondition [Opdyke, 1992, Roberts, 1999, Tichelaar, ´ Cinn´eide, 2001]. The postcondition specifies the guarantees that will 2001, O be fulfilled in case the requirements specified in the precondition have been met. This means that the outcome of the refactoring is undefined in case the refactoring is applied in a context in which the precondition is not met. To informally illustrate the specification of a refactoring, we consider the specification of the Move Method refactoring. Among others, the Move Method postcondition guarantees that the method to be moved will be contained in the target class after applying the refactoring, when the precondition is met, requiring that the method to be moved is a non-overriding, non-overridden method implemented by the source class, for which no similarly signatured method exists in the target class hierarchy. Formalization of the context in which a refactoring is applied – The context in which a refactoring is applied is a model, which corresponds to a structure described in a meta-model. A meta-model specifies the entities and relationships which can be described in a model. Therefore, the context in which a refactoring is applied can be formalized using a meta-model and operations on the entities and relationships which the meta-model describes. Examples of these operations are the cardinality of the set of instances of an entity or a relationship (e.g., the number of classes), the selection of instances satisfying particular properties (e.g., the set of classes which have no attributes) and the statement of the existence of an instance (e.g., there exists a class c satisfying particular properties). The pre- and postcondition of a refactoring are expressed in terms of the formalization of the context in which it is applied. I.e., among others, the Move Method precondition requires that the method to be moved does not reference non-public sibling attributes. This condition can be formalized in terms of the existence of a class in which the method to be moved is contained, the existence
9.1. INTRODUCTION
109
of a non-public attribute contained in this class, and the existence of a reference relationship between the method to be moved and this non-public attribute. Outcome of a refactoring – The outcome of a refactoring can be described as a translation of the postcondition of a refactoring in terms of given functions of the context in which it is applied. E.g., the outcome of the Move Method refactoring in terms of the size of the source class in numbers of methods can be described by translating the expression “the source class will no longer contain the method to be moved after refactoring” to “the number of methods of the source class will be decreased with one after applying Move Method”. In this case, part of the a-priori Move Method knowledge w.r.t. the size of the source class is that it will reduce the number of methods of the source class with one. Applications of a-priori refactoring knowledge in a maintenance context – Current refactoring tools provide support in the application of the transformation, thereby guaranteeing the postcondition in case the precondition is met. However, it is currently unclear which refactoring steps a maintainer should apply in order to improve a (set of) quality attribute(s). This means that any attempt to quality driven refactoring is dependent upon the skills of the maintainer suggesting the refactoring. This work attempts to reduce the effort required by the maintainer to the specification of quality attributes in need of optimization. I.e., it should be sufficient for a maintainer to specify that he would like to optimize coupling and cohesion while keeping complexity within a reasonable margin. An advanced refactoring tool could then devise a sequence of refactorings, which, together, result in an alternative composition of the given software system that satisfies the stated optimization goals. While the above application scenario suggests a fully-automatic quality driven refactoring process, we reduce our ambition to stimulating the awareness of the outcome of a refactoring with regard to interesting quality attributes. This would support the more modest goal of a manual quality driven refactoring process. Contribution of this part – In this part of the thesis, we elaborate on a means to construct a-priori refactoring knowledge, and demonstrate this construction process on a selected set of refactorings and coupling and cohesion metrics.
110
CHAPTER 9. QUALITY-DRIVEN REFACTORING
As a concrete result, we present impact tables, which specify a-priori knowledge on the effect of a refactoring on a set of key metrics for coupling and cohesion dimensions. These impact tables can be used to devise guidelines on the context in which to apply a refactoring to optimize coupling and cohesion. By formalizing these guidelines as extensions of the precondition of a refactoring, additional postconditions can be guaranteed that refine the more general postcondition of the refactoring. We call such refined refactorings refactoring variants. In the next chapters, we will demonstrate how such variants can be derived, thereby progressing a small step towards quality driven refactoring.
9.1.1
Structure of Part II
The remainder of this part is organized as follows: Chapter 10 presents the impact tables of a selected set of formalized refactorings and coupling and cohesion metrics. The impact derivation process itself, used to compose the impact tables, is discussed in Appendix B. These impact tables provide prediction formulae which specify how a metric value will be affected by a refactoring. Chapter 11 validates the accuracy of the impact tables. Chapter 12 exploits the impact table of one refactoring – Move Method – to devise a Move Method variant. This variant is demonstrated to optimize coupling and cohesion.
Chapter 10
Predicting Quality Impacts In this chapter, we formalize the effect of three selected refactorings on a selected set of metrics for coupling and cohesion. These formalizations are restructured in impact tables, containing formulae which can be used to predict the metric value after refactoring. The impact derivation process underlying the composition of these impact tables is presented in Appendix B. This chapter is organized as follows. First, we introduce a meta-model, which is used to formalize metrics and refactorings. Second, we present the associated impact tables, which are the result of a formal derivation. These impact tables will be validated in the next chapter.
10.1
Meta-model
In this section, we recapitulate a meta-model proposed in [Briand et al., 1996, Briand et al., 1997]. This meta-model will be used in the next sections to formalize a set of refactorings and coupling and cohesion metrics. The meta-model allows to describe the following predicates: System – An object-oriented system consists of a set of classes C. There can exist inheritance relationships between classes such that for each class c ∈ C, we define: • P arents(c) ⊂ C as the set of parent classes of class c as defined by its inheritance relationships. 111
112
CHAPTER 10. PREDICTING QUALITY IMPACTS
• Children(c) ⊂ C as the set of child classes of class c as defined by its inheritance relationships. • Ancestors(c) ⊂ C as the closure of P arents(c) • Descendents(c) ⊂ C as the closure of Children(c) Methods –
For each class c ∈ C, we define:
• MIN H (c) as the set of methods that c inherits from P arents(c). • MOV R (c) ⊂ MIN H (c) as the set of methods inherited by c but which c overrides (provides a method implementation for). • MN EW (c) as the set of methods declared in c which c did not inherit from P arents(c). Therefore, we have MN EW (c) ∩ MIN H (c) = ∅ and MN EW (c) ∩ MOV R (c) = ∅. • MD (c) as the set of methods declared in the scope of c, i.e.: (i) methods that c inherits but does not override MIN H (c) \ MOV R (c); or (ii) methods that c declares as virtual (in Java terms: abstract). • MI (c) as the set of methods implemented in c, i.e.: (i) methods that c overrides MOV R (c); or (ii) methods that c declares as non-virtual, were not inherited and therefore provides an implementation for MN EW (c). Therefore, we have MI (c) = MOV R (c) ∪ MN EW (c). • M (c) = MD (c) ∪ MI (c) = MIN H ∪ MOV R (c) ∪ MN EW (c) as the set of all methods of c. Note that MD (c) ∩ MI (c) = ∅. • M (C) = ∪c∈C M (c) as the set of all methods of the system. • For each m ∈ M (C), we define P ar(m) as the set of non-return parameters of method m. • MP U B (C) as the set of methods that are defined with public visibility in the system. Method invocations – For each class c, for each method m ∈ MI (c), we define: • M I(m) as the set of method invocations contained in m. For each method invocation i ∈ M I(m), the method called is referred to as target(i).
10.1. META-MODEL
113
Attributes – Similar to methods, we define, for each class c ∈ C: • AD (c) as the set of attributes inherited by c from P arents(c). • AI (c) as the set of attributes implemented in class c. • A(c) = AD (c) ∪ AI (c) as the set of all attributes of c. • A(C) = ∪c∈C A(c) as the set of all attributes of the system. • AP U B (C) as the set of attributes that are defined with public visibility in the system. Attribute references – define:
For each class c, for each method m ∈ MI (c), we
• AT R(m) as the set of attribute references contained in m. For each attribute reference atr ∈ AT R(m), the attribute referenced is referred to as target(atr). Types – We define the following sets of types: • BT as the set of built-in types provided by the programming language (also known as primitive types) • U DT as the set of user-defined types of global scope (e.g., enumerations). However, these are not classes. • T = BT ∪ U DT ∪ C as the set of all available types. • For each attribute a ∈ A(C), we define T (a) ∈ T as the type of a. • For each method m ∈ M (C) and each parameter p ∈ P ar(m), we define T (p) ∈ T as the type of parameter p, and T (m) ∈ T as the return-type of method m.
10.1.1
Analysis functions
In order not to expose the reader to too much detail, we merely describe those analysis functions suggested by [Briand et al., 1996, Briand et al., 1997] that will be used in the remainder of this chapter. ∀m1 , m2 ∈ M (C), ∀c ∈ C:
114
CHAPTER 10. PREDICTING QUALITY IMPACTS
• SIM (m1 ) = ∪i∈M I(m1 ) target(i), or the set of methods statically invoked by m1 . Let m1 ∈ MI (c) and m2 ∈ M (C). Then m2 ∈ SIM (m2 ) ⇐⇒ ∃i ∈ M I(m1 ) | m2 = target(i). • N SI(m1 , m2 ) =| {i ∈ M I(m1 ) | target(i) = m2 } |, or the number of static invocations from m1 to m2 . • P IM (m1 ) = {m3 ∈ M (C) | m3 ∈ SIM (m1 ) ∨ ∃m2 ∈ SIM (m1 ) ∧ m3 overrides m2 }, or the set of methods that m1 invokes due to polymorphism. • N P I(m1 , m2 ) =| {i ∈ M I(m1 ) | m2 = target(i) ∨ m2 overrides target(i)} |, or the number of polymorphic invocations by m1 to m2 . • AR(m) = ∪atr∈AT R(m1 ) target(atr), or the set of attributes referenced by m1 . MI (c) ∩ P IM (m1 ) ∪ AI (c) ∩ AR(m1 ) • uses(m1 , c) = 6= ∅, or we say that a method m1 uses a class c if and only if m1 invokes a method implemented by c (possibly due to polymorphism), or m1 references an attribute implemented by c.
10.2
Selection of Metrics
Coupling and cohesion are very wide concepts, signifying different kinds of dependencies and interrelationships. By detecting groups of measures describing similar phenomena, [Briand and W¨ ust, 2001] identified 5 coupling and 2 cohesion dimensions. In this subsection, we discuss each dimension and provide a formalization of a single indicative metric for it. The selection of a single indicative metric causes a threat to validity, as it introduces a bias towards the particular aspects of the phenomena which the metric quantifies. While it is unfeasible to eliminate this threat to validity, we choose to at least make this threat explicit by clarifying potential causes of selection bias for each of the dimensions of coupling and cohesion employed in this chapter.
10.2.1
Import Coupling
Import coupling indicates the usage of methods from other classes by a given class. The dependency on the signature and result of these methods increases
10.2. SELECTION OF METRICS
115
the likelihood and impact of change ripples. Metrics related to import coupling are presented in Table 10.1. Table 10.1: Metrics indicating import coupling Acronym MPC PIM OMMIC AMMIC ICP IH-ICP NIH-ICP
Explanation Message passing coupling. Polymorphically invoked methods. Import coupling based on method-invocations to classes unrelated by inheritance. Import coupling based on method-invocations to ancestor classes. Information-flow-based coupling. Information-flow-based coupling to ancestor classes. Information-flow-based coupling to classes unrelated by inheritance.
Acronyms of metrics related to import coupling, cited from [Briand and W¨ ust, 2001].
Different aspects of import coupling provide a finer-grained categorization of the measures: • weight of a dependency – both the number of invocations (MPC, OMMIC) and the number of parameters (ICP) increase the weight of a dependency. • relationship with the class providing the methods invoked – the providing class can be an ancestor (IH-ICP, AMMIC), not an ancestor (OMMIC, NIH-ICP) or either (ICP, MPC, PIM). • nature of the dependency – the dependency can hold at compile time (MPC, AMMIC, OMMIC) or at runtime (PIM, ICP series). As a key indicator of import coupling, we select the metric Message Passing Coupling (MPC), calculating the number of static invocations from all methods contained in a given class to methods contained in other classes. Its formal definition is provided in [Briand et al., 1996]: M P C(c) =
P
m1 ∈MI (c)
P
m2 ∈SIM (m1 )\MI (c)
N SI(m1 , m2 )
The MPC measure has three characteristics. This metric takes into account both inheritance-related classes and unrelated classes, does not weight
116
CHAPTER 10. PREDICTING QUALITY IMPACTS
the strength of coupling (e.g., based on parameters) and concentrates on compile time dependencies only. Accordingly, in case the passing of arguments or the set of methods overriding the invoked methods are regarded as considerable factors in the strength of connections, this metric is not well suited as an indicator.
10.2.2
Export Coupling
Export coupling indicates the set of responsibilities provided by a class. These responsibilities do not all have be provided by the method, but can also incorporate those delegated to other classes. Metrics related to Export Coupling are presented in Table 10.2. Table 10.2: Metrics indicating export coupling Acronym RFCi OMMEC OCMEC OCAEC
Explanation Response set for a class. Export coupling based on method-invocations to classes unrelated by inheritance. Export coupling based on parameter-instantiations in classes unrelated by inheritance. Export coupling based on attribute-instantiation in classes unrelated by inheritance.
Acronyms of metrics related to export coupling, cited from [Briand and W¨ ust, 2001].
The dependencies characterized as export coupling can be divided into two main groups: • Method based – The most intuitive manner of providing responsibilities is having methods that can be invoked by clients (RFC1 , OMMEC). However, by publishing a method, change ripples from delegated responsibilities in other classes are also exposed to clients (RFC∞ ). • Class based – A more subtle way of providing responsibilities is by providing a class declaration which clients can instantiate. Such usage of the class definition is noted for attributes (OCAEC) and method parameters (OCMEC). The metric Export coupling based on method-invocations to classes unrelated by inheritance (OMMEC) quantifies the number of static invocations from
10.2. SELECTION OF METRICS
117
methods contained in classes other than the ancestors or descendants of a given class, to methods contained in the given class. It’s formal definition is provided in [Briand et al., 1996]: OM PM EC(c) P P = c2 ∈Others(c) m1 ∈MI (c2 )
m2 ∈ SIM (m1 )∩(MN EW (c)∪MOV R (c)
N SI(m1 , m2 )
In which Others(c) = C − {c} ∪ Ancestors(c) ∪ Descendants(c) OMMEC is an indicator for method-based export coupling, as it focuses on the invocation of methods as the major form of coupling, rather than coupling caused by the instantiation of external classes in method parameters or attributes. Accordingly, in case the instantiation of external classes is regarded as a considerable factor in the strength of connections, we advice to incorporate two additional metrics, respectively focusing on the instantiation through attributes (OCAEC) and method parameters (OCMEC).
10.2.3
General Coupling
General coupling is concerned with bidirectional coupling between classes. Indications provided by general coupling measures are an aggregation (or mix) of indications on import and on export coupling. Metrics related to General Coupling are presented in Table 10.3. Table 10.3: Metrics indicating general coupling Acronym CBO CBO’
Explanation Coupling between object classes. Coupling between object classes unrelated by inheritance.
Acronyms of metrics related to general coupling, cited from [Briand and W¨ ust, 2001].
The two indicators of general coupling differ with regard to the incorporation of inheritance related classes (CBO) and general coupling exclusively with classes unrelated to inheritance (CBO’). The metric Coupling Between Object classes (CBO) is calculated as the number of classes used by or using a given class. A uses relationship can be implemented using a method invocation or an attribute reference. CBO is formalized in [Briand et al., 1996] as:
118
CHAPTER 10. PREDICTING QUALITY IMPACTS CBO(c) = CBOSet(c) with CBOSet(c) W W = d ∈ C \{c} | m1 ∈MI (c) uses(m1 , d)∨ md ∈MI (d) uses(md , c)
As it is unclear when the inclusion of classes related by inheritance would be undesirable, we do not consider this as a threat to validity.
10.2.4
Aggregation Import Coupling
Aggregation import coupling indicates the dependency of a given class on other classes based on the aggregation (or composition) relationship using attributes. Metrics related to Aggregated Import Coupling are presented in Table 10.4. Table 10.4: Metrics indicating aggregated import coupling Acronym DAC OCAIC
Explanation Data Abstraction Coupling. Import coupling based on attribute instantiation from classes unrelated by inheritance.
Acronyms of metrics related to aggregated import coupling, cited from [Briand and W¨ ust, 2001].
The aggregation or composition relationship can be refined with regard to whether the aggregated element type might be related by inheritance (DAC) or not (OCAIC). The metric Data Abstraction Coupling (DAC) counts the set of other classes which are the declared static type of a given class’s attributes. Or formally, as provided in [Briand et al., 1996]: DAC(c) =| a | a ∈ AI (c) ∧ T (a) ∈ C \ {c} | DAC is characteristic in that it also incorporates coupling to inheritance related classes. Again, we do not consider this as a threat to validity.
10.2.5
Cohesion
When methods use the same attributes, they are considered to belong together. We differentiate between non-normalized and normalized cohesion, in which the latter normalizes the result with regard to the number of methods of the class. Metrics related to cohesion are presented in Table 10.5.
10.2. SELECTION OF METRICS
119
Table 10.5: Metrics indicating cohesion Acronym LCOM1–5 Co TCC LCC ICH RCI NRCI PRCI ORCI
Explanation Lack of cohesion in methods. Connectivity. Tight class cohesion. Loose class cohesion. Information-flow-based cohesion. Ratio of cohesive interactions. Neutral ratio of cohesive interactions. Pessimistic ratio of cohesive interactions. Optimistic ratio of cohesive interactions.
Acronyms of metrics related to cohesion, cited from [Briand and W¨ ust, 2001].
The set of cohesion measures can be classified based upon many different criteria [Briand et al., 1998]. The impact of one criterion is closely related to the subject of transformations: does the measure take into account indirect connections or not. • Direct connections only – These measures state that a method accesses an attribute only in case of a direct access. This means that a method which use an accessor for a specific attribute is not regarded as accessing the attribute. These measures are LCOM1, Co, LCOM2, LCOM5, TCC and ICH. • Indirect connections – These measures state that a method accesses an attribute when it either directly accesses it, or when it invokes another method which accesses it (potentially even after a sequence of invocations). These measures are LCOM3, LCOM4, LCC, RCI, NRCI, PRCI and ORCI. Non-normalized Cohesion – The Lack of Cohesion in Methods 1 (LCOM1) metric is defined as the number of couplings of methods which do not share references to attributes in the same class. Formally, it is defined in [Briand et al., 1997] as: LCOM 1(c) = LCOM 1Set(c) with LCOM 1Set(c) = {m1 , m2 } | m1 , m2 ∈ MI (c) ∧ m 1 6= m2 ∧AR(m1 ) ∩ AR(m2 ) ∩ AI (c) = ∅
120
CHAPTER 10. PREDICTING QUALITY IMPACTS
LCOM1 is characteristic in that it disregards indirect attribute accesses. Our argument is that there is a semantical difference between a direct and an indirect attribute access: an method accessing an attribute in an indirect manner is merely an indirect client of the encapsulated data. The question is therefore whether indirect clients are also considered to be cohesive with the providing class. In case the answer is yes, we advise to use LCOM3. Normalized Cohesion – The selected metric Lack of Cohesion in Methods 5 (LCOM5) is defined formally in [Briand et al., 1997] as: LCOM 5(c) =
|MI (c)|− |A 1(c)| I
P
a∈AI (c) |{m1 |m1 ∈MI (c)∧a∈AR(m1 )}|
|MI (c)|−1
As is LCOM1, LCOM5 is characteristic in that it disregards indirect attribute accesses. One of the possible alternatives is LCC. Table 10.6: Selected metrics. Dimension Import Coupling Export Coupling
Metric Message Passing P P Coupling – M P C(c) = m1 ∈MI (c) m2 ∈SIM (m1 )\MI (c) N SI(m1 , m2 ) Export coupling based on method invocations from classes unrelated by inheritance – OM M EC(c) P P = c2 ∈Others(c) m1 ∈MI (c) P N SI(m1 , m2 )
General Coupling
Coupling betweenWobject classes – CBO(c) = d ∈ C \ {c} | m1 ∈MI (c) uses(m1 , d) W ∨ md ∈MI (d) uses(md , c) Data Abstraction Coupling – DAC(c) =| a | a ∈ AI (c) ∧ T (a) ∈ C \ {c} |
m2 ∈ SIM (m1 )∩(MN EW (c)∪MOV R (c)
Aggregated Import Coupling Normalized Cohesion Nonnormalized Cohesion
Lack of cohesionPin methods – LCOM 5(c) |MI (c)|−
1
a∈A (c) |{m1 |m1 ∈MI (c)∧a∈AR(m1 )}|
|AI (c)| I = |MI (c)|−1 Lack of Cohesion in methods – LCOM 1(c) = {m1 , m2 } | m1 , m2 ∈ MI (c) ∧ m1 6= m2 ∧AR(m1 ) ∩ AR(m2 ) ∩ AI (c) = ∅
Formal description of the selected indicative class metrics for each of the dimensions of coupling and cohesion.
10.3. SELECTION OF REFACTORINGS
10.2.6
121
Summary
Summarizing, we have selected a single indicative metric for each of 5 coupling and 2 cohesion dimensions. Table 10.6 recapitulates their acronyms and formalizations.
10.3
Selection of Refactorings
In this section, we formalize a selected set of refactorings in terms of the metamodel presented by [Briand et al., 1996, Briand et al., 1997]. Accordingly, the formalizations of pre- and postconditions will form merely a subset of those required for the implementation of the refactorings. I.e., the implementation might incorporate more entities and relationships then merely the ones present in the meta-model presented earlier. However, w.r.t. the selected meta-model, the formalizations are claimed to be complete, which is sufficient to reason about these refactorings w.r.t. their effect on the selected coupling and cohesion metrics. The objective of our selection is to investigate those refactorings which redistribute responsibilities either within the class or in between classes. This redistribution is the main principle to address coupling and cohesion issues. For a population as vast and as diverse as the population of refactorings, it is infeasible to be representative. Moreover, this population is ever growing, as every day, software engineers are describing more source code transformations satisfying the definition of a refactoring. Accordingly, we do not have the ambition to generalize the results of our small set of selected refactorings to other refactorings. Rather, we acknowledge that properties of refactorings are specific to the selected refactoring. In contrast, our selection criteria aims to “compose a small set of refactorings which redistribute responsibilities by manipulating method interactions within or between classes”. Therefore, we choose to select 3 refactorings which are categorized in Martin Fowler’s refactoring catalogue in the categories Composing Methods and Moving features between objects [Fowler, 1999]: Extract Method: This refactoring is supported in most popular refactoring tools (e.g., in refactoring such as tools Eclipse, IntelliJ Idea, RefactorIT, JRefactory and XRefactory). Extract Method supports the goal of responsibility redistribution by enabling the disentangling of multiple responsibilities from a single method.
122
CHAPTER 10. PREDICTING QUALITY IMPACTS
Move Method: This refactoring as well is supported in the refactoring tools mentioned earlier. The Move Method refactoring is fundamental to responsibility redistribution by enabling the migration of methods between classes. Replace Method with Method Object: To the best of our knowledge, this refactoring is not supported by current refactoring tools. Nonetheless, it supports the goal of responsibility redistribution by moving the body of a method which entwines multiple responsibilities to a separate class. The suggested procedure to continue disentangling these responsibilities (as indicated by [Fowler, 1999]), is to extract methods and move them to more appropriate classes. Without empirical studies on the usage of refactorings in an industrial context, it is hard to quantify the practical importance of these refactorings. Nonetheless, the support of Extract Method and Move Method in most current refactoring tools indicates that these refactorings are popular operations. This cannot be stated of the the Replace Method with Method Object operation. Through a meta-analysis of the dependencies between Fowler’s 72 refactorings, [Wheeldon and Counsell, 2003] searched for core refactorings, upon which many other refactorings depend. The three most important of these core refactorings are Extract Method, Move Field and Move Method. Accordingly, our selection of three refactorings comprises a basic set of transformations which provide fundamental support for redistributing responsibilities. In the next subsections, we present their pre- and postconditions expressed in the same meta-model as in which the selected refactorings were formalized.
10.3.1
Notation
The notation used for the formalization of the pre- and postcondition of the three selected refactorings is similar to the one employed in [Roberts, 1999]. The value of a predicate of entities or relations before applying the refactoring is referred to in the predicate’s usual notation. E.g., we refer to the set of methods implemented by a class c before refactoring as MI (c). In contrast, to refer to the value of a predicate after applying the refactoring, we write an accent behind the predicate. E.g., we refer to the set of methods implemented by a class c after refactoring as MI0 (c). A refactoring’s postcondition is expressed as the specification of the value of predicates after applying the refactoring in terms of the value of these predicates
10.3. SELECTION OF REFACTORINGS
123
before applying the refactoring. E.g., to indicate that a refactoring will cause a class c to implement a new method m, the postcondition of this refactoring specifies that MI0 (c) = MI (c) ∪ {m}. This means that refactoring will cause the set of implemented methods of class c to be expanded with a new method m.
10.3.2
Extract Method
Extract Method extracts a set of statements appearing in one or more methods into a new method. Its signature is: ExtractM ethod C c, M ms , P(M I) I, P(AT R) A , for which: • c is the class in which the method is to be extracted; • ms is the method from which the statements will be extracted; • I ∪ A characterizes the set of statements S that will be extracted. I represents the set of method invocations, and A represents the set of attribute references. It is important to note that our formal specification of Extract Method targets the extraction of a single instance of a set of statements to a separate method. In contrast, current refactoring tools (e.g., incorporated in the Eclipse IDE) detect duplicate instances of this set of statements and replace all these duplications with a method invocation to the separated method. Most likely, such a multi-instance Extract Method application will affect coupling and cohesion indicators differently than the single instance Extract Method discussed in this work. Precondition The precondition for Extract Method requires that the given method ms is implemented by the given class c, and that the given sets of method invocations I and attribute references A are contained in ms . Or formally: • ms ∈ MI (c) • I ⊂ M I(ms ) • A ⊂ AT R(ms ) Additional preconditions which are unrelated to our study are: • The set of statements S should be uninterupted by statements outside S;
124
CHAPTER 10. PREDICTING QUALITY IMPACTS
Postcondition The postcondition is extracted from the informal description provided in [Fowler, 1999]. The postcondition poses that, after applying Extract Method, c will implement a new method mt which contains the method invocations and attribute references selected from ms . The selected part of ms will be replaced with a single method invocation to mt . Or formally: • M 0 (C) = M (C) ∪ {mt }, in which mt represents a the newly extracted method 0 • MN EW (c) = MN EW (c) ∪ {mt }
• M I 0 (mt ) = I • AT R0 (mt ) = A • M I 0 (ms ) = M I(ms ) \ I ∪ i, in which i is a new method invocationfrom ms to mt , i.e., target(i) = mt. Therefore, M I 0 (m s ) = M I(ms ) \ m ∈ M I(ms ) |6 ∃m1 ∈ M I(ms ) \ I : target(m1 ) = m 0 • AT R0 (ms ) = AT R(ms ) \ A, and therefore, AR (ms ) = AR(ms ) \ a ∈ AR(ms ) |6 ∃a1 ∈ AT R(ms ) \ A : target(a1 ) = a An additional postcondition, unrelated to our study, is that the set of parameters of mt is determined by the number of local variables of ms that are referenced and/or updated in S. As our selected coupling and cohesion metrics do not involve parameters, this postcondition can be disregarded in our study.
10.3.3
Move Method
Move Method moves a method from one class to another, possibly adding a parameter when resources of the original class are used: M oveM ethod C cs , M m, C ct , for which • cs signifies the class from which the method will be moved, also referred to as the source class; • m signifies the method which will be moved; • ct signifies the class to which the method will be moved, also referred to as the target class;
10.3. SELECTION OF REFACTORINGS
125
Precondition The Move Method precondition requires that the target class ct is different from the source class. The given method m should be a public method, implemented (and not overridden) by the source class, invoking only public methods and referencing only public attributes of the source class. Otherwise, these methods and attributes will no longer be visible when the method is moved. Additionally, the method to be moved may not be overridden itself in descendants of the source class, and the inheritance hierarchy of the target class may not declare a method with a signature similar to m. Formally, this precondition is described as: • cs 6= ct • m ∈ MN EW (cs ) ∩ MP U B (cs ) or m is a public method implemented by cs • M (cs ) ∩ SIM (m) ⊂ MP U B (cs ), or m is only allowed to invoke public methods of its source class. • A(cs ) ∩ AR(ms ) ⊂ AP U B (cs ), or ms is only allowed to reference public attributes of its source class. • m is not overridden in Descendants(cs ) S • 6 ∃mt ∈ c∈Descendants(ct )∪{ct } : mt ∈ M (c) ∧ mt has the same signature as m. Postcondition The postcondition is extracted from the informal description provided in [Fowler, 1999]. The postcondition states that the Move Method refactoring will cause m to be no longer implemented by the source class cs , but by the target class ct . Formally, we have: • m 6∈ MI0 (cs ) • m ∈ MI0 (ct ) An additional postcondition unrelated to our study is that, after the method is moved, its parameter set will be expanded with an additional parameter ps in case m invokes a method or references an attribute implemented by cs , with T 0 (ps ) = cs . This additional parameter would be required to be able to enable these invocations and references.
126
10.3.4
CHAPTER 10. PREDICTING QUALITY IMPACTS
Replace Method with Method Object
Replace Method with Method Object creates a new class, which has only one method and a constructor. The local variables and parameters of the method are promoted to attributes of the newly created class. Its signature is: RM W M O C cs , M ms , P(LV ) L , for which • cs signifies the class from which the method will be replaced; • ms signifies the method which will be replaced; • L signifies the set of local variables L contained in ms . Precondition The precondition for Replace Method with Method Object requires that the method to be replaced is implemented by the source class, and does only invoke or reference public methods and attributes of the source class. • ms ∈ MI (cs ) • M (cs ) ∩ SIM (ms ) ⊂ MP U B (C), or ms does not invoke non-public methods of it’s source class. • A(cs ) ∩ AR(ms ) ⊂ AP U B (C), or ms does not reference non-public attributes of it’s source class. Postcondition The postcondition is extracted from the informal description provided in [Fowler, 1999]. The postcondition stipulates that the refactoring will cause the introduction of a new class ct , implementing two new methods: a constructor mct and a method mt similar in name to the method to be replaced ms . The constructor will have copies of the parameters of ms and an additional parameter to pass the original instance of the source class to. The newly created class ct will declare an attribute for each local variable of ms , for each parameter of ms , and additionally, an attribute as a reference to the original instance of the source class. The constructor mct of the newly created class ct will be responsible for initializing those attributes which are copies of the parameters of method ms with the corresponding values of its parameters. Therefore, the constructor will
10.3. SELECTION OF REFACTORINGS
127
contain one attribute reference for each of these attributes. The constructor mct will invoke no methods. The new method mt of the newly created class ct is in fact the method which will replace the method body of ms . Accordingly, mt will reference all the attributes which ms did. Furthermore, mt will have no parameters, as the newly created class ct provides an attribute as a copy of each parameter of ms . Thus, mt will additionally reference all attributes declared by the newly created class ct . Also, method mt will perform all method invocations which ms did. Thus, if ms invoked itself, mt will mimic this behavior by also invoking ms (and not itself, which might otherwise change behavior due to potential polymorphic calls to methods overriding ms ). Finally, the replacement of the method body of ms is performed through the removal of all attribute references from ms , and the replacement of all method invocations from ms with two new method invocations: one to the constructor mct of the newly created class ct and one to the method mt replacing its method body. • C 0 = C ∪ {ct }, in which ct represents the newly created class • M 0 (C) = M (C) ∪ {mt , mct }, in which mt represents the replaced method and mct represents the constructor 0 • MN EW (ct ) = {mt , mct }
• P ar0 (mt ) = ∅ • P ar0 (mct ) = LP ∪ {ps }, in which LP represents a set of parameters which correspond by type to P ar(ms ). Moreover, ps represents an additional parameter for the source class. I.e., T 0 (ps ) = cs . • A0 (C) = LA ∪ P A ∪ {as }, in which LA represents a set of attributes which correspond by type to the set of local variables L contained in ms . P A represents a set of attributes which correspond by type to P ar(ms ) Moreover, as represents an additional attribute for the source class. Thus, T (as ) = cs . • A0I (ct ) = LA ∪ P A ∪ {as } S • AT R0 (mct ) = a∈A0 (ct )\{LA} new AT R(mct , a) where new AT R(mct , a) I represents the creation of a new attribute reference from method mct to attribute a.
128
CHAPTER 10. PREDICTING QUALITY IMPACTS Therefore, AR0 (mct ) = A0I (ct ) \ LA, or the new constructor mct will initialize all attributes of ct , accept the ones that represents the previous local variables. These will be initialized by mt .
• M I 0 (mct ) = ∅, or the new constructor will not invoke any other methods. S • AT R0 (mt ) = a∈A0 (ct )∪AR(ms ) new AT R(mt , a). I
0
Therefore, AR (mt ) = A0I (ct )∪AR(ms ), or the new method mt will behave like the former ms with regard to attribute references, but it will additional reference attributes instead of local variables or parameters. • M I 0 (mt ) = M I(ms ), or the new method mt will behave like the former ms with regard to method invocations. • AT R0 (ms ) = ∅, or the method to be replaced will no longer contain attribute references Therefore, AR0 (ms ) = ∅, or the former method ms will no longer reference attributes. This is taken over by the new method mt . • M I 0 (ms ) = {mi1 , mi2 }, in which mi1 is a method invocation from the former method ms to the constructor mct to instantiate an object of type ct , and mi2 is a method invocation from ms to the new method mt . I.e., target(mi1 ) = mct and target(mi2 ) = mt .
10.4
Quality Impact Prediction
In this section, we present the impact tables specifying the prediction of the value of the selected coupling and cohesion metrics as affected by the three selected refactorings. These impact tables are composed through a formal derivation process. We decide to present this derivation process in Appendix B. We argue that it is better to postpone the presentation of this process until the exploitation of the impact tables is discussed in Chapter 12 in a case study. This order will better clarify the relevance of the derivation process itself. Accordingly, we first present the impact tables themselves. In the next chapter (Chapter 11), the validation of these impact tables is presented. Subsequently, in Chapter 12, we discuss the exploitation of the validated impact tables for a refinement of a refactoring variant, optimizing the selected coupling and cohesion metrics. Only after this goal has been achieved, we feel that the
10.4. QUALITY IMPACT PREDICTION
129
time is right to discuss the formal derivation process itself, which otherwise might burden the understanding of the path towards refactoring variants.
10.4.1
Extract Method
Table 10.8 summarizes the effect of applying Extract Method on the selected set of indicative metrics for the different dimensions of coupling and cohesion. This effect description states that a single-instance Extract Method application (not replacing duplicate statements) does not affect coupling. In contrast, cohesion is potentially reduced, due to the introduction of a new method. Table 10.7: Impact table for Extract Method MPCpred (c) OMMECpred (c) CBOpred (c) DACpred (c) LCOM5pred (c) with t1
= = = = = =
t2
=
t3 LCOM1pred (c) with t1
= = =
t2
=
t3
=
Prediction formula MPCbef (c) OMMECbef (c) CBObef (c) DACbef (c) t1 .LCOM5bef (c) + t2 + t3 |MI (c)|−1
|MI (c)| a∈AI (c)∩AR(ms )|6∃a1 ∈
AT R(ms )\A :target(a1 )=a |AI (c)|.|MI (c)| S |AI (c)\ atr∈A target(a)| |AI (c)|.|MI (c)|
bef (c) + t1 + t2 + t3 LCOM1 {m1 , ms } | m1 ∈ MI (c) \ {ms } ∧ AR(m1 ) ∩ AR(ms ) ∩ AI (s) 6= ∅ ∧ AR(m S 1 ) ∩ AR(ms ) ∩ AI (c) ⊆ target(atr) S atr∈A \ atr∈AT R(ms )\A target(atr) {m1 , mt } | m1 ∈ MI (c) \ {ms } S ∧ AR(m1 ) ∩ S atr∈A target(atr) ∩ AI (c) = ∅ {ms , mt } | atr∈AT R(ms )\A target(atr) S ∩ atr∈A target(atr) ∩ AI (c) = ∅
Formal description of the effect of applying Extract Method on class metrics.
The potentially harmful effect w.r.t. cohesion can be explained as follows. Extract Method makes the relationship between the extracted set of statements
130
CHAPTER 10. PREDICTING QUALITY IMPACTS
and the other methods of the current class more explicit. Therefore, if the extracted statements are unrelated to the current class, this will become visible in reduced cohesion. In such cases, the extracted method is typically moved to a more appropriate host in a new refactoring step, e.g., using Move Method. This in fact demonstrates a typical strategy for redistributing functionality between classes: first disentangle existing responsibilities and then redistribute them across the class hierarchy. We discuss the predicted effect on coupling metrics for normalized and nonnormalized cohesion separately: Normalized cohesion – The Lack of Cohesion in Methods metric LCOM5 is an inverse cohesion metric. Accordingly, its value indicates the extent to which cohesion is violated. Thus, the increase predicted by Table 10.7 based on the two terms t2 and t3 signifies an actual decrease in cohesion. However, the prediction formula also indicates that the Extract Method refactoring might, in some cases, improve cohesion, as indicated by term t1 (≤ 1). The second term, t2 , calculates the number of attributes, implemented by class c, which are referenced in the method m from which statements will be extracted. From this set of attributes, t2 selects those attributes which are not referenced in the remaining statements of m. This set therefore indicates the set of attributes which method m will no longer reference after the Extract Method is applied. The size of term t2 is relative to the number of attributes and methods implemented by c. The third term, t3 , calculates the number of attributes, implemented by class c, which the extracted statements do not reference. This set indicates the set of attributes which the new method mt will not reference, after the Extract Method is applied. Again, the size of this term is relative to the number of attributes and methods implemented by c. Term t1 (always ≤ 1) indicates that, in case the extracted and remaining statements both reference all the attributes implemented by class c, then a resulting increase in cohesion is relative to the number of methods implemented by c. E.g., if class c implements two methods m1 and m2 , and m1 consists of two blocks of statements b1 , b2 which both reference all attributes implemented by c, then the extraction of either block b1 or b2 will reduce the lack of cohesion of class c by half. Non-normalized cohesion – The non-normalized variant of Lack of Cohesion in Methods, metric LCOM1, is also an inverse cohesion metric. The
10.4. QUALITY IMPACT PREDICTION
131
prediction formula mentioned in Table 10.7 predicts the LCOM1 metric value to be increased after applying the Extract Method refactoring, dictated in three terms t1 , t2 and t3 . Table 10.8: Impact description for Extract Method. Metric M P C(c) OM M EC(c) CBO(c) DAC(c) LCOM 5(c)
Value after refactoring Will remain unchanged. Will remain unchanged. Will remain unchanged. Will remain unchanged. Will be (t2 ) increased proportionate to the number of sibling attributes which the remaining statements do not reference; (t3 ) and additionally increased proportionate to the number of sibling attributes which the extracted statements do not reference.
LCOM 1(c)
Will be (t1 ) increased with the number of sibling methods which share references to sibling attributes with the extracted statements, but not with the remaining statements; (t2 ) and additionally increased with the number of sibling methods which do not share references to sibling attributes with the extracted statements; (t3 ) and additionally increased with 1 in case the remaining statements do not share references to sibling attributes with the extracted statements.
Summarizing description of the effect of Extract Method on class metrics.
The first term, t1 , represents the number of methods implemented by class c with which the original method m shared attribute references before refactoring. In case the remaining statements no longer share references with these methods, an increase in lack of cohesion is introduced.
132
CHAPTER 10. PREDICTING QUALITY IMPACTS Term t2 dictates a similar increase in lack of cohesion, corresponding to the number of methods (excluding the original method m), with which the extracted statements do not share attribute references. Lastly, term t3 specifies that, in case the extracted and remaining statements do not share attribute references, than after refactoring, the original method and the newly created method will not be cohesive.
This effect description is summarized in Table 10.8.
10.4.2
Move Method
The impact table of Move Method is presented in Table 10.9. We discuss each prediction formula separately: MPC: The Message Passing Coupling value is predicted to be decreased with a term t1 , and increased with a term t2 . The decrease is due to the method invocations contained in the method to be moved, which will no longer depart from the source class (t1 ). The increase, as represented by t2 , indicates that, in case the other methods of the source class cs invoke the method to be moved, then these method invocations will be considered outgoing invocations after the move operation. OMMEC: The value of the selected metric for export coupling is also predicted to be both increased and decreased. Similar to the effect of Move Method on import coupling, after the method is moved, method invocations involving this method will be considered invocations to or from a different class. Term t1 describes a decrease of OMMEC with the number of method invocations from methods implemented by classes other than the source class cs to the method to be moved m. In contrast, method invocations from m to the other methods of the source class will be added to the OMMEC metric value after refactoring (t2 ). CBO: The impact table specifies that the Coupling Between Objects metric value will be altered by the Move Method refactoring in three ways, formalized in terms t1 , t2 and t3 . First, classes other than the source and target class that were coupled exclusively to the source class via the method to be moved m will no longer be incalculated in the CBO metric value after refactoring (t1 ).
10.4. QUALITY IMPACT PREDICTION
133
Table 10.9: Impact table for Move Method MPCpred (cs ) with t1 t2 OMMECpred (cs ) with t1 t2 CBOpred (cs ) with t1 =
t2 =
t3 =
DACpred (cs ) LCOM5pred (cs ) with t1 t2 LCOM1pred (c) with t1
= = = = = =
Prediction formula MPCbef (cs ) - t1 + t2 P N SI(m, m2 ) Pm2 ∈SIM (m)\MI (cs ) N SI(m 1 , m) m1 ∈MI (cs )\{m} OMMECbef (csP ) - t1 + t 2 P m1 ∈MI (c2 ) N SI(m1 , m) s) Pc2 ∈Others(c N SI(m, m2 ) m2 ∈
SIM (m)∩(MN EW (cs )∪MOV R (c)) \{m}
= CBObef (cs ) - t1 -t2 + t3 x ∈ C \ {cs , ct } | uses(m, x) ∨ ∃md ∈ MI (x) : m ∈ P IM (md ) ∧ 6 ∃ms ∈ MI (cs ) \ {m} : uses(ms , x) ∧ ∀md ∈ MI (x) : (MI (cs ) \ {m}) ∩ P IM (md ) ∪(AI (cs ) ∩ AR(md )) = ∅ x ∈ {ct } | uses(m, ct ) ∨ ∃md ∈ MI (ct ) : m ∈ P IM (md ) ∧ 6 ∃ms ∈ MI (cs ) \ {m} : uses(ms , ct ) ∧ ∀md ∈ MI (ct ) : (MI (cs ) \ {m}) ∩ P IM (md ) ∪(AI (cs ) ∩ AR(md )) = ∅ W m ∈ P IM (ms ) x ∈ {ct } | ms ∈ MI (cs )\{m} ∨ MI (cs ) \ {m} ∩ P IM (m) 6= ∅ ∧ ¬uses(ct , cs ) = DACbef (cs ) = t1 . LCOM5bef (c) - t2 |MI (c)|−1 = |M I (c)|−2 |AI (cs )\AR(m)| = |AI (cs )|. |MI (cs )|−1
= =
bef (c) - t1 LCOM1 m1 | m1 ∈ MI (cs ) \ {m} ∧m1 6= m ∧ AR(m1 ) ∩ AR(m) ∩ AI (cs ) = ∅
Formal description of the effect of applying Move Method on class metrics.
Second, term t2 describes a similar consequence, but then specified for
134
CHAPTER 10. PREDICTING QUALITY IMPACTS the target class. In case method m was the only cause of coupling from the source class to the target class, then the target class will no longer be coupled to the source class via m. Lastly, in case the target class was not coupled to the source class, this might be altered after the Move Method refactoring. Term t3 specifies that this will occur in case the other methods of the source class invoke the method to be moved m, or in case m invokes the other methods of the source class.
DAC: The Data Abstraction Coupling metric value is predicted not to be affected by the Move Method refactoring. This can be explained by the fact that the Move Method refactoring does not create or remove attributes, and nor does it change the type of attributes implemented by the source class. The prediction formulae w.r.t. the selected cohesion metrics can be interpreted as follows: LCOM5: The normalized lack of cohesion variant is predicted to be affected by two terms, t1 and t2 . The first term, t1 , is a multiplication factor (always ≥ 1). Accordingly, it dictates that the effect of applying Move Method on a class which has only few methods will be larger than an equivalent application on a class with many methods. The second term, t2 , calculates the number of attributes implemented by the source class cs that are not referenced by the method to be moved. Again, the size of this term is relative to the number of attributes and methods implemented by c. LCOM1: The prediction formula for the non-normalized lack of cohesion variant is predicted to be decreased with the number of other methods implemented by the source class that do not share references with the method to be moved. Once again, we summarize the description of the predicted effect in a separate table, namely Table 10.10.
10.4. QUALITY IMPACT PREDICTION
135
Table 10.10: Impact description for Move Method. Metric M P C(cs )
OM M EC(cs )
CBO(cs )
DAC(cs ) LCOM 5(cs )
LCOM 1(cs )
Value after refactoring Will be decreased with the number of static invocations from the method to be moved to external methods; and additionally increased with the number of static invocations from the other methods implemented by the source class to the method to be moved. Will be decreased with the number of static invocations from methods implemented by classes not contained in the source class’ inheritance hierarchy to the method to be moved (t1 ); and additionally increased with the number of static invocations from the method to be moved to other new or overridden methods from the source class (t2 ). Will be (t1 ) decreased with the number of classes (6= ct ) coupled to the source class exclusively by the method to be moved; (t2 ) additionally decreased with 1 in case the target class is coupled to the source class exclusively by the method to be moved, which may in that case also not invoke or reference other methods or attributes from the source class; and (t3 ) additionally increased with 1 in case the target class is not coupled to the source class, and either: (i) any sibling method uses the method to be moved; or (ii) the method to be moved uses any sibling method or attribute. Will remain unchanged. Will be decreased proportionate to the number of attributes implemented by the source class, which the method to be moved does not reference (t2 ). Will be decreased with the number of methods implemented by the source class that do not share references to sibling attributes with the method to be moved (t1 ).
Summarizing description of the effect of Extract Method on class metrics.
10.4.3
Replace Method with Method Object
Table 10.11 stipulates how the Replace Method with Method Object refactoring will affect the selected coupling and cohesion metrics.
136
CHAPTER 10. PREDICTING QUALITY IMPACTS
MPC: The selected metric for import coupling, Message Passing coupling, is predicted to be decreased with (t1 ) the number of invocations from the method to be replaced (ms ). Additionally, as the method body of this method will be replaced with an invocation to the constructor of the newly created class ct , and an invocation to the new method of ct , two new invocations will be incalculated in the MPC metric value after refactoring. Table 10.11: Impact table for Replace Method w Method Object MPCpred (cs ) with t1 OMMECpred (cs ) with t2 CBOpred (cs ) with t1 =
= = = =
Prediction formula MPCbef (cs ) - t1 + 2 P m2 ∈SIM (m)\MI (cs ) N SI(ms , m2 ) OMMECbef (cs ) + t1 P m2 ∈ SIM (ms )∩(MN EW (cs )∪MOV R (cs )
N SI(ms , m2 ) = n CBObef (cs ) - t1 + 1 x ∈ C \ {cs } | uses(ms , x) o V ∧ mc ∈(MI (cs )\{ms }) ¬uses(mc , x) ∧¬uses(x, cs )
DACpred (cs ) LCOM5pred (cs ) with t1
= = =
DACbef (cs ) LCOM5bef (c) + t1 |AR(ms )∩AI (cs )|
LCOM1pred (cs ) with t1
= =
bef (c) + t1 LCOM1 {m1 , ms } | m1 ∈ MI (cs ) ∧ m1 6= ms ∧ AR(m1 ) ∩ AR(ms ) ∩ AI (cs ) 6= ∅
|AI (cs )|. |MI (cs )|−1
Formal description of the effect of applying Replace Method with Method Object on class
metrics.
OMMEC: The prediction formula for OMMEC states that (t1 ) the number of method invocations from the method to be replaced ms to other methods of the source class cs will be added to the OMMEC metric value. CBO: As the Replace Method with Method Object refactoring incorporates the creation of a new class and its usage by the source class, a fixed value of 1 will be added to the CBO metric value after refactoring. However, (t1 ) the number of classes used only by ms and not by the other methods of the source class will decrease the value of the CBO metric, on the condition that the methods of these classes do not use the source class.
10.4. QUALITY IMPACT PREDICTION
137
DAC: As was the case for the two other refactorings, neither is the Replace Method with Method Object predicted to affect the Data Abstraction Coupling metric. Once again, this can be explained by the fact that this metric does not affect the attributes of the source class. Lastly, we discuss the prediction formulae w.r.t. the selected coupling metrics: Table 10.12: Impact description for Replace Method with Method Object Metric M P C(cs )
OM M EC(cs ) CBO(cs )
DAC(cs ) LCOM 5(cs ) LCOM 1(cs )
Value after refactoring Will be decreased with the number of static invocations from ms to methods implemented by classes other than cs (t1 ); and additionally increased with 2 Will be increased with the number of static invocations from ms to new and overriding sibling methods(t2 ). Will be decreased with the number of classes for which ms is the single cause of coupling (t1 ); and additionally increased with 1 Will remain unchanged. Will be increased proportionate to the number of sibling attributes, which ms references (t1 ). Will be increased with the number of sibling methods that share references to sibling attributes with ms (t1 ).
Summarizing description of the effect of applying Replace Method with Method Object on class metrics.
LCOM5: The LCOM5 metric value is predicted to be increased with a single term t1 . This term calculates the number of attributes implemented by the source class, which the method to be replaced references. Term t1 is relative to the number of attributes and methods implemented by the source class, indicating that this effect is relative to the size of a class. LCOM1: After performing the Replace Method with Method Object refactoring, the LCOM1 metric value is predicted to be increased with (t1 ) the number of other methods implemented by the source class that share attribute references with the method to be replaced ms . This can be explained by the fact that, after refactoring, the method body of ms will no longer contain attribute references.
138
CHAPTER 10. PREDICTING QUALITY IMPACTS
A summary of the predicted effect of Replace Method with Method Object is provided in Table 10.12. Accordingly, we have presented three impact tables, which we will validate in the next chapter.
Chapter 11
Validating Predicted Impacts In this chapter, we report on the validation of the impact tables presented in the previous chapter. These impact tables provide formalizations of a-priori knowledge w.r.t. the effect of applying a refactoring on indicative metrics for coupling and cohesion. As a means for validation, we compare the values of the selected metrics before and after refactoring with the value predicted by the impact tables.
11.1
Introduction
For each of the three refactorings discussed in the previous chapter, we validate the associated impact table according to the following stepwise procedure: 1. Collect a set of refactoring candidates, satisfying the precondition of the refactoring. These candidates are characterized by the parameters mentioned in the signature of the formalized refactorings. E.g., the signature of the Extract Method refactoring is defined as ExtractM ethod C cs , M ms , P(M I) I, P(AT R) A . Extract Method candidates are therefore characterized by a specification of a class cs , a method ms , and a set of method invocations I and attribute references A. A refactoring candidate provides these arguments, which satisfy the precondition of Extract Method as specified in the previous chapter. In other words, refactoring 139
140
CHAPTER 11. VALIDATING PREDICTED IMPACTS candidates indicate where a refactoring can be applied.
2. Select a set of refactoring candidates. For each refactoring, our selection consists of ten refactoring candidates. This selection provides a variation of the different terms described by the predicted metric impact. Each prediction describes the value of a metric after refactoring as a formula of the metric value before refactoring, plus and/or minus a number of terms. These terms consist of queries for which the cardinality of the result set is taken. By assuring that different candidates have different values for these terms (e.g., some have a value of zero for a term, while others do not), we can verify the accuracy of the prediction formula under different conditions, thereby strengthening the validation. 3. Collect the metric values of the classes associated with the selected refactoring candidates. This collection provides the metric values before refactoring. For each metric M etric, the value before refactoring is referred to as M etricbef . 4. Calculate the different terms of the prediction formulae in the impact table for the code fragment associated with the refactoring candidate before refactoring. 5. Apply the selected refactoring candidates. For this step, we use the Eclipse IDE (v3.2M4). Eclipse provides automated support for the Extract Method and Move Method refactorings. In contrast, we apply Replace Method with Method manually as this refactoring is not automated in Eclipse. The transformation process for this refactoring is dictated by the specification of the Replace Method with Method Object refactoring, as presented in the previous chapter. 6. Collect the metric values of the classes associated with the selected refactoring candidates. This collection provides the metric values after refactoring. For each metric M etric, the value after refactoring is referred to as M etricaf t . 7. Apply the prediction formula by substituting the calculated values for the different terms (step 4). For each metric M etric, substituting these calculated terms provides the predicted value after refactoring, referred to as M etricpred .
11.1. INTRODUCTION
141
8. Verify that the predicted value after refactoring is equal to the actual value after refactoring, i.e., that M etricpred = M etricaf t . This step is reported in the validation tables reported on in the next section. This procedure leads to the validation of each prediction formula presented in the impact tables for Extract Method (Table 10.7), Move Method (Table 10.9) and Replace Method with Method Object(10.11). In case we found that M etricpred 6= M etricaf t , this was due to a defect in the impact derivation presented in Chapter B, which was then corrected, followed by a restart of the validation procedure.
11.1.1
System Under Study
To collect refactoring candidates, we analyze software systems that are likely to contain many refactoring candidates. As systems under study, we selected two systems written in Java: (i) the open source UML modeling tool ArgoUML1 ; and (ii) a toy-example used frequently in software engineering research, entitled the LAN simulation [?]: ArgoUML v0.19.8 was released in November 2005, about 11 years after its initial design. We select ArgoUML because it is a software system of reasonable size (ArgoUML contains about 1300 classes) and has a considerable development history. The project started in 1994 and provides monthly releases. These monthly releases demonstrate a process of continuous extension, in which opportunities for refactoring are likely to be found. Therefore, we expect to have no problems detecting refactoring candidates. The LAN Simulation v2.0 is a toy example consisting of 5 classes, written in Java. We collect refactoring candidates in this software system in case a specific combination of term values is uncommon in practice. For example, part of the precondition of the Replace Method with Method Object refactoring requires that the method to be moved does not reference non-public attributes. However, the prediction formulae for the selected cohesion metrics incorporate references to attributes in their terms. Therefore, in order to exploit variation in these terms, we adapted the source code of the LAN simulation. These artificially created refactoring candidates enable us to validate the prediction formulae for the Replace Method with Method Object refactoring in the uncommon case of a class having public attributes referred by its methods. 1 http://www.argouml.tigris.org
142
CHAPTER 11. VALIDATING PREDICTED IMPACTS
Accordingly, these software systems provide us with candidates for the three selected refactorings.
11.1.2
Measurement Instrument
As a means to collect the metric values before and after refactoring, as well as the values for the terms mentioned in the prediction formulae, we implemented two tools. First, a tool was implemented to transform an Abstract Syntax Tree (AST) representation of a software system to a representation in an implementation of the metamodel discussed in section 10.1 (originating from [Briand et al., 1996, Briand et al., 1997]). The tool is implemented as an Eclipse plugin, and employs the AST representation provided by the Eclipse Java Development Tools (JDT) as the input for the transformation. Accordingly, we applied the tool to construct a representation of both ArgoUML and the LAN simulation as instances of the metamodel described in section 10.1. A second tool was implemented to calculate the selected coupling and cohesion metrics on the representations of ArgoUML and the LAN simulation. As this metamodel was identical to the metamodel in which the metrics were formalized, we are confident that the metric definitions are implemented correctly. This metric tool is used to collect the metric values before and after refactoring, and also to calculate the value of the terms specified in the prediction formulae.
11.2
Data Analysis
In this section we present the data collected for validating the impact tables. The validation is based on the calculation of the following values: Metricbef : Metric value before applying the refactoring. Metricaf t : Actual metric value after applying the refactoring. In case Metricaf t equals Metricbef , we indicate this by writing a tilde (∼). Otherwise, we write the actual value. Metricpred : Prediction of the metric value after applying the refactoring. This prediction is dictated by the formulae in the impact table of each refactoring. In case √ Metricpred equals Metricaf t , we indicate this by writing a check mark ( ). In the rare event where this is not the case, we write the actual predicted value.
11.2. DATA ANALYSIS
143
ti : Value of the i-th term of a prediction formula. For each selected refactoring, we verify that, for each selected metric, it holds that Metricpred = Metricaf t . In other words, we verify that the predicted value equals the actual value after applying the refactoring. We demonstrate this equality in tables illustrating the calculation of Metricpred .
11.2.1
Extract Method
The impact table which is validated in this subsection is specified in the previous chapter in Table 10.7 and informally described in Table 10.8. Effect on coupling metrics – The Extract Method refactoring is predicted not to affect the selected coupling metrics. Tables 11.1 – 11.4 illustrate the result of the validation for these predictions. The rows in each table signify either the value of the metric before (Metricbef ) or after (Metricaf t ) applying the refactoring candidate. The last row provides the prediction of the value of the metric after refactoring (Metricpred ). A table confirms the accuracy of the prediction of √ the effect of a refactoring on a metric in case the Metricpred row is filled with marks. As illustrated in Table 11.1, the predicted value corresponds to the actual value after refactoring for all Extract Method candidates except candidate 8. For Extract Method candidate 8, we observe that MPCpred =45, which is not equal to the actual value 42. For this Extract Method candidate, Eclipse detected a duplicate of the extracted statements in the constructor, and therefore replaced these statements as well with a method call. As this duplicate consisted of three method invocations to external classes, the value of MPC after refactoring was reduced with three. Table 11.1: MPC impact validation for Extract Method. Metric MPCbef MPCaf t MPCpred
1 37 ∼ √
2a 10 ∼ √
2b 264 ∼ √
3 53 ∼ √
4 30 ∼ √
6 25 ∼ √
7 69 ∼ √
8 45 42 45
9 23 ∼ √
10 45 ∼ √
Validation of the prediction formula for the effect of Extract Method w.r.t. MPC, stating that: MPCpred = MPCbef . A ∼ symbol in the √ MPCaf t row indicates that MPCaf t =MPCbef . A symbol in the MPCpred row indicates that MPCpred =MPCaf t .
144
CHAPTER 11. VALIDATING PREDICTED IMPACTS
Table 11.2: OMMEC impact validation for Extract Method. Metric OMMECbef OMMECaf t OMMECpred
1 1 ∼ √
2a 0 ∼ √
2b 380 ∼ √
3 2 ∼ √
4 2 ∼ √
6 0 ∼ √
7 25 ∼ √
8 7 ∼ √
9 8 ∼ √
10 12 ∼ √
Validation of the prediction formula for the effect of Extract Method w.r.t. OMMEC, stating that: OMMECpred = OMMECbef .
Table 11.3: CBO impact validation for Extract Method. Metric CBObef CBOaf t CBOpred
1 20 ∼ √
2a 157 ∼ √
2b 187 ∼ √
3 31 ∼ √
4 17 ∼ √
6 18 ∼ √
7 17 ∼ √
8 37 ∼ √
9 229 ∼ √
10 68 ∼ √
Validation of the prediction formula for the effect of Extract Method w.r.t. CBO, stating that: CBOpred = CBObef .
Table 11.4: DAC impact validation for Extract Method. Metric DACbef DACaf t DACpred
1 0 ∼ √
2a 1 ∼ √
2b 19 ∼ √
3 1 ∼ √
4 1 ∼ √
6 1 ∼ √
7 7 ∼ √
8 3 ∼ √
9 10 ∼ √
10 3 ∼ √
Validation of the prediction formula for the effect of Extract Method w.r.t. DAC, stating that: DACpred = DACbef .
Accordingly, Extract Method candidate 8 demonstrates that the predictions according to the impact tables are invalid in case the application of the refactoring violates the specification of the refactoring in terms of its pre- and postconditions. More specific, the Extract Method specification specified the extraction of a single set of statements, without duplicates. The extraction of duplicate sets of statements (as applied for candidate 8) is a different refactoring, which (potentially) has a different effect on coupling and cohesion metrics. Effect on cohesion metrics – The same set of Extract Method candidates is used to validate the accuracy of the impact table w.r.t. the effect of Extract Method on cohesion metrics. Tables 11.5 and 11.6 illustrate the different terms in the formulae for predicting respectively LCOM5 and LCOM1.
11.2. DATA ANALYSIS
145
Table 11.5: LCOM5 impact validation for Extract Method t1 LCOM5bef +t2 +t3 LCOM5af t LCOM5pred
1
2a
2b
3
4
6
7
8
9
10
1 2
2 3
79 80
4 5
5 6
4 5
18 19
11 12
11 12
12 13
NaN
1.5 0
.945 0
1
1 0
.886 0
.98
.861 0
1 3
22 1760
1.33 √
.95 √
0 ∼ √
∼ √
1 0 0 .8 √
.896
1 5
0 0 0 0
∼ √
1 6
1 152 7 152
.901 √
1 12
1 120 9 120
.896 √
.982 √
2 39
.846 √
Validation of the prediction formula for the effect of Extract Method w.r.t. LCOM5: LCOM5pred (c) = t1 .LCOM5bef (c) + t2 + t3 .
These tables are to be interpreted similarly to the previous tables: Table 11.5: Aside rows for the value of LCOM5 before and after applying the Extract Method candidate, the table also contains rows which signify the three terms of the formula for LCOM5 as provided in impact table 10.7. This formula states that the Lack of Cohesion in Methods value of the class in which the Extract Method is applied is multiplied with a term t1 and then potentially increased with two terms t2 and t3 . E.g., for Extract Method candidate 3, we have LCOM5pred (c) = t1 .LCOM5bef (c) + t2 + t3 = 45 .1 + 15 + 0 = 1 = LCOM5af t (c). Table 11.6: LCOM1 impact validation for Extract Method LCOM1bef +t1 +t2 +t3 LCOM1af t LCOM1pred
1 1 0 1 1 3 √
2a 3 0 2 1 6 √
2b 2716 0 78 1 2795 √
3 10 0 4 1 15 √
4 15 0 5 1 21 √
6 10 0 4 0 14 √
7 154 2 16 1 173 √
8 60 0 11 1 72 √
9 54 0 9 1 64 √
10 70 0 11 0 81 √
Validation of the prediction formula for the effect of Extract Method w.r.t. LCOM1, stating that: LCOM1pred (c) = LCOM1bef (c) + t1 + t2 + t3 .
Table 11.6: The formula for predicting the value of LCOM1 after applying the refactoring requires the addition of three terms t1 , t2 and t3 to the value of LCOM1 before refactoring. E.g., for Extract Method candidate 3, we
146
CHAPTER 11. VALIDATING PREDICTED IMPACTS have LCOM1pred (c) = LCOM1bef (c) + t1 + t2 + t3 = 10 + 0 + 4 + 1 = 15 = LCOM1af t (c).
Thus, the application of the ten selected Extract Method candidates confirms the accuracy of impact Table 10.9.
11.2.2
Move Method
The impact table which is validated in this subsection is specified in the previous chapter in Table 10.9 and informally described in Table 10.10.
Effect on coupling metrics – The Move Method refactoring is predicted to affect all coupling metrics except Data Abstraction Coupling (DAC).
Table 11.7: MPC impact validation for Move Method MPCbef -t1 +t2 MPCaf t MPCpred
124 9 -9 0 0 √
71 18 -9 0 9 √
155 1 -1 0 0 √
163 25 -1 0 24 √
A 144 -92 1 53 √
B 94 0 0 ∼ √
C 4 -3 1 2 √
D 9 0 0 ∼ √
E 43 -4 0 39 √
F 72 -10 1 63 √
Validation of the prediction formula for the effect of Move Method w.r.t. MPC, stating that MPCpred = MPCbef - t1 + t2 .
We discuss each coupling metric separately: Table 11.7: The prediction formula for the Message Passing Coupling value describes that, after applying Move Method, some method invocations will no longer depart from the source class (t1 ), and that method invocations from other methods in the source class cs to the method which is moved will be considered invocations to a method from a different class (t2 ). We illustrate the application of Move Method candidate 71. For this candidate, we have MPCbef (cs ) = MPCbef (cs ) - t1 + t2 = 18 − 9 + 0 = 9 = MPCaf t (cs ).
11.2. DATA ANALYSIS
147
Table 11.8: OMMEC impact validation for Move Method OMMECbef -t1 +t2 OMMECaf t OMMECpred
124 1 -1 0 0 √
71 4 0 0 ∼ √
155 0 0 0 ∼ √
163 164 0 0 ∼ √
A 16 -1 0 15 √
B 6 -1 2 7 √
C 16 0 0 ∼ √
D 2 0 1 3 √
E 13 -4 0 9 √
F 3 0 0 ∼ √
Validation of the prediction formula for the effect of Move Method w.r.t. OMMEC, stating that: OMMECpred = OMMECbef - t1 + t2 .
Table 11.8: Similarly, the Move Method refactoring is predicted to affect the selected metric for export coupling according to two changes. First, the method invocations from other classes to the method to be moved will no longer arrive in the source class (t1 ). Second, method invocations from the method which is moved to the other methods in the source class will be considered new incoming method invocations (t2 ). For Move Method candidate A, this calculation goes as follows: OMMECpred (cs ) = OMMECbef (cs ) - t1 + t2 = 16 − 1 + 0 = 15 = OMMECaf t (cs ) Table 11.9: CBO impact validation for Move Method CBObef -t1 -t2 +t3 CBOaf t CBOpred
124 3 -2 -1 0 0 √
71 15 -1 -1 0 13 √
155 4 0 -1 0 3 √
163 47 0 -1 0 46 √
A 66 0 0 1 67 √
B 39 0 0 1 40 √
C 25 -3 0 1 23 √
D 11 0 0 0 ∼ √
E 9 0 -1 0 8 √
F 18 0 0 1 19 √
Validation of the prediction formula for the effect of Move Method w.r.t. CBO, stating that: CBOpred = CBObef - t1 - t2 + t3 .
Table 11.9: The impact table specifies that the Coupling Between Object classes value will be decreased with the number of methods exclusively coupled to the source class via the method to be moved (t1 ), which might also apply for the target class (t2 ). Term t3 signifies that a value of 1 will be subsequently added in case the method to be moved and the other methods of the source class invoke one another. For example, for Move
148
CHAPTER 11. VALIDATING PREDICTED IMPACTS Method application 71, we have: CBOpred (cs ) = CBObef (cs ) - t1 - t2 + t3 = 15 − 1 − 1 + 0 = 13 = CBOaf t (cs ).
Table 11.10: The Data Abstraction Coupling value is predicted not to be affected by the Move Method refactoring. Accordingly, the predicted value is equal to the value before refactoring. Table 11.10: DAC impact validation for Move Method 124 0 ∼ √
DACbef DACaf t DACpred
71 1 ∼ √
155 16 ∼ √
163 5 ∼ √
A 2 ∼ √
B 1 ∼ √
C 0 ∼ √
D 0 ∼ √
E 1 ∼ √
F 1 ∼ √
Validation of the prediction formula for the effect of Move Method w.r.t. DAC, stating that: DACpred = DACbef .
Effect on cohesion metrics – The validation of the effect of Move Method on the two selected cohesion metrics is discussed in two tables: Table 11.11: The Lack of Cohesion in Methods variant LCOM5 is predicted to be decreased proportionate to the number of sibling attributes not referenced by the method to be moved (t2 ). The fact that this effect is relative to the number of methods in the source class is made explicit through a multiplication factor (t1 ). As an example, we consider Move Method candidate 71: LCOM5 (c ) = t . LCOM 5 (c ) t = 34 . 1 pred s 1 pred s 2 1 - 4 = 1 = LCOM5af t (cs ).
Table 11.11: LCOM5 impact validation for Move Method t1 LCOM5bef -t2 LCOM5af t LCOM5pred
124
71
155
163
A
B
C
D
E
F
0 −1
4 3
0 −1
30 29
17 16
15 14
2 1
5 4
10 9
7 6
NaN
1 - 14 1 √
NaN
.913 1 - 30 .910 √
.871 5 - 85 .863 √
.905 7 - 105 .898 √
NaN
NaN
0 0
0 0
∼ √
∼ √
1 1 - 10 ∼ √
.714 - 17 .667 √
0 0
∼ √
16 0
∼ √
Validation of the prediction formula for the effect of Move Method w.r.t. LCOM5, stating ` ´ that: LCOM5pred = t1 . LCOM5bef - t2 .
11.2. DATA ANALYSIS
149
Table 11.12: The non-normalized LCOM1 variant is specified to be affected by the Move Method refactoring through a decrease with the number of other methods in the source class with which the method to be moved did not share attribute references (t1 ). E.g., for Move Method candidate A, we have: LCOM1pred (cs ) = LCOM1bef (cs ) - t1 = 130 − 17 = 113 = LCOM1af t (cs ). Table 11.12: LCOM1 impact validation for Move Method LCOM1bef -t1 LCOM1af t LCOM1pred
124 0 0 ∼ √
71 10 -4 6 √
155 0 0 ∼ √
163 312 -30 282 √
A 130 -17 113 √
B 111 -15 96 √
C 3 -2 1 √
D 15 -5 10 √
E 55 -10 45 √
F 25 -7 18 √
Validation of the prediction formula for the effect of Move Method w.r.t. LCOM1, stating that: LCOM1pred = LCOM1bef - t1 .
Summarizing, our results regarding the effect of the ten selected Move Method candidates confirm the correctness of impact Table 10.9.
11.2.3
Replace Method with Method Object
The impact table which is validated in this subsection is specified in the previous chapter in Table 10.11 and informally described in Table 10.12. The Replace Method with Method Object precondition dictates, among others, that the method which will be replaced may not reference non-public attributes. Therefore, to incorporate refactoring candidates that provide different values for the terms w.r.t. the cohesion metrics, we require methods that reference public attributes. As this is uncommon, five out of the eleven selected refactoring candidates were artificially created using the LAN simulation case. These candidates are notated as L1–L5. These five artificial candidates all originate from the same class. Accordingly, for all metrics, the value of the metric before applying the refactoring (Metricpre ) is equal for L1 to L5. Effect on coupling metrics – We discuss the effect of Replace Method with Method Object separately for each metric:
150
CHAPTER 11. VALIDATING PREDICTED IMPACTS
Table 11.13: The Message Passing Coupling metric value is predicted to be decreased with the number of invocations from the method to be replaced to other classes (t1 ). Subsequently, the value of two has to be added to incorporate two new calls: one to the constructor of the new class, and one for the delegation to the method in the new class. When we apply this formula for Replace Method with Method Object candidate 7a, we have: MPCpred (cs ) = MPCbef (cs ) - t1 + 2 = 80 − 9 + 2 = 73 = MPCaf t (cs ). Table 11.13: MPC impact validation for Replace Method w Method Object MPCbef -t1 +2 MPCaf t MPCpred
1 25 0
3 27 0
5a 7 -4
7a 80 -9
7b 36 -5
8a 6 -2
L1
L2
L4
L5
-12
L3 120 -9
-6
-15
-11
116 √
110 √
113 √
107 √
111 √
2 27 √
29 √
5 √
73 √
33 √
∼ √
Validation of the prediction formula for the effect of Replace Method with Method Object w.r.t. MPC, stating that: MPCpred = MPCbef - t1 + 2.
Table 11.14: The prediction formula for the selected export coupling metric specifies an increase of the OMMEC value after applying the Replace Method with Method Object refactoring equal to the number of method invocations from the method to be replaced to sibling methods (t1 ). For Replace Method with Method Object candidate 7a, this yields: OMMECpred (cs ) = OMMECbef (cs ) + t1 = 16+1 = 17 = OMMECaf t (cs ). Table 11.14: OMMEC impact validation for Replace Method w Method Object OMMECbef +t1 OMMECaf t OMMECpred
1 158 1 159 √
3 11 0 ∼ √
5a 17 0 ∼ √
7a 16 1 17 √
7b 0 0 ∼ √
8a 0 1 1 √
L1
L2
3 44 √
1 42 √
L3 41 1 42 √
L4
L5
1 42 √
1 42 √
Validation of the prediction formula for the effect of Replace Method with Method Object w.r.t. OMMEC, stating that: OMMECpred = OMMECbef + t1 .
Table 11.15: The Replace Method with Method Object refactoring is predicted to affect the Coupling Between Object classes with a decrease of the
11.2. DATA ANALYSIS
151
number of classes to which the method to be replaced is exclusively coupled (t1 ); and a subsequent addition of 1 for the use of the newly created class. Accordingly, for Replace Method with Method Object candidate 7b, we have: CBOpred (cs ) = CBObef (cs ) - t1 + 1 = 34 − 2 + 1 = 33 = CBOaf t (cs ). Table 11.15: Object CBObef -t1 +1 CBOaf t CBOpred
CBO impact validation for Replace Method w Method 1 47 0
3 18 0
5a 51 0
7a 66 0
7b 34 -2
48 √
19 √
52 √
67 √
33 √
8a 15 -2 1 14 √
L1
L2
L4
L5
0
L3 13 0
0
0
0
14 √
14 √
14 √
14 √
14 √
Validation of the prediction formula for the effect of Replace Method with Method Object w.r.t. CBO, stating that: CBOpred = CBObef + 1 - t1 .
Table 11.16: The Data Abstraction Coupling value is predicted not to be affected by the Replace Method with Method Object refactoring. Accordingly, for each refactoring candidate, the predicted value is equal to the value before refactoring. Table 11.16: DAC impact validation for Replac e Method w Method Object DACbef DACaf t DACpred
1 5 ∼ √
3 2 ∼ √
5a 2 ∼ √
7a 2 ∼ √
7b 30 ∼ √
8a 2 ∼ √
L1 0 ∼ √
L2 3 ∼ √
L3 3 ∼ √
L4 3 ∼ √
L5 3 ∼ √
Validation of the prediction formula for the effect of Replace Method with Method Object w.r.t. DAC, stating that: DACpred = DACbef .
Effect on cohesion metrics – Finally, we discuss the effect of Replace Method with Method Object w.r.t. the two cohesion metrics: Table 11.17: The Lack of Cohesion in Methods variant LCOM5 is specified to be increased proportionate to the number of sibling methods which
152
CHAPTER 11. VALIDATING PREDICTED IMPACTS share sibling attribute references with the method to be replaced (t1 ). E.g., for Replace Method with Method Object candidate L3, we have 2 LCOM5pred (cs ) = LCOM5bef (cs ) + t1 = .636+ 33 = .697 = LCOM5af t (cs ).
Table 11.17: LCOM5 impact validation for Replace Method with Method Object LCOM5bef +t1 LCOM5af t LCOM5pred
1
3
5a
7a
7b
8a
.913 0 ∼ √
.972
.667
.998
.788
NaN
0 ∼ √
0 ∼ √
0 ∼ √
0 ∼ √
0 ∼ √
L1
L2
L3 .636
L4
L5
2 33
1 33
2 33
1 33
2 33
.697
.667
.697
.667
.697
√
√
√
√
√
Application of the prediction formula for LCOM5 after refactoring, stating that LCOM5pred =LCOM5bef + t1 .
Table 11.18: Lastly, the prediction of the LCOM1 value after the application of Replace Method with Method Object dictates an increase by the number of sibling methods with which the method to be replaced shares sibling attribute references. As an example, for Replace Method with Method Object candidate L5, we have LCOM1pred (cs ) = LCOM1bef (cs ) + t1 = 32 + 6 = 38 = LCOM1af t (cs ).
Table 11.18: Object LCOM1bef +t1 LCOM1af t LCOM1pred
LCOM1 impact validation for Replace Method with Method 1 312 0 ∼ √
3 168 0 ∼ √
5a 15 0 ∼ √
7a 230 0 ∼ √
7b 70 0 ∼ √
8a 98 0 ∼ √
L1
L2
9 41 √
6 38 √
L3 32 9 41 √
L4
L5
6 38 √
6 38 √
Application of the prediction formula for LCOM1 after refactoring, stating that LCOM1pred =LCOM1bef + t1 .
Summarizing, the demonstrated application of the eleven selected Replace Method with Method Object candidates corroborates the accuracy of impact Table 10.11.
11.3. THREATS TO VALIDITY
11.3
153
Threats to Validity
With regard to internal validity, a potential selection bias is present, as the author selected the refactoring candidates and performed the evaluation himself. However, strict selection criteria were composed as to select a limited set of refactorings that vary with regard to values for the different terms in the prediction formulae. Accordingly, the accuracy of the effect prediction is tested under different conditions, as present in a representative open-source software system (ArgoUML). Moreover, additional artificial refactoring candidates were created to test the accuracy of the prediction in those cases which are uncommon in practice. Therefore, we do not consider the procedure for selection to be a threat. Evidently, a validation according to ten refactoring candidates cannot be considered a solid proof of the accuracy of the impact tables. There is indeed an inherent possibility that there does exist a refactoring candidate for which the predictions would not correspond to the actual value. However, aside the validation presented in this chapter, the stepwise formal derivation of the impact tables has been incorporated in Appendix B. This stepwise procedure follows the principles of common mathematical refinements, which further reduces the likelihood of errors made in the composition of the prediction formulae. Theoretically, there is a possibility that the implementation of the metric tool used in the validation contained defects. However, standard software engineering practices were applied to test for such defects. Moreover, the implementation of the metric tool using a software structure representation identical to the metamodel in which the metrics themselves were formalized reduces the probability of defects. With regard to external validity, we stress that the prediction formulae are only stated to provide accurate results in case the applied refactoring corresponds to the pre- and postconditions specified in the previous chapter. In the validation, we demonstrated the application of an Extract Method candidate which deviates from this specification. In such cases, the prediction formula cannot be applied. However, in cases where the pre- and postconditions are in fact satisfied, the formulae do consistently provide accurate results.
11.4
Conclusion
In this chapter, ten candidates were applied for each of the three selected refactorings. The predicted effect corresponded to the actual change in metric values.
154
CHAPTER 11. VALIDATING PREDICTED IMPACTS
Accordingly, we state that the impact tables provide a valid prediction. The prediction formulae indicate the conditions under which a coupling or cohesion metric will be increased or decreased. Moreover, the formulae also allow to calculate the exact value of this increase or decrease. Therefore, the formulae provide a-priori knowledge w.r.t. to the effect of the selected refactorings on the selected metrics. This knowledge can be used to filter those refactoring candidates which do not satisfy the expectations of a maintainer, e.g., by requiring that coupling is reduced and cohesion is increased. The application of this a-priori knowledge will be demonstrated in the next chapter.
Chapter 12
Case Study: Move Method Variant In this chapter, we demonstrate the exploitation of a-priori knowledge w.r.t. the impact of a refactoring on coupling and cohesion indicators. As an illustrative example, we elaborate a variant of the Move Method refactoring, and apply it on the ArgoUML software system.
12.1
Introduction
The goals of the case study presented in this chapter are twofold: • First, this case study demonstrates the exploitation of the impact tables validated in the previous chapter to identify refinements (named variants in the remainder of this chapter) of a refactoring. This refactoring variant attempts to optimize a set of quality indicators. • Second, this case study assesses the applicability of the devised refactoring variant, providing sufficient information as to allow the derivation of so called patch refactorings which themselves are not directed towards optimizing quality attributes, but rather serve to fulfill the preconditions of refactorings that do. Table 12.1 recapitulates the prediction formulae as mentioned in the impact table for Move Method represented in Table 10.9. For each formula, the table 155
156
CHAPTER 12. CASE STUDY: MOVE METHOD VARIANT
describes the conditions under which the optimization of the coupling or cohesion metric is optimal. These conditions are described by specifying which terms to be minimized, and which to be maximized. The optimization of coupling is achieved through a decrease to a minimal value, while the optimization of cohesion is achieved through an increase to a maximal value. However, as the selected cohesion metrics indicate lack of cohesion, their optimization is expressed in terms of a decrease. The table is constituted by evaluating the signs (+ or -) of the different terms of each of the prediction formulae. In case a metric value is to be minimized, the terms to be maximized are those terms which contribute negatively to the metric value after refactoring (terms with a sign -), and the terms to be minimized are those which contribute positively (terms with a sign +). In contrast, when the metric value is to be maximized, we maximize the terms contributing positively, and minimize those contributing negatively. However, as none of the coupling nor cohesion metrics are optimized by maximization, the latter case is not illustrated. Table 12.1: Move Method impact optimization table. Prediction formula MPCpred OMMECpred CBOpred DACpred LCOM5pred LCOM1pred
= = = = = =
MPCbef - t1 + t2 OMMECbef - t1 + t2 CBObef - t1 - t2 + t3 DACbef t1 . LCOM5bef - t2 LCOM1bef - t1
Optimization condition Maximize Minimize t1 t2 t1 t2 t1 , t 2 t3 — — t2 t1 t1 —
Indication of which terms to maximize, and which to minimize in order to optimize the coupling and cohesion metrics as affected by the Move Method refactoring.
Accordingly, to specify a Move Method variant that optimizes coupling and cohesion, we introduce additional conditions as specified in the second column of Table 12.1.
12.2
Notation
To describe the Move Method variant, we present the specification of additional conditions in a special notation. This notation was employed to specify the input
12.2. NOTATION
157
for a code generator. This code generator is entitled MotMot1 . The authors of MotMot describe their tool as follows: “MoTMoT stands for Model driven, Template based, Model Transformer. It is a compiler from visual model transformations to repository manipulation code. The compiler takes models conforming to a UML profile for Story Driven Modeling (SDM) as input and outputs JMI code.” JMI2 is a specification that defines how metadata can be queried and manipulated in the Java programming language. Accordingly, MotMot takes story diagrams as an input, and generates corresponding Java code which queries and manipulates representations of software systems. The structure of this representation conforms to the meta-model presented in section 10.1. Table 12.2 depicts the notation which is adhered to in this chapter, when specifying story diagrams as input for MotMot. A story diagram is described as an activity diagram consisting of states. State transitions, indicated by unidirectional arrows, indicate the state that is triggered after the current state is completed. The initial state represents the start of the story, and similarly, a final state represents the end of a story. A final state returns execution to the context in which the story was initiated. Between the initial and the final state, different types of states specify the type of activity performed in this state. We differentiate between loop and code states. Loop states trigger the collection of a set of tuples, consisting of instances of entities and relations which satisfy a set of conditions. E.g., a loop state can trigger the collection of classes implementing a given interface. The result of this collection will provide tripples, consisting of the given interface, a class implementing this interface, and the implementation relation between the interface and the class. Each time a tuple is found, the state transition labeled each time indicates the state that is triggered. This state can be considered as the loop body in traditional programming languages. Within this loop body, the instances of entities and relations within the result tuple can be read or manipulated. 1 MotMot was created through a collaboration between Pieter Van Gorp, Hans Schippers and Olaf Muliawan. For more information, visit http://www.fots.ua.ac.be/motmot 2 http://java.sun.com/products/jmi/
158
CHAPTER 12. CASE STUDY: MOVE METHOD VARIANT
Table 12.2: Story Driven Modeling (SDM) notation. Type
Explanation statePurpose
State Initial state Final state statePurpose {jcmtg.constraint=constraintStatement, jcmtg.transprimitive=NameOfTransformationPrimitive}
stateInsideLoop
stateAfterLoop
Loop state
statePurpose
Code state [condition]
conditional
stateInCaseConditionalIsTrue
[!condition]
stateInCaseConditionalIsFalse
Conditional state
Note
Comments Notations employed in the story diagrams described in this chapter.
Code states trigger the execution of a code statement. This code statement operates on instances of entities and relations present in the context of the code state. E.g., a code state can specify a print-statement which writes the value of an entity to standard output. A conditional state can be used as a selector
12.3. SPECIFYING THE MOVE METHOD VARIANT
159
for the next state. Conditional states specify guards on the state transitions departing from this state. A guard specifies a condition, which can be either satisfied or dissatisfied, and controls the state transitions departing from the code state. Thus, a code state corresponds to an if-else statement in traditional programming languages.
12.3
Specifying the Move Method Variant
Before specifying additional constraints that assure the optimization of coupling and cohesion measures, we translate the pre- and postconditions of the general Move Method refactoring to story diagrams. The Move Method refactoring moves a method from one class to another, possibly adding a parameter when resources of the original classes are used. The precondition involves three model-element instances: (i) msrc , the method to be moved; (ii) csrc , the source class; and (iii) ctrg , the target class. • Figure 12.1 portrays the precondition w.r.t. relationship between the method to be moved (msrc ) and the class from which it will be moved (source class csrc ). This condition represents part the precondition of the Move Method refactoring as presented in the previous chapter. The eight states specified in the story diagram displayed in Figure 12.1 specify that the method to be moved . . . 1. . . . must not be a constructor. 2. . . . must be a public method, implemented by the source class. 3. . . . must not reference non-public sibling attributes. 4. . . . must not reference attributes of outer classes. This condition might occur in case the source class is an inner class. 5. . . . must not invoke non-public sibling methods. 6. . . . must not invoke methods of outer classes. 7. . . . must not override a method implemented by its ancestors. 8. . . . must not be overridden by a method implemented by its descendants. In case these eight negative conditions are satisfied, the precondition w.r.t. the relationship between the method to be moved and the source class is satisfied.
160
CHAPTER 12. CASE STUDY: MOVE METHOD VARIANT
[isConstructor]
Is not a constructor? [!isConstructor] Is public method?
[!isPublic]
[isPublic]
Retrieve Reference to Non-Public Sibling Attribute {jcmtg.transprimitive=retrieveNonPublicAttributeAccess}
Retrieve Reference to Outer Type Attribute {jcmtg.transprimitive=retrieveOuterTypeAttrRef}
Retrieve Call to Non-Public Sibling Method {jcmtg.transprimitive=retrieveNonPublicMethodCall} Retrieve Call to Outer Type Method {jcmtg.transprimitive=retrieveOuterTypeMethodCall}
Overrides a supertype method? [!overrides] Is overridden? [!isOverridden]
[false]
Return false
[true] FALSE
[false]
[false]
Return _false_
Return false bis
[true]
[true] [true]
[false]
Return -false-
[overrides]
boolean overrides = !aMethod.getOverriddenMethods().isEmpty(); [isOverridden]
boolean isOverridden = !aMethod.getOverridingMethods().isEmpty();
TRUE
Figure 12.1: Move Method source class precondition story diagram
• Figure 12.2 portrays the precondition w.r.t. relationship between the method to be moved msrc and the class to which it will be moved (target class ctrg ). This condition states that the target class must be editable (i.e., may not be a library class whose source code cannot be modified), and the target class hierarchy must not implement a method with a similar
12.3. SPECIFYING THE MOVE METHOD VARIANT
161
signature.
boolean isEditable = !(aClass instanceof MlibraryClass); Is the target class editable?
[!isEditable]
[isEditable] FALSE
Does the target class hierarchy implements a similar signature?
[classHierarchyImplementsSignature]
[!classHierarchyImplementsSignature] TRUE
be.ac.ua.lore.refactorings.PreconditionVerifier pv = new be.ac.ua.lore.refactorings.PreconditionVerifier(); boolean classHierarchyImplementsSignature = pv.typeDeclaresSignature(aMethod, aClass).booleanValue() || pv.typeInheritsMethodWithSimilarSignature(aMethod, aClass).booleanValue() || pv.subHierarchyDeclaresMethodSignature(aMethod, aClass).booleanValue();
Figure 12.2: Move Method target class precondition story diagram
Together the story diagrams described in Figures 12.1 and 12.2 specify the precondition of the Move Method refactoring specified in Chapter 10.
12.3.1
Refining the precondition
By specifying additional preconditions, we design a Move Method variant. The precondition of this variant is stricter then the precondition of the general Move Method refactoring. Accordingly, this variant can provide more specific guarantees in its postcondition. In Table 12.1, the conditions were specified under which the application of Move Method will optimize the value of the selected coupling and cohesion metrics for the source class. We describe these conditions for each metric, in preparation of the formulation of additional preconditions:
162
CHAPTER 12. CASE STUDY: MOVE METHOD VARIANT
Message Passing Coupling: According to our prediction formula, the MPC metric value is optimized in case the method to be moved contains many method invocations to other classes (quantified by term t1 ), and is preferably not called by the other methods implemented in the source class. The latter condition is quantified by term t2 . Export Coupling: The OMMEC metric value is optimally effected in case the method to be moved is called frequently by methods from other classes (t1 ), and preferably does not invoke other methods implemented in the source class (quantified by t2 ). Coupling Between Object classes: The CBO metric value is optimally reduced when the method to be moved constitutes the only form of coupling with many other classes (t1 ), and preferably also forms the only form of coupling with the target class (t2 ). Preferably, the method to be moved and the other methods of the source class should not invoke one another (t3 ). Data Abstraction Coupling: As the DAC metric value is predicted not to be affected, this metric value cannot be optimized using the Move Method refactoring. Lack of Cohesion in Methods, normalized: The metric value of LCOM5 is predicted to be optimized in case the method to be moved references very few, preferably none, of the sibling attributes of the source class (t2 ). An optimal reduction of the LCOM5 metric value is achieved when the Move Method refactoring is applied in a source class containing few methods, as the effect of the Move Method refactoring on LCOM5 is relative to the number of methods of the source class. Lack of Cohesion in Methods, non-normalized: Moving methods which share very few, preferably none, attribute references with sibling methods from the source class (as quantified by t1 ) will optimize the reduction of the LCOM1 metric value. These guidelines for optimizing the effect of Move Method on the selected coupling and cohesion metrics w.r.t. the source class can be summarized as follows: (i) the method to be moved should be incohesive with the source class; and (ii) this method should encapsulate coupling to the source class. We specify these two conditions in additional story diagrams, which can be considered as
12.3. SPECIFYING THE MOVE METHOD VARIANT
163
qualitative preconditions, in that they specify the preconditions under which coupling and cohesion will be optimized: • Figure 12.3 specifies an additional qualitiative precondition. This condition specifies that the method to be moved should be incohesive with the source class. The states in the story diagram therefore describe that . . . 1. . . . the other methods of the source class must not be invoked by the method to be moved. 2. . . . the attributes of the source class must not be referenced by the method to be moved. 3. . . . the other methods of the source class must not invoke the method to be moved. • Figure 12.4 specifies a second additional qualitative precondition. This condition specifies that the method to be moved should encapsulate coupling to the target class, using states specifying negative conditions. These negative conditions specify that . . . 1. . . . other methods implemented by the source class must neither invoke methods of the target class, be invoked by methods from the target class, nor reference attributes of the target class. 2. . . . attributes implemented by the source class must not be referenced by methods of the target class. In case these additional qualitative preconditions are satisfied, the Move Method variant will guarantee additional qualitative postconditions, discussed in the next subsection.
12.3.2
Resulting qualitative postcondition
The additional qualitative preconditions specified in the previous subsection stimulate the optimization of the selected coupling and cohesion metrics. This optimization guarantees to optimize particular terms in the prediction formulae for the metric values, described in Table 12.3. The terms which are guaranteed to be zero are those terms advised in Table 12.1 to be minimized. The terms are guaranteed to be non-zero are those terms advised to be maximized.
164
CHAPTER 12. CASE STUDY: MOVE METHOD VARIANT
Prepare PreconditionVerifier
Retrieve called public method of class {jcmtg.transprimitive=retrieveStaticallyInvokedPublicMethod, jcmtg.constraint=publicMethod != aMethod}
[false]
Return false
[true]
FALSE Retrieve referenced public attribute of class {jcmtg.transprimitive=retrieveReferencedPublicAttribute}
Retrieve caller-method from class {jcmtg.transprimitive=retrieveCallerMethodFromClass, jcmtg.constraint=callerMethod != aMethod}
Retrieve called method from superHierarchy of class {jcmtg.transprimitive=retrieveCalledSuperHierarchyMethod, jcmtg.constraint=(methodCalled != aMethod)
[false]
[false]
[false]
Return false bis
[true]
[true]
Return false tris
[true] Return false quattro
&&(pv.subHierarchyContains(aType, aClass)).booleanValue()}
TRUE
Figure 12.3: Qualitative precondition on msrc and csrc
Accordingly, we can substitute these fixed values to refine the effect of the Move Method variant. Table 12.4 describes the impact table of the Move Method variant presented in this chapter. Terms which are guaranteed to be zero by the Move Method variant are left out, and in prediction formulae for which fixed valued terms can be guaranteed (e.g., CBO and LCOM1), these
12.3. SPECIFYING THE MOVE METHOD VARIANT
Initialize a Query Engine
Retrieve Sibling Method {jcmtg.transprimitive=retrieveSiblingMethod, jcmtg.constraint=!siblingMethod.equals(aMethod)}
Retrieve Call to targetClass {jcmtg.transprimitive=retrieveCallToTargetClass}
[false]
Retrieve Reference to targetClass {jcmtg.transprimitive=retrieveReferenceToTargetClass}
Retrieve Call from targetClass {jcmtg.transprimitive=retrieveCallFromTargetClass}
Retrieve Sibling Attributes {jcmtg.transprimitive=retrieveSiblingAttribute}
165
[false]
[false]
Retrieve Reference from targetClass {jcmtg.transprimitive=retrieveReferenceFromTargetClass}
[false]
FALSE [true] Return false
Return false bis
Return false tris
[true]
[true]
Return false quattro
[true]
TRUE
Figure 12.4: Qualitative precondition on msrc and ctrg
terms are substituted by their fixed value. Table 12.3: Move Method variant effect description. Prediction formula MPCpred = MPCbef - t1 + t2 OMMECpred = OMMECbef - t1 + t2 CBOpred = CBObef - t1 - t2 + t3 DACpred = DACbef LCOM5pred = t1 . LCOM5bef - t2 LCOM1pred = LCOM1bef - t1
Fixed term values t2 = 0 t2 = 0 t2 = 1, t3 = 0 — — t1 = | MI (cs ) | −1
Specification of the fixed values guaranteed by the two additional qualitative preconditions for the Move Method variant.
Once again, we stress that the prediction formulae in this table only apply in case both the preconditions of the general Move Method refactoring and the two additional qualitative preconditions are satisfied.
166
CHAPTER 12. CASE STUDY: MOVE METHOD VARIANT
Table 12.4: Impact table for the Move Method variant. MPCpred (cs ) with t1 OMMECpred (cs ) with t1 CBOpred (cs ) with t1 = x ∈
DACpred (cs ) LCOM5pred (cs ) with t1 t2 LCOM1pred (c) with t1
Prediction formula = P MPCbef (cs ) - t1 = m2 ∈SIM (m)\MI (cs ) N SI(m, m2 ) = P OMMECbef (csP ) - t1 = c2 ∈Others(cs ) m1 ∈MI (c2 ) N SI(m1 , m) = CBObef (cs ) - t1 - 1 C \ {cs , ct } | uses(m, x) ∨ ∃md ∈ MI (x) : m ∈ P IM (md ) ∧ 6 ∃ms ∈ MI (cs ) \ {m} : uses(ms , x) ∧ ∀md ∈ MI (x) : (MI (cs ) \ {m}) ∩ P IM (md ) ∪(AI (cs ) ∩ AR(md )) = ∅ = DACbef (cs ) = t1 . LCOM5bef (c) - t2 |MI (c)|−1 = |M I (c)|−2 |AI (cs )\AR(m)| = |AI (cs )|. |MI (cs )|−1
= =
bef (c) - t1 LCOM1 m1 | m1 ∈ MI (cs ) \ {m} ∧m1 6= m ∧ AR(m1 ) ∩ AR(m) ∩ AI (cs ) = ∅
Formal description of the effect of applying Move Method variant on the value of metrics of the source class.
Table 12.4 thus predicts that the (aggregated) import and export coupling metrics will either remain unchanged or decrease, and similar for the lack of cohesion. Moreover, the Coupling Between Object classes metric, indicative for general coupling, is guaranteed to be decreased with at least 1.
12.4
Data Collection
In this section, we collect data to verify two criteria required for a useful refactoring variant. First, a refactoring variant should indeed optimize the coupling and cohesion metrics. Second, a refactoring variant should not be too artificial as to be inapplicable in realistic software systems. Accordingly, we first validate the accuracy of the impact table for the Move
12.4. DATA COLLECTION
167
Method variant. Subsequently, we analyse the applicability of the Move Method variant on ArgoUML.
12.4.1
Validating predicted impacts
To validate the accuracy of the impact table of the described Move Method variant (see Table 12.4), we reuse four refactoring candidates presented in the validation of the general Move Method refactoring in Chapter 11. These candidates were selected to satisfy the additional qualitative preconditions which the Move Method variant requires. Therefore, these candidates are also candidates for the Move Method variant. Table 12.5: Variant impact validation. Metric
Predicted term value
MPCpred OMMECpred CBOpred DACpred LCOM5pred LCOM1pred
t2 t2 t2 t3
t1 =
=0 =0 =1 =0
— — | MI (cs ) | −1
Value for candidate 124 71 155 163 √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √
√
√
√
√
Validation of the prediction formula for the effect of the Move Method variant w.r.t. the fixed terms in the prediction formulae.
Table 12.5 illustrates the value of the terms predicted to have a fixed value by the impact table for the Move Method variant (see Table 12.4). In case the value of a term, as calculated for a particular Move Method refactoring candidate, √ is equal to the predicted term value, this is indicated using a check mark ( ). The table confirms that the terms predicted by the impact table for the Move Method variant (Table 12.4) to have a fixed value do indeed have the predicted value. E.g., for Move Method refactoring candidate 155, we observe that the actual value of term t2 , as mentioned in the prediction formula for CBO, equals the fixed value 1, as predicted. Thus, we summarize that the Move Method variant presented in this chapter indeed optimizes the selected coupling and cohesion metrics.
168
CHAPTER 12. CASE STUDY: MOVE METHOD VARIANT
12.4.2
Applicability of the Move Method variant Ratio of Move Method candidates per class
1
(1) m_src and c_src (2) 1 and m_src and c_trg (3) 2 and qualPre m_src and c_trg (4) 3 and qualPre m_src and c_src
0.8
Ratio
0.6
0.4
0.2
0 1160
1180
1200
1220
1240
1260 Classes
1280
1300
1320
1340
1360
Figure 12.5: Move Method variant applicability in ArgoUML v0.19.8
The optimization of coupling and cohesion metrics as guaranteed by the Move Method variant presented in this chapter can be exploited in two ways: • In case a considerable number of refactoring candidates satisfying the additional preconditions of the refactoring variant can be detected, the refactoring variant can be considered useful to optimize coupling and cohesion metrics. • In contrast, if only a very limited number of refactoring candidates can be detected, there are few cases in which the refactoring variant can be exploited. Accordingly, if this is the case, it is interesting to verify which patch refactorings can be applied to manipulate the satisfaction of the preconditions of the refactoring variant.
12.4. DATA COLLECTION
169
Figure 12.5 illustrates the degree to which refactoring candidates can be found that satisfy each of the preconditions of the Move Method variant discussed in this chapter. The X-axis represents the set of classes present in ArgoUML v0.19.8, containing a total of 1362 classes. The Y-axis represents the ratio of methods in a class that satisfies the (set of) precondition(s). I.e., in case all the methods of a class satisfying the (set of) precondition(s) of the Move Method variant, the Y-value will be 1. Similarly, in case only half of the methods of a class satisfying the (set of) precondition(s), the Y-value will be 0.5. Each line represented in Figure 12.5 indicates a precondition, as explained by the legend. The earlier the line rises on the Y-axis, the more classes were detected containing at least one method satisfying the associated preconditions. The conditions associated with each of the lines are discussed in the following overview: First line: The first line represents the ratio of methods satisfying the precondition specified in the story diagram illustrated in Figure 12.1. This condition describes the required relationship between the method to be moved and the class from which it will be moved. In ArgoUML v0.19.8, 168 candidates are detected to satisfy this condition, representing 12.3% of the classes. Second line: The second line represents the ratio of methods satisfying two conditions. First, the condition specified in the first line is required, and additionaly, the precondition specified in the story diagram illustrated in Figure 12.2 is required to be satisfied. The latter condition dictates the required relationship between the method to be moved and the class to which the method will be moved. Thus, the second line quantifies the number of classes on which the general Move Method refactoring can be applied, as specified in Chapter 10. 98 Classes, or 7.2% of all classes, satisfy this condition. Accordingly, about half of the classes satisfying the condition represented in the first line contain at least one method satisfying the general Move Method precondition. Third line: The third line again represents an additional condition, which is to be combined with the conditions indicated by the first two lines. The additional condition is specified in the story diagram depicted in Figure 12.3, specifying that the method to be moved should be incohesive with the method from which it will be moved.
170
CHAPTER 12. CASE STUDY: MOVE METHOD VARIANT The number of classes satisfying this condition is 47, constituting 3.5% of the classes. This means that for about half of the classes in which the general Move Method refactoring variant can be applied, at least one of the methods in these classes is incohesive.
Fourth line: The fourth line requires the complete precondition of the Move Method variant to be satisfied. Additionally to the requirements of the third line, this condition requires that the method to be moved encapsulates coupling to the target class, as illustrated in the story diagram in Figure 12.4. 9 Classes satisfy the condition specified in this condition, encounting for merely 0.7% of the classes in ArgoUML v0.19.8. Thus, we observe that, for ArgoUML v0.19.8, the Move Method variant presented in this chapter can be applied on merely one tenth of the classes in which the general Move Method refactoring can be applied. Accordingly, this observation leads us to assume that the presented Move Method variant is ten times less applicable then the general Move Method refactoring. If this assumption is correct, then for nine out of ten Move Method candidates, the selected coupling and cohesion metrics will not be optimized in case the Move Method refactoring is actually applied.
12.5
Interpretation of Results
The observation of the poor applicability of the Move Method variant suggests that there is indeed a need for patch refactorings which prepare the application of the Move Method variant. The availability of such patch refactorings could potentially support the exploitation of coupling and cohesion improvements for considerably (potentially 9 times) more Move Method candidates. Nonetheless, our results also demonstrate that, in case the preconditions of the Move Method variant are in fact satisfied, the optimization of the selected coupling and cohesion metrics do occur.
12.6
Conclusion
In this chapter, we have exploited the predicted effect of the Move Method refactoring on coupling and cohesion metrics to refine a Move Method variant. The claim that this Move Method variant optimizes the selected coupling and
12.6. CONCLUSION
171
cohesion metrics has been validated. However, through a detection of classes satisfying the additional preconditions required by the Move Method variant, in a representative software system (ArgoUML v0.19.8), we observe that the Move Method variant is rarely applicable. The main conclusion of this chapter is that it is indeed possible to devise refactoring variants which improve internal program quality metrics. However, these refactoring variants can not frequently be applied. We hypothesize that the lack of application candidates can be addressed using refactorings that manipulate the source code as to satisfy the preconditions of the refactoring variant. Thus, this conclusion suggests that it is interesting to also investigate refactorings that themselves do not improve quality as indicated by coupling and cohesion metrics, yet serve as stepstones towards quality improvement.
172
CHAPTER 12. CASE STUDY: MOVE METHOD VARIANT
Chapter 13
Summary In this chapter, we summarize the findings with regard to the investigation of coupling and cohesion improvements by refactoring. Subsequently, we describe the limitations of this research approach, and enlist the lessons learned this part of the dissertation.
13.1
Findings
In this part of the thesis, we evaluated the effect of three selected refactorings on indicative metrics of coupling and cohesion. Our analysis demonstrated that the impact of the selected refactorings on either coupling or cohesion was nontrivial. I.e., it is infeasible to generalize that any application of a refactoring either improves or impaires one of these internal quality characteristics. Accordingly, instead of stating that a refactoring has a partical impact on a metric, we found that, more often than not, the effect of a refactoring on a metric is described by an impact spectrum. An impact spectrum limits the impact on a metric within particular boundaries. These boundaries can be both narrow and wide. An example of a narrow impact spectrum is a description which predicts that a metric will be increased or remain unchanged, but cannot decrease. In contrast, a wide impact spectrum states that a metric might be increased or remain unchanged, yet might also be decreased. Thus, the concept of an impact spectrum clarifies that the particular impact of the refactoring will depend on the context in which the refactoring is applied. The impact spectrum, describing the effect of a refactoring on a metric, is 173
174
CHAPTER 13. SUMMARY
formalized as a prediction formula. This prediction formula specifies different terms which are added or subtracted from the value of the metric before refactoring. Each of these terms is specified as the cardinality of the resultset of a query on the context in which the refactoring is applied. I.e., the conditions expressed in this query specify under which conditions the term will have a particular value. As an example, let us consider the effect of the Move Method refactoring on the Message Passing Coupling (MPC) metric. The impact spectrum for MPC is defined as: MPCpred (cP s ) = MPCbef (cs ) - t1 + t2 with t1 = m2 ∈SIM (m)\MI (cs ) N SI(m, m2 ) P and t2 = m1 ∈MI (cs )\{m} N SI(m1 , m) This impact spectrum specifies that the Move Method refactoring can either improve or impair the MPC value, specified respectively by terms t1 and t2 . When we investigate one of these terms, say t1 , we observe that it states the conditions under which the MPC value will be decreased, and that it additional specifies the extent of this decrease. In this example, term t1 states that, in case method m invokes methods implemented by classes other than cs , then the MPC value will be decreased with the number of these method invocations. These prediction formulae thus specify the conditions required for a particular effect to occur (e.g., a decrease of the MPC value). We call this knowledge a-priori knowledge on the effect of a refactoring, as it allows to predict the outcome of applying a refactoring before it has been applied. In the last chapter, we have demonstrated the exploitation of such a-priori knowledge by refining the associated refactoring. This refinement narrows down the set of conditions under which the refactoring will have an optimal effect. In the case of an effect specified in terms of coupling and cohesion, an optimal effect is achieved when coupling is minimized and cohesion is maximized. Therefore, we specify additional preconditions, which, for the same refactoring, allow to guarantee additional postconditions. These extended pre- and postconditions define a variant of the more general refactoring. The additional postconditions of this refactoring variant are of a qualitative nature, in that they specify the impact on coupling and cohesion as a narrow impact spectrum. In other words, while the general refactoring specifies a wide interval of potential effects (e.g., a MPC metric value change specified in the interval ]−∞,+∞[), the refactoring variant specifies a narrow interval of potential effects (e.g., a MPC metric value specified in the interval ]−∞,0]). Thus, the exploitation of a-priori knowledge
13.2. LIMITATIONS
175
allows to specify refactoring variants which optimize internal quality characteristics. A drawback of these refactoring variants is that they are inherently less applicable than the general refactoring which they refine. This calls out for the definition of so called patch refactorings, which themselves do not address the optimization of quality characteristics. However, these patch refactorings serve to prepare for the application of a refactoring variant. I.e., the postcondition of such patch refactorings corresponds to the precondition of the refactoring variant, thereby assuring the applicability of the refactoring variant. Accordingly, the concept of patch refactorings theoretically enable the improvement of the applicability of a quality optimizing refactoring variant.
13.2
Limitations
The derivation of a-priori knowledge is limited by the expressive power of the meta-model used to formalize the studied refactorings. Evidently, if the metamodel does not allow to express the presence of an entity or a relation between entities (e.g., Exceptions or the throwing of exceptions by a method), it is infeasible to express metrics regarding this entity or these relations (e.g., the number of exceptions thrown by a method), and it is equally infeasible to predict the effect of any refactoring on such a metric. Accordingly, our approach to predicting the impact of a refactoring on a quality characteristic is limited by the expressiveness of the meta-model. A more pragmatic limitation is the effort required to apply the impact derivation process explained in Appendix B. This required effort is mostly determined by the complexity of the postcondition of the refactoring, and of the complexity of the formalization of the metric. I.e., if the metric refers to many different analysis functions (e.g., the set of methods implemented by a class) and the postcondition specifies changes to many different analysis functions, then a large number of substitutions will have to be applied in order to relate the value of the metric after refactoring to the value of the metric before refactoring.
176
CHAPTER 13. SUMMARY
Chapter 14
Further Work This chapter describes interesting continuations of the research proposed in this thesis.
14.1
Extensions
In this thesis, we have restricted our attention in two ways. First, we have demarcated the set of quality characteristics to coupling and cohesion. Accordingly, the impact tables specified in this thesis do not provide information w.r.t. other relevant quality characteristics as complexity. We therefore do not claim our refined Move Method variant to optimize quality in general, yet restrict its guarantees to the selected set of metrics. In case other quality characteristics, such as complexity, are incorporated in the impact specification, one could investigate the potential trade-offs which are inherent to any optimization problem. E.g., it is theoretically possible that improvements in coupling and cohesion tend to impair complexity. These complex relationships among quality characteristics can be investigated using the impact derivation process presented in this thesis. Second, we have selected a small set of refactorings. Accordingly, we can provide no claims about the effect of other refactorings, e.g., Extract Class, on the selected coupling and cohesion metrics. However, in the introduction of this thesis, we indicated that it is possible to compose the lower level refactorings as studied in this thesis (e.g., Extract Method and Move Method). It has been shown that the postconditions of these compositions can be derived from the set 177
178
CHAPTER 14. FURTHER WORK
´ Cinn´eide, 2001]. Thus, it of postconditions of the constituting refactorings [O would be interesting to verify to which extent the impact specifications of these constituting refactorings can be reused in the impact derivation process for the composite refactoring.
14.2
Tool Integration
We envision the application of the results of this research in three different scenario’s: 1. A maintainer might desire to optimize a set of quality characteristics. However, it is non-trivial to assess how to improve these quality characteristics while preserving the behavior of the existing software system. Accordingly, an advanced refactoring tool could evaluate the preconditions of a set of refactoring variants, and present a list of refactoring candidates for which the tool can guarantee that these will improve the desired quality characteristics. 2. A code smell refers to a structural property of part of a software system, which is known to be undesireable in certain circumstances. Code smell detectors (e.g., PMD1 ) allow to quantify the presence of code smells, and are used to assess the degree to which a software system exhibits these undesireable characteristics. The precondition of a quality characteristic optimizing refactoring variant can be regarded as a code smell. I.e., this precondition expresses the condition in which a more optimal software solution can be formed. As it is mostly undesireable to have a sub-optimal solution, the availability of a code smell detector that quantifies the number of refactoring candidates can allow to assess the extent to which the current software system deviates from its optimal form. Evidently, optimal has to be considered relative w.r.t. the quality characteristics incorporated in the postcondition of the refactoring variant. 3. In the introduction, we described an alternative research approach for composing guidelines on how to apply refactorings in order to improve quality characteristics. We termed this alternative approach the brute force method, as it consists of exploring all alternative solutions for a given 1 http://pmd.sourceforge.net
14.2. TOOL INTEGRATION
179
software design until a (local or global) optimum is found. Accordingly, this approach consideres the optimization of quality attributes to be a search problem, in which each step is defined as the application of a single refactoring. This approach is advocated in [Seng et al., 2005]. A pragmatic limitation of this search based quality optimization approach is the lack of a-priori knowledge with regard to the effect of progressing a single step, i.e., of applying a refactoring. This lack of knowledge requires to perform each step, and backtracking in case the step turned out to be undesireable. However, this a-priori knowledge is exactly what the impact tables presented in this thesis provide. Therefore, the application of the impact tables proposed in this research into the search based approach can provide a lookahead. This lookahead can predict the outcome of a series of steps, without the need for applying them physically. Accordingly, the integration of the results of this research into the search based approach can theoretically reduce the time required to achieve a (local or global) optimum.
180
CHAPTER 14. FURTHER WORK
Chapter 15
Conclusions In this chapter, we present our conclusions w.r.t. the study of quality improvements by refactoring. Our study was comprised of two parts, focusing respectively on program comprehension and coupling and cohesion improvements. A discussion of our contributions w.r.t. the evaluation of program comprehension improvements by refactoring was discussed in Chapter 8. For a summary of the results of our research w.r.t. coupling and cohesion improvements, we refer to Chapter 13.
15.1
Conclusions
The research presented in this dissertation targeted the validation of common claims about the effect of refactoring on software quality. Accordingly, we discuss our conclusions in terms of the confirmation or refutation of these claims.
15.1.1
Program Comprehension Improvements
One of the claimed benefits of refactoring has been that it “makes software easier to understand ” [Fowler, 1999]. This support has been previously clarified to be provided in two ways. First, one can physically apply refactorings to reflect hypotheses about the purpose of the code, and second, one can apply refactoring to make the code better communicate its purpose. We conclude that these claimed benefits can indeed occur. In fact, we validated two patterns, Refactor to Understand and Split Up God Class, both 181
182
CHAPTER 15. CONCLUSIONS
introduced by [Demeyer et al., 2002]. We have observed that these patterns respectively support the construction of a mental representation during bottom-up comprehension, and the discovery of relations between the source code and the problem domain during top-down comprehension. These observations thereby clearly confirm the claim that refactoring can be used to make software easier to understand.
15.1.2
Coupling and Cohesion Improvements
Another claimed benefit of refactoring has been to “improve the design of software“, by redistributing parts of the code to the “right” places [Fowler, 1999]. Our initial assumption, that refactoring can both improve and impair software design, has been confirmed through a formal analysis of the effect of refactorings on coupling and cohesion as criteria to quantify design quality. Our analysis clarifies how a selected set of refactorings can be used to optimize coupling and cohesion, yet also indicates that, more often than not, these quality characteristics are not at all improved by the application of a refactoring. Therefore, we refined under which conditions these refactorings can indeed improve the design of software.
15.1.3
General Conclusions
We conclude that, in particular circumstances, refactoring can indeed be used to improve software quality. However, more research is needed on guidelines that clarify the context in which a refactoring is best applied, discuss the tradeoffs which are inherent to any optimization problem, and guide the process of applying refactorings by distinguishing essential and optional steps.
Appendix A
Experimental Material In this chapter, we publish the post-experiment questionnaire used in the controlled experiment described in Chapter 5.
A.1
Refactor to Understand
At the end of the Refactor to Understand experiment, a questionnaire was handed out, which was an adaptation from [Briand et al., 2001]. Closed questions were asked about motivation, adherence to guidelines, understanding of requirements, approach to answering the questions, accuracy estimation, reasons for not completing, code quality estimate and perceived difficulty of questions on the three tasks. The questionnaire consists of two pages. Figure A.1 depicts the first page, and Figure A.2 the second.
183
184
APPENDIX A. EXPERIMENTAL MATERIAL
[email protected]
SRe2LIC study
29/03/2004
Motivation and performance debriefing questionnaire The information you provide in this questionnaire may be very valuable to us. Please answer each question as honestly as you can. Anything you write down will be treated confidentially. Thank you. Your name: _________________________________________________________ 1. Estimate how motivated you were to perform well in the study. Not
Poorly
Fairly
Well
Highly
1
2
3
4
5
2. Estimate how rigorous you adhered to the comprehension technique guidelines: a. Read to Understand: no writing in the source code b. Refactor to Understand: no beautification Not adhered to 1
Not always adhered to
Rigorously adhered to
2
3
3. Estimate how well you understood what was required of you. Not
Poorly
Fairly
Well
Highly
1
2
3
4
5
4. What approach did you adopt when receiving the questions? (tick only once)
Re-read the code while thinking about the tasks Straight into the tasks, re-reading the code as required Straight into the tasks, not re-reading the code Other – please specify: _________________________________________ ___________________________________________________________
5. Estimate the accuracy (in %) of your answers. 0 - 20
21 - 40
41 - 60
61 - 80
81 - 100
1
2
3
4
5
Figure A.1: Page 1 of the debriefing questionnaire
A.1. REFACTOR TO UNDERSTAND
[email protected]
185
SRe2LIC study
29/03/2004
6. If you could not complete all the tasks, please indicate why. (tick only once)
Ran out of time Did not fully understand the task Did not fully understand the code Other – please specify: _________________________________________ ___________________________________________________________
7. On a scale of 1 to 10 estimate, in terms of comprehensibility, the quality of the code to which the tasks referred. (1 – barely comprehensible; 10 – easily comprehensible)
Please specify your estimate number: _________ 8. Estimate the difficulty of the questions of Task 1 on method SearchPattern::createMethodPattern. Too difficult
Quite difficult
Fairly solvable
Quite easy
Too easy
1
2
3
4
5
9. Estimate the difficulty of the questions of Task 2 on method IndexAllPattern::execute. Too difficult
Quite difficult
Fairly solvable
Quite easy
Too easy
1
2
3
4
5
10. Estimate the difficulty of the questions of final Task 3 on method SurroundWithTryCatchRefactoring::addEdits. Too difficult
Quite difficult
Fairly solvable
Quite easy
Too easy
1
2
3
4
5
11. Having performed the tasks, would you do anything different next time around? Please specify : _________________________________________________ 12.
Any additional comments?
Thanks once again.
Figure A.2: Page 2 of the debriefing questionnaire
186
APPENDIX A. EXPERIMENTAL MATERIAL
Appendix B
Formal Impact Derivation In this appendix chapter, we present the impact derivation of the selected refactorings Extract Method, Move Method and Replace Method with Method Object. This derivation results in impact tables that specify their effect on a selected set of coupling and cohesion metrics. These impact tables were presented in Chapter 10 and validated in Chapter 11. Their application is demonstrated in Chapter 12, where these tables were used to refine the Move Method refactoring to a form which optimizes coupling and cohesion.
B.1
Introduction
In this appendix, we do not recapitulate the pre- and postconditions of the refactorings. For these formal descriptions, we refer to Chapter 10. The notation adhered to in the impact derivation process is the same notation used for the specification of the postcondition of each of the refactorings in Chapter 10, which is similar to the one in [Roberts, 1999]. When a predicate of entities or relations is provided, the value of this predicate always refers to the value before applying the refactoring. E.g., we refer to the set of methods implemented by a class c before refactoring as MI (c). In contrast, to refer to the value of a predicate after applying the refactoring, we write an accent behind 187
188
APPENDIX B. FORMAL IMPACT DERIVATION
the predicate. E.g., we refer to the set of methods implemented by a class c after refactoring as MI0 (c). The derivation proces proceeds according to the following steps. First, the formalization of the metric value is adapted as to reflect the state after the refactoring is applied. This adaptation requires the replacement of all predicates used in the formalization of the metric by their postcondition equivalents. I.e., if a metric formalization would be defined as | MI (c) |, it would be adapted to | MI0 (c) |, in which MI (c) signifies the number of methods implemented by class c before refactoring and MI0 (c) represents the number of methods implemented by c after refactoring. Second, as the postcondition of each refactoring expresses the value of the predicates in terms of their values before refactoring, we can substitute each 0 postcondition predicate. E.g., if the postcondition specified that M I (c) = 0 MI (c) \ {ms }, then we substitute references to MI (c) by MI (c) \ {ms } . These substitutions are performed iteratively, and constitute the main part of the derivation process. Once all the postcondition predicates are substituted, we rewrite the resulting formula until we can relate it to the metric formalization before applying the refactoring. Example – Let us consider the hypothetical case of a metric entitled Number of Methods (NOM), which is defined on a class c as N OM (c) =| MI (c) |. Accordingly, to reflect the value of the metric Number of Methods after refactoring, we adapt the formula to: N OM 0 (c) =| MI0 (c) | Let us now consider a refactoring RemoveM ethod(C c, M m), which is defined by the following pre- and postcondition: Precondition: m ∈ MI (c) Postcondition: MI0 (c) = MI (c) \ {ms } To derive the impact of the refactoring RemoveMethod on the metric Number of Methods, we then substitute the predicates used in the metric formula with their postcondition equivalent as dictated by the postcondition of the refac toring. Accordingly, we substitute MI0 (c) by MI (c) \ {ms } , which provides: N OM 0 (c) = MI (c) \ {ms }
B.2. EXTRACT METHOD
189
At this moment, all the postcondition predicates are substituted. Thus, we try to rewrite the resulting formula until we can relate it to the metric formalization before applying the refactoring. Accordingly, we attempt to relate N OM 0 (c) to | MI (c) |. This is performed through rewrite rules based on principles from set theory. One of these principles states that, for two sets A and B, with B ⊆ A, we have: | A \ B |=| A | − | B |. As the precondition of the RemoveMethod refactoring tells us that m ∈ MI (c), we know that {m} ⊆ MI (c), and therefore, the rewrite rule is applicable. Accordingly, we can rewrite the Number of Methods metric value after refactoring to: N OM 0 (c) =| MI (c) | − | {m} | Since the definition of NOM states that N OM (c) =| MI (c) |, we can relate this expression to N OM (c) as follows: N OM 0 (c) = N OM (c)− | {m} | Finally, since the cardinality of a set containing only a single element is 1, we can rewrite this to: N OM 0 (c) = N OM (c) − 1 This example illustrates the derivation process which is applied to derive the impact of the three selected refactorings (Extract Method, Move Method and Replace Method with Method Object) on the selected coupling and cohesion metrics.
B.2
Extract Method
In Chapter 10, the signature of the Extract Method refactoring was specified as: ExtractM ethod C c, M ms , P(M I) I, P(AT R) A for which: • c is the class in which the method is to be extracted; • ms is the method from which the statements will be extracted;
190
APPENDIX B. FORMAL IMPACT DERIVATION
• I ∪ A characterizes the set of statements S that will be extracted. I represents the set of method invocations, and A represents the set of attribute references. These arguments for the Extract Method signature are used in the following impact derivation.
B.2.1
Import Coupling
We can express the value of the Message Passing Coupling metric after applying the Extract Method refactoring as: P P M P C 0 (c) = m1 ∈M 0 (c) m2 ∈SIM 0 (m1 )\M 0 (c) N SI 0 (m1 , m2 ) I
I
Since MI0 (c) = MI (c) ∪ {mt }, we have: P P = 0 m1 ∈ MI (c)∪{mt }
m2 ∈SIM (m1 )\ MI (c)∪{mt }
N SI 0 (m1 , m2 )
When we split the first term we have: P P N SI 0 (m1 , m2 ) = m1 ∈MI (c) m2 ∈SIM 0 (m1 )\ MI (c)∪{mt } P N SI 0 (mt , m2 ) + 0 m2 ∈SIM (mt )\ MI (c)∪{mt }
Since A \ (B ∪ C) = (A \ B) \ A ∩ (C \ B) , we can rewrite the first term: P P N SI 0 (m1 , m2 ) = m1 ∈MI (c) m2 ∈ SIM 0 (m1 )\MI (c) \ SIM 0 (ms )∩({mt }\MI (c)) P N SI 0 (mt , m2 ) + 0 m2 ∈SIM (mt )\ MI (c)∪{mt }
Since {mt } 6∈ MI (c) ∧ {mt } ∈ SIM 0 (ms ), we can rewrite the first term as follows: P P = N SI 0 (m1 , m2 ) m1 ∈MI (c) m2 ∈ SIM 0 (m1 )\MI (c) \{mt } P N SI 0 (mt , m2 ) + 0 m2 ∈SIM (mt )\ MI (c)∪{mt }
P P P We can then split the first term using x∈A\B f (x) = x∈A f (x)− x∈A∩B f (x): P P 0 = m1 ∈MI (c) m2 ∈SIM 0 (m1 )\MI (c) N SI (m1 , m2 ) P 0 − m1 ∈MI (c) N SI (m1 , mt ) P N SI 0 (mt , m2 ) + 0 m2 ∈SIM (mt )\ MI (c)∪{mt }
B.2. EXTRACT METHOD
191
Since MI (c) = MI (c) \ {ms } ∪ {ms }, we can rewrite the first and second term as follows: P P 0 = m1 ∈MI (c)\{ms } m2 ∈SIM 0 (m1 )\MI (c) N SI (m1 , m2 ) P 0 + m2 ∈SIM 0 (ms )\MI (c) N SI (ms , m2 ) P − m1 ∈MI (c)\{ms } N SI 0 (m1 , mt ) 0 −N PSI (ms , mt ) N SI 0 (mt , m2 ) + 0 m2 ∈SIM (mt )\ MI (c)∪{mt }
Since • ∀m1 ∈ MI (c) \ {ms } : mt 6∈ M I 0 (m1 ) • N SI 0 (ms , mt ) = 1 we can simplify to: P P 0 = m1 ∈MI (c)\{ms } m2 ∈SIM 0 (m1 )\MI (c) N SI (m1 , m2 ) P 0 + m2 ∈SIM 0 (ms )\MI (c) N SI (ms , m2 ) P N SI 0 (mt , m2 ) −0−1+ 0 m2 ∈SIM (mt )\ MI (c)∪{mt }
Since ∀m1 ∈ MI (c) \ {ms } : SIM 0 (m1 ) = SIM (m1 ) ∧∀m2 ∈ SIM (m1 ) : N SI 0 (m1 , m2 ) = N SI(m1 , m2 ), we have: P P = m1 ∈MI (c)\{ms } m2 ∈SIM (m1 )\MI (c) N SI(m1 , m2 ) P + m2 ∈SIM 0 (ms )\MI (c) N SI 0 (ms , m2 ) P N SI 0 (mt , m2 ) −0−1+ 0 m2 ∈SIM (mt )\ MI (c)∪{mt }
Since 0 SIM (ms ) = SIM (ms )\ m1 ∈ SIM (ms ) |6 ∃mi ∈ M I(ms )\I : target(mi) = m1 ∪ {mt }, we can rewrite the second term as follows: P P M P C 0 (c) = m1 ∈MI (c)\{ms } m2 ∈SIM (m1 )\MI (c) N SI(m1 , m2 ) P + m2 ∈
SIM (ms )\ m1 ∈SIM (ms )|6∃mi∈ M I(ms )\I :target(mi)=m1
0
N SI (ms , P m2 ) −0−1+
m2 ∈SIM 0 (mt )\ MI (c)∪{mt }
And since mt 6∈ MI (c), we have:
N SI 0 (mt , m2 )
∪{mt }
\MI (c)
192 =
APPENDIX B. FORMAL IMPACT DERIVATION P P m1 ∈MI (c)\{ms } m2 ∈SIM (m1 )\MI (c) N SI(m1 , m2 ) P + + −
m2 ∈ SIM (ms )\ m1 ∈SIM (ms )|6∃mi∈ M I(ms )\I :target(mi)=m1 N SI 0 (mP s , mt ) N SI 0 (mt , m2 ) 0−1+ m2 ∈SIM 0 (mt )\ MI (c)∪{mt }
\MI (c)
N SI 0 (ms , m2 )
Since N SI 0 (ms , mt ) = 1, we have: P P = m ∈M (c)\{m } m2 ∈SIM (m1 )\MI (c) N SI(m1 , m2 ) 1 s I P + N SI 0 (ms , m2 ) m2 ∈ SIM (ms )\ m1 ∈SIM (ms )|6∃mi∈ M I(ms )\I :target(mi)=m1 \MI (c) P N SI 0 (mt , m2 ) +1−0−1+ 0 m2 ∈SIM (mt )\ MI (c)∪{mt }
P P = m1 ∈MI (c)\{ms } m2 ∈SIM (m1 )\MI (c) N SI(m1 , m2 ) P + N SI 0 (ms , m2 ) m2 ∈ SIM (ms )\ m1 ∈SIM (ms )|6∃mi∈ M I(ms )\I :target(mi)=m1 \MI (c) P N SI 0 (mt , m2 ) + m2 ∈SIM 0 (mt )\ MI (c)∪{mt }
Since (A \ B) \ C = (A \ C) \ B, we can rewrite the second term as follows: P P = m ∈M (c)\{m } m2 ∈SIM (m1 )\MI (c) N SI(m1 , m2 ) 1 s I P N SI 0 (ms , m2 ) + (ms )|6∃mi∈ M I(ms )\I :target(mi)=m1 Pm2 ∈ SIM (ms )\MI (c) \ m1 ∈SIM N SI 0 (mt , m2 ) + m2 ∈SIM 0 (mt )\ MI (c)∪{mt }
P
P P Since x∈A\B f (x) = x∈A f (x) − x∈A∩B , we can split the second term as follows: P P = m1 ∈MI (c)\{ms } m2 ∈SIM (m1 )\MI (c) N SI(m1 , m2 ) P N SI 0 (ms , m2 ) + Pm2 ∈ SIM (ms )\MI (c) − N SI 0 (ms , m2 ) m2 ∈SIM (ms )|6∃mi∈ M I(ms )\I :target(mi)=m2 P N SI 0 (mt , m2 ) + m2 ∈SIM 0 (mt )\ MI (c)∪{mt }
Since ∀m2 ∈ SIM (ms ) \ MI (c) : N SI 0 (ms , m2 ) = N SI(ms , m2 ), we can rewrite the second term to: P P = m1 ∈MI (c)\{ms } m2 ∈SIM (m1 )\MI (c) N SI(m1 , m2 ) P N SI(ms , m2 ) + m2 ∈ SIM (ms )\MI (c) P N SI 0 (ms , m2 ) − m2 ∈ SIM (ms )\MI (c) |6∃mi∈ M I(ms )\I :target(mi)=m2 P N SI 0 (mt , m2 ) + 0 m2 ∈SIM (mt )\ MI (c)∪{mt }
B.2. EXTRACT METHOD
193
We can then unify the first and the second term as follows: P P = m ∈M (c) m2 ∈SIM (m1 )\MI (c) N SI(m1 , m2 ) 1 I P − N SI 0 (ms , m2 ) Pm2 ∈ SIM (ms )\MI (c) |6∃mi∈ M I(m0s )\I :target(mi)=m2 + N SI (mt , m2 ) m2 ∈SIM 0 (mt )\ MI (c)∪{mt }
= MP P C(c) − N SI 0 (ms , m2 ) Pm2 ∈ SIM (ms )\MI (c) |6∃mi∈ M I(m0s )\I :target(mi)=m2 + N SI (mt , m2 ) 0 m2 ∈SIM (mt )\ MI (c)∪{mt }
Since 0 SIM (ms ) = SIM (ms )\ m1 ∈ SIM (ms ) |6 ∃mi ∈ M I(ms )\I : target(mi) = m1 ∪ {mt }, we can rewrite the third term as follows: = MP P C(c) − P m2 ∈SIM (ms )\MI (c) |6∃mi∈ + m2 ∈
M I(ms )\I :target(mi)=m2
N SI 0 (ms , m2 )
SIM (ms )\ m1 ∈SIM (ms )|6∃mi∈ M I(ms )\I :target(mi)=m1
∪{mt }
\ MI (c)∪{mt }
N SI 0 (mt , m2 ) = MP P C(c) − I (c) |6∃mi∈ Pm2 ∈ SIM (ms )\M +
M I(ms )\I :target(mi)=m2
= MP P C(c) − m2 ∈ SIM (ms )\MI (c) |6∃mi∈ P +
M I(ms )\I :target(mi)=m2
N SI 0 (ms , m2 )
m2 ∈ SIM (ms )\ m1 ∈SIM (ms )|6∃mi∈ M I(ms )\I :target(mi)=m1 N SI 0 (mt , m2 )
\MI (c)
N SI 0 (ms , m2 )
N SI 0 (ms , m2 )
m2 ∈ SIM (ms )\MI (c) |6∃mi∈ M I(ms )\I :target(mi)=m2
= M P C(c) Which means that after applying Extract Method, M P C(c) will remain unchanged.
B.2.2
Export Coupling
The value of the OMMEC metric after applying the Extract Method is expressed as:
194
APPENDIX B. FORMAL IMPACT DERIVATION OM M EC 0 (c) = P
P
P
m1 ∈MI0 (c2 ) N SI 0 (m1 , m2 ) 0 0 m2 ∈ SIM 0 (m1 )∩(MN EW (c)∪MOV R (c) c2 ∈Others0 (c)
Since Others0 (c) = Others(c), we have: P P P = c2 ∈Others(c) m1 ∈M 0 (c2 )
0 0 m2 ∈ SIM 0 (m1 )∩(MN EW (c)∪MOV R (c)
I
N SI 0 (m1 , m2 )
0 0 Since MN EW (c) = MN EW (c) ∪ {mt }, and MOV R (c) = MOV R (c), we have: P P P N SI 0 (m1 , m2 ) = c2 ∈Others(c) m1 ∈M 0 (c2 ) 0 m2 ∈ SIM (m1 )∩(MN EW (c)∪{mt }∪MOV R (c)
I
=
P
c2 ∈Others(c)
+
P
P
c2 ∈Others(c)
m1 ∈MI0 (c2 )
P
P
m1 ∈MI0 (c2 )
SIM 0 (m1 )∩(MN EW (c)∪MOV R (c) 0 mt ∈SIM 0 (m1 ) N SI (m1 , mt )
m2 ∈ P
N SI 0 (m1 , m2 )
Since ∀c2 ∈ Others(c) : MI0 (c2 ) = MI (c2 ), we have: P P P N SI 0 (m1 , m2 ) = c2 ∈Others(c) m1 ∈MI (c2 ) m2 ∈ SIM 0 (m1 )∩(MN EW (c)∪MOV R (c) P P P + c2 ∈Others(c) m1 ∈MI (c2 ) mt ∈SIM 0 (m1 ) N SI 0 (m1 , mt ) Since ∀c2 ∈ Others(c), ∀m1 ∈ MI (c2 ) : M I 0 (m1 ) = M I(m1 ), we have: P P P N SI(m1 , m2 ) = c2 ∈Others(c) m1 ∈MI (c2 ) m2 ∈ SIM (m1 )∩(MN EW (c)∪MOV R (c) P P P + c2 ∈Others(c) m1 ∈MI (c2 ) mt ∈SIM (m1 ) N SI(m1 , mt ) P P P N SI(m1 , m2 )+ = c2 ∈Others(c) m1 ∈MI (c2 ) m2 ∈ SIM (m1 )∩(MN EW (c)∪MOV R (c)
0 = OM M EC(c) Which means that after applying Extract Method, OM M EC(c) will remain unchanged.
B.2.3
General Coupling
The Coupling Between Object classes metric value after applying the Extract Method is expressed as: CBO0 (c) = CBOSet0 (c) with CBOSet0 (c) =
B.2. EXTRACT METHOD =
195
W W d ∈ C 0 \{c} | m1 ∈M 0 (c) uses0 (m1 , d)∨ md ∈M 0 (d) uses0 (md , c) I
I
Since C 0 = C and MI0 (c) = MI (c) ∪ {mt }, we have: W W = d ∈ C \ {c} | m1 ∈MI (c)∪{mt } uses0 (m1 , d) ∨ md ∈MI (d) uses0 (md , c) When we refine uses(md , c), we have: W = d ∈ C \ {c} | m1 ∈MI (c)∪{mt } uses0 (m1 , d) W 0 0 0 0 ∨ md ∈M 0 (d) MI (c) ∩ P IM (md ) ∪ AI (c) ∩ AR (md ) 6= ∅ I
Since ∀d ∈ C \ {c}, ∀md ∈ MI (d) : • A0I (c) = AI (c) • MI0 (d) = MI (d) • P IM 0 (md ) = P IM (md ) • AR0 (md ) = AR(md ) we have: W = d ∈ C \ {c} | m1 ∈MI (c)∪{mt } uses0 (m1 , d) W ∨ md ∈MI (d) (MI (c) ∪ {mt }) ∩ P IM (md ) ∪ AI (c) ∩ AR(md ) 6= ∅ Since ∀md ∈ M (C) : mt 6∈ P IM (md ), we have: W = d ∈ C \ {c} | m1 ∈MI (c)∪{mt } uses0 (m1 , d) W ∨ md ∈MI (d) MI (c) ∩ P IM (md ) ∪ AI (c) ∩ AR(md ) 6= ∅ =
W d ∈ C \ {c} | m1 ∈MI (c)∪{mt } uses0 (m1 , d) W ∨ md ∈MI (d) uses(md , c)
196
APPENDIX B. FORMAL IMPACT DERIVATION
We can split the set in two parts: W 0 = d ∈ C \ {c} | ms ∈MI (c)∪{mt } uses (ms , d) W ∪ d ∈ C \ {c} | md ∈MI (d) uses(md , c) We will now focus on the first term, to prove that it equals d ∈ C \ {c} | W and that therefore, CBOSet0 (c) = CBOSet(c). m1 ∈MI (c) uses(m1 , d) W d ∈ C \ {c} | m1 ∈MI (c)∪{mt } uses0 (m1 , d) =
d ∈ C \ {c} | W
m1 ∈MI (c)∪{mt }
MI0 (d)
0
∩ P IM (m1 ) ∪ A0I (d) ∩ AR0 (m1 )
6 ∅ =
Since ∀d ∈ C \ {c} : MI0 (d) = MI (d) ∧ A0I (d) = AI (d), we have: = d ∈ C \ {c} | W 0 0 MI (d) ∩ P IM (m1 ) ∪ AI (d) ∩ AR (m1 ) 6= ∅ m1 ∈MI (c)∪{mt } Since: • ∀m1 ∈ MI (c) \ {ms } : P IM 0 (m1 ) = P IM (m1 ) ∧ AR0 (m1 )AR(m1 ) • P IM 0 (ms ) ∪ P IM 0 (mt ) = P IM (ms ) ∧ AR0 (ms ) ∪ AR0 (mt ) = AR(ms ) we have: = d ∈ C \ {c} | W M (d) ∩ P IM (m ) ∪ A (d) ∩ AR(m ) = 6 ∅ I 1 I 1 m1 ∈MI (c) =
W d ∈ C \ {c} | m1 ∈MI (c) uses(m1 , d)
B.2. EXTRACT METHOD
197
And therefore CBOSet0 (c) W = d ∈ C \ {c} | ms ∈MI (c) uses(ms , d) W ∪ d ∈ C \ {c} | md ∈MI (d) uses(md , c) W W = d ∈ C \ {c} | ms ∈MI (c) uses(ms , d) ∨ md ∈MI (d) uses(md , c) = CBOSet(c) Which means that after applying Extract method, CBO will remain unchanged.
B.2.4
Aggregation Import Coupling
The value of the Data Abstraction Coupling metric after applying the Extract Method refactoring is described as: DAC 0 (c) =| {a | a ∈ A0I (c) ∧ T 0 (a) ∈ C 0 \ {c}} | Since C 0 = C, A0I (c) = AI (c), and ∀a ∈ AI (c) : T 0 (a) = T (a), we have: = | {a | a ∈ AI (c) ∧ T (a) ∈ C \ {c}} |= DAC(c)
B.2.5
Normalized Cohesion
We describe the value of the Lack of Cohesion in Methods metric variant 5 after applying Extract Method as: LCOM 50 (c) =
|MI0 (c)|− |A01(c)| I
P
0 0 a∈A0 (c) |{m1 |m1 ∈MI (c)∧a∈AR (m1 )}| I |MI0 (c)|−1
Since A0I (c) = AI (c) and MI0 (c) = MI (c) ∪ {mt }, we have: P =
|MI (c)∪{mt }|− |A 1(c)| I
a∈AI (c) |{m1 |m1 ∈
MI (c)∪{mt } ∧a∈AR0 (m1 )}|
|MI (c)∪{mt }|−1
Since mt 6∈ MI (c), we have | MI (c) ∪ {mt } |=| MI (c) | +1:
198 =
APPENDIX B. FORMAL IMPACT DERIVATION |MI (c)|+1− |A 1(c)|
P
I
a∈AI (c) |{m1 |m1 ∈
MI (c)∪{mt } ∧a∈AR0 (m1 )}|
|MI (c)|+1−1
Since MI (c) ∪ {mt } = MI (c) \ {ms } ∪ {ms } ∪ {mt } , we have: P =
|MI (c)|− |A 1(c)| P
a∈AI (c) |{m1 |m1 ∈{ms }∧a∈AR
−1+ |A 1(c)|
=
MI (c)\{ms } ∧a∈AR0 (m1 )}|
|MI (c)| 1 |AI (c)|
−
Since have:
a∈AI (c) |{m1 |m1 ∈
I
− P
P
I
a∈AI
| {m1 | m1 ∈ {mx } ∧ a ∈ AR0 (mx )} |=| AI (c) ∩ AR0 (mx ) |, we
|MI (c)|− |A 1(c)|
P
I
−
(ms )}|
|MI (c)| 0 (c) |{m1 |m1 ∈{mt }∧a∈AR (mt )}| |MI (c)|
a∈AI (c)
−
0
a∈AI (c) |{m1 |m1 ∈
MI (c)\{ms } ∧a∈AR0 (m1 )}|
|MI (c)|
1 |AI (c)∩AR0 (ms )| |AI (c)|
|MI (c)| −1+ |A 1(c)| |AI (c)∩AR0 (mt )| I
|MI (c)|
Since • ∀m1 ∈ MI (c) \ {ms } : AR0 (m1 ) = AR(m1 ) 0 • AR (m ) = AR(m )\ a ∈ AR(m ) |6 ∃a ∈ AT R(m )\A : target(a1 ) = s s s 1 s a S • AR0 (mt ) = a∈A target(a) we rewrite to: =
|MI (c)|− |A 1(c)|
P
I
− −
1 |AI (c)∩ |AI (c)|
a∈AI (c) |{m1 |m1 ∈
MI (c)\{ms } ∧a∈AR(m1 )}|
|MI (c)|
AR(ms )\ a∈AR(ms )|6∃a1 ∈ AT R(ms )\A :target(a1 )=a
|
|MI (c)| −1+
S |AI (c)∩ atr∈A target(a)| |AI (c)|
|MI (c)|
Since A ∩ (B \ C) = (A ∩ B) \ (A ∩ B ∩ C), we have | A ∩ (B \ C) |=| A ∩ B | − | A ∩ B ∩ C | and therefore can rewrite the second term as follows: P =
|MI (c)|− |A 1(c)| I
a∈AI (c) |{m1 |m1 ∈
|MI (c)|
−
1 | |AI (c)|
AI (c)∩AR(ms ) | |MI (c)|
MI (c)\{ms } ∧a∈AR(m1 )}|
B.2. EXTRACT METHOD + −
1 | |AI (c)|
199
a∈AI (c)∩AR(ms )|6∃a1 ∈ AT R(ms )\A :target(a1 )=a | |MI (c)|
−1+
S |AI (c)∩ atr∈A target(a)| |AI (c)|
|MI (c)|
At this moment, we can unify the first and second term: =
|MI (c)|− |A 1(c)|
−
=
1 | |AI (c)|
S |AI (c)∩ atr∈A target(a)| |AI (c)|
|MI (c)|
=
z−1 x−y z . z−1 ,
we have:
1 | |AI (c)|
P
a∈AI (c) |{m1 |m1 ∈MI (c)∧a∈AR(m1 )}|
|MI (c)|−1
−
S |AI (c)∩ atr∈A target(a)| |AI (c)|
|MI (c)|
1 | |AI (c)|
a∈AI (c)∩AR(ms )|6∃a1 ∈ AT R(ms )\A :target(a1 )=a | |MI (c)|
−1+
S |AI (c)∩ atr∈A target(a)| |AI (c)|
|MI (c)| −|AI (c)| |AI (c)| ,
we can rewrite the last term as:
|MI (c)|−1 LCOM 5(c) |MI (c)|
−
|MI (c)| −1+
Since −1 =
+
a∈AI (c)∩AR(ms )|6∃a1 ∈ AT R(ms )\A :target(a1 )=a |
|MI (c)|−1 LCOM 5(c) |MI (c)|
+
a∈AI (c)∩AR(ms )|6∃a1 ∈ AT R(ms )\A :target(a1 )=a |
1 |MI (c)|−1 |MI (c)|− |AI (c)| . |MI (c)|
−
=
|MI (c)| −1+
x−y z
+
=
a∈AI (c) |{m1 |m1 ∈MI (c)∧a∈AR(m1 )}|
|MI (c)|
+
Since
P
I
1 | |AI (c)|
a∈AI (c)∩AR(ms )|6∃a1 ∈ AT R(ms )\A :target(a1 )=a |
|MI (c)| S −|AI (c)|+|AI (c)∩ atr∈A target(a)| |AI (c)| |MI (c)|
Since −(− | A | + | A ∩ B |) =| A | − | A ∩ B | =| A \ B |, we have: =
|MI (c)|−1 |MI (c)| LCOM 5(c)
+ +
| a∈AI (c)∩AR(ms )|6∃a1 ∈ AT R(ms )\A :target(a1 )=a | |AI (c)|.|MI (c)| S |AI (c)\ atr∈A target(a)| |AI (c)|.|MI (c)|
200
APPENDIX B. FORMAL IMPACT DERIVATION
Which means that after applying Extract Method, LCOM 5 will be increased with a factor proportionate to the number of attributes which the remaining part of ms does not reference, and additionally increased with a factor proportionate to the number of attributes which the extracted part of ms does not reference.
B.2.6
Non-normalized Cohesion
The value of the Lack of Cohesion in Methods metric variant 1 after applying Extract Method is described as: LCOM 10 (c) = LCOM 1Set0 (c) with LCOM 10 Set(c) = {m1 , m2 } | m1 , m2 ∈ MI0 (c) ∧ m 1 6= m2 ∧ AR0 (m1 ) ∩ AR0 (m2 ) ∩ A0I (c) = ∅ Since MI0 (c) = MI (c) ∪ {mt }, and A0I (c) = AI (c), we have: = {m1 , m2 } | m1 , m2 ∈ MI (c) ∧ m1 6= m2 ∧ 0 0 AR (m1 ) ∩ AR (m2 ) ∩ AI (c) = ∅} ∪ {m1 , mt } | m1 ∈ MI (c)∧ AR0 (m1 ) ∩ AR0 (mt ) ∩ AI (c) = ∅ S Since AR0 (mt ) = atr∈A target(atr), we have: = {m1 , m2 } | m1 , m2 ∈ MI (c) ∧ m1 6= m2 ∧ 0 0 AR (m1 ) ∩ AR (m2 ) ∩ AI (c) = ∅} ∪ {m1 , mt } | m1 ∈ MI (c)∧ S AR0 (m1 ) ∩ atr∈A target(atr) ∩ AI (c) = ∅ When we split the first term using MI (c) = MI (c) \ {ms } ∪ {ms }, we have: = {m1 , m2 } | m1 , m2 ∈ MI (c) \ {m s } ∧ m1 6= m2 ∧ 0 0 AR (m ) ∩ AR (m ) ∩ A (c) = ∅} 1 2 I ∪ {m1 , ms } | m1 ∈ MI (c) \ {ms }∧ 0 0 AR (m1 ) ∩ AR (ms ) ∩ AI (c) = ∅} ∪ {m1 , mt } | m1 ∈ MI (c)∧ S AR0 (m1 ) ∩ atr∈A target(atr) ∩ AI (c) = ∅ Since AR0 (ms ) = AR(ms ) \ (AR0 (mt ) \ AR0 (ms )), we have:
B.2. EXTRACT METHOD =
201
{m1 , m2 } | m1 , m2 ∈ MI (c) \ {m s } ∧ m1 6= m2 ∧ 0 0 AR (m ) ∩ AR (m ) ∩ A (c) = ∅} 1 2 I ∪ {m1 , ms } | m1 ∈ MI (c) \ {ms }∧ 0 0 0 AR (m1 ) ∩ AR(ms ) \ (AR (mt ) \ AR (ms )) ∩ AI (c) = ∅} ∪ {m1 , mt } | m1 ∈ MI (c)∧ S AR0 (m1 ) ∩ atr∈A target(atr) ∩ AI (c) = ∅
Since X ∩ (Y \ Z) = ∅ ⇔ X ∩ Y \ (X ∩ Y ∩ Z) = ∅ ⇔ X ∩Y ⊆X ∩Y ∩Z we can rewrite the second term as follows: = {m1 , m2 } | m1 , m2 ∈ MI (c) \ {m s } ∧ m1 6= m2 ∧ 0 0 AR (m ) ∩ AR (m ) ∩ A (c) = ∅} 1 2 I ∪ {m1 , ms } | m1 ∈ MI (c) \ {m s }∧ 0 0 0 AR (m1 ) ∩ AR(ms ) ∩ AI (c) ⊆ AR (mt ) \ AR (ms ) ∪ {m1 , mt } | m1 ∈ MI (c)∧ S AR0 (m1 ) ∩ atr∈A target(atr) ∩ AI (c) = ∅ Since X ⊆ Y ⇔ (X = ∅) ∨ (X 6= ∅) ∧ (X ⊆ Y ) we can rewrite the second term as follows: = {m1 , m2 } | m1 , m2 ∈ MI (c) \ {m s } ∧ m1 6= m2 ∧ 0 0 AR (m1 ) ∩ AR (m2 ) ∩ AI (c) = ∅} ∪ {m1 , ms } | m1 ∈ MI (c) \ {ms }∧ AR0 (m1 ) ∩ AR(ms ) ∩ AI (c) = ∅ ∨ AR0 (m1 ) ∩ AR(ms ) ∩ AI (c) 6= ∅ ∧ AR0 (m1 ) ∩ AR(ms ) ∩ AI (c) ⊆ AR0 (mt ) \ AR0 (ms ) ∪ {m1 , mt } | m1 ∈ MI (c)∧ S AR0 (m1 ) ∩ atr∈A target(atr) ∩ AI (c) = ∅ Since {x | a ∧ (b ∨ c)} = {x | a ∧ b} ∪ {x | a ∧ c}, we can split up the second term as follows:
202 =
APPENDIX B. FORMAL IMPACT DERIVATION
{m1 , m2 } | m1 , m2 ∈ MI (c) \ {m s } ∧ m1 6= m2 ∧ 0 0 AR (m ) ∩ AR (m ) ∩ A (c) = ∅} 1 2 I ∪ {m1 , ms } | m1 ∈ MI (c) \ {ms }∧ 0 AR (m1 ) ∩ AR(ms ) ∩ AI (c) = ∅ ∪ {m1 , ms } | m1 ∈ MI (c) \ {ms }∧ AR0 (m1 ) ∩ AR(ms ) ∩ AI (c) 6= ∅ ∧ AR0 (m1 ) ∩ AR(ms ) ∩ AI (c) ⊆ AR0 (mt ) \ AR0 (ms ) } ∪ {m1 , mt } | m1 ∈ MI (c)∧ S AR0 (m1 ) ∩ atr∈A target(atr) ∩ AI (c) = ∅
Since ∀m1 ∈ MI (c) \ {ms } : AR0 (m1 ) = AR(m1 ), we have: = {m1 , m2 } | m1 , m2 ∈ MI (c) \ {m s } ∧ m1 6= m2 ∧ AR(m 1 ) ∩ AR(m2 ) ∩ AI (c) = ∅ ∪ {m1 , ms } | m1 ∈ MI (c) \ {ms }∧ AR(m 1 ) ∩ AR(ms ) ∩ AI (c) = ∅} ∪ {m1 , ms } | m1 ∈ MI (c) \ {ms }∧ AR0 (m1 ) ∩ AR(ms ) ∩ AI (c) 6= ∅ ∧ AR0 (m1 ) ∩ AR(ms ) ∩ AI (c) ⊆ AR0 (mt ) \ AR0 (ms ) } ∪ {m1 , mt } | m1 ∈ MI (c)∧ S AR0 (m1 ) ∩ atr∈A target(atr) ∩ AI (c) = ∅ At this moment we can unify the first and second term: = {m1 , m2 } | m1 , m2 ∈ MI (c) ∧ m 1 6= m2 ∧ AR(m ) ∩ AR(m ) ∩ A (c) = ∅ 1 2 I ∪ {m1 , ms } | m1 ∈ MI (c) \ {ms }∧ AR0 (m1 ) ∩ AR(ms ) ∩ AI (c) 6= ∅ ∧ AR0 (m1 ) ∩ AR(ms ) ∩ AI (c) ⊆ AR0 (mt ) \ AR0 (ms ) } ∪ {m1 , mt } | m1 ∈ MI (c)∧ S AR0 (m1 ) ∩ atr∈A target(atr) ∩ AI (c) = ∅} = LCOM 1Set(c) ∪ {m1 , ms } | m1 ∈ MI (c) \ {ms }∧ AR0 (m1 ) ∩ AR(ms ) ∩ AI (c) 6= ∅ ∧ AR0 (m1 ) ∩ AR(ms ) ∩ AI (c) ⊆ AR0 (mt ) \ AR0 (ms ) } ∪ {m1 , mt } | m1 ∈ MI (c)∧ S AR0 (m1 ) ∩ atr∈A target(atr) ∩ AI (c) = ∅
B.2. EXTRACT METHOD
203
We once again divide MI (c) into MI (c) \ {ms } and {ms }: = LCOM 1Set(c) ∪ {m1 , ms } | m1 ∈ MI (c) \ {ms }∧ AR0 (m1 ) ∩ AR(ms ) ∩ AI (c) 6= ∅ ∧ AR0 (m1 ) ∩ AR(ms ) ∩ AI (c) ⊆ AR0 (mt ) \ AR0 (ms ) } ∪ {m1 , mt } | m1 ∈ MI (c) \ {ms }∧ S 0 AR ∩ AI (c) = ∅} (ms ) ∩ atr∈A0 target(atr) S ∪ {ms , mt } | AR (ms ) ∩ atr∈A target(atr) ∩ AI (c) = ∅ Once again, we apply the rule that ∀m1 ∈ MI (c) \ {ms } : AR0 (m1 ) = AR(m1 ), so that we can rewrite the first and third term to: = LCOM 1Set(c) ∪ {m1 , ms } | m1 ∈ MI (c) \ {ms }∧ AR(m1 ) ∩ AR(ms ) ∩ AI (c) 6= ∅ ∧ AR(m1 ) ∩ AR(ms ) ∩ AI (c) ⊆ AR0 (mt ) \ AR0 (ms ) } ∪ {m1 , mt } | m1 ∈ MI (c) \ {ms }∧ S AR(m target(atr) ∩ AI (c) = ∅ 1 ) ∩ A atr∈A S ∪ {ms , mt } | AR0 (ms ) ∩ atr∈A target(atr) ∩ AI (c) = ∅ Since • AR0 (ms ) =
S
• AR0 (mt ) =
S
atr∈AT R(ms )\A
atrA
target(atr):
target(atr):
we have: = LCOM 1Set(c) ∪ {m1 , ms } | m1 ∈ MI (c) \ {ms }∧ AR(m1 ) ∩ AR(ms ) ∩ AI (c) 6= ∅ S S ∧ AR(m1 )∩AR(ms )∩AI (c) ⊆ target(atr)\ atr∈AT R(ms )\A target(atr) } atrA ∪ {m1 , mt } | S m1 ∈ MI (c) \ {ms } ∧ AR(m1 ) ∩ atr∈A target(atr) ∩ AI (c) = ∅ ∪ {ms , mt } | S S atr∈AT R(ms )\A target(atr) ∩ atr∈A target(atr) ∩ AI (c) = ∅ Since these parts are disjunct, we can state that LCOM 10 (c) =| LCOM 1Set0 (c) |:
204
APPENDIX B. FORMAL IMPACT DERIVATION
= LCOM 1(c) + | {m1 , ms } | m1 ∈ MI (c) \ {ms }∧ AR(m1 ) ∩ AR(ms ) ∩ AI (c) 6= ∅ S S ∧ AR(m1 )∩AR(ms )∩AI (c) ⊆ target(atr)\ atr∈AT R(ms )\A target(atr) } atrA + | {m1 , mt } | S m1 ∈ MI (c) \ {ms } ∧ AR(m1 ) ∩ atr∈A target(atr) ∩ AI (c) = ∅ | + | {ms , mt } | S S atr∈AT R(ms )\A target(atr) ∩ atr∈A target(atr) ∩ AI (c) = ∅ | Which means that after applying Extract Method, LCOM 1(c) will be increased with: • the number of methods m1 ∈ MI (c) which share references to attributes implemented by c with ms , but not with the remaining part; • the number of methods m1 ∈ MI (c) which do not share references to attributes implemented by c with the extracted part of ms ; • 1 in case the remaining part of ms does not share references to attributes implemented by c with the extracted part of ms .
B.3. MOVE METHOD
B.3
205
Move Method
B.3.1
Import Coupling
The Message Passing Coupling metric value after applying Move Method is defined as: M P C 0 (cs ) = =
P
P
m1 ∈MI0 (cs )
m1 ∈MI (cs )\{m}
P
m2 ∈SIM 0 (m1 )\MI0 (cs )
P
N SI 0 (m1 , m2 )
m2 ∈SIM (m1 )\(MI (cs )\{m})
N SI(m1 , m2 )
Since A \ (B \ C) = (A \ B) ∪ (A ∩ C), this can be rewritten to: P P = m1 ∈MI (cs )\{m} m2 ∈(SIM (m1 )\(MI (cs ))∪(SIM (m1 )∩{m}) N SI(m1 , m2 ) P P P P As x∈A∪B f (x) = x∈A f (x) + x∈B f (x) − x∈(A∩B) f (x) , we can separate the parts as follows: =
P P m1 ∈MI (cs )\{m} m2 ∈SIM (m1 )\MI (cs ) N SI(m1 , m2 ) P P + m1 ∈MI (cs )\{m} m2 ∈SIM (m1 )∩{m} N SI(m1 , m2 ) P P − m1 ∈MI (cs )\{m}
m2 ∈ SIM (m1 )\MI (cs ) ∩ SIM (m1 )∩{m}
N SI(m1 , m2 )
At this time we will demonstrate in a sub-proof that the last term (LT) is equal to zero and can therefore be dropped. Subproof
– Since:
• A \ (B ∪ C) = (A \ B) ∩ (A \ C) • MI (cs ) = MI (cs ) \ {m} ∪ {m} we can rewrite SIM (m1 ) \ MI (cs ) to SIM (m1 ) \ MI (cs ) \ {m} ∩ SIM (m1 ) \ {m} : and so we rewrite SIM (m1 ) \ MI (cs ) ∩ SIM (m1 ) ∩ {m} to: =
SIM (m1 ) \ MI (cs ) \ {m}
∩ SIM (m1 ) \ {m} ∩ SIM (m1 ) ∩ {m}
206
APPENDIX B. FORMAL IMPACT DERIVATION
Since (A \ B) ∩ (A ∩ B) = ∅, we have SIM (m1 ) \ {m} ∩ SIM (m1 ) ∩ {m} = ∅ and therefore: = SIM (m1 ) \ MI (cs ) \ {m} ∩ ∅ As A \ ∅ = ∅, our last term reduces to: P P LT = m1 ∈MI (cs )\{m} m2 ∈∅ N SI(m1 , m2 ) = 0 Q.E.D. (subproof) As the last term can be dropped, we can simplify to: P P = m1 ∈MI (cs )\{m} m2 ∈SIM (m1 )\MI (cs ) N SI(m1 , m2 ) P P + m1 ∈MI (cs )\{m} m2 ∈SIM (m1 )∩{m} N SI(m1 , m2 ) Because ∀m1 | m 6∈ SIM (m1 ) ⇔ N SI(m1 , m) = 0, the latter can be simplified to: P P = m ∈M (c )\{m} m2 ∈SIM (m1 )\MI (cs ) N SI(m1 , m2 ) 1 s I P + m1 ∈MI (cs )\{m} N SI(m1 , m) Taking into account that: P P P • x∈A\B f (x) = x∈A f (x) − x∈A∩B f (x) • MI (cs ) ∩ {m} = {m} we can split the first term as follows: P P = N SI(m1 , m2 ) m ∈M (c ) 1 s I P Pm2 ∈SIM (m1 )\MI (cs ) − m1 ∈{m} m2 ∈SIM (m1 )\MI (cs ) N SI(m1 , m2 ) P + m1 ∈MI (cs )\{m} N SI(m1 , m) Since this leaves the first term equal to M P C(cs ), and since we have: P = M P C(cs ) − m2 ∈SIM (m)\MI (cs ) N SI(m, m2 ) P + m1 ∈MI (cs )\{m} N SI(m1 , m)
P
x∈{y}
f (x) = f (y)
B.3. MOVE METHOD
207
This means that, after applying the Move Method, the Message Passing Coupling of the source class will: P P • increase in case m1 ∈MI (cs )\{m} N SI(m1 , m) > m2 ∈SIM (m)\MI (cs ) N SI(m, m2 ) P P • reduce in case m1 ∈MI (cs )\{m} N SI(m1 , m) < m2 ∈SIM (m)\MI (cs ) N SI(m, m2 ) P P • remain equal in case m1 ∈MI (cs )\{m} N SI(m1 , m) = m2 ∈SIM (m)\MI (cs ) N SI(m, m2 )
B.3.2
Export Coupling
The selected export coupling metric (OMMEC) value after applying Move Method is described as: OM M EC 0 (cs ) P P P = c2 ∈Others0 (cs ) m1 ∈M 0 (c2 ) I
0 0 m2 ∈ SIM 0 (m1 )∩(MN EW (cs )∪MOV R (cs )
N SI 0 (m1 , m2 )
Since: • Others0 (cs ) = C 0 \ Ancestors0 (cs ) ∪ Descendants0 (cs ) = Others(cs ) we have: P P = c ∈Others(c ) m1 ∈MI0 (c2 ) 2 s P 0 0 m2 ∈ SIM 0 (m1 )∩(MN EW (cs )∪MOV R (cs )
=
P P 0 Pc2 ∈Others(cs ) m1 ∈MI (c2 ) 0 0 m2 ∈ SIM 0 (m1 )∩(MN EW (cs )∪MOV R (cs )
=
N SI 0 (m1 , m2 )
N SI(m1 , m2 )
P P m1 ∈MI0 (c2 ) s) Pc2 ∈Others(c m2 ∈
SIM (m1 )∩ (MN EW (cs )\{m})∪MOV R (cs )
N SI(m1 , m2 )
Since (A \ B) ∪ C = (A ∪ C) \ (B \ C), we have: MN EW (cs ) \ {m} ∪ MOV R (cs ) = MN EW (cs ) ∪ MOV R (cs ) \ {m} \ MOV R (cs ) = MN EW (cs ) ∪ MOV R (cs ) \ {m}
208
APPENDIX B. FORMAL IMPACT DERIVATION
Moreover, since A ∩ (B \ C) = (A ∩ B) \ C, we have: SIM (m1 ) ∩ (MN EW (cs ) ∪ MOV R (cs )) \ {m} = SIM (m1 ) ∩ (MN EW (cs ) ∪ MOV R (cs ) \ {m} And therefore OM M EC 0 (cs ) P P = m1 ∈MI0 (c2 ) s) Pc2 ∈Others(c m2 ∈
N SI(m1 , m2 )
SIM (m1 )∩(MN EW (cs )∪MOV R (cs ) \{m}
Since: • ∀c ∈ Others(cs ) \ {ct } : MI0 (c) = MI (c) • MI0 (ct ) = MI (ct ) ∪ {m} we have: P P = m1 ∈MI (c2 ) s) Pc2 ∈Others(c
SIM (m1 )∩(MN EW (cs )∪MOV R (cs ) \{m}
m2 ∈
+
P
m2 ∈
Since =
N SI(m1 , m2 )
P
x∈(A\B)
N SI(m, m2 )
SIM (m)∩(MN EW (cs )∪MOV R (cs ) \{m}
f (x) =
P
x∈A
f (x) −
P
x∈B
P P Pc2 ∈Others(cs ) m1 ∈MI (c2 ) m2 ∈ SIM (m1 )∩(MN EW (cs )∪MOV R (cs )
f (x) +
P
x∈(B\A)
f (x), we have:
N SI(m1 , m2 )
P P − c2 ∈Others(cs ) m1 ∈MI (c2 ) N SI(m1 , m) P P + c2 ∈Others(cs ) m1 ∈MI (c2 ) P N SI(m1 , m) m2 ∈
+
P
{m}\ SIM (m1 )∩(MN EW (cs )∪MOV R (cs )
m2 ∈
SIM (m)∩(MN EW (cs )∪MOV R (cs ) \{m}
= OM PM EC(cs ) P − c2 ∈Others(cs ) m1 ∈MI (c2 ) N SI(m1 , m)
N SI(m, m2 )
B.3. MOVE METHOD
209
P P + c2 ∈Others(cs ) m1 ∈MI (c2 ) P m2 ∈
+
P
{m}\ SIM (m1 )∩(MN EW (cs )∪MOV R (cs )
m2 ∈
N SI(m1 , m)
N SI(m, m2 )
SIM (m)∩(MN EW (cs )∪MOV R (cs ) \{m}
Since m ∈ (MN EW (cs ) ∪ MOV R (cs ), we have: = OM PM EC(cs ) P − c2 ∈Others(cs ) m1 ∈MI (c2 ) N SI(m1 , m) P P P N SI(m1 , m) + c2 ∈Others(cs ) m1 ∈MI (c2 ) m2 ∈ {m}\SIM (m1 ) P N SI(m, m2 ) + m2 ∈
SIM (m)∩(MN EW (cs )∪MOV R (cs ) \{m}
Finally, since ∀m1 ∈ M (C) : m 6∈ SIM (m1 ) ⇐⇒ N SI(m1 , m) = 0, we have: = OM PM EC(cs ) P − c2 ∈Others(cs ) m1 ∈MI (c2 ) N SI(m1 , m) P + m2 ∈
N SI(m, m2 )
SIM (m)∩(MN EW (cs )∪MOV R (cs ) \{m}
Which means that OMMEC will be decreased with static invocations from methods implemented in classes other than cs to m, but will be increased with the static invocations from m to the methods (different from m) which cs implements. This leaves us with three possibilities of the effect of the Move Method refactoring on OM M EC: • P OM M EC will P decrease when cP ∈Others(c ) m1 ∈MI (c2 ) N SI(m1 , m) 2 s > m2 ∈
SIM (m)∩(MN EW (cs )∪MOV R (cs ) \{m}
• P OM M EC will P remain unchanged when cP m1 ∈MI (c2 ) N SI(m1 , m) 2 ∈Others(cs ) = m2 ∈
N SI(m, m2 )
SIM (m)∩(MN EW (cs )∪MOV R (cs ) \{m}
N SI(m, m2 )
210
APPENDIX B. FORMAL IMPACT DERIVATION
• OM increase when P M EC will P cP m1 ∈MI (c2 ) N SI(m1 , m) 2 ∈Others(cs ) < m2 ∈
B.3.3
N SI(m, m2 )
SIM (m)∩(MN EW (cs )∪MOV R (cs ) \{m}
General Coupling
The Coupling Between Object classes metric value after applying Move Method is defined as: CBO(cs ) = CBOSet(cs ) with CBOSet(cs ) = d ∈ C \ {cs } | uses(cs , d) ∨ uses(d, cs ) W When we rewrite uses(c, d) as mc ∈MI (c) uses(mc , d) with ∀mc ∈ MI (c) : uses(mc , d) ⇔ MI (d) ∩ P IM (mc ) ∪ AI (d) ∩ AR(mc ) 6= ∅ we have: W W = d ∈ C \ {cs } | ms ∈MI (cs ) uses(ms , d) ∨ md ∈MI (d) uses(md , cs ) When comparing CBO0 (cs ) with CBO(cs ), we have three possibilities: 1. CBOSet0 (cs ) < CBOSet(cs ) , or a decrease after refactoring 2. CBOSet0 (cs ) = CBOSet(cs ) , or a status-quo after refactoring 3. CBOSet0 (cs ) > CBOSet(cs ) , or an increase after refactoring This means that we can reason about the effect of applying the Move Method refactoring on CBO(cs ) by comparing CBOSet0 (cs ) with CBOSet(cs ). The general strategy of the proof goes as follows: • First, we demonstrate that either CBOSet0 (cs ) \ CBOSet(cs ) is empty, or contains ct in proof A. • Second, we demonstrate that CBOSet(cs ) \ CBOSet0 (cs ) can contain ct , but other classes as well in proof B.
B.3. MOVE METHOD
211
Proof A – First, we pay our attention to CBOSet0 (cs ) \ CBOSet(cs ) \ {ct }. We demonstrate that this set is empty, and afterwards demonstrate the condition under which {ct } will b e contained in this set in a different subproof, thereby showing that CBOSet0 (cs ) \ CBOSet(cs ) = [{ct }. Let’s take a class x ∈ CBOSet0 (cs )\CBOSet(cs ) \{ct }. This can be rephrased to: W W x ∈ d ∈ C \ {cs } | ms ∈M 0 (cs ) uses0 (ms , d) ∨ md ∈M 0 (d) uses0 (md , cs ) I I W W \ d ∈ C \ {cs } | ms ∈MI (cs ) uses(ms , d) ∨ md ∈MI (d) uses(md , cs ) Therefore, the following condition must hold: W W 0 0 ⇔ uses (m , x) ∨ uses (m , c ) 0 0 s d s ms ∈MI (cs ) md ∈MI (x) W W ∧ x 6∈ d ∈ C \ {cs } | ms ∈MI (cs ) uses(ms , x) ∨ md ∈MI (x) uses(md , cs ) We can rephrase the second term by negating it: W W 0 0 ⇔ ms ∈MI0 (cs ) uses (ms , x) ∨ md ∈MI0 (x) uses (md , cs ) V V ∧x ∈ d ∈ C\{cs } | ms ∈MI (cs ) ¬uses(ms , x)∧ md ∈MI (x) ¬uses(md , cs ) Now we can focus on x, with x 6= cs : W W 0 0 ⇔ ms ∈MI0 (cs ) uses (ms , x) ∨ md ∈MI0 (x) uses (md , cs ) V V ∧ ms ∈MI (cs ) ¬uses(ms , x) ∧ md ∈MI (x) ¬uses(md , cs ) Since (a ∨ b) ∧ (c ∧ d) = (a ∧ c ∧ d) ∨ (b ∧ c ∧ d) we can reshuffle the parts as follows: W V V 0 ⇔ uses (m , x)∧ ¬uses(m , x)∧ ¬uses(m , c ) 0 s s d s ms ∈MI (cs ) ms ∈MI (cs ) md ∈MI (x) W V V 0 ∨ uses (m , c )∧ ¬uses(m , x)∧ ¬uses(m , c ) d s s d s md ∈MI (x) ms ∈MI (cs ) md ∈MI (x)
212
APPENDIX B. FORMAL IMPACT DERIVATION
We rewrite uses0 (ms , x) by going back to its definition, knowing that x 6∈ {cs , ct }: ⇔
0 0 0 0 M (x) ∩ P IM (m ) ∪ A (x) ∩ AR (m ) = 6 ∅ ∧ s s I I ms ∈MI0 (cs ) V V ms ∈MI (cs ) ¬uses(ms , x) ∧ md ∈MI (x) ¬uses(md , cs ) W 0 0 0 0 MI (cs ) ∩ P IM (md ) ∪ AI (cs ) ∩ AR (md ) 6= ∅ ∧ ∨ md ∈MI (x) V V ¬uses(m , x) ∧ ¬uses(m , c ) s d s ms ∈MI (cs ) md ∈MI (x) W
Since ∀x ∈ C \ {cs , ct } , it holds that: • MI0 (x) = MI (x) • A0I (x) = AI (x) • ∀mx ∈ MI (x) : P IM 0 (mx ) = P IM (mx ) ∧ AR0 (mx ) = AR(mx ) And therefore we have: W MI (x) ∩ P IM 0 (ms ) ∪ AI (x) ∩ AR0 (ms ) ⇔ 6= ms ∈MI0 (cs ) V V ms ∈MI (cs ) ¬uses(ms , x) ∧ md ∈MI (x) ¬uses(md , cs ) W 0 0 (c ) ∩ AR(m ) ∨ M (c ) ∩ P IM (m ) ∪ A 6= s d s d I I md ∈MI (x) V V ms ∈MI (cs ) ¬uses(ms , x) ∧ md ∈MI (x) ¬uses(md , cs ) Since • A0I (cs ) = AI (cs ) • MI0 (cs ) = MI (cs ) \ {m} • ∀ms ∈ MI (cs ) : P IM 0 (ms ) = P IM (ms ) ∧ AR0 (ms ) = AR(ms ) we have:
∅ ∧
∅
∧
B.3. MOVE METHOD
213
⇔
MI (x)∩P IM (ms ) ∪ AI (x)∩AR(ms ) 6= ∅ ∧ ms ∈ MI (cs )\{m} V V ¬uses(m , x) ∧ ¬uses(m , c ) s d s ms ∈MI (cs ) md ∈MI (x) W ∨ (MI (cs ) \ {m}) ∩ P IM (md ) ∪ AI (cs ) ∩ AR(md ) 6= md ∈MI (x) V V ∅ ∧ ms ∈MI (cs ) ¬uses(ms , x) ∧ md ∈MI (x) ¬uses(md , cs ) W
This simplification shows us that we can translate the first broken down term back: W V V ⇔ ms ∈MI (cs )\{m} uses(ms , x)∧ ms ∈MI (cs ) ¬uses(ms , x)∧ md ∈MI (x) ¬uses(md , cs ) W M (c ) \ {m} ∩ P IM (m ) ∪ A (c ) ∩ AR(m ) ∨ 6= I s d I s d md ∈MI (d) V V ∅ ∧ ms ∈MI (cs ) ¬uses(ms , x) ∧ md ∈MI (x) ¬uses(md , cs ) To make it more easy to reference certain terms of this expression, we map it to (a ∧ c ∧ d) ∨ (b ∧ c ∧ d). This allows to combine the parts as follows: • a ∧ c is f alse, since the latter states that ∀ms ∈ MI (cs ) : ¬uses(ms , x) while the former states that ∀ms ∈ MI (cs ) \ {m} : uses(ms , x). It is impossible for both to be true. • b ∧ d is f alse, since the latter states that ∀md ∈ MI (x) : ¬uses(md , cs ) while the former states that ∀md ∈ MI (x) : uses(md , cs \ {m}). It is impossible for both to be true. Therefore we have: ⇔ (f alse) ∨ (f alse) ⇔ f alse This means that our assumption was wrong and that x ∈ / CBOSet(cs ) \ {ct }. In other words, we have: CBOSet0 (cs ) \ CBOSet(cs ) \ {ct } = ∅
CBOSet0 (cs ) \
214
APPENDIX B. FORMAL IMPACT DERIVATION
This leaves us to demonstrate under which condition ct ∈ CBOSet(cs ) .
CBOSet0 (cs ) \
W W 0 0 ct ∈ d ∈ C \ {cs } | ms ∈M 0 (cs ) uses (ms , d) ∨ md ∈M 0 (d) uses (md , cs ) I I W W \ d ∈ C \ {cs } | ms ∈MI (cs ) uses(ms , d) ∨ md ∈MI (d) uses(md , cs ) We apply the same strategy as for the general x, and come to: W V V 0 ⇔ uses (m , c )∧ ¬uses(m , c )∧ ¬uses(m , c ) s t s t d s ms ∈MI0 (cs ) ms ∈MI (cs ) md ∈MI (ct ) W V V 0 ∨ md ∈MI (ct ) uses (md , cs )∧ ms ∈MI (cs ) ¬uses(ms , ct )∧ md ∈MI (ct ) ¬uses(md , cs ) ⇔
W m ∈ M (c )\{m}
MI (ct )∪{m} ∩P IM (ms ) ∪ AI (ct )∩AR(ms ) 6=
s I s V V ∅ ∧ ms ∈MI (cs ) ¬uses(ms , ct ) ∧ md ∈MI (ct ) ¬uses(md , cs ) W ∨ md ∈MI (ct )∪{m} MI (cs )\{m} ∩P IM (md ) ∪ AI (cs )∩AR(md ) 6= V V ∅ ∧ ms ∈MI (cs ) ¬uses(ms , ct ) ∧ md ∈MI (ct ) ¬uses(md , cs )
=
W m ∈ P IM (ms ) x ∈ {ct } | ms ∈ MI (cs )\{m} ∨ MI (cs ) \ {m} ∩ P IM (m) 6= ∅ ∧
V
ms ∈MI (cs )
¬uses(ms , ct ) ∧
V
md ∈MI (ct ) ¬uses(md , cs )
W m ∈ P IM (ms ) = x ∈ {ct } | ms ∈ MI (cs )\{m} ∨ MI (cs ) \ {m} ∩ P IM (m) 6= ∅ ∧ ¬uses(ct , cs ) Since we already demonstrated that CBOSet0 (cs ) \ CBOSet(cs ) \ {ct } = ∅, we can conclude that:
B.3. MOVE METHOD
215
• CBOSet0 (cs ) \ CBOSet(cs ) W m ∈ P IM (ms ) = x ∈ {ct } | ms ∈ MI (cs )\{m} ∨ MI (cs ) \ {m} ∩ P IM (m) 6= ∅ ∧ ¬uses(ct , cs ) Which means that, after applying Move Method, CBOSet(cs ) will be expanded with ct in case ct was not coupled to cs ; and either (a) any sibling method uses m; or (b) m uses any sibling method or attribute. Q.E.D. (end of proof A) Proof B – Second, we pay our attention to CBOSet(cs ) \ CBOSet0 (cs ), and demonstrate that it can contain classes, among which ct . Assuming that x ∈ CBOSet(cs ) \ CBOSet0 (cs ) , we have: W W x ∈ d ∈ C \ {cs } | ms ∈MI (cs ) uses(ms , d) ∨ md ∈MI (d) uses(md , cs ) W W 0 0 \ d ∈ C \ {cs } | ms ∈M 0 (cs ) uses (ms , d) ∨ md ∈M 0 (d) uses (md , cs ) I
I
Once again, we rewrite this to (with x 6= cs ): W W ⇔ ms ∈MI (cs ) uses(ms , x) ∨ md ∈MI (x) uses(md , cs ) V V 0 ∧ ms ∈M 0 (cs ) ¬uses (ms , x) ∧ md ∈M 0 (x) ¬uses0 (md , cs ) I
I
And re-apply the rule (a ∨ b) ∧ (c ∧ d) = (a ∧ c ∧ d) ∨ (b ∧ c ∧ d) to reshuffle the parts as follows: W V V 0 0 ⇔ ms ∈MI (cs ) uses(ms , x)∧ ms ∈MI0 (cs ) ¬uses (ms , x)∧ md ∈MI0 (x) ¬uses (md , cs ) W V V 0 ∨ uses(m , c )∧ (m , x)∧ ¬uses ¬uses(m , c ) 0 0 d s s d s md ∈MI (x) ms ∈M (cs ) md ∈M (x) I
I
⇔
∃ms ∈ MI (cs ) : uses(ms , x) ∧ 6 ∃ms ∈ MI0 (cs ) : uses0 (ms , x)∧ 6 ∃md ∈ MI0 (x) : uses0 (md , cs )
216
APPENDIX B. FORMAL IMPACT DERIVATION ∨ ∃md ∈ MI (x) : uses(md , cs ) ∧ 6 ∃ms ∈ MI0 (cs ) : uses0 (ms , x)∧ 6 ∃md ∈ MI0 (x) : uses0 (md , cs )
Since MI0 (cs ) = MI (cs ) \ {m}, we have: ⇔ ∃ms ∈ MI (cs ) : uses(ms , x) 0
∧ 6 ∃ms ∈ MI (cs ) \ {m} : uses (ms , x)∧ 6 ∃md ∈ ∨ ∃md ∈ MI (x) : uses(md , cs )
MI0 (x)
: uses (md , cs ) 0
∧ 6 ∃ms ∈ MI (cs ) \ {m} : uses0 (ms , x)∧ 6 ∃md ∈ MI0 (x) : uses0 (md , cs ) As this moment, we will differentiate between x = ct and x 6= ct . Assumption 1: x = ct – Since we then have that MI0 (x) = MI0 (ct ) = MI (ct )∪ {m}, we have x = ct ∈ CBOSet(cs ) \ CBOSet0 (cs ) : ⇔
∃ms ∈ MI (cs ) : uses(ms , ct ) ∧ 6 ∃ms ∈ MI (cs )\{m} : uses (ms , ct )∧ 6 ∃md ∈ MI (ct )∪{m} : uses (md , cs ) ∨ ∃md ∈ MI (ct ) : uses(md , cs ) 0
0
∧ 6 ∃ms ∈ MI (cs ) \ {m} : uses0 (ms , ct )
∧ 6 ∃md ∈ MI (ct ) ∪ {m} : uses0 (md , cs ) Since ∀m1 ∈ M (C) : uses0 (m1 , ct ) ⇐⇒ have: ⇔ ∃ms ∈ MI (cs ) : uses(ms , ct )
uses(m1 , ct ) ∨ m ∈ P IM (m1 ) , we
∧ 6 ∃ms ∈ MI (cs ) \ {m} : uses(ms , ct ) ∨ m ∈ P IM (ms )
∧ 6 ∃md ∈ MI (ct ) ∪ {m} : uses0 (md , cs )
B.3. MOVE METHOD
217
∨ ∃md ∈ MI (ct ) : uses(md , cs ) ∧ 6 ∃ms ∈ MI (cs ) \ {m} : uses(ms , ct ) ∨ m ∈ P IM (ms )) ∧ 6 ∃md ∈ MI (ct ) ∪ {m} : uses0 (md , cs )
Since ∀md ∈ M (C) : uses0 (md , cs )
(MI (cs ) \ {m}) ∩ P IM (md ) ∪ (AI (cs ) ∩ AR(md ) 6= ∅ , we have ct ∈ CBOSet(cs ) \ CBOSet0 (cs ) : ⇔ ∃ms ∈ MI (cs ) : uses(ms , ct ) ∧ 6 ∃ms ∈ MI (cs ) \ {m} : uses(m s , ct ) ∨ m ∈ P IM (ms ) (MI (cs ) \ {m}) ∩ P IM (md ) ∪ (AI (cs ) ∩ ∧ 6 ∃md ∈ MI (ct ) ∪ {m} : AR(md ) 6= ∅ ∨ ∃md ∈ MI (ct ) : uses(md , cs ) ∧ 6 ∃ms ∈ MI (cs ) \ {m} : uses(m s , ct ) ∨ m ∈ P IM (ms ) (MI (cs ) \ {m}) ∩ P IM (md ) ∪ (AI (cs ) ∩ ∧ 6 ∃md ∈ MI (ct ) ∪ {m} : AR(md ) 6= ∅ ⇐⇒
⇔
uses(m, ct )
∧ 6 ∃ms ∈ MI (cs ) \ {m} : uses(ms , ct ) ∨ m ∈ P IM (ms ) ∧∀m d ∈ MI (ct )∪{m} : (MI (cs )\{m})∩P IM (md )∪(AI (cs )∩AR(md )) = ∅ ∨ ∃md ∈ MI (ct ) : m ∈ P IM (md ) ∧ 6 ∃ms ∈ MI (cs ) \ {m} : uses(ms , ct ) ∨ m ∈ P IM (ms ) ∧∀m d ∈ MI (ct )∪{m} : (MI (cs )\{m})∩P IM (md )∪(AI (cs )∩AR(md ) = ∅ Which means that after applying the Move Method refactoring, the general coupling between cs and ct will be broken if and only if all the methods imple-
218
APPENDIX B. FORMAL IMPACT DERIVATION
mented by ct do not use cs without m, and nor does m, and all the methods implemented by cs except m do not use ct nor m, and: • either m uses m and/or ct ; • or there exists a method implemented by ct which uses m 0 Assumption 2: x 6= ct – Thus x 6∈ {cs , ct }. Since we then have that MI (x) = 0 MI (x), we have x ∈ CBOSet(cs ) \ CBOSet (cs ) : ⇔ ∃ms ∈ MI (cs ) : uses(ms , x) ∧ 6 ∃ms ∈ MI (cs ) \ {m} : uses0 (ms , x)∧ 6 ∃md ∈ MI0 (x) : uses0 (md , cs ) ∨ ∃md ∈ MI (x) : uses(md , cs ) 0
∧ 6 ∃ms ∈ MI (cs )\{m} : uses (ms , x)∧ 6 ∃md ∈
MI0 (x)∪{m}
: uses (md , cs ) 0
Since ∀x ∈ C \ {cs , ct }: • ∀m1 ∈ MI (cs ) \ {m} : uses0 (m1 , x) ⇔ uses(m1 , x) and also MI0 (x) = MI (x) • ∀md ∈ MI (x) : uses0 (md , cs ) ⇔ (MI (cs ) \ {m}) ∩ P IM (md ) ∪ (AI (cs ) ∩ AR(md )) 6= ∅ we have x ∈ CBOSet(cs ) \ CBOSet0 (cs ) : ⇔ uses(m, x) ∧ 6 ∃ms ∈ MI (cs ) \{m} : uses(ms , x) ∧ 6 ∃md ∈ MI (x) : (MI (cs ) \ {m}) ∩ P IM (md ) ∪ (AI (cs ) ∩ AR(md )) 6= ∅ ∨ ∃md ∈ MI (x) : m ∈ P IM (md ) ∧ 6 ∃ms ∈ MI (cs ) \{m} : uses(ms , x) ∧ 6 ∃md ∈ MI (x) : (MI (cs ) \ {m}) ∩ P IM (md ) ∪ (AI (cs ) ∩ AR(md )) 6= ∅
B.3. MOVE METHOD
219
⇔
uses(m, x) ∧ 6 ∃ms ∈ MI (cs ) \ {m} : uses(ms , x) ∧ ∀md ∈ MI (x) : (MI (cs ) \ {m}) ∩ P IM (md ) ∪ (AI (cs ) ∩ AR(md )) = ∅ ∨ ∃md ∈ MI (x) : m ∈ P IM (md ) ∧ 6 ∃ms ∈ MI (cs ) \ {m} : uses(ms , x) ∧ ∀md ∈ MI (x) : (MI (cs ) \ {m}) ∩ P IM (md ) ∪ (AI (cs ) ∩ AR(md )) = ∅
Which means that after applying the Move Method refactoring, the general coupling between cs and x ∈ C \ {cs , ct } will be broken if and only if all the methods implemented by x do not use cs without m, and all the methods implemented by cs except m do not use ct nor m, and: • m uses x; • or there exists a method implemented by x which uses m We therefore have seen that CBOSet(cs ) \ CBOSet0 (cs ): = x ∈ C \ {cs , ct } | uses(m, x)∧ 6 ∃ms ∈ MI (cs ) \ {m} : uses(ms , x) ∧ ∀md ∈ MI (x) : (MI (cs ) \ {m}) ∩ P IM (md ) ∪ (AI (cs ) ∩ AR(md )) = ∅ ∨ ∃md ∈ MI (x) : m ∈ P IM (md )∧ 6 ∃ms ∈ MI (cs ) \ {m} : uses(ms , x) ∧∀md ∈ MI (x) : (MI (cs )\{m})∩P IM (md )∪(AI (cs )∩AR(md )) = ∅ ∪ x ∈ {ct } | uses(m, ct ) ∧ ∀ms ∈ MI (cs ) \ {m} : ¬ uses(ms , ct ) ∨ m ∈ P IM (ms ) ∧∀m d ∈ MI (ct )∪{m} : (MI (cs )\{m})∩P IM (md )∪(AI (cs )∩AR(md )) = ∅ ∨ ∃md ∈ MI (ct ) : m ∈ P IM (md ) ∧ ∀ms ∈ MI (cs ) \ {m} : ¬ uses(ms , ct ) ∨ m ∈ P IM (ms ) ∧∀m d ∈ MI (ct )∪{m} : (MI (cs )\{m})∩P IM (md )∪(AI (cs )∩AR(md )) = ∅
220
APPENDIX B. FORMAL IMPACT DERIVATION
Which can be shortened using (a ∧ c ∧ d) ∨ (b ∧ c ∧ d) = (a ∨ b) ∧ (c ∧ d): = x ∈ C \ {cs , ct } | uses(m, x) ∨ ∃md ∈ MI (x) : m ∈ P IM (md ) ∧ 6 ∃ms ∈ MI (cs ) \ {m} : uses(ms , x) ∧∀md ∈ MI (x) : (MI (cs )\{m})∩P IM (md )∪(AI (cs )∩AR(md )) = ∅ ∪ x ∈ {ct } | uses(m, ct ) ∨ ∃md ∈ MI (ct ) : m ∈ P IM (md ) ∧ ∀ms ∈ MI (cs ) \ {m} : ¬ uses(ms , ct ) ∨ m ∈ P IM (ms ) ∧∀m d ∈ MI (ct )∪{m} : (MI (cs )\{m})∩P IM (md )∪(AI (cs )∩AR(md )) = ∅ Summarizing, we have demonstrated that after applying the Move Method refactoring: • CBO(cs ) can remain constant when there exists no class which is coupled to m but not to the other methods implemented by cs . With method m1 is coupled to class c1 we mean that m1 invokes methods or references attributes implemented by c1 , or that the c1 implements methods which call m1 (potentially through polymorphism). • CBO(cs ) can decrease when there do exists such classes. End of proof B At this moment, we have demonstrated: • CBOSet0 (cs )\CBOSet(cs ), which signifies what is added to CBOSet(cs ) after applying Move Method. Let us call this X. • CBOSet(cs )\CBOSet0 (cs ), which signifies what is removed from CBOSet(cs ) after applying Move Method. Let us call this Y. We therefore can construct CBOSet0 (cs ) as CBOSet0 (cs ) = (CBOSet(cs ) \ Y)∪X And since X 6⊆ CBOSet(cs ) and X∩Y = ∅, we have CBO0 (cs ) =| CBOSet0 (cs ) | = CBO(cs )− | Y | + | X | = CBO(c s) − x ∈ C \ {cs , ct } | uses(m, x) ∨ ∃md ∈ MI (x) : m ∈ P IM (md )
B.3. MOVE METHOD ∧
221
6 ∃ms ∈ MI (cs ) \ {m} : uses(ms , x)
∧∀md ∈ MI (x) : (MI (cs )\{m})∩P IM (md )∪(AI (cs )∩AR(md )) = ∅ − x ∈ {ct } | uses(m, ct ) ∨ ∃md ∈ MI (ct ) : m ∈ P IM (md ) ∧ ∀ms ∈ MI (cs ) \ {m} : ¬ uses(ms , ct ) ∨ m ∈ P IM (ms ) ∧∀m d ∈ MI (ct )∪{m} : (MI (cs )\{m})∩P IM (md )∪(AI (cs )∩AR(md )) = ∅ W m ∈ P IM (ms ) + x ∈ {ct } | ms ∈ MI (cs )\{m} ∨ MI (cs ) \ {m} ∩ P IM (m) 6= ∅ ∧ ¬uses(ct , cs ) Which means that, after applying Move Method, CBO(cs ) will be: • decreased with the number of classes (6= ct ) which were coupled to cs exclusively by m • and additionally decreased with 1 in case ct was coupled to cs exclusively by m and m does not use the remainder of cs . • and additionally increased with 1 in case ct was not coupled to cs , and either (a) any sibling method uses m; or (b) m uses any sibling method or attribute.
B.3.4
Aggregation Import Coupling
The Data Abstraction Coupling metric value after applying Move Method is defined as: DAC 0 (cs ) =| {a | a ∈ A0I (cs ) ∧ T 0 (a) ∈ C 0 \ {cs }} | Since C 0 = C, A0I (cs ) = AI (cs ) and ∀a ∈ AI (cs ) : T 0 (a) = T (a), we have: = | {a | a ∈ AI (cs ) ∧ T (a) ∈ C \ {cs }} |= DAC(cs )
222
APPENDIX B. FORMAL IMPACT DERIVATION
B.3.5
Normalized Cohesion
The metric value after applying Move Method of the selected normalized cohesion metric is: 0
LCOM 5 (cs ) = = = =
|(MI (cs )\{m}|− |A
|MI (cs )|−1− |A
1 I (cs )|
|MI (cs )|−1− |A
1 I (cs )|
P
=
a∈AI (cs ) |{m1 |m1 ∈(MI (cs )\{m})∧a∈AR(m1 )}|
a∈AI (cs ) |{m1 |m1 ∈MI (cs )∧a∈AR(m1 )}|
P
a∈AI (cs ) |{m1 |m1 ∈{m})∧a∈AR(m1 )}|
|MI (cs )|−2
|MI (cs )|− |A
1 I (cs )|
P
a∈AI (cs ) |{m1 |m1 ∈MI (cs )∧a∈AR(m1 )}|
|MI (cs )|−2 1+ |A
1 I (cs )|
|MI (cs )|− |A
x y
P
a∈AI (cs ) |{m1 |m1 ∈{m})∧a∈AR(m1 )}|
|MI (cs )|−2
1− |A
1 I (cs )|
P
a∈AI (cs ) |{m1 |m1 ∈MI (cs )∧a∈AR(m1 )}|
|MI (cs )|−2 1 |AI (cs )∩AR(m)| I (cs )| |MI (cs )|−2
−
z y
y+1 x y y+1
=
−
z y+1
, we have:
P 1 a∈AI (cs ) |{m1 |m1 ∈MI (cs )∧a∈AR(m1 )}| |MI (cs )|−1 |MI (cs )|− |AI (cs )| |MI (c)|−2 |MI (c)|−1 1− |A 1(c )| |AI (cs )∩AR(m)| I
s
|MI (cs )|−1
|MI (cs )|−1 |MI (cs )|−2
Since 1 = =
a∈AI (cs ) |{m1 |m1 ∈(MI (cs )\{m})∧a∈AR(m1 )}|
|MI (cs )|−2 1 |AI (cs )|
− =
P
0 0 a∈A0 (cs ) |{m1 |m1 ∈MI (cs )∧a∈AR (m1 )}| I 0 |MI (cs )|−1
|MI (cs )|−2
+
Since
1 I (cs )|
P s )|
|(MI (cs )\{m})|−1
−
=
I
P
−
=
|MI0 (cs )|− |A0 1(c
LCOM 5(cs ) −
|AI (cs )| |AI (cs )| ,
|MI (cs )|−1 |MI (cs )|−2
1−
|AI (cs )∩AR(m)| |AI (cs )|
|MI (cs )|−1
we have:
LCOM 5(cs ) −
|AI (cs )|−|AI (cs )∩AR(m)| |AI (cs )|
|MI (cs )|−1
Since | A | − | A ∩ B |=| A \ B | on the condition that B ⊆ A, we have:
B.3. MOVE METHOD =
|MI (cs )|−1 |MI (cs )|−2
LCOM 5(cs ) −
=
|MI (cs )|−1 |MI (cs )|−2
LCOM 5(cs ) −
223 |AI (cs )\AR(m)| |AI (cs )|
|MI (cs )|−1 |AI (cs )\AR(m)| |AI (cs )|. |MI (cs )|−1
This means that applying the Move Method refactoring can increase or decrease LCOM 5, depending on | MI (c) | and the number of attributes which m references. When we hold the number of methods factor constant, we find that the less attributes m will reference, the higher the decrease will be.
B.3.6
Non-normalized Cohesion
The metric value after applying Move Method of the selected non-normalized cohesion metric is: LCOM 1(cs ) = LCOM 1Set(cs ) with LCOM 1Set(cs ) = {m1 , m2 } | m1 , m2 ∈ MI0 (cs ) ∧ m 1 6= m2 ∧ AR0 (m1 ) ∩ AR0 (m2 ) ∩ A0I (cs ) = ∅ = {m1 , m2 } | m1 , m2 ∈ MI (cs ) \ {m} ∧ m1 6= m2 ∧ AR(m1 ) ∩ AR(m2 ) ∩ AI (cs ) = ∅ = {m1 , m2 } | m1 , m2 ∈ MI (cs ) ∧ m16= m2 ∧ AR(m1 ) ∩ AR(m2 ) ∩ AI (cs ) = ∅ \ {m1 , m} | m1 ∈ MI (cs ) \ {m} ∧ m1 6= m∧ AR(m1 ) ∩ AR(m) ∩ AI (cs ) = ∅ = LCOM 1Set(cs ) \ {m1 , m} | m 1 ∈ MI (cs ) \ {m} ∧ m1 6= m∧ AR(m1 ) ∩ AR(m) ∩ AI (cs ) = ∅ And therefore LCOM 10 (cs ) = LCOM 1Set(cs ) \ {m1 , m} | m 1 ∈ MI (cs ) \ {m} ∧ m1 6= m∧ AR(m1 ) ∩ AR(m) ∩ AI (cs ) = ∅ = | LCOM 1Set(cs ) | − {m1 , m} | m1 ∈ MI (cs ) \ {m} ∧ m1 6= m∧ AR(m1 ) ∩ AR(m) ∩ AI (cs ) = ∅ = | LCOM 1Set(cs ) | − m1 | m1 ∈ MI (cs ) \ {m} ∧ m1 6= m∧ AR(m1 ) ∩ AR(m) ∩ AI (cs ) = ∅
224
APPENDIX B. FORMAL IMPACT DERIVATION
= LCOM 1(cs ) − m1 | m1 ∈ MI (cs ) \ {m} ∧ m1 6= m∧ AR(m1 ) ∩ AR(m) ∩ AI (cs ) = ∅ Which means that after applying Move Method, LCOM 1(cs ) will be decreased with the number of methods implemented by cs which do not share references to attributes implemented by cs with method m.
B.4. REPLACE METHOD WITH METHOD OBJECT
B.4
225
Replace Method with Method Object
B.4.1
Import Coupling
We can express the value of the Message Passing Coupling metric after applying the Replace Method with Method Object refactoring as: M P C 0 (cs ) =
P
m1 ∈MI0 (cs )
P
m2 ∈SIM 0 (m1 )\MI0 (cs )
N SI 0 (m1 , m2 )
Since MI0 (cs ) = MI (cs ), we have: =
P
m1 ∈MI (cs )
P
m2 ∈SIM 0 (m1 )\MI (cs )
N SI 0 (m1 , m2 )
When we separate ms from MI (cs ), we have: =
P +
P
m2 ∈SIM 0 (m1 )\MI (cs ) 0 m2 ∈SIM 0 (m1 )\MI (cs ) N SI (ms , m2 )
m1 ∈ MI (cs )\{ms }
N SI 0 (m1 , m2 )
P
Since ∀m1 ∈ MI (cs ) \ {ms } , it holds that M I 0 (m1 ) = M I(m1 ), we have: P P = m2 ∈SIM (m1 )\MI (cs ) N SI(m1 , m2 ) m1 ∈ MI (cs )\{ms } P + m2 ∈SIM 0 (m1 )\MI (cs ) N SI 0 (ms , m2 ) The postcondition also specifies that M I 0 (ms ) = {mi1 , mi2 }, with mi1 , mi2 method invocations from ms for which it holds that target(mi1 ) = mct , target(mi2 ) = mt . Therefore, we can write SIM 0 (ms ) = {mct , mt }. Consequently, we can write M P C 0 (cs ): =
P
P
N SI(m1 , m2 )
P
N SI(m1 , m2 )
m2 ∈SIM (m1 )\MI (cs ) 0 m2 ∈{mct ,mt }\MI (cs ) N SI (ms , m2 )
m1 ∈ MI (cs )\{ms }
P
=
+ P +
m1 ∈ P
MI (cs )\{ms }
m2 ∈{mct ,mt }
m2 ∈SIM (m1 )\MI (cs )
N SI 0 (ms , m2 )
Since we know that M I 0 (ms ) = {mct , mt }, we can rewrite the last term to: P P = m2 ∈SIM (m1 )\MI (cs ) N SI(m1 , m2 ) m1 ∈ MI (cs )\{ms }
+2
226
APPENDIX B. FORMAL IMPACT DERIVATION
When we subsequently add and remove the set of method invocations from ms to methods implemented by other classes, we have: P P = m2 ∈SIM (m1 )\MI (cs ) N SI(m1 , m2 ) m1 ∈ MI (cs )\{ms }
+2P + m2 ∈SIM (m1 )\MI (cs ) N SI(m1 , m2 ) P − m2 ∈SIM (m1 )\MI (cs ) N SI(m1 , m2 ) When we unify the first and third term, we have: P P = m1 ∈MI (cs ) m2 ∈SIM (m1 )\MI (cs ) N SI(m1 , m2 ) +2P − m2 ∈SIM (m1 )\MI (cs ) N SI(m1 , m2 ) At this time, we recognize that we can replace the first term by M P C(cs ): = MP P C(cs ) − m2 ∈SIM (m1 )\MI (cs ) N SI(m1 , m2 ) +2
B.4.2
Export Coupling
The selected export coupling metric value after applying Replace Method with Method Object is: OM M EC 0 (cs ) P P = 0 (c ) c ∈Others m1 ∈MI0 (c2 ) 2 s P 0 0 m2 ∈ SIM 0 (m1 )∩(MN EW (cs )∪MOV R (cs )
N SI 0 (m1 , m2 )
Since Others0 (cs ) = Others(cs ) ∪ {ct }, we have: P P P N SI 0 (m1 , m2 ) = 0 0 c2 ∈Others(cs ) m1 ∈MI0 (c2 ) m2 ∈ SIM 0 (m1 )∩(MN EW (cs )∪MOV R (cs ) P P N SI 0 (m1 , m2 ) + m1 ∈M 0 (ct ) 0 0 0 I
m2 ∈ SIM (m1 )∩(MN EW (cs )∪MOV R (cs )
0 0 Since MN EW (cs ) = MN EW (cs ) and MOV R (cs ) = MOV R (cs ): P P P N SI 0 (m1 , m2 ) = c2 ∈Others(cs ) m1 ∈MI0 (c2 ) m2 ∈ SIM 0 (m1 )∩(MN EW (cs )∪MOV R (cs ) P P N SI 0 (m1 , m2 ) + m1 ∈M 0 (ct ) 0 I
m2 ∈ SIM (m1 )∩(MN EW (cs )∪MOV R (cs )
B.4. REPLACE METHOD WITH METHOD OBJECT
227
0 Since MN EW (ct ) = {mt , mct }:
=
P
c2 ∈Others(cs )
P
m1 ∈MI0 (c2 )
P
m2 ∈ SIM 0 (m1 )∩(MN EW (cs )∪MOV R (cs ) N SI 0 (mt , m2 ) + 0 Pm2 ∈ SIM (mt )∩(MN EW (cs )∪MOV R (cs ) + N SI 0 (mct , m2 ) m2 ∈ SIM 0 (mct )∩(MN EW (cs )∪MOV R (cs )
N SI 0 (m1 , m2 )
P
Since MI0 (mct ) = ∅, we have: =
P
c2 ∈Others(cs )
+
P
m1 ∈MI0 (c2 )
P
m2 ∈ SIM 0 (m1 )∩(MN EW (cs )∪MOV R (cs ) N SI 0 (mt , m2 ) m2 ∈ SIM 0 (mt )∩(MN EW (cs )∪MOV R (cs )
N SI 0 (m1 , m2 )
P
Since MI0 (mt ) = MI (ms ), we have: =
P
c2 ∈Others(cs )
+
P
m1 ∈MI0 (c2 )
P m2 ∈ SIM 0 (m1 )∩(MN EW (cs )∪MOV R (cs )
P m2 ∈ SIM (ms )∩(MN EW (cs )∪MOV R (cs )
N SI 0 (m1 , m2 )
N SI(ms , m2 )
Since ∀c2 ∈ Others(cs ) : MI0 (c2 ) = MI (c2 ), and ∀m1 ∈ MI (c2 ) : M I 0 (m1 ) = M I(m1 ) we have: =
P
c2 ∈Others(cs )
+
P
m1 ∈MI (c2 )
P m2 ∈ SIM (m1 )∩(MN EW (cs )∪MOV R (cs )
P m2 ∈ SIM (ms )∩(MN EW (cs )∪MOV R (cs )
= OM PM EC(cs ) +
m2 ∈ SIM (ms )∩(MN EW (cs )∪MOV R (cs )
N SI(m1 , m2 )
N SI(ms , m2 )
N SI(ms , m2 )
Which means that after applying Replace Method with Method Object, OM M EC(cs ) will be increased with the number of static invocations from ms to new and overridden methods implemented by cs .
B.4.3
General Coupling
Informally – The number of classes by which cs is used or which cs uses itself will alter depending on the number of classes which ms used but the other methods in MI (cs ) did not. Moreover, CBO(cs ) will contain ct .
228
APPENDIX B. FORMAL IMPACT DERIVATION
Formally – The CBO metric value after applying Replace Method with Method Object is: CBO(cs ) =| CBOSet(cs ) | with CBOSet(cs ) W W = d ∈ C\{cs } | mc ∈MI (cs ) uses(mc , d)∨ md ∈MI (d) uses(md , cs ) Our tactic for formally deriving the impact is the following. We first split up CBOSet(cs ) in two parts. A part not involving ms , and a part involving ms . W = d ∈ C\{cs } |
=
mc ∈ MI (cs )\{ms } ∪{ms }
W uses(mc , d)∨ md ∈MI (d) uses(md , cs )
W d ∈ C \ {cs } | mc ∈MI (cs )\{ms } uses(mc , d) ∨ uses(ms , d) W ∨ md ∈MI (d) MI (cs ) ∩ P IM (md ) ∪ AI (cs ) ∩ AR(md ) 6= ∅
W = d ∈ C \ {cs } | mc ∈MI (cs )\{ms } uses(mc , d) ∨ uses(ms , d) W ∨ md ∈MI (d) (MI (cs ) \ {ms }) ∩ P IM (md ) ∪ AI (cs ) ∩ AR(md ) 6= ∅ W ∨ md ∈MI (d) ms ∈ P IM (md ) Since {x ∈ X | a ∨ b} = {x ∈ X | a} ∪ {x ∈ X | b}, we can rewrite CBOSet(cs ) to: W = d ∈ C \ {cs } | mc ∈MI (cs )\{ms } uses(mc , d) W ∨ md ∈MI (d) (MI (cs )\{ms })∩P IM (md ) ∪ AI (cs )∩AR(md ) 6= ∅ W ∪ d ∈ C \ {cs } | uses(ms , d) ∨ md ∈MI (d) ms ∈ P IM (md ) The two parts therefore are:
B.4. REPLACE METHOD WITH METHOD OBJECT
229
• A part that is due to MI (cs ) \ {ms }. This part will be called A, and is described by W d ∈ C \ {cs } | mc ∈MI (cs )\{ms } uses(mc , d) W ∨ md ∈MI (d) (MI (cs )\{ms })∩P IM (md ) ∪ AI (cs )∩AR(md ) 6= ∅ We will demonstrate that this part will remain unchanged, aside the conditional inclusion of ct . • A part that is due to ms . This part will be called B, and isdescribed by W d ∈ C \ {cs } | uses(ms , d) ∨ md ∈MI (d) ms ∈ P IM (md ) We will demonstrate that this part will be affected. At this time we will demonstrate in a sub-proof that A0 = A[∪ct ]. Subproof – We first start by expanding A0 : W = d ∈ C 0 \ {cs } | mc ∈M 0 (cs )\{ms } uses0 (mc , d) I W ∨ md ∈M 0 (d) (MI0 (cs )\{ms })∩P IM 0 (md ) ∪ A0I (cs )∩AR0 (md ) 6= ∅ I
Since C 0 = C ∪ {ct }, we have: W = d ∈ C \ {cs } | mc ∈M 0 (cs )\{ms } uses0 (mc , d) I W ∨ md ∈M 0 (d) (MI0 (cs )\{ms })∩P IM 0 (md ) ∪ A0I (cs )∩AR0 (md ) 6= ∅ I W ∪ d ∈ {ct } | mc ∈M 0 (cs )\{ms } uses0 (mc , ct ) I W 0 0 0 0 ∨ md ∈M 0 (ct ) (MI (cs )\{ms })∩P IM (md ) ∪ AI (cs )∩AR (md ) 6= ∅ I
It is trivial to derive the following from the postcondition: ∀c ∈ C \ {cs }, ∀m ∈ MI (c), it holds that: • MI0 (c) = MI (c) • A0I (c) = AI (c) • P IM 0 (m) = P IM (m)
230
APPENDIX B. FORMAL IMPACT DERIVATION
• AR0 (m) = AR(m) which gives: W = d ∈ C \ {cs } | mc ∈MI (cs )\{ms } uses0 (mc , d) W ∨ md ∈MI (d) (MI (cs )\{ms })∩P IM (md ) ∪ AI (cs )∩AR(md ) 6= ∅ W ∪ d ∈ {ct } | mc ∈MI (cs )\{ms } uses0 (mc , ct ) W ∨ md ∈M 0 (ct ) (MI (cs )\{ms })∩P IM 0 (md ) ∪ AI (cs )∩AR0 (md ) 6= ∅ I
Since ∀mc ∈ MI (cs ) \ {ms } : uses0 (mc , ct ) = f alse, we can rewrite the second term as follows: W = d ∈ C \ {cs } | mc ∈MI (cs )\{ms } uses0 (mc , d) W ∨ md ∈MI (d) (MI (cs )\{ms })∩P IM (md ) ∪ AI (cs )∩AR(md ) 6= ∅ ∪ d ∈ {ct } | f alse W ∨ md ∈M 0 (ct ) (MI (cs )\{ms })∩P IM 0 (md ) ∪ AI (cs )∩AR0 (md ) 6= ∅ I
Since MI0 (ct ) = {mct , mt }, and: 0 0 • ∪m∈MI (ct ) P IM (m) ∩ MI (cs ) \ {ms } = P IM (ms ) ∩ MI (cs ) \ {ms } • ∪m∈MI0 (ct )
AR (m) ∩ AI (cs ) = AI (ms ) ∩ AI (cs ) 0
we can make the second part conditional (marked with square brackets): W = d ∈ C \ {cs } | mc ∈MI (cs )\{ms } uses0 (mc , d) W ∨ md ∈MI (d) (MI (cs )\{ms })∩P IM (md ) ∪ AI (cs )∩AR(md ) 6= ∅ ∪ c ∈ {ct } | P IM (ms ) ∩ MI (cs ) \ {ms } ∪ AI (ms ) ∩ AI (cs ) 6= ∅
B.4. REPLACE METHOD WITH METHOD OBJECT
231
Since ∀d ∈ C \ {cs }, ∀mc ∈ MI (cs ) \ {ms } : uses0 (mc , d) = uses(mc , d), we have: W = d ∈ C \ {cs } | mc ∈MI (cs )\{ms } uses(mc , d) W ∨ md ∈MI (d) (MI (cs )\{ms })∩P IM (md ) ∪ AI (cs )∩AR(md ) 6= ∅ ∪ c ∈ {ct } | P IM (ms ) ∩ MI (cs ) \ {ms } ∪ AI (ms ) ∩ AI (cs ) 6= ∅ As this first term is identical to A, we have: = A ∪ c ∈ {ct } | P IM (ms ) ∩ MI (cs ) \ {ms } ∪ AI (ms ) ∩ AI (cs ) 6= ∅ Q.E.D. (Subproof) Summarizing, we have just demonstrated the condition under which A0 = A, and under which A0 = A ∪ {ct }. At this time we will demonstrate in a new sub-proof the condition under which B 0 = B. Subproof – We first start by expanding B 0 : W = d ∈ C 0 \ {cs } | uses0 (ms , d) ∨ md ∈M 0 (d) ms ∈ P IM 0 (md ) I
Since C 0 = C ∪ {ct }, we can write: W = d ∈ C \ {cs } | uses0 (ms , d) ∨ md ∈MI (d) ms ∈ P IM 0 (md ) W ∪ d ∈ {ct } | uses0 (ms , ct ) ∨ md ∈M 0 (ct ) ms ∈ P IM 0 (md ) I
As the postcondition states that ms invokes both methods from ct , we have: W = d ∈ C \ {cs } | uses0 (ms , d) ∨ md ∈MI (d) ms ∈ P IM 0 (md ) ∪ {ct } Since ∀d ∈ C \ {cs } : uses0 (ms , d) = f alse, and since ∀d ∈ C \ {cs }, ∀md ∈ MI (d) : P IM 0 (md ) = P IM (md ): W = d ∈ C \ {cs } | f alse ∨ md ∈MI (d) ms ∈ P IM (md ) ∪ {ct }
232 =
APPENDIX B. FORMAL IMPACT DERIVATION
d ∈ C \ {cs } |
W
md ∈MI (d)
ms ∈ P IM (md ) ∪ {ct }
Since {x ∈ X | f (x)} = {x ∈ X | f (x) ∨ g(x)} \ {x ∈ X | f (x) ∧ ¬g(x)}, we have: W = d ∈ C 0 \ {cs } | uses0 (ms , d) ∨ md ∈M 0 (d) ms ∈ P IM 0 (md ) \ d ∈ I C \ {cs } | uses(ms , d) W ∪ d ∈ C \ {cs } | uses(ms , d) ∧ md ∈MI (d) ms 6∈ P IM (md ) ∪ {ct } = B\ d ∈ C \ {cs } | uses(ms , d) W ∪ d ∈ C \ {cs } | uses(ms , d) ∧ md ∈MI (d) ms 6∈ P IM (md ) ∪ {ct } Since (X \ Y ) ∪ Z = (X ∪ Z) \ (Y \ Z), we can rewrite to: W = B ∪ d ∈ C \{cs } | uses(ms , d)∧ md ∈MI (d) ms 6∈ P IM (md ) \ d∈ W C \ {cs } | uses(ms , d) ∧ md ∈MI (d) ms 6∈ P IM (md ) ∪ {ct } W As d ∈ C \ {cs } | uses(ms , d) ∧ md ∈MI (d) ms 6∈ P IM (md ) ⊂ B we can simplify to: V = B \ d ∈ C \ {cs } | uses(ms , d) ∧ md ∈MI (d) ms 6∈ P IM (md ) ∪ {ct } Which means that after refactoring, B will be reduced with all classes which are unidirectionally coupled from ms but themselves implement no methods which call ms . However, ct will be added to B. Q.E.D. (Subproof) When we combine the results of the subproofs for A0 and for B 0 , we CBOSet0 = = A0 ∪ B 0 = A ∪ c ∈ {ct } | P IM (ms ) ∩ MI (cs ) \ {ms } ∪ AI (ms ) ∩ AI (cs ) 6= ∅ V ∪ B \ d ∈ C \ {cs } | uses(ms , d) ∧ md ∈MI (d) ms 6∈ P IM (md ) ∪ {ct } V = A ∪ B \ d ∈ C \ {cs } | uses(ms , d) ∧ md ∈MI (d) ms 6∈ P IM (md ) ∪ {ct }
B.4. REPLACE METHOD WITH METHOD OBJECT
233
Since X ∪ (Y \ Z) = (X ∪ Y ) \ (Y ∩ Z) \ X , we have: =
(A ∪ B) V \ B ∩ d ∈ C \{cs } | uses(ms , d)∧ md ∈MI (d) ms 6∈ P IM (md ) \A ∪ {ct }
Since A ∪ B = CBOSet(cs ), we have: = CBOSet(cs ) V \ B ∩ d ∈ C \{cs } | uses(ms , d)∧ md ∈MI (d) ms 6∈ P IM (md ) \A ∪ {ct } = CBOSet(cs ) W \ d ∈ C \ {cs } | uses(ms , d) ∨ md ∈MI (d) ms ∈ P IM (md ) V ∩ d ∈ C \ {cs } | uses(ms , d) ∧ md ∈MI (d) ms 6∈ P IM (md ) \A ∪ {ct } = CBOSet(cs ) W d ∈ C \ {cs } | uses(ms , d) ∨ md ∈MI (d) ms ∈ P IM (md ) \ V ∩ d ∈ C \ {cs } | uses(ms , d) ∧ md ∈MI (d) ms 6∈ P IM (md ) W \ d ∈ C \ {cs } | mc ∈MI (cs )\{ms } uses(mc , d) W ∨ md ∈MI (d) (MI (cs ) \ {ms }) ∩ P IM (md ) ∪ AI (cs ) ∩ AR(md ) 6= ∅ ∪ {ct } = CBOSet(cs ) \ d ∈ C \ {cs } | uses(ms , d)
234
APPENDIX B. FORMAL IMPACT DERIVATION V ∧ md ∈MI (d) ms 6∈ P IM (md ) V ∧ mc ∈(MI (cs )\{ms } ¬uses(mc , d) V ∧ md ∈MI (d) (MI (cs ) \ {ms }) ∩ P IM (md ) ∪ AI (cs ) ∩ AR(md ) = ∅ ∪ {ct }
Since | A \ B | =| A | − | B | on the condition that B ⊆ A, we have CBO0 (cs ) = | CBOSet(c s) | − | d ∈ C \ {cs } | uses(ms , d) V ∧ md ∈MI (d) ms 6∈ P IM (md ) V ∧ mc ∈(MI (cs )\{ms } ¬uses(mc , d) V ∧ md ∈MI (d) (MI (cs ) \ {ms }) ∩ P IM (md ) ∪ AI (cs ) ∩ AR(md ) = ∅ | + | {ct } | = CBO(c s) − | d ∈ C \ {cs } | uses(ms , d) V ∧ md ∈MI (d) ms 6∈ P IM (md ) V ∧ mc ∈(MI (cs )\{ms } ¬uses(mc , d) V ∧ md ∈MI (d) (MI (cs ) \ {ms }) ∩ P IM (md ) ∪ AI (cs ) ∩ AR(md ) = ∅ | +1 = CBO(c s) −V | d ∈ C \ {cs } | uses(ms , d) ∧ mc ∈(MI (cs )\{ms } ¬uses(mc , d) V ∧ md ∈MI (d) MI (cs ) ∩ P IM (md ) ∪ AI (cs ) ∩ AR(md ) = ∅ | +1 = CBO(cs )− | d ∈ C \ {cs } | uses(ms , d) V ∧ mc ∈(MI (cs )\{ms } ¬uses(mc , d) ∧ ¬uses(x, cs ) | +1 Which means that ct is added to CBOSet(cs ), and that all the classes for which ms was the single cause of general coupling are removed.
B.4.4
Aggregated Import Coupling
The Data Abstraction Coupling metric value after applying Replace Method with Method Object is:
B.4. REPLACE METHOD WITH METHOD OBJECT
235
DAC 0 (cs ) =| {a | a ∈ A0I (cs ) ∧ T 0 (a) ∈ C 0 \ {cs }} | Since C 0 = C, A0I (cs ) = AI (cs ) and ∀a ∈ AI (cs ) : T 0 (a) = T (a): = | {a | a ∈ AI (cs ) ∧ T (a) ∈ C \ {cs }} |= DAC(cs ) Which means that after applying Replace Method with Method Object, DAC(cs ) will remain unchanged.
B.4.5
Normalized Cohesion
The Lack of Cohesion in Methods metric variant 5 value after applying Replace Method with Method Object is: LCOM 50 (cs ) =
|MI0 (cs )|− |A0 1(c I
P s )|
0 0 a∈A0 (cs ) |{m1 |m1 ∈MI (cs )∧a∈AR (m1 )}| I 0 |MI (cs )|−1
Since MI0 (cs ) = MI (cs ) and A0I (cs ) = AI (cs ), we have: = =
|MI cs )|− |A
1 I (cs )|
P
a∈AI (cs ) |{m1 |m1 ∈MI (cs )∧a∈AR
0
(m1 )}|
|MI (cs )|−1 |MI cs )|− |A
1 I (cs )|
P
a∈AI (cs ) |{m1 |m1 ∈
MI (cs )\{ms } ∧a∈AR0 (m1 )}|
|MI (cs )|−1
−
1 |AI (cs )|
P
a∈AI (cs ) |{m1 |m1 ∈{ms }∧a∈AR
0
(ms )}|
|MI (cs )|−1
Since ∀m1 ∈ MI (cs ) \ {ms } : AR0 (m1 ) = AR(m1 ), and since AR0 (ms ) = ∅we have: P =
|MI cs )|− |A
1 I (cs )|
a∈AI (cs ) |{m1 |m1 ∈
MI (cs )\{ms } ∧a∈AR(m1 )}|
|MI (cs )|−1
Since x = x + y − y, we have: =
|MI cs )|− |A
P
a∈AI (cs ) |{m1 |m1 ∈
MI (cs )\{ms } ∧a∈AR(m1 )}|
|MI (cs )|−1
− + =
1 I (cs )|
1 |AI (cs )|
P
a∈AI (cs ) |{m1 |m1 ∈{ms }∧a∈AR(ms )}|
1 |AI (cs )|
P
a∈AI (cs ) |{m1 |m1 ∈{ms }∧a∈AR(ms )}|
|MI (cs )|−1 |MI (cs )|−1
|MI cs )|− |A 1(c )| I s
P
a∈AI (cs ) |{m1 |m1 ∈MI (cs )∧a∈AR(m1 )}|
|MI (cs )|−1
+
1 |AI (cs )|
P
a∈AI (cs ) |{m1 |m1 ∈{ms }∧a∈AR(ms )}|
|MI (cs )|−1
−0
236
APPENDIX B. FORMAL IMPACT DERIVATION
= LCOM 5(c ) Ps +
1 |AI (cs )|
a∈AI (cs ) |{m1 |m1 ∈{ms }∧a∈AR(ms )}|
|MI (cs )|−1
= LCOM 5(cs ) +
|AR(ms )∩AI (cs )| |AI (cs )|. |MI (cs )|−1
Which means that after applying Replace Method with Method Object, LCOM 5(cs ) will be increased proportionate to the number of attributes which ms references.
B.4.6
Non-normalized Cohesion
The Lack of Cohesion in Methods metric variant 1 value after applying Replace Method with Method Object is: LCOM 1(cs ) = LCOM 1Set(cs ) with LCOM 1Set(cs ) =
{m1 , m2 } | m1 , m2 ∈ MI0 (cs ) ∧ m1 6= m2 ∧ AR0 (m1 ) ∩ AR0 (m2 ) ∩ A0I (cs ) = ∅
Since MI0 (cs ) = MI (cs ) and A0I (cs ) = AI (cs ), we have: = {m1 , m2 } | m1 , m2 ∈ MI (cs ) ∧ m1 6= m2 ∧ AR0 (m1 ) ∩ AR0 (m2 ) ∩ AI (cs ) = ∅ Since MI (cs ) = MI (cs ) \ {ms } ∪ {ms }, we have: = {m1 , m2 } | m1 , m2 ∈ MI (cs ) \ {ms } ∧ m1 6= m2 ∧ AR0 (m1 ) ∩ AR0 (m2 ) ∩ AI (cs ) = ∅ ∪ {m1 , ms } | m1 ∈ MI (cs ) \ {ms } ∧ AR0 (m1 ) ∩ AR0 (ms ) ∩ AI (cs ) = ∅ Since AR0 (ms ) = ∅, and ∀m2 ∈ MI (cs ) \ {ms } : AR0 (m2 ) = AR(m2 ), we have: = {m1 , m2 } | m1 , m2 ∈ MI (cs ) \ {m s } ∧ m1 6= m2 ∧ AR(m1 ) ∩ AR(m2 ) ∩ AI (cs ) = ∅ ∪ {m1 , ms } | m1 ∈ MI (cs ) \ {ms }
B.4. REPLACE METHOD WITH METHOD OBJECT
237
{m1 , m2 } | m1 , m2 ∈ MI (cs ) ∧ m1 6= m2 ∧ AR(m1 ) ∩ AR(m2 ) ∩ AI (cs ) = ∅ \ {m1 , ms } | m1 ∈ MI (cs ) ∧ m1 6= ms ∧ AR(m1 ) ∩ AR(ms ) ∩ AI (cs ) = ∅ ∪ {m1 , ms } | m1 ∈ MI (cs ) \ {ms } = LCOM 1Set(cs ) \ {m1 , ms } | m1 ∈ MI (cs ) ∧ m1 6= ms ∧ AR(m1 ) ∩ AR(ms ) ∩ AI (cs ) = ∅ ∪ {m1 , ms } | m1 ∈ MI (cs ) \ {m} =
When we refer to the latter as (A \ B) ∪ C), we can state that B ⊆ C, and therefore this equals to A ∪ C = A ∪ (C \ A). = LCOM 1Set(cs ) ∪ {m1 , ms } | m1 ∈ MI (cs ) \ {m} \ LCOM 1Set(cs ) Let us focus on {m1 , ms } | m1 ∈ MI (cs ) \ {m} \ LCOM 1Set(cs ) which we symbolize as C \ LCOM 1Set(cs ) C\LCOM 1Set(cs ) = {m1 , ms } | m1 ∈ MI (cs )\{m} \LCOM 1Set(cs ) = C \ (LCOM 1Set(cs ) ∩ C) = {m1 , ms } | m1 ∈ MI (cs ) \ {m} \ LCOM 1Set(cs ) ∩ {m1 , ms } | m1 ∈ MI (cs ) \ {m} = {m 1 , ms } | m1 ∈ MI (cs ) \ {m} \ {m1 , m2 } | m1 , m2 ∈ MI (cs ) ∧ m 1 6= m2 ∧ AR(m1 ) ∩ AR(m2 ) ∩ AI (cs ) = ∅ ∩ {m1 , ms } | m1 ∈ MI (cs ) \ {m} = {m 1 , ms } | m1 ∈ MI (cs ) \ {m} \ {m1 , ms } | m1 ∈ MI (cs ) ∧ m1 6= ms ∧ AR(m1 ) ∩ AR(ms ) ∩ AI (cs ) = ∅ ∩ {m1 , ms } | m1 ∈ MI (cs ) \ {m} = {m 1 , ms } | m1 ∈ MI (cs ) \ {m} \ {m1 , ms } | m1 ∈ MI (cs ) ∧ m1 6= ms ∧ AR(m1 ) ∩ AR(ms ) ∩ AI (cs ) = ∅ = {m1 , ms } | m1 ∈ MI (cs ) ∧ m1 6= m s ∧ AR(m1 ) ∩ AR(ms ) ∩ AI (cs ) 6= ∅
238
APPENDIX B. FORMAL IMPACT DERIVATION
And therefore: LCOM 1Set0 (cs ) = LCOM 1Set(cs ) ∪ (C \ LCOM 1Set(cs )) = LCOM 1Set0 (cs ) ∪ {m1 , ms } | m1 ∈ MI (cs ) ∧ m1 6= ms ∧ AR(m1 ) ∩ AR(ms ) ∩ AI (cs ) 6= ∅ Since LCOM 10 (cs ) =| LCOM 1Set0 (cs ) |, we have: 0 LCOM 1 (cs ) = LCOM 1(cs ) + | {m1 , ms } | m1 ∈ MI (cs ) ∧ m1 6= ms ∧ AR(m1 ) ∩ AR(ms ) ∩ AI (cs ) 6= ∅ |
Which means that after applying Replace Method with Method Object, LCOM 1(cs ) will be increased with the number of methods implemented by cs which shared attribute references with ms .
Bibliography [Arisholm and Sjøberg, 2004] Arisholm, E. and Sjøberg, D. I. K. (2004). Evaluating the effect of a delegated versus centralized control style on the maintainability of object-oriented software. IEEE Trans. Softw. Eng., 30(8):521–534. [Beck and Cunningham, 1989] Beck, K. and Cunningham, W. (1989). A laboratory for teaching object oriented thinking. In OOPSLA ’89: Conference proceedings on Object-oriented programming systems, languages and applications, pages 1–6, New York, NY, USA. ACM Press. [Berard, 1993] Berard, E. V. (1993). Essays on Object-Oriented Software Engineering. Prentice-Hall, Inc., Englewood Cliffs, New Jersey. [Bergantz and Hassell, 1991] Bergantz, D. and Hassell, J. (1991). Information relationships in prolog programs: how do programmers comprehend functionality? Int. J. Man-Mach. Stud., 35(3):313–328. [Biggerstaff et al., 1993] Biggerstaff, T. J., Mitbander, B. G., and Webster, D. (1993). The concept assignment problem in program understanding. In ICSE ’93: Proceedings of the 15th international conference on Software Engineering, pages 482–498, Los Alamitos, CA, USA. IEEE Computer Society Press. [Briand et al., 2001] Briand, L. C., Bunse, C., and Daly, J. W. (2001). A controlled experiment for evaluating quality guidelines on the maintainability of object-oriented designs. IEEE Trans. Software Engineering, 27(6):513–530. [Briand et al., 1996] Briand, L. C., Daly, J., and W¨ ust, J. (1996). A unified framework for coupling measurement in object-oriented systems. Technical Report ISERN-96-14, Fraunhofer Institute for Experimental Software Engineering, Kaiserslautern, Germany. 239
240
BIBLIOGRAPHY
[Briand et al., 1997] Briand, L. C., Daly, J., and W¨ ust, J. (1997). A unified framework for cohesion measurement in object-oriented systems. Technical Report ISERN-97-05, Fraunhofer Institute for Experimental Software Engineering, Kaiserslautern, Germany. [Briand et al., 1998] Briand, L. C., Daly, J., and W¨ ust, J. (1998). A unified framework for cohesion measurement in object-oriented systems. Empirical Software Engineering, 3(1):65–117. [Briand and W¨ ust, 2001] Briand, L. C. and W¨ ust, J. (2001). The impact of design properties on development cost in object-oriented system. IEEE Trans. Software Engineering, 27(11):963–986. [Brooks, 1978] Brooks, R. (1978). Using a behavioral theory of program comprehension in software engineering. In ICSE ’78: Proceedings of the 3rd international conference on Software engineering, pages 196–201, Piscataway, NJ, USA. IEEE Press. [Brooks, 1983] Brooks, R. (1983). Towards a theory of the comprehension of computer programs. International Journal of Man-Machine Studies, 18:543– 554. [Brown et al., 1998] Brown, W. J., Malveau, R. C., McCormick, III, H. W., and Mowbray, T. J. (1998). AntiPatterns: refactoring software, architectures, and projects in crisis. John Wiley and Sons, Inc. [Buschmann et al., 1996] Buschmann, F., Meunier, R., Rohnert, H., Sommerlad, P., and Stal, M. (1996). Pattern-Oriented Software Architecture — A System of Patterns. John Wiley and Sons. [Canfora et al., 1996] Canfora, G., Mancini, L., and Tortorella, M. (1996). A workbench for program comprehension during software maintenance. In Proceedings of the International Workshop on Program Comprehension, pages 30–39. [Chapin, 1988] Chapin, N. (1988). Software maintenance life cycle. In Proceedings of the International Conference on Software Maintenance, pages 6–13. [Chung et al., 2000] Chung, L., Nixon, B., Yu, E., and Mylopoulos, J. (2000). Non-Functional Requirements in Software Engineering. Kluwer Academic Publishers.
BIBLIOGRAPHY
241
[Coad and Yourdon, 1991] Coad, P. and Yourdon, E. (1991). Object-Oriented Design. Yourdon Press. [Coolican, 2004] Coolican, H. (2004). Research Methods and Statistics in Psychology, fourth edition. Hodder Arnold. [Corritore and Wiedenbeck, 1991] Corritore, C. and Wiedenbeck, S. (1991). What do novices learn during program comprehension? International Journal of Human-Computer Interaction, 3(2):199–222. [Crosby et al., 2002] Crosby, M. E., Scholtz, J., and Wiedenbeck, S. (2002). The roles beacons play in comprehension for novice and expert programmers. In Proceedings of the 14th Workshop of the Psychology of Programming Interest Group. [Davies, 2000] Davies, S. P. (2000). Expertise and the comprehension of objectoriented programs. In Blackwell, A. and Bilotta, E., editors, Collected Papers of the 12th Annual Workshop of the Psychology of Programming Interest Group (PPIG-12), pages 61–66. [Demeyer et al., 2002] Demeyer, S., Ducasse, S., and Nierstrasz, O. (2002). Object-Oriented Reengineering Patterns. Morgan Kaufmann and DPunkt. [Deursen and Moonen, 2002] Deursen, A. and Moonen, L. (2002). The video store revisited - thoughts on refactoring and testing. In Marchesi, M. and Succi, G., editors, Proceedings of the 3nd International Conference on Extreme Programming and Flexible Processes in Software Engineering (XP2002), pages 71–76. University of Cagliari. [Du Bois and Demeyer, 2003] Du Bois, B. and Demeyer, S. (2003). Accommodating changing requirements with EJB. In Proc. 9th Int’l Conf. on Object Oriented Information Systems, OOIS 2003. [Du Bois et al., 2004] Du Bois, B., Demeyer, S., and Verelst, J. (2004). Refactoring – improving coupling and cohesion of existing code. In WCRE, pages 144–151. [Du Bois et al., 2005] Du Bois, B., Demeyer, S., and Verelst, J. (2005). Does the “refactor to understand” reverse engineering pattern improve program comprehension? In CSMR, pages 334–343.
242
BIBLIOGRAPHY
[Du Bois et al., 2006] Du Bois, B., Demeyer, S., Verelst, J., Mens, T., and Temmerman, M. (2006). Does God Class Decomposition Affect Comprehensibility? In IASTED International Multi-Conference on Software Engineering, pages 346–355. [Engebretson and Wiedenbeck, 2002] Engebretson, A. and Wiedenbeck, S. (2002). Novice comprehension of programs using task-specific and non-taskspecific constructs. In HCC ’02: Proceedings of the IEEE 2002 Symposia on Human Centric Computing Languages and Environments (HCC’02), page 11, Washington, DC, USA. IEEE Computer Society. [Fichman and Moses, 1999] Fichman, R. G. and Moses, S. A. (1999). An incremental process for software implementation. Sloan Management Review, 40(2):39–52. [Fix et al., 1993] Fix, V., Wiedenbeck, S., and Scholtz, J. (1993). Mental representations of programs by novices and experts. In CHI ’93: Proceedings of the SIGCHI conference on Human factors in computing systems, pages 74–79, New York, NY, USA. ACM Press. [Fowler, 1999] Fowler, M. (1999). Refactoring: Improving the Design of Existing Code. Addison-Wesley. [Gamma et al., 1994] Gamma, E., Helm, R., Johnson, R., and Vlissides, J. (1994). Design Patterns: Elements of Reusable Object-Oriented Languages and Systems. Addisson-Wesley. [Griswold, 1991] Griswold, W. (1991). Program Restructuring as an Aid to Software Maintenance. PhD thesis, University of Washington. [Jacobson et al., 1992] Jacobson, I., M.Christerson, Jonsson, P., and Overgaard, G. (1992). Object-Oriented Software Engineering — A Use Case Driven Approach. Addisson-Wesley. [Johansson et al., 2001] Johansson, E., Wesslen, A., Bratthall, L., and Host, M. (2001). The importance of quality requirements in software platform development - a survey. hicss, 09:9057. [Kataoka et al., 2002] Kataoka, Y., Imai, T., Andou, H., and Fukaya, T. (2002). A quantitative evaluation of maintainability enhancement by refactoring. In Proc. Int’l Conf. Software Maintenance, pages 576–585. IEEE Computer Society Press.
BIBLIOGRAPHY
243
[Khan et al., 1996] Khan, M. K., Rashid, M. A., and Lo, B. W. (1996). A task-oriented software maintenance model. Malaysian Journal of Computer Science, 9(2):36–42. [Khoshgoftaar et al., 2006] Khoshgoftaar, T. M., Seliya, N., and Sundaresh, N. (2006). An empirical study of predicting software faults with case-based reasoning. Software Quality Control, 14(2):85–111. [Kniesel and Koch, 2004] Kniesel, G. and Koch, H. (2004). Static composition of refactorings. Sci. Comput. Program., 52(1-3):9–51. [Koenemann and Robertson, 1991] Koenemann, J. and Robertson, S. P. (1991). Expert problem solving strategies for program comprehension. In CHI ’91: Proceedings of the SIGCHI conference on Human factors in computing systems, pages 125–130, New York, NY, USA. ACM Press. [Krasner and Pope, 1988] Krasner, G. E. and Pope, S. T. (1988). A cookbook for using the model-view-controller user interface paradigm in smalltalk-80. J. Object-Oriented Programming, pages 26–49. [Lange et al., 2005] Lange, C., Du Bois, B., Chaudron, M. R., and Demeyer, S. (2005). An experimental investigation of uml modeling conventions. TU Eindhoven CS-Report 06-14, to appear in UML/Models 2006. [Larman, 2001] Larman, C. (2001). Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and the Unified Process. Prentice Hall PTR, Upper Saddle River, NJ, USA. [M¨antyl¨a et al., 2004] M¨ antyl¨ a, M., Vanhanen, J., and Lassenius, C. (2004). Bad smells - humans as code critics. In ICSM, pages 399–408. [McConnell, 1993] McConnell, S. (1993). Code complete: a practical handbook of software construction. Microsoft Press, Redmond, WA, USA. [McGregor and Kamath, 1995] McGregor, J. D. and Kamath, S. (1995). A psychological complexity measure at the domain analysis phase for an objectoriented system. Technical report, Clemson University. ´ Cinn´eide, 2001] O ´ Cinn´eide, M. (2001). Automated Application of Design [O Patterns: a Refactoring Approach. PhD thesis, University of Dublin, Trinity College.
244
BIBLIOGRAPHY
[O’Brien and Buckley, 2001] O’Brien, M. P. and Buckley, J. (2001). Inferencebased and expectation-based processing in program comprehension. In IWPC ’01: Proceedings of the 9th International Workshop on Program Comprehension, page 71, Washington, DC, USA. IEEE Computer Society. [Opdyke, 1992] Opdyke, W. (1992). Refactoring Object-Oriented Frameworks. PhD thesis, University of Illinois at Urbana-Champaign. [Or-Bach and Lavy, 2004] Or-Bach, R. and Lavy, I. (2004). Cognitive activities of abstraction in object orientation: an empirical study. SIGCSE Bull., 36(2):82–86. [Page-Jones, 1992] Page-Jones, M. (1992). Comparing techniques by means of encapsulation and connascence. Commun. ACM, 35(9):147–151. [Parnas, 1978] Parnas, D. L. (1978). Designing software for ease of extension and contraction. In ICSE ’78: Proceedings of the 3rd international conference on Software engineering, pages 264–277, Piscataway, NJ, USA. IEEE Press. [Pennington, 1987a] Pennington, N. (1987a). Comprehension strategies in programming. In Proc. 2nd Workshop on Empirical Studies of Programmers, pages 100–112. Ablex Publishing, Norwood, N.J. [Pennington, 1987b] Pennington, N. (1987b). Stimulus structures and mental representations in expert comprehension of computer programs. Cognitive Psychology, 19:295–341. [Pfahl, 2001] Pfahl, D. (2001). An Integrated Approach to Simulation-Based Learning in Support of Strategic and Project Management in Software Organisation. PhD thesis, Department of Computer Science, Univer- sity of Kaiserslautern. [Rajlich and Cowan, 1997] Rajlich, V. and Cowan, G. S. (1997). Towards standard for experiments in program comprehension. In WPC, pages 160–161. [Ramalingam and Wiedenbeck, 1997] Ramalingam, V. and Wiedenbeck, S. (1997). An empirical study of novice program comprehension in the imperative and object-oriented styles. In ESP ’97: Papers presented at the seventh workshop on Empirical studies of programmers. [Riel, 1996] Riel, A. J. (1996). Object-Oriented Design Heuristics. AddisonWesley Publishing Company.
BIBLIOGRAPHY
245
[Roberts, 1999] Roberts, D. (1999). Practical Analysis for Refactoring. PhD thesis, University of Illinois at Urbana-Champaign. [Sahraoui et al., 2000] Sahraoui, H. A., Godin, R., and Miceli, T. (2000). Can metrics help to bridge the gap between the improvement of oo design quality and its automation? In Proc. International Conference on Software Maintenance, pages 154–162. [Sajaniemi and Navarro-Prieto, 2005] Sajaniemi, J. and Navarro-Prieto, R. (2005). An investigation into professional programmers’ mental representations of variables. In International Workshop on Program Comprehension, pages 55–64. [Schuh and Punk, 2001] Schuh, P. and Punk, S. (2001). Objectmother: Easing test object creation in xp. XP Universe Conference. [Seng et al., 2005] Seng, O., Bauer, M., Biehl, M., and Pache, G. (2005). Searchbased improvement of subsystem decompositions. In GECCO ’05: Proceedings of the 2005 conference on Genetic and evolutionary computation, pages 1045–1051, New York, NY, USA. ACM Press. [Shadish et al., 2002] Shadish, W. R., Cook, T. D., and Campbell, D. T. (2002). Experimental and Quasi-Experimental Designs for Generalized Causal Inference. Houghton Mifflin. [Simon et al., 2001] Simon, F., Steinbr¨ uckner, F., and Lewerentz, C. (2001). Metrics based refactoring. In Proc. European Conf. Software Maintenance and Reengineering, pages 30–38. IEEE Computer Society Press. [Soloway and Ehrlich, 1984] Soloway, E. and Ehrlich, K. (1984). Empirical studies of programming knowledge. IEEE Trans. Software Engineering, SE10(5):595–609. [Soloway et al., 1988] Soloway, E., Lampert, R., Letovsky, S., Littman, D., and Pinto, J. (1988). Designing documentation to compensate for delocalized plans. Commun. ACM, 31(11):1259–1267. [Stevens et al., 1974] Stevens, W. P., Myers, G. J., and Constantine, L. L. (1974). Structured design. IBM Systems Journal, 13(2):115–139. [Tahvildari and Kontogiannis, 2002a] Tahvildari, L. and Kontogiannis, K. (2002a). On the role of design patterns in quality-driven re-engineering. In CSMR, pages 230–240.
246
BIBLIOGRAPHY
[Tahvildari and Kontogiannis, 2002b] Tahvildari, L. and Kontogiannis, K. (2002b). A software transformation framework for quality-driven objectoriented re-engineering. In ICSM ’02: Proceedings of the International Conference on Software Maintenance (ICSM’02), page 596, Washington, DC, USA. IEEE Computer Society. [Tahvildari et al., 2003] Tahvildari, L., Kontogiannis, K., and Mylopoulos, J. (2003). Quality-driven software re-engineering. J. Syst. Softw., 66(3):225– 239. [Tichelaar, 2001] Tichelaar, S. (2001). Modeling Object-Oriented Software for Reverse Engineering and Refactoring. PhD thesis, University of Bern. [Tokuda and Batory, 2001] Tokuda, L. and Batory, D. (2001). Evolving objectoriented designs with refactorings. Automated Software Engg., 8(1):89–120. [van Deursen et al., 2003] van Deursen, A., Marin, M., and Moonen, L. (2003). Aspect mining and refactoring. In Proceedings of the First International Workshop on REFactoring: Achievements, Challenges, Effects (REFACE03). University of Waterloo, Canada. [van Emden and Moonen, 2002] van Emden, E. and Moonen, L. (2002). Java quality assurance by detecting code smells. In Proceedings of the 9th Working Conference on Reverse Engineering. IEEE Computer Society Press. [Vok´a˘c et al., 2004] Vok´ a˘c, M., Tichy, W., Sjøberg, D. I. K., Arisholm, E., and Aldrin, M. (2004). A controlled experiment comparing the maintainability of programs designed with and without design patterns replication in a real programming environment. Empirical Softw. Engg., 9(3):149–195. [von Mayrhauser and Vans, 1995] von Mayrhauser, A. and Vans, A. M. (1995). Program comprehension during software maintenance and evolution. IEEE Computer, 28(8):44–55. [Wake, 2003] Wake, W. C. (2003). Refactoring Workbook. Addison-Wesley Longman Publishing Co., Inc., Boston, MA, USA. [Wheeldon and Counsell, 2003] Wheeldon, R. and Counsell, S. (2003). Making refactoring decisions in large-scale java systems: an empirical stance. CoRR, cs.SE/0306098. [Wiedenbeck and Scholtz, 1989] Wiedenbeck, S. and Scholtz, J. (1989). Beacons an initial program comprehension. SIGCHI Bull., 21(1):90–91.
BIBLIOGRAPHY
247
[Zaidman et al., 2006] Zaidman, A., Du Bois, B., and Demeyer, S. (2006). How webmining and coupling metrics improve early program comprehension. In ICPC ’06: Proceedings of the 14th IEEE International Conference on Program Comprehension (ICPC’06), pages 74–78, Washington, DC, USA. IEEE Computer Society.