Upload
others
View
1
Download
0
Embed Size (px)
Citation preview
Quality-Driven Object-Oriented
Re-engineering Framework
by
Ladan Tahvildari
A thesis
presented to the University of Waterloo
in fulfilment of the
thesis requirement for the degree of
Doctor of Philosophy
in
Electrical and Computer Engineering
Waterloo, Ontario, Canada, 2003
c©Ladan Tahvildari 2003
I hereby declare that I am the sole author of this thesis.
I authorize the University of Waterloo to lend this thesis to other institutions or
individuals for the purpose of scholarly research.
Ladan Tahvildari
I further authorize the University of Waterloo to reproduce this thesis by photocopying
or by other means, in total or in part, at the request of other institutions or individuals
for the purpose of scholarly research.
Ladan Tahvildari
ii
The University of Waterloo requires the signatures of all persons using or photocopying
this thesis. Please sign below, and give address and date.
iii
Abstract
Object-orientation in software engineering defines methods and techniques that assist
software engineers to build large, flexible, modular, and reusable systems. Many of the
systems that have been built over the past decade using object-oriented techniques like
inheritance, encapsulation, polymorphism, information hiding, and late binding are al-
ready considered legacy systems. It is of no surprise that it is already difficult to maintain
these systems. Since these legacy systems often incorporate undocumented valuable busi-
ness logic, decommissioning or reimplementing them is a very difficult and risky task. A
possible solution to this problem is software re-engineering, that aims on analyzing and
transforming such systems while retaining their functionality and improving their quality
characteristics.
In this context, we need a comprehensive framework that allows for the definition and
enactment of the re-engineering process. This thesis presents a framework for providing
quality based and quality-driven re-engineering of object-oriented systems. The frame-
work allows for specific design and quality requirements (performance, and maintainabil-
ity) of the target migrant system to be considered during the re-engineering process.
Quality requirements for the migrant system can be encoded using soft-goal interde-
pendency graphs and be associated with specific software transformations that need to be
carried out for the specific target quality requirement to be achieved. These transforma-
tions can be applied as a series of the iterative and incremental steps to the source code.
An evaluation procedure can be used at each transformation step to determine whether
specific goals have been achieved.
iv
Acknowledgements
But words are things, and a small drop of ink,
Falling like dew, upon a thought, produces;
That which makes thousands, perhaps millions, think.
Lord Byron
If the words in this dissertation cause even a very small fraction of thousands to think,
it is in large part due to advice, support, help, and encouragement I received of many
people to whom I will always be indebted.
First and foremost, I would like to express my deep appreciation to my supervisor,
Professor Kostas Kontogiannis, for his invaluable advice and constant support. His en-
thusiasm for research is infectious and I left every discussion with him full of new ideas
and energy for continuing this work. Kostas shaped this research with his vision, his
sharp thought, and his scientific standards. This journey would have never started and
would have not been the enjoyable adventure that it was if he had not been there. He
has always been a mentor, a teacher, and a brother to me.
I feel very lucky to have been introduced to Professor John Mylopoulos at the begin-
ning of my Ph.D. by Kostas. I cannot thank John enough for exposing me to the field
of Non-Functional Requirement, for providing me with the brainstorming meetings in his
office at the Pratt Building of University of Toronto, for showing me his tremendous sup-
port and encouragement whenever I needed, and throughout for being such a wonderful
mentor and an admirable role model.
I wish to thank the members of my dissertation committee : Professor Peter Aiken, my
external examiner, for having accepted to take the time out of his busy schedule to read
my thesis and provide me with his insightful suggestions, Professor Don Cowan for his
invaluable comments on the thesis, Professor Rudolph Seviora for his inspiring remarks,
Professor Paul Dasiewicz and Professor Sagar Naik for taking the time and the effort to
participate in my committee, Professor Ken Salem for serving as the Thesis Examination
v
Chair, and Professor Krzysztof Czarnecki for serving as a delegate in my oral defence.
I would like to express my sincere appreciation to Professor Panos Linos, Profes-
sor Hausi Muller, and Professor Vaclav Rajlich for their kind, and encouraging attitude
towards me, and for their tremendous support and influence on my career.
Many renowned researchers from all over the world have enriched and supported
my academic life with their insightful comments and enjoyable discussions in a variety
of forms. I thank a number of them : Professor Parham Aarabi, Dr. Mario Barbacci,
Dr. Len Bass, Professor Gerardo Canfora, Dr. David Card, Dr. Ned Chapin, Profes-
sor Cristina Cifuentes, Professor Jim Cordy, Professor Jurgen Ebert, Professor Mike God-
frey, Dr. Tibor Gyimothy, Professor Ric Holt, Professor Dennis Kafura, Dr. Rainer Koschke,
Dr. Burton Leathers, Professor Manny Lehman, Professor Pas Pasupathy, Dr. Den-
nis Smith, Mr. Harry Sneed, and Professor Kenny Wong.
I am grateful to have an opportunity to be a member of organizing committee for
“Working Conference on Reverse Engineering” (WCRE2003). It was a great learning ex-
perience for me and I enjoyed every moment of it while working with Professor Margaret-
Anne Storey, Professor Arie van Deursen, Professor Eleni Stroulia, and Mr. Elliot Chikof-
sky for contriving the 10th Anniversary of WCRE.
Financial support for this work by IBM Canada, Ontario Graduate Scholarship (OGS)
of Canada, and University of Waterloo is greatly appreciated. Special thanks to the IBM
Centre for Advanced Studies (CAS) for awarding me a Ph.D. Research Fellowship. Many
thanks to Mr. Joe Wigglesworth, and Dr. Marin Litoiu and the other members from
IBM CAS for providing a wonderful and friendly research environment at IBM Toronto
Research Laboratory which I was lucky enough to enjoy for the past few years.
I am indebted to the other members of the University of Waterloo. I would like to
thank Professor Adel Sedra for showing me his invaluable support and advising me with
his wise words at a very crucial moment in my life when the going was tough, Profes-
vi
sor Arokia Nathan for being my model of what a professor should be and his sage advice
whenever I have needed, Professor Anthony Vannelli for his priceless support and an
enormous amount of faith in me in numerous occasions, Professor Safieddin (Ali) Safavi-
Naeini for his true friendship, Professor Farhad Mavaddat for his care always as a father,
and Professor Farid Golnaraghi for his attention, and moral support when it was most
required. Special thanks to Wendy Boles for her open-door policy and tireless patience,
to Wendy Gauthier for her kindness and assistance, to Phil Regier and Fernando Hernan-
dez for their timely responses and phenomenal speed to all sorts of computing problems.
Research would not be as much fun without accompanying all my friends and fellow
students at Waterloo who inspired me along the way.
I owe an immense debt of gratitude to my Father and Mother who provided me
a loving family environment in which I could thrive. They have been parents when I
needed support, friends when I needed to talk, teachers when I needed to learn. Special
thanks to both of them who instilled the following in me as a child : if a thing is worth
doing, it is worth doing well. Many thanks to Babak and Radin, for starting by being
my little brothers and growing to become my best friends.
None of these would have been possible without the love of my life, my husband :
Professor AmirKeyvan Khandani. When I was a child, I dreamed of becoming a scientist.
I have been very fortunate that destiny gave me the opportunity to meet AmirKeyvan
who never stopped to support, encourage, understand, and love me but also shared with
me the joys and the tears of my graduate studies, and along the way always believed in
me even when I did not. I could not achieve this without his unlimited sacrifice. I hope
that I will be able to give to him as much as I received.
Near and far, past and present, all have contributed to this research in some way.
Without these unconditional support, the thoughts in this dissertation would never have
found the necessary ink to make its bits for the digital age.
vii
Dedicated To :
My beloved husband, AmirKeyvan,
for being so tremendously patient and supportive of all my dreams.
My adorable parents, Mozafar and Louise,
for raising me, caring me, teaching me, and loving me.
The loving memories of my grandfathers, Hossein and Hadi,
for being such exemplary human beings.
viii
List of Publications
Journal Papers
• Ladan Tahvildari, Kostas Kontogiannis, John Mylopoulos, “Quality-Driven Soft-
ware Re-engineering”, The Journal of Systems and Software (JSS), Special Issue
on : Software Architecture - Engineering Quality Attributes, Volume 66, Issue 3,
pp. 225-239, June 2003.
• Ladan Tahvildari, Kostas Kontogiannis, “Improving Design Quality Using Meta-
Pattern Transformations : A Metric-Based Approach”, Journal of Software Main-
tenance and Evolution : Research and Practice, 25 pages, to appear.
Book Chapter
• Ladan Tahvildari, Kostas Kontogiannis, Computer Aided Software Engineering
(CASE), In John G. Webster, Editor, Encyclopedia of Electrical and Electronics
Engineering, John Wiley & Sons, 35 pages, to appear.
Refereed Conference Papers
• Ladan Tahvildari, Kostas Kontogiannis, “A Metric-Based Approach to Enhance
Design Quality Through Meta-Pattern Transformations”, In Proceedings of the 7th
IEEE European Conference on Software Maintenance and Reengineering (CSMR),
Benevento, Italy, pp. 183-192, March 2003.
• Ladan Tahvildari, Kostas Kontogiannis, “A Methodology for Developing Trans-
formations Using the Maintainability Soft-Goal Graph”, In Proceedings of the 9th
IEEE Working Conference on Reverse Engineering (WCRE), Richmond, Virginia,
USA, pp. 77-86, November 2002.
ix
• Ladan Tahvildari, Kostas Kontogiannis, “A Software Transformation Framework for
Quality-Driven Object-Oriented Re-engineering”, In Proceedings of the IEEE Inter-
national Conference on Software Maintenance (ICSM), Montreal, Canada, pp. 596-
605, October 2002.
• Ladan Tahvildari, Kostas Kontogiannis, “On the Role of Design Patterns in Quality-
Driven Re-engineering”, In Proceedings of the 6th IEEE European Conference on
Software Maintenance and Reengineering (CSMR), Budapest, Hungary, pp. 230-
240, March 2002.
• Ladan Tahvildari, Kostas Kontogiannis, John Mylopoulos, “Requirements-Driven
Software Re-engineering”, In Proceedings of the 8th IEEE Working Conference on
Reverse Engineering (WCRE), Stuttgart, Germany, pp. 71-80, October 2001.
• Ladan Tahvildari, Kostas Kontogiannis, “A Workbench for Quality Based Software
Re-engineering to Object Oriented Platforms”, ACM International Conference in
Object Oriented Programming, Systems, Languages, and Applications (OOPSLA) -
Doctoral Symposium, Minneapolis, Minnesota, USA, pp. 157-158, October 2000.
• Ladan Tahvildari, Richard Gregory, Kostas Kontogiannis, “An Approach for Mea-
suring Software Evolution Using Source Code Features”, In Proceedings of the IEEE
Asia-Pacific Software Engineering (APSEC), Takamatsu, Japan, pp. 10-17, Decem-
ber 1999.
x
Contents
1 Introduction 1
1.1 Problem Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
1.2 Thesis Contributions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.3 Thesis Organization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2 Related Work 9
2.1 Software Re-engineering . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.1.1 The Re-engineering Taxonomy . . . . . . . . . . . . . . . . . . . . 10
2.1.2 Program Transformations . . . . . . . . . . . . . . . . . . . . . . . 11
2.1.3 Program Representation . . . . . . . . . . . . . . . . . . . . . . . . 16
2.2 Software Requirements Modeling . . . . . . . . . . . . . . . . . . . . . . . 21
2.2.1 Non-Functional Requirements . . . . . . . . . . . . . . . . . . . . . 23
2.2.2 Software Quality Metrics . . . . . . . . . . . . . . . . . . . . . . . 27
2.3 Software Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
2.3.1 Architecture Reconstruction . . . . . . . . . . . . . . . . . . . . . . 48
2.3.2 Architectural Patterns and Design Patterns . . . . . . . . . . . . . 49
2.3.3 Patterns in Software Re-engineering . . . . . . . . . . . . . . . . . 50
2.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
xi
3 Quality-Driven Re-engineering Framework 53
3.1 Software Re-engineering Life Cycle . . . . . . . . . . . . . . . . . . . . . . 54
3.2 Problem Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.3 Quality-Driven Object-Oriented Re-engineering . . . . . . . . . . . . . . . 58
3.4 Soft-Goal Interdependency Graphs . . . . . . . . . . . . . . . . . . . . . . 60
3.4.1 Maintainability Soft-Goal Graph . . . . . . . . . . . . . . . . . . . 62
3.4.2 Performance Soft-Goal Graph . . . . . . . . . . . . . . . . . . . . . 65
3.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
4 Software Transformation Algebra 68
4.1 Role of Design Patterns in Software Re-engineering . . . . . . . . . . . . . 69
4.1.1 Overall Structure of GoF Catalogue . . . . . . . . . . . . . . . . . 71
4.1.2 Classifying Relationships . . . . . . . . . . . . . . . . . . . . . . . 72
4.1.3 Modifying Relationships . . . . . . . . . . . . . . . . . . . . . . . . 78
4.1.4 Design Patterns in a Layered Architecture . . . . . . . . . . . . . . 80
4.2 A Software Transformation Framework . . . . . . . . . . . . . . . . . . . . 84
4.3 Algebra for Composing Software Transformations . . . . . . . . . . . . . . 88
4.3.1 Approaches for Defining Semantics . . . . . . . . . . . . . . . . . . 89
4.3.2 An Algebraic Framework for Transformations . . . . . . . . . . . . 91
4.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
5 Code-Improving Transformations Catalogue 97
5.1 Mathematical Notations . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
5.2 Investigative Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
5.3 Supporting Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
5.4 Positioning Transformations . . . . . . . . . . . . . . . . . . . . . . . . . . 103
5.5 Primitive Design Pattern Transformations . . . . . . . . . . . . . . . . . . 104
xii
5.5.1 ABSTRACTION Transformation . . . . . . . . . . . . . . . . . . . 106
5.5.2 EXTENSION Transformation . . . . . . . . . . . . . . . . . . . . . 107
5.5.3 MOVEMENT Transformation . . . . . . . . . . . . . . . . . . . . 108
5.5.4 ENCAPSULATION Transformation . . . . . . . . . . . . . . . . . 109
5.5.5 BUILDRELATION Transformation . . . . . . . . . . . . . . . . . 110
5.5.6 WRAPPER Transformation . . . . . . . . . . . . . . . . . . . . . . 111
5.6 Modifications on SIGs with Transformations . . . . . . . . . . . . . . . . . 112
5.7 Complex Design Pattern Transformations . . . . . . . . . . . . . . . . . . 114
5.8 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
6 Software Transformation Process 119
6.1 A Model for a SIG Representation . . . . . . . . . . . . . . . . . . . . . . 120
6.1.1 Types of Contributions in SIGs . . . . . . . . . . . . . . . . . . . . 120
6.1.2 Soft-Goal Adjacency Matrix (SAM) . . . . . . . . . . . . . . . . . 123
6.1.3 Transformation Impact Matrix (TIM) . . . . . . . . . . . . . . . . 126
6.2 A Model for Quality Assessment . . . . . . . . . . . . . . . . . . . . . . . 130
6.2.1 A Classification of OO Design Flaws . . . . . . . . . . . . . . . . . 130
6.2.2 Role of Design Flaws in the QDR Framework . . . . . . . . . . . . 134
6.2.3 Assigning Object-Oriented Metrics to Soft-Goals . . . . . . . . . . 138
6.2.4 Mapping Software Transformations to a Metrics Suite . . . . . . . 143
6.3 A Multi-Objective Search Algorithm for SIGs . . . . . . . . . . . . . . . . 146
6.3.1 Soft-Goal Evaluation Procedure . . . . . . . . . . . . . . . . . . . . 148
6.3.2 Impact Analysis : Generate Individual Label (GIL) . . . . . . . . . 149
6.3.3 Objective Analysis : Combine Generated Labels (CGL) . . . . . . 152
6.3.4 Problem Formulation : A Graph Search Approach . . . . . . . . . 154
6.3.5 Select Transformation Path (STP) . . . . . . . . . . . . . . . . . . 158
xiii
6.3.6 Usage of the Proposed Multi-Objective Algorithm : An Example . 163
6.4 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
7 Case Studies 168
7.1 Objectives and Scopes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
7.1.1 Experimentation Suite . . . . . . . . . . . . . . . . . . . . . . . . . 169
7.1.2 Experimentation Hardware Platform . . . . . . . . . . . . . . . . . 172
7.2 A Prototype for QDR Framework . . . . . . . . . . . . . . . . . . . . . . . 172
7.2.1 Pre-Process Components . . . . . . . . . . . . . . . . . . . . . . . 174
7.2.2 Analysis Components . . . . . . . . . . . . . . . . . . . . . . . . . 175
7.2.3 Post-Process Components . . . . . . . . . . . . . . . . . . . . . . . 175
7.3 Detailed Process of QDR Prototype . . . . . . . . . . . . . . . . . . . . . 177
7.3.1 Selected Criteria for Implementing Transformations . . . . . . . . 178
7.4 Some Statistics of the Subject Software Systems . . . . . . . . . . . . . . 180
7.4.1 Time and Space Complexity . . . . . . . . . . . . . . . . . . . . . . 180
7.4.2 Impact of Applied Transformations on Soft-Goals . . . . . . . . . . 182
7.5 Discussion on QDR Framework Evaluation . . . . . . . . . . . . . . . . . 187
7.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195
8 Future Directions and Conclusions 196
8.1 Contributions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
8.2 Future Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
8.3 Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201
A Investigative Functions Catalogue 202
B Supporting Functions Catalogue 207
xiv
C Positioning Transformations Catalogue 211
D Primitive DP Transformations Catalogue 225
Bibliography 236
xv
List of Figures
2.1 A Taxonomy of Program Transformation. . . . . . . . . . . . . . . . . . . 12
2.2 Relation Between Kinds of Program Transformation. . . . . . . . . . . . . 13
2.3 A Soft-Goal Interdependency Graph. . . . . . . . . . . . . . . . . . . . . . 24
2.4 Contributions of the Shared Data and Abstract Data Type in Soft-Goal
Graph. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.5 Sequential Cohesion. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
2.6 Maximal Cohesion. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
3.1 The Re-engineering Life-Cycle. . . . . . . . . . . . . . . . . . . . . . . . . 55
3.2 The Block Diagram of the Quality-Based Re-engineering Process. . . . . . 60
3.3 Maintainability Soft-Goal Decomposition. . . . . . . . . . . . . . . . . . . 63
3.4 Performance Soft-Goal Decomposition. . . . . . . . . . . . . . . . . . . . . 66
4.1 On the Role of Design Patterns in Re-engineering Context. . . . . . . . . 70
4.2 Classified Structure of Design Pattern Catalogue. . . . . . . . . . . . . . . 80
4.3 Arrangement of Design Pattern Catalogue in Layers. . . . . . . . . . . . . 81
4.4 Meta-Model of the Transformations. . . . . . . . . . . . . . . . . . . . . . 85
4.5 Comparison of Approaches. . . . . . . . . . . . . . . . . . . . . . . . . . . 90
4.6 Specification Language for Software Transformation Framework. . . . . . 92
xvi
5.1 Principle Program Entities and Their Relationships. . . . . . . . . . . . . 100
5.2 Relating Primitive Design Patterns Transformations to Maintainability
Soft-Goal Graph. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113
5.3 Relating Primitive Design Patterns Transformations to Performance Soft-
Goal Graph. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
5.4 Relating Transformations to Maintainability Soft-Goal Graph. . . . . . . . 115
6.1 Generate Adjacency Matix Algorithm. . . . . . . . . . . . . . . . . . . . . 125
6.2 Non-Functional Soft-Goal, Transformations and Their Relationships. . . . 126
6.3 Generate Impact Matrix Algorithm. . . . . . . . . . . . . . . . . . . . . . 129
6.4 Design Flaws Classification. . . . . . . . . . . . . . . . . . . . . . . . . . . 132
6.5 Re-engineering Strategy for Design Flaws. . . . . . . . . . . . . . . . . . . 135
6.6 Key Classes in an Object-Oriented Legacy System. . . . . . . . . . . . . . 138
6.7 A Catalogue of Impact Links. . . . . . . . . . . . . . . . . . . . . . . . . . 148
6.8 A Catalogue of Objectives Based on Label Values. . . . . . . . . . . . . . 149
6.9 Soft-Goal Evaluation Algorithm. . . . . . . . . . . . . . . . . . . . . . . . 150
6.10 Multi-objective Search Problem Formulation. . . . . . . . . . . . . . . . . 157
6.11 Selection Transformation Path Algorithm. . . . . . . . . . . . . . . . . . . 161
6.12 State Space Graph for the Example. . . . . . . . . . . . . . . . . . . . . . 164
6.13 Graphical Trace of the Operation of the Proposed Multi-Objective Algo-
rithm. (a) Iteration 1, (b) Iteration 2, (c) Iteration 3, (d) Iteration 4. . . . 165
7.1 The Architectural Design of the Prototype for QDR Framework. . . . . . 173
7.2 A Snapshot of the Quality-Driven Re-engineering Framework. . . . . . . . 176
7.3 Graph of Parsing Time and Size Results for the Case Studies. . . . . . . . 181
7.4 Graph of Extracting Metrics Time and Size Results for the Case Studies. 182
7.5 Impact of Applying Primitive Transformations on Maintainability. . . . . 183
xvii
7.6 Impact of Applying Different Transformations on Performance. . . . . . . 185
7.7 Impact of Applying Some Complex Transformations on Maintainability. . 186
7.8 A Part of Object Model of Java Expert System Shell (JESS). . . . . . . . 188
7.9 The Same Part of JESS After Applying WRAPPER Meta-Pattern Trans-
formation. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
7.10 Object Model of AVL GNU Library System. . . . . . . . . . . . . . . . . . 192
7.11 Object Model of AVL After Applying Transformations. . . . . . . . . . . 193
7.12 Object Model of WELTAB Election Tabulation System. . . . . . . . . . . 194
7.13 Object Model of WELTAB After Applying Transformations. . . . . . . . 195
xviii
List of Tables
2.1 Relationship Types Between CC and SC and Their corresponding Contri-
bution α to Change Dependency. . . . . . . . . . . . . . . . . . . . . . . . 39
4.1 Overall Structure of the Design Pattern Catalogue. . . . . . . . . . . . . . 73
4.2 Revised Classification. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
4.3 Primary Level of Design Patterns. . . . . . . . . . . . . . . . . . . . . . . 82
5.1 A List of Investigative Functions. . . . . . . . . . . . . . . . . . . . . . . . 101
5.2 A List of Supporting Functions. . . . . . . . . . . . . . . . . . . . . . . . . 104
5.3 A List of Positioning Transformations. . . . . . . . . . . . . . . . . . . . . 105
5.4 A List of Primitive Design Pattern Transformations. . . . . . . . . . . . . 108
5.5 A List of Generators for Complex Design Pattern Transformations. . . . . 116
6.1 A Catalogue of Contribution Operators. . . . . . . . . . . . . . . . . . . . 122
6.2 Selected Object-Oriented Metrics and Their Relationships with Soft-Goals. 141
6.3 Impact of the Transformations on OO Metrics Suite. . . . . . . . . . . . . 144
6.4 The Individual Impact of An Offspring. . . . . . . . . . . . . . . . . . . . 152
6.5 Numerical Trace of the Operation of Multi-Objective Algorithm. . . . . . 166
7.1 Source Code Statistics of the Case Study Software Systems. . . . . . . . . 170
7.2 Some Time and Space Statistics of the Case Study Software Systems. . . 181
xix
7.3 Impact of Applied Transformations on OO Metric Suite for the Case Studies.184
7.4 Object-Oriented Metrics for Three classes of JESS. . . . . . . . . . . . . . 189
xx
Chapter 1
Introduction
Programs, like people, get old. We can’t prevent aging, but we can understand its
causes, take steps to limit its effects, temporarily reverse some of the damage it
has caused, and prepare for the day when the software is no longer viable.
David L. Parnas
The re-engineering of legacy systems has become a major concern in today’s software
industry. Traditionally, most re-engineering efforts were focused on systems written in
traditional programming languages such as Fortran, COBOL, and C [4, 10, 19, 121, 155].
However, over the past few years we observed an increasing demand for the re-engineering
of object-based systems [40, 46, 96, 132, 140, 174]. The object-oriented paradigm pro-
vides methodologies for software engineers to build large, flexible, modular, and reusable
systems. Many of the systems that have been built using object-oriented techniques
like inheritance, encapsulation, polymorphism, information hiding, and late binding are
already considered legacy systems. It is of no surprise that it becomes more and more diffi-
cult to maintain these systems or to extend their functionality. Since these legacy systems
often incorporate undocumented valuable business logic, discarding or re-implementing
these systems is a very difficult task that encompasses many risks. A possible solution to
this problem is re-engineering these legacy systems, that is retaining their functionality
1
CHAPTER 1. INTRODUCTION 2
while improving their non-functional quality properties.
There are several reasons that contribute to the need for the re-engineering of object-
oriented legacy systems. These include :
• Misuse of Object-Orientation. It requires several years of experience to fully ex-
ploit the potential of the object-oriented paradigm in large software applications.
Moreover domain specific experience is often acquired during the initial stages of
a project, at the time when the most crucial parts of the system are implemented,
specified, and designed. Therefore, object-oriented systems can become easily un-
manageable.
• Technology Expansion. Legacy systems should benefit from emerging standards
(e.g., UML [150], CORBA [139]), technological advancements (e.g., design pat-
terns, architectural styles) and extra language features (e.g., C++ template, Ada
inheritance). Re-engineering these systems will allow their maintainers to use mod-
ern technologies for keeping these systems operational.
• Prolonged Maintenance. The law of the software entropy [82] states that even
when a system is well-designed at its deployment time, requirements evolve and
users demand new functionality, in ways the original architecture was not designed
to accommodate. A complete redesign of a large system is not practical in most
cases, and a system is bound to gradually lose its original structure and deform
into a collection of highly coupled modules often referred to as “object-oriented
spaghetti” [35].
• Lack of Supporting Documentation. Many legacy software systems do not have a
documented system design and architecture. Even if there is a well-documented and
high-level view of such system during initial development, it is highly likely that
CHAPTER 1. INTRODUCTION 3
an actual implementation will differ greatly from the documented design especially
after prolonged maintenance. One approach to recovering the understanding of a
system is to extract architecture documentation from the system implementation.
This enhanced understanding can be used as part of a re-engineering effort.
The re-engineering of object-oriented legacy systems requires a comprehensive frame-
work to relate software transformation activities with non-functional requirements of
the target migrant system. The focal point of the proposed research is to exploit the
synergy between the areas of software requirements analysis [183], software architec-
ture [17, 48, 74, 136], and source code analysis and transformation [10, 121]. Effective
system maintenance and evolution requires the understanding both of the inner-workings
of the system (i.e., its structure) and the rationale or requirements that justify its evo-
lution. Understanding the architecture and the source code of an existing system aids
in assessing the impact specific re-engineering and transformation activities have on the
legacy system.
In this context, we have built a re-engineering framework that allows for specific
quality requirements for the migrant system to be modelled as a collection of soft-goal
graphs and a system that allows for the selection of the transformational steps that
need to be applied on a legacy system being re-engineered. In such a framework, software
transformational steps may lead to addressing contradictory requirements (i.e., increasing
performance while decreasing maintainability). For this reason, we have also investigated
how design and source code programming patterns may assist on such selection of the
transformational steps that need to be applied in any given re-engineering scenario. A
framework that assesses the impact of the re-engineering transformation steps on specific
software qualities (performance and maintainability) for the new migrant system has also
been developed.
CHAPTER 1. INTRODUCTION 4
This research is noteworthy for two main reasons. First, it addresses a problem that
challenges the research community for several years, namely the maintenance of object-
oriented systems. Second, it devises a framework in which re-engineering activities do
not occur in a vacuum, but can be evaluated and fine-tuned in order to address specific
quality requirements for the new target system such as, enhancements in maintainability,
and performance.
1.1 Problem Description
In most cases, software re-engineering tasks have to conform to hard and soft quality
constraints (or non-functional requirements) such as “a re-engineered system must run
as fast as the original”, or “a new system should be more easily maintainable than the
original”. These desired qualities (or, more precisely, desired deltas on these qualities)
play a fundamental role in defining the re-engineering process and the tools that support
it. We have developed a software re-engineering methodology that is requirements-driven
in the sense that it uses quality requirements to define and guide the re-engineering
process.
The scenario that we want to assume is as follows : “An existing object-oriented
legacy system is being re-engineered in order to conform with a new requirement (i.e.,
performance enhancement). After studying the code and the desired requirement, it
is concluded that the existing structure of the program makes the desired extension
difficult to achieve, and that the application of some design patterns or source code
transformations would help to achieve the desired property”. In this context, we have
provided a semi-automatic support for the developer. In this approach, the developer can
also decide what design pattern or transformation to apply towards achieving a specific
non-functional requirement for the new system.
CHAPTER 1. INTRODUCTION 5
To represent information about different software qualities, their interdependencies,
and the software transformations that affect them, we use the non-functional requirement
framework originally proposed in [43] and discussed in detail in [44]. According to the
framework, software qualities are represented as soft-goals, i.e., goals that can be partially
achieved. The leaves of the soft-goal interdependency graph represent transformations
which fulfil or contribute positively/negatively to soft-goals above them. Given a quality
constraint for a re-engineering problem, one can look up the soft-goal interdependency
graph for that quality, and examine how it relates to other soft-goals, also what are
the transformations that may affect it positively or negatively. Transformations are also
represented as soft-goals (which are fulfilled when they are included in the re-engineering
process).
To present the problem more formally, we assume that the re-engineering process
consists of a series of transformations t1, t2, ..., tn on the abstract syntax tree AST (S) [3]
of a software system S. We also assume that for each quality of interest, say Q, there is a
metric MQ which measures how well a software system (or a system fragment) fares with
respect to the quality. Therefore, a quality-driven re-engineering problem can be defined
as follows :
Given a software system S, relevant quality metrics MQ1,MQ2
, ...,MQn, a desired
software property P , and a set of constraints C1, C2, ..., Ct on the software quali-
ties Q1, Q2, ..., Qn, find a sequence of transformations tl, t2, ..., tn such that the new
re-engineered system S′ = tn(tn−1(...(t1(AST (S)...) is such that P (S ′) and the con-
straints C1(S′), C2(S
′), ..., Ct(S′) hold.
Examples of software quality properties we would like the migrant system to posses
include the issues of how maintainable the new system is, and how portable or customiz-
able it can be. To tackle the problem presented above, we need to resolve several issues.
CHAPTER 1. INTRODUCTION 6
Firstly, we need a catalogue of re-engineering transformation rules that are relevant to
particular software qualities. Secondly, we need to know how such transformation rules
would affect other software qualities. In this sense, we need quantitative data to as-
sess the impact of a particular transformation rule on a particular quality. Thirdly, we
need a software re-engineering environment that assists software engineers to apply these
transformation rules to large legacy systems.
1.2 Thesis Contributions
The contribution of this thesis to the problem of re-engineering object-oriented systems is
the design a framework that helps to improve specific qualities in a migrant system by fol-
lowing specific re-engineering steps as these are modelled in soft-goal graphs. Specifically,
the major contributions of this thesis are :
• The design and development of a collection of comprehensive soft-goal interdepen-
dency graphs as they pertain to performance and maintainability of large object-
oriented legacy systems.
• The design and compilation of a comprehensive catalogue of transformations as
these have been modelled in the soft-goal interdependency graphs and can be ap-
plied at source code level of an object-oriented legacy system to address specific
re-engineering objectives.
• The design and implementation of an object-oriented restructuring methodology
that allows for the identification of error-prone architectural design and source code
programmatic patterns that can be “repaired” according to the transformational
steps identified by the soft-goal graphs.
CHAPTER 1. INTRODUCTION 7
• The design and implementation of a prototype system that assists with the re-
engineering process that pertains to enhancements of performance and maintain-
ability of object-oriented systems.
1.3 Thesis Organization
This document is further organized as follows :
• Chapter 2 explores the background related work, with the aim of putting this thesis
in context. It covers three research fields that form the foundation of this thesis,
namely software re-engineering, software requirements, and software architecture.
• Chapter 3 proposes a quality-driven framework for software re-engineering. The
framework uses target qualities for the migrant code to define and guide the re-
engineering process. This framework devises a workbench in which re-engineering
activities do not occur in a vacuum, but can be evaluated and fine-tuned in order
to address specific quality requirements for the new target system such as, enhance-
ments in maintainability, and performance.
• Chapter 4 discusses the role of design patterns in software re-engineering and specif-
ically in the quality-driven framework. It also describes our approach to define
transformation rules based on a layered architecture while it discusses an algebra
for composing the transformation rules.
• Chapter 4 discusses the design and development of a comprehensive catalogue of
transformations that can be modelled in the soft-goal interdependency graphs and
can be applied at the source code level of an object-oriented legacy system to address
specific re-engineering objectives.
CHAPTER 1. INTRODUCTION 8
• Chapter 6 addresses the design and development of an analysis methodology that
allows for the identification of error prone architectural design and source code
programmatic patterns that can be “repaired” according to the transformational
steps identified by the soft-goal graphs.
• Chapter 7 shows the application of the proposed quality-driven object-oriented re-
engineering framework on some case studies. First, the case studies will be explained
and then the collected results are presented and discussed.
• Chapter 8 presents the conclusions and discusses future research directions in the
area of quality-driven object-oriented software re-engineering.
• Appendix A contains the list of the proposed investigative functions in this research
work. It also describe them with all details in an alphabetic order based on our
proposed software transformation framework.
• Appendix B contains the list of the proposed supporting functions in this research
work. This appendix also describe them with all details in an alphabetic order
based on our proposed software transformation framework.
• Appendix C contains the list of the proposed positioning transformations in this
research work. It also describe them with all details in an alphabetic order based
on our proposed software transformation framework.
• Appendix D contains the list of the proposed primitive design pattern transforma-
tions this research work. This appendix also describe them with all details in an
alphabetic order based on our proposed software transformation framework.
Chapter 2
Related Work
Research is the art of seeing what everyone elsehas seen, and doing what no-one else has done.
Albert Einstein
In this chapter, we present related work, with the aim of putting this thesis in con-
text. We survey the three research fields that form the foundation of this thesis, namely
software re-engineering, software requirements, and software architecture. The Software
Re-engineering section discusses approaches for representing information extracted from
the source code, defines standard terminology pertaining to software re-engineering, and
program transformations. The Software Requirements Modeling section discusses non-
functional requirements, software quality, and software metrics. The Software Architec-
ture section presents generic technologies for modeling software architecture. Finally, the
last section summarizes the material presented in this chapter.
2.1 Software Re-engineering
There is a constant need for updating and renovating business-critical software systems
for many and diverse reasons : business requirements and policies change, technological
9
CHAPTER 2. RELATED WORK 10
infrastructure is modernized, or the government regulations change [66]. Therefore, the
areas of reverse engineering and system renovation become more and more important. The
interest in such areas originates from the difficulties that one encounters when attempting
to maintain large software systems. Such software systems are often called legacy systems,
since these systems are considered mission critical and have significantly evolved over this
operational life. It is not hard to understand that it is very difficult–if not impossible–to
maintain them. Also at this point there is a challenge for software engineers since the
documentation of these systems is not current and in most cases the only documentation
that is left is the source code itself. Thus, since the vital information of the software
is solely accessible via the source code it is necessary to develop tools to facilitate the
maintenance activities [169].
2.1.1 The Re-engineering Taxonomy
The term reverse engineering finds its origins in hardware technology and denotes the
process of obtaining the specification of complex hardware systems. Now the meaning of
this notion has shifted to software. In 1990, Chikofsky and Cross proposed a taxonomy
for Reverse Engineering and Re-engineering [42]. This taxonomy defines re-engineering
as the examination and alteration of a subject system to reconstitute it in a new form,
that is at the same or a higher level of abstraction as the original subject system, and the
subsequent implementation of the new form. The purpose of re-engineering or renovation
is to study the system, by making a specification at a higher abstraction level, adding new
functionality to this specification and develop a completely new system on the basis of the
original one by using forward engineering techniques. Re-engineering is often presented
as consisting of three steps, involving : i) Reverse Engineering, ii) Restructuring, and
iii) Forward Engineering.
CHAPTER 2. RELATED WORK 11
The taxonomy [42] defines reverse engineering as the process of analyzing a subject
system with two goals in mind : i) to identify the system’s components and their inter-
relationships, ii) to create representations of the system in another form or at a higher
level of abstraction. Reverse engineering restricts itself to investigating a system.
The taxonomy [42] defines restructuring as a transformation from one form of rep-
resentation to another at the same relative level of abstraction. An essential aspect of
restructuring is that the semantic behaviour of the original system and the new one
should remain the same; no modifications of the functionality is involved.
The taxonomy [42] defines forward engineering as the traditional process of moving
from high-level abstractions and logical, implementation-independent designs to the phys-
ical implementation of a system. Reverse engineering can be seen as the inverse process.
It can be characterized as analyzing a software system in order to, firstly, identify the
system components and their interactions, and to, secondly, make representations of the
system on a different, possible higher, level of abstraction.
2.1.2 Program Transformations
A program is a structured object annotated with semantics. The structure allows us to
transform a program. The semantics provide us the means to compare programs and
to reason about the validity of transformations. Semantics include the extensional and
intensional behaviour of a program.
Program transformation is the act of changing one program into another. The lan-
guage in which the program being transformed and the resulting program are written are
called the source and target languages, respectively. Program transformation is known
under many different names such asmeta programming [178], generative programming [56],
CHAPTER 2. RELATED WORK 12
program synthesis [130].
Program transformation is used in many areas of software engineering, including com-
piler construction, software visualization, documentation generation, and automatic soft-
ware renovation. In all these applications, we can distinguish two main scenarios : i) sce-
narios where the source and target language are different (translations), ii) scenarios
where they are the same (rephrasings). These main scenarios can be refined into a num-
ber of typical sub-scenarios based on their effect on the level of abstraction of a program
and to what extent they preserve the semantics of a program. This refinement results in
a taxonomy which is depicted in Figure 2.1 and will be elaborated in detail further.
- Refinement
- Compilation
Reverse Engineering
Translation Rephrasing
- Desugaring
- Weaving
- Decompilation
- Architecture Extraction
- Documentation Generation
- Data-Flow Analysis
- Control-Flow Analysis
- Simplification
- Inlining
- Fusion
- Obsfucation
- Specialization
- Design Improvement
- Software Visualization
Program Migration
Program Synthesis
Program Analysis
Program Normalization
Program Optimization
Program Refactoring
Software Renovation/Reengineering
Figure 2.1: A Taxonomy of Program Transformation.
Many systems for program transformation exist that are often specialized for a specific
object language and/or kind of transformation. All these systems share many concepts
about program transformation and use similar techniques, but are often ad-hoc in many
respects. The ultimate goal of research and development in the area of program transfor-
CHAPTER 2. RELATED WORK 13
mation is to achieve a specification language or family of specification languages for the
high-level, declarative specification of program transformation systems in which generic,
language independent schemas of transformation can be captured, and which admits
efficient implementation of those transformations that scale up to large programs.
Translation
In a translation scenario a program is transformed from a source language into a program
in a different target language. Translation scenarios can be distinguished by their effect
on the level of abstraction of a program. Although translations aim at preserving the
extensional semantics of a program, it is usually not possible to retain all information
across a translation. Examples of translation scenarios are program synthesis, program
migration, reverse engineering, and program analysis. Their relations are illustrated by
the diagram in Figure 2.2.
AspectLanguage Language1
High-Level High-Level Language2
Low-Level Language
Synthesis ReverseEngineering
MigrationAnalysis
Rephrasing Rephrasing Rephrasing
Rephrasing
Figure 2.2: Relation Between Kinds of Program Transformation.
• Program Migration transforms a program to another language at the same level
of abstraction. This can be a translation between dialects, for example, transforming
a Fortran77 program to an equivalent Fortran90 program or a translation from one
CHAPTER 2. RELATED WORK 14
language to another, e.g., porting a Pascal program to C.
• Program Synthesis is the derivation of a program from a specification model.
When the synthesis is done according to semantically correct transformation rules
the resulting program is a correct implementation of the specification. The pro-
gram synthesis can be further divided in three categories namely program refine-
ment [154], program compilation [3, 124], code generation. In program refinement
an implementation is derived from a high-level specification such that the imple-
mentation satisfies the specification. Compilation is a form of synthesis in which a
program in a high-level language is transformed to machine code. This translation
is usually achieved in several phases in which a high-level language is first trans-
lated into an intermediate representation. Instruction selection then translates the
intermediate representation into machine instructions. Other examples of synthesis
are parser and pretty-printer generation from context-free grammars [3, 31].
• Reverse Engineering extracts a low-level program from a high-level program
or specification, or at least some higher-level aspects [42]. Reverse engineering
raises the level of abstraction and is the dual of synthesis. Examples of reverse
engineering are decompilation in which an object program is translated into a high-
level program, architecture extraction in which the design of a program is derived,
documentation generation, and software visualization in which some aspect of a
program is depicted in an abstract way.
• Program Analysis reduces a program to one aspect such as its control flow.
Analysis can thus be considered a transformation to a sub-language.
CHAPTER 2. RELATED WORK 15
Rephrasing
Rephrasings are transformations that transform a program into a different program in
the same language, i.e., source and target language are the same. In general, rephrasings
try to say the same thing in different words thereby aiming at improving some aspect of
the program, which entails that they change the semantics of the program. The main
sub-scenarios of rephrasing are normalization, optimization, refactoring, and renovation.
This is exactly the area that this research thesis addresses.
• Program Normalization reduces a program to a program in a sub-language,
with the purpose of decreasing its syntactic complexity. Desugaring is a kind of
normalization in which some of the constructs (syntactic sugar) of a language are
eliminated by translating them into more fundamental constructs. For example,
the Haskell language definition [97] describes for many constructs how they can be
desugared to a kernel language. Simplification is a more general kind of normaliza-
tion in which a program is reduced to a normal (standard) form, without necessarily
removing simplified constructs. For example, consider canonicalization of interme-
diate representation and algebraic simplification of expressions. Note that normal
form does not necessarily correspond to being a normal form with respect to a set
of rewrite rules.
• Program Optimization [124] is a transformation that improves the run-time
and/or space performance of a program. Examples of optimization are fusion, in-
lining, constant propagation, constant folding, common-subexpression elimination,
and dead code elimination.
• Program Refactoring is a transformation that improves the design of a program
by restructuring it such that it becomes easier to understand while preserving its
CHAPTER 2. RELATED WORK 16
functionality. The first use of the term “refactoring” in the literature was in the
work of Opdyke and Johnson [132], though the practice was in use well before
this. Program refactoring [71] is an important component of the Extreme Pro-
gramming [21] software engineering methodology. Tools for carrying out specific
refactorings have been built over the years. Commercial tools for restructuring
spaghetti code in COBOL and FORTRAN have been available since the late 1970s.
There are reputed to be tools that will restructure C programs and headers to
use minimal numbers of INCLUDEs. Specific tools include : Smalltalk Refactoring
Browser [148], Clone Doctor [49], IDEA [92], Transmogrify [176], JRefactory [98],
jFactor [95], RECODER [144], InjectJ [91]. Obfuscation [52] is a transformation
that makes a program harder to understand by renaming variables, inserting dead
code, etc. Obfuscation is done to hide the business rules embedded in software by
making it harder to reverse engineer the program.
• Software Renovation/Re-engineering changes the extensional behaviour of a pro-
gram in order to repair an error or to bring it up to date with respect to changed
requirements. Examples are repairing a Y2K bug.
A program transformation system is determined by the choices it makes in pro-
gram representation, the kind of transformation it specializes for, and the programming
paradigm used for implementing transformations. The next section discusses considera-
tions in choosing a representation for programs.
2.1.3 Program Representation
The area of program representation deals with the techniques for representing source code
information at a higher level of abstraction than source code text, and in a structural
way, suitable for algorithmic manipulation with computers. Much work has already been
CHAPTER 2. RELATED WORK 17
done in the area of program presentation.
A number of issues should be considered when choosing a program representation : to
use parse trees or abstract syntax trees, trees or graphs, how to represent variables and
variable bindings, and how to exchange programs between transformation components.
Also, a program representation should be supported by an exchange format that makes it
possible to exchange programs between transformation components. Example formats are
XML, which supports exchange of tree shaped data, and the Annotated Term Format [30],
which supports exchange of directed-acyclic graphs, maintaining maximal sharing.
In the following, we present some program representation formalisms that have been
used extensively, by numerous researchers for source code analysis and software re-
engineering.
Parse Trees or Abstract Syntax Trees
Parse trees contain syntactic information such as layout (whitespace and comments), and
parentheses and extra nodes introduced by disambiguating grammar transformations.
Since this information is often irrelevant for transformation, parse trees are usually trans-
formed into abstract syntax trees that do not contain such information. However, for
some applications (such as software renovation and refactoring) it is necessary to restore
as much as possible the original layout of the program after transformation. This requires
that layout is stored in the tree and preserved throughout transformation. Especially the
latter aspect is problematic as it is not clear in a generic manner where to insert comments
in a transformed fragment of a program. Origin tracking [59] might be useful here.
For other applications (e.g., certain optimizations and compilation) it is necessary to
carry type information in the tree. This requires the extension of the tree format to store
CHAPTER 2. RELATED WORK 18
type information and to preserve consistency of types throughout transformation.
Concrete Syntax or Abstract Syntax
Related to the internal representation of programs is the representation of program frag-
ments in the specification of transformation rules. While abstract syntax provides a
good model for program transformation, the direct manipulation of abstract syntax trees
may not be appropriate. Abstract syntax trees are represented using the data structur-
ing facilities of the transformation language : records (structs) in imperative languages
(C), objects in object-oriented languages (C++, Java), algebraic data types in functional
languages (ML, Haskell), and terms in term rewriting systems.
Such representations allow the full capabilities of the transformation language to be
applied in the implementation of transformations. In particular, when working with
high-level languages that support symbolic manipulation by means of pattern matching
(e.g., ML, Haskell) it is easy to compose and decompose abstract syntax trees. For
transformation systems such as compilers, programming with abstract syntax is adequate;
only small fragments, i.e., a few constructors per pattern, are manipulated at a time.
Often, object programs are reduced to a core language that only contains the essential
constructs. The abstract syntax can then be used as an intermediate language, such that
multiple languages can be expressed in it, and transformations can be reused for several
source languages.
However, there are many applications of transformation programming in which the
use of abstract syntax is not satisfactory since the conceptual distance between the con-
crete programs that we understand and the data structure access operations used for
composition and decomposition of abstract syntax trees is too large. This is evident in
the case of record manipulation in C, where the construction and reconstruction of pat-
CHAPTER 2. RELATED WORK 19
terns of more than a couple of constructors becomes unreadable. But even in languages
that support pattern matching on algebraic data types, the construction of large code
fragments in a program generator can become painful.
Transformation languages supporting concrete object syntax [178] let the programmer
define transformations using the concrete syntax of the object language, while internally
using abstract syntax trees.
Trees or Graphs
Program structure can be represented by means of trees, directed-acyclic graphs (DAGs),
or full edged graphs with cycles.
Using pure trees is costly because copying of a tree (e.g., by using a variable twice
in constructing a new tree) requires creating a complete copy. Therefore, most systems
use DAGs. When copying a tree, only a pointer to the tree gets copied, thus subtrees
are shared by multiple contexts. The advantage of sharing is reduced memory usage.
In the ATerm library [30] this approach is taken to the extreme by only constructing
one instance for each subtree that is constructed, thus achieving maximal sharing and
minimal memory usage.
Sharing saves memory, makes copying cheap, and, in the case of maximal sharing,
testing for equality is cheap as well. However, the downside of sharing is that performing
a transformation of a tree requires rebuilding the context in which the transformed tree
is used. It would be more attractive to overwrite the root node of the sub-tree that is
changed with the new tree, thus updating all contexts in which the old tree was used.
However, this is not valid in general. Two occurrences of a shared tree that are syntacti-
cally the same can have a completely different meaning depending on their context. Even
CHAPTER 2. RELATED WORK 20
if they have the same meaning, it is not always desirable to change both occurrences.
The same problem of occurrence arises when associating information with nodes.
When sharing is based on syntactic equivalence alone, annotations become associated
with all occurrences of the tree. Consider the examples of position information in parse
trees and type annotations in abstract syntax trees to conclude that this is usually not
desirable. On the other hand, if annotation of a tree node results in a new tree, then
equivalence becomes equivalence with annotations, and equivalence modulo annotations
is no longer a constant operation.
Finally, full edged graphs can be useful to represent back-links in the tree to represent,
for example, loops in a control flow graph [9, 124], or links to declarations [56]. Updateable
graphs make it easy to attach new information to nodes, for example results of analysis.
The problem of destructive update versus copying while doing transformation is even
more problematic in graphs. Since a subgraph can have links to the entire graph, it may
be required to reconstruct the entire graph after a transformation if it is necessary to keep
the original graph as well. For very specific purposes such as lazy evaluation of functional
programs, it is possible to make such graph updates transparent.
Variable Bindings
A particular problem of program transformation is the handling of variables and variable
bindings. In the common approach variables and variable bindings in an abstract syntax
tree are treated just like any other construct and the transformation system has no special
knowledge of them. This requires the implementation of operations to rename bound
variables, substitution, etc. Transformations need to be aware of variables by means of
extra conditions to avoid problems such as free variable capture during substitution and
lifting variable occurrences out of bindings.
CHAPTER 2. RELATED WORK 21
Transparent handling of variable bindings is desirable. Higher order abstract syntax
(HOAS) [90] gives a solution to such problems by encoding variable bindings as lambda
abstractions. In addition to dealing with the problem of variable capture, HOAS provides
higher order matching which synthesizes new functions for higher order variables. One of
the problems of higher order matching is that there can be many matches for a pattern,
requiring a mechanism for choosing between them. FreshML [138] provides a weaker
mechanism for dealing with variable bindings that transparently refreshes variable names,
thus solving the capture problem. Substitution for variables has to be dealt with explicitly.
Both HOAS and FreshML require some amount of encoding for the syntactic structure to
fit the lambda abstraction binding scheme. This can become rather far removed from the
structure described by the grammar for more complex binding schemes. Furthermore,
implicit variable binding may be in conflict with the ease of performing transformations,
for instance, the possibility of performing traversals over syntax trees. All approaches
that rename variables are in conflict with requirements that original names are preserved,
which is required in applications such as refactoring and renovation.
A problem that is not addressed by the approaches discussed above is associating
declaration information, e.g., type declarations, with usage. This usually requires main-
taining a symbol table during transformation, or distributing the information over the
tree, annotating usage occurrences of a symbol with the information in the declarations.
Either way, the information needs to be kept consistent during transformations.
2.2 Software Requirements Modeling
Software quality has been recognized to be an important topic since the early days of
software engineering [75, 158]. When we are discussing software systems, we often hear
the term “non-functional properties” in contrast with the “functional properties” which
CHAPTER 2. RELATED WORK 22
are only assumed implicitly. A functional property deals with a particular aspect of a
system’s functionality, and is usually related to a specified functional requirement [37].
A functional property may either be made directly visible to users of an application by
means of a particular function, or it may represent aspects of its implementation, such as
the algorithm used to compute the function. While developers in the past concentrated
on providing the stated functional properties for software, today non-functional proper-
ties are becoming increasingly important. A non-functional property denotes a feature of
a system that is not covered by its functional description [37]. A non-functional prop-
erty typically addresses aspects related to the reliability, compatibility, cost, ease of use,
maintenance or development of a software system, and so on.
Over the last 30 years, a number of researchers and practitioners alike have exam-
ined how systems achieve software quality attributes. Boehm in [26] classified a number
of software attributes such as flexibility, integrity, performance, maintainability, and so
on. These quality attributes are hard to deal with, because they are often ill defined,
subjective, and system specific. International Organization for Standardization (ISO)
introduced taxonomies of quality attributes [93] which divides quality into six charac-
teristics : functionality, reliability, usability, efficiency, maintainability and portability.
For example, the ISO9126 standard recommends measuring the characteristics directly,
but does not indicate clearly how to accomplish this task. Rather, it suggests that if the
characteristic cannot be measured directly (particularly during development), some other
related attribute should be measured as a surrogate to predict the required characteristic.
The recent interest on software architecture and design patterns have refocused at-
tention on how these software qualities can be achieved [17, 27, 74, 99, 136]. With the
shift to the new, short-cycled, component-oriented software environment, priorities among
many quality objectives have changed, and new objectives such as reusability and stan-
CHAPTER 2. RELATED WORK 23
dards compliance are becoming more prominent. While performance will continue to be
important, it must now be traded-off against many kinds of flexibility.
Bass and Bergey have analyzed the relationship between software architecture and
quality attributes [17, 24]. The Software Engineering Institute’s (SEI’s) work in Attribute-
Based Architecture Style (ABAS) [105, 14] was the first attempt to document the relation-
ship between architecture and quality attributes. By codifying mechanisms, architects
can identify the choices necessary to achieve quality attribute goals. This, in turn, will
set a foundation for further software architectural design and analysis. In fact, this work
was motivated by the need for such foundations for the Architecture Tradeoff Analysis
Method (ATAM) [100] and the Attribute-Driven Design (ADD) method [11].
2.2.1 Non-Functional Requirements
Complementary to the product-oriented approaches, the NFR (Non-Functional Require-
ments) Framework [125, 43, 44] takes a process-oriented approach to dealing with quality
requirements. In the framework, quality requirements are treated as potentially conflict-
ing or synergistic goals to be achieved, and are used to guide and rationalize the various
design decisions taken during system/software development. Because quality require-
ments are soft subjective by nature, they are often achieved not in an absolute sense, but
a sufficient or satisfactory extent. Accordingly, the NFR Framework introduces the con-
cept of soft-goals whose achievement judged by the sufficiency of contributions from other
(sub-) soft-goals. A soft-goal interdependency graph is used to support the systematic,
goal oriented process of architectural design.
According to the framework, software qualities are represented as soft-goals, i.e., goals
with no clearcut criterion as to whether they have been fulfilled or not. Soft-goals can be
related to other soft-goals in terms of relations such as AND, OR, +, ++, or −, −− [43].
CHAPTER 2. RELATED WORK 24
The meaning of these relations has as follows :
• AND(G,G1, G2, ..., Gn) – soft-goal G is fulfilled when all of G1, G2, ..., Gn are ful-
filled and there is no negative evidence against it.
• OR(G,G1, G2, ..., Gn) – soft-goal G is fulfilled when one of G1, G2, ..., Gn is fulfilled
and there is no negative evidence against it.
• +(G1, G2) – soft-goal G1 contributes positively to the fulfilment of soft-goal G2.
• −(G1, G2) – soft-goal G1 contributes negatively to the fulfilment of soft-goal G2.
For example, suppose a system developer has to design and produce source code
that complies with an initial set of quality requirements, such as “the system should be
modifiable” and “the system should have good performance”. In this process-oriented
approach, the developer explicitly represents each of these as a soft-goal to be achieved
during the development process. Each soft-goal (e.g., Modifiability [system]) is associated
with a type (Modifiability) and a topic (System), along with other information such as
importance, satisfying status and time of creation. Figure 2.3 shows the two soft-goals
as the top level nodes.
Modifiability[System]
Performance[System]
Modifiability[Algorithm]
Modifiability[Data Representation]
Space Performance[System]
Time Performance[System]
[Function]Modifiability
Figure 2.3: A Soft-Goal Interdependency Graph.
CHAPTER 2. RELATED WORK 25
As these high level requirements may mean different things to different people, the
developer needs to first clarify their meanings. This is done through an iterative pro-
cess of soft-goal refinement which may involve domain experts. After consultation, the
developer may refine Modifiability [System] into three offspring soft-goals : Modifiabil-
ity [Algorithm], Modifiability [Data Representation], and Modifiability [Function]. This
refinement is based on topic, since it is the topic (System) that gets refined, while the
soft-goal type (Modifiability) is unchanged. This step may be justified by referring to the
work by Garlan and Shaw [74] who consider changes in processing algorithm and changes
in data representation, and to Garlan and Kaiser [73] who extend the consideration with
enhancement to system function. Similarly, the developer refines Performance [System],
this time based on its type, into Space Performance [System] and Time Performance [Sys-
tem] referring to work in [129].
Figure 2.3 illustrates the two refinements where a small “arc” between edges denotes
an “AND” contribution, meaning that in order to satisfy the parent soft-goal, all of its
offsprings need to be satisfied. There are also other contribution types, including “OR”
and partial positive (+) or negative (−) contributions. Contribution types are important
for deciding the success status of a soft-goal according to recorded contributions towards
it. Let us assume that the developer is interested in a design which can contribute
positively to the soft-goal Modifiability [Data Representation], and considers the use of
an “Abstract Data Type” style as discussed by Parnas [134] and Garlan [74]. It means
that the components communicate with each other by means of explicit invocation of
procedures as defined by component interfaces. As the developer would learn sooner or
later, the positive contribution of the “Abstract Data Type” towards modifiable data
representation is made at the expense of another soft-goal, namely the time performance
soft-goal. Figure 2.4 shows the positive contribution made by the abstract data type
CHAPTER 2. RELATED WORK 26
solution by means of “+” and the negative contribution by “-” contribution link.
Modifiability[System]
Performance[System]
Time Performance[System]
Modifiability[Algorithm]
[Data Representation]
Modifiability
Space Performance[System]
Modifiability[Function]
--+
+ -
Shared Data Abstract Data Type
Figure 2.4: Contributions of the Shared Data and Abstract Data Type in Soft-GoalGraph.
The developer would also want to consider other alternatives in order to better satisfy
the stated soft-goals. The developer may discover that a “Shared Data” style typically
would not degrade system response time, at least when compared to the Abstract Data
Type, and more importantly perhaps it is quite favourable with respect to space require-
ments. This discovery draws on work by Parnas [134] and by Garlan [74] where the basic
components (modules) communicate with each other by means of shared storage. Not
unlike the Abstract Data Type, the Shared Data architecture also has negative influ-
ence on several other soft-goals : a negative (-) impact on modifiability of the underlying
algorithm (process) and a very negative (- -) impact on modifiability of data represen-
tation. Figure 2.4 shows both non-functional requirements steps along with the various
contributions that each alternative makes towards the refined soft-goals.
The NFR framework is one significant step in making the relationships between quality
requirements and intended decisions explicit. The framework uses non-functional require-
CHAPTER 2. RELATED WORK 27
ments to drive design to support architectural design level and to deal with the changes.
To represent information about different software qualities, their interdependencies, and
the software transformations that may affect them, we adopt the NFR framework.
2.2.2 Software Quality Metrics
One of the major goals in software engineering is to control the software development
process, thereby controlling costs and schedules, as well as the quality of the software
products. As a direct result of software engineering research, software metrics have been
brought to attention of many software engineers and researchers. As De Marco indicates,
“you cannot control what you cannot measure” [58]. Software metrics measure certain
properties of a software project by mapping them to numbers (or other symbols) according
to well-defined measurement rules. The measurement results are then used to describe,
assess or predict characteristics of the software project with respect to the property
that has been measured. Usually, measurements are made to provide a foundation of
information upon which decisions about software engineering tasks can be both planned
and performed better [137].
The software metrics for the procedural paradigm have concentrated on measures of
complexity and have used different aspects of the software source code. Some count cer-
tain lexical tokens [12, 81], or are based on its control graph [116, 117]. Another set of
metrics measures the inter-connection among statements or functions [2, 85]. Since the
object-oriented paradigm exhibits different characteristics from the procedural paradigm,
software specific metrics have been developed for it [113, 182]. The object-oriented soft-
ware metrics need to consider the basic concepts of the object-oriented model as : object,
class, attributes, inheritance, method and message passing [1]. So far, a number of object-
oriented metrics have been proposed, and few studies to validate them were made [33].
However, further work in this direction needed to be done.
CHAPTER 2. RELATED WORK 28
Software metrics also play an important role when re-engineering (object-oriented)
legacy systems. Software metrics support numerous re-engineering tasks, because they
help to focus re-engineering efforts. They aid in forming an initial understanding of
the legacy system and can often uncover information about system design flaws. The
following sections provide an overview of some important object-oriented software metrics
and explains some basic properties that can be measured by them. This provides the
background needed to present how metrics can be used during re-engineering. We believe
that discussing how metrics are applied in these usage scenarios will illustrate how to
use metrics in the re-engineering process. In the following subsections, we present the
most important object-oriented metrics defined in software metrics literature. These
metrics fall into several categories depending on the aspects of a system they measure.
The metrics presented in this section are classified in four different sections : complexity
metrics, metrics measuring the class hierarchy layout, metrics that measure the coupling
between classes, and finally a set of metrics that measure the cohesion of a class [172].
For each analyzed metric the definition of the metric is provided together with its main
characteristics. For most of the metrics the criticism found in the literature are also
discussed.
Complexity Metrics
By complexity metrics, we consider those metrics that may give us indications about the
level of complexity for a given class. Analyzing the several viewpoints suggested for each
metric, it becomes clear that we generally expect from these metrics to be predictors of
the maintenance effort for a class. They may also be an indicator of the central classes in a
project. We may also say that the place of the complexity metrics in the object oriented
design (OOD) process [29] may be the phase of identifying the semantics of classes,
and some of the metrics may be used also in the class identification phase. Obviously,
CHAPTER 2. RELATED WORK 29
complexity metrics play an important role when re-engineering software systems as classes
with high complexity measurements are difficult to understand and consequently difficult
to change.
• Weighted Method Count (WMC). Consider a class C1, with methods M1, M2,
..., Mn that are defined in the class. Let c1, ..., cn be the complexity of the methods
of that class. Then:
WMC =n∑
i=1
ci
Concerning the way this metric defined, there are two issues that should be consid-
ered. The first observation that should be made is that the notion of complexity is
deliberately not defined more specifically in order to raise the generality degree of
the WMC metric. The way complexity is specifically defined for an implementation
of this metric is a decision that can taken in different ways. One possible direction
is the use of some traditional static complexity metrics, like the McCabe’s Cyclo-
matic Complexity Metric [173]. This was suggested by Li and Henry in [109]. The
second observation is that if we consider each metric having a unitary complexity,
then WMC = n, the number of methods in that class. That means that if we
consider all the methods of the class having equal complexity, this metric indicates
the number of methods of the class. From another perspective, this metric can be
seen as a generalization of the Number of Methods metric.
Chidamber and Kemerer in [41] also give a set of three viewpoints that should
be used in interpreting the results of this metric : i) the number of methods and
the complexity of methods involved is a predictor of how much time and effort is
required to develop and maintain the class, ii) the larger the number of methods in a
class the greater the potential impact on the children, since the children will inherit
all the methods defined in the class, iii) classes with large numbers of methods are
CHAPTER 2. RELATED WORK 30
likely to be more application specific, limiting the possibility of reuse.
The WMC metric is widely accepted in the literature. Yet, it has been indirectly
criticized by Churcher and Shepperd in [45]. The criticism was referring to the
computation of the number of methods in a class. The number of methods is
required directly for the computation of WMC, as we already pointed above. The
main thesis of Churcher and Shepperd is that the computation of the number of
methods in a class is open to a variety of interpretations. For example they suggest
that overloaded constructors, that share of course the same name identifier should
not be counted distinctly. Another suggestion the two authors make is that the
inherited methods should also be counted. Chidamber and Kemerer replied to
these criticism in [41] by referencing the principle of counting the methods in a
class : “the methods that required additional design effort and that are defined in
the class should be counted, and those that do not should not”.
• Response For a Class (RFC). It is a set of methods that can be potentially
executed in response to a message received by an object of that class (RS). Mathe-
matically, it can be defined using elements of set theory as :
RS = {M} ∪i {Ri}
where {Ri} is the set of methods called by method i and {M} is the set of all
methods in the class. The Response for a Class (RFC) is the cardinality of the
response set for that class. Mathematically, the RFC metric can be expressed as :
RFC = |RS|
The response for a class (RFC) metric measures two different aspects : i) on the one
CHAPTER 2. RELATED WORK 31
hand it measures the attributes of the objects in the class, ii) on the other hand it
expresses the potential communication between the class that is measured and the
other classes, as it includes method called from the outside the class.
Chidamber and Kemerer [41] also suggests a set of three viewpoints that should
guide the interpreting and use of the results of this metric : i) if a large number of
methods can be invoked in response to a message the testing and debugging of the
class becomes more complicated since it requires a greater level of understanding
required on the part of the tester, ii) the large number of methods that can be
invoked from a class, the greater the complexity of that class, iii) a worst case value
for possible responses will assist in appropriate allocation of testing times. We have
to observe that the three viewpoints are not independent, but logically derived. The
first and the third viewpoints are conceptually derived form the second viewpoint.
In the same time the first and the third viewpoint are very similar. This affirmation
is based on the fact that high complexity logically implies complicated and therefore
time-expensive, testing and debugging phases.
Referring to the RFC metric, Hitz and Montazeri in [88] give another definition of
the metric : “RFC is the union of the protocol a class offers to its clients and the
protocols it requests from other classes”. Their criticism towards this metric refers
to the fact that by measuring the total communication potential, this measure is
not only a measure of the complexity of the class but it is obviously related to
coupling and by this it is not independent of the CBO metric, also defined in [41].
• SIZE1 and SIZE2. These two size metrics were defined by Li and Henry in [109].
Size has been used as a software measure for a long time. The Lines of Code (LOC)
metric is used to measure a procedure or a function. The SIZE1 metric is in fact the
traditional LOC metric which is calculated by counting the number of semicolons
CHAPTER 2. RELATED WORK 32
in a class. Thus :
SIZE1 = number of semicolons in a class
The second size metric defined in the mentioned paper is the number of properties,
including the attributes and methods defined in a class. This metric is referred as
SIZE2 and is calculated as follows :
SIZE2 = number of attributes + number of local methods
The critic of SIZE1 is that it is a metric defined for the traditional approach and,
as the author himself underlined the size factor in an object oriented program has
not been well established.
• Class Definition Entropy (CDE). This metric identifies complex classes in an
object-oriented system [13]. Classes with higher values of CDE can be expected
to have a complex implementation and a more than average number of errors and
changes. CDE computes a decimal number to indicate a class definition complexity
based on the usage and frequency of different name strings in a class declaration.
Consider n1 is the number of unique name strings used in the class definition, N1
is the total number (non-unique) of name strings used in the class definition, fi for
1 ≤ i ≤ n1 is the frequency of occurrence of the ith name string used in the class.
Then :
CDE = −n1∑
i=1
(fi/N1)log(fi/N1)
CHAPTER 2. RELATED WORK 33
Inheritance Metrics
This category of metrics attempts to provide indications on the quality of the class hi-
erarchy layout of a project. The quality of the class hierarchy plays a major role in the
design of an object oriented system. It is clear that this kind of metrics could be very
important indicators in the early phases of the design.
• Depth of Inheritance Tree (DIT). It represents the length of the tree from that
class to the root class of the inheritance tree. In cases involving multiple inheritance,
the DIT value will be maximum length from that node class to the root class of the
tree. An observation should be made, concerning this definition : as some object
oriented languages, e.g. C++, permit the use of multiple inheritance the classes
can be organized into a directed acyclic graph instead of trees. For this metric
the two authors also suggest three viewpoints that should guide its interpretation
and usage of the results : i) the deeper the class in the hierarchy, the greater the
number of methods it is likely to inherit, making it more complex to predict its
behaviour, ii) deeper trees constitute greater design complexity for that class, since
more methods and classes are involved, iii) the deeper the class is in the hierarchy,
the greater the potential reuse of inherited methods.
Concerning the viewpoints defined before, especially the first two, one theoretical
assumption that can be made is that well designed OO systems are those structured
as forests of classes, rather than as one very large inheritance tree, as suggested
in [16]. It means that a class located deeper in a class inheritance lattice is supposed
to be more fault-prone because the class inherits a large number of definitions from
its ancestors.
For this metric, no criticism were found in the researched literature. Instead, Li and
Henry [109] analyzed this metric together with NOC, that will be presented below,
CHAPTER 2. RELATED WORK 34
from the perspective of coupling. Their viewpoint is that inheritance is a mechanism
by which coupling is realized. They call it coupling through inheritance [109].
• Number of Children (NOC). It represents the number of immediate subclasses
subordinated to a class in the class hierarchy. The greater the number of children,
the greater the reuse, since inheritance is a form of reuse. The greater the number
of children, the greater the likelihood of improper abstraction of the parent class.
If a class has a large number of children, it may be a case of misuse of subclassing.
The number of children gives an idea of the potential influence a class has on the
design. If a class has a large number of children, it may require more testing of the
methods in that class. An immediate conclusion is that the classes with a greater
number of children have to provide more services in different contexts, and thus
they should be more flexible. An assumption that can be made is that such classes
will introduce more complexity in the design.
For this metric, no criticism were found in the researched literature. Instead, Li and
Henry [109] analyzed this metric together with DIT, that was already presented,
from the perspective of coupling.
Coupling Metrics
The relationships between classes represent a major aspect of the object-oriented design.
Analyzing the viewpoints suggested for the different coupling metrics, we can remark that
the reuse degree and the maintenance effort for a class are decisively influenced by the
coupling level between classes. It means that this kind of metric should help designers to
design the classes and especially the relations between them, so that the coupling level
might be as low as possible.
CHAPTER 2. RELATED WORK 35
• Coupling Between Objects (CBO). It is a count of other classes to which
one class is coupled. Excessive coupling between object classes is detrimental to
modular design and prevents reuse. The more independent a class is, the easier it
is to reuse it in another application. In order to improve modularity and promote
encapsulation, inter-object class couples should be kept to a minimum. The larger
the measure of coupling, the higher the sensitivity to changes in other parts of the
design and therefore maintenance is more difficult. A measure of coupling is useful
to determine how complex the testing of various parts of a design is likely to be.
The higher the inter-object class coupling, the more rigorous the testing needs to
be.
Although the definition of coupling proposed by Chidamber and Kemerer in [41]
was widely accepted and appreciated in the literature some deficiencies have been
identified. In [86], the authors make a survey of the previously defined metrics that
should reflect the coupling between classes. Their analysis starts exactly from this
definition of coupling given by Chidamber and Kemerer [41]. The first critic is that
it does not differentiate between the strength of couples, assuming that all couples
are of equal strength. They differentiate and make a hierarchy of coupling strength.
The worst coupling that has been identified is the direct access of foreign instance
variables. Also the coupling realized by sending messages to a component of one
of the object’s components is considered stronger (worse) than sending messages to
the object itself. Access to instance variables of foreign classes constitutes stronger
coupling than access to instance variables of superclasses. Another differentiation
can be made between passing a message with a wide parameter interface which yields
a stronger coupling compared with a message with a slim interface. The second critic
found in [88] concerns the fact that it is not clear whether messages sent to a part of
CHAPTER 2. RELATED WORK 36
self, i.e., to a instance variable of class type, contribute to CBO or not. Using strictly
the definition given by Chidamber and Kemerer this kind of class coupling should
not be considered. This aspect is also analyzed by Li and Henry in [109]. They
also propose a metric that measures exactly this type of coupling (DAC). The third
deficiency of the CBO metric is that it neglects inheritance related connections, that
means they exclude from their measure the couples realized by immediate access to
instance variables inherited from superclasses, a kind of coupling considered to be
among the worst types of coupling.
• Data Abstraction Coupling (DAC). Li and Henry propose also a set of metrics
on coupling [109]. The metrics correspond to the two from the three forms of ob-
ject coupling that they have identified : coupling through data abstraction, coupling
through message passing and coupling through inheritance. The metric which mea-
sures the coupling complexity caused by ADT’s is called Data Abstraction Coupling
(DAC) and is defined as :
DAC = number of ADT ′s defined in a class
A class can be viewed as an implementation of an abstract data type (ADT). A
variable declared within a class X may have a type of ADT which is another class
definition, causing a particular type of coupling between the X and the other class,
since X can access the properties of the ADT class. This type of coupling may cause
a violation of encapsulation if the programming language permits direct access to
the private properties in the ADT.
The number of variables having an ADT type may indicate the number of the data
structures dependent upon the definitions of other classes. The more ADT’s a class
CHAPTER 2. RELATED WORK 37
has, the more complex is the coupling of that class with other classes.
For this metric, no criticism were found in the literature. Instead it is positively
cited and accepted in the software metrics literature.
• Message Passing Coupling (MPC). One of the communication channels the
object oriented paradigm allows is message passing. When an object needs some
service that another object provides, messages are sent from the object to the other
objects. A message is usually composed of the object-ID, the service (method)
requested, and the parameter list for that method. Although messages are passed
among objects, the types of messages passed are defined in classes. Therefore,
message passing is calculated at the class level instead of the object level. Message
Passing Coupling (MPC) is used to measure the complexity of message passing
among classes. Since the pattern of the message is defined by a class and used by
objects of the class, the MPC metric is also given as an indication of how many
messages are passed among objects of the classes :
MPC = number of send statements defined in a class
The number of messages sent out from a class may indicate how dependent the
implementation of the local methods are upon the methods in other classes. This
metric may not be indicative of the number of messages received by the class. It
means that in defining this metric as a coupling measure the authors did not take
into account the dependencies of other classes to the class being analyzed.
• Number of Local Methods (NOM). Since the local methods in a class constitute
the interface increment of the class, NOM serves well as an interface metric. NOM
CHAPTER 2. RELATED WORK 38
is easy to collect in most object-oriented programming languages.
NOM = number of local methods in a class
The number of methods in a class may indicate the operation property of a class.
The more methods a class has, the more complex the class interface has incremented.
This metric is just an interface metric. By itself it does not bring very much. In
order to be used, it has to be combined with the previously presented metric, that
is MPC.
• Change Dependency Between Classes (CDBC). In [88], the authors propose
two metrics for measuring of coupling. The first one is called Change Dependency
Between Classes (CDBC). In order to give the definition of this metric we need to
define some concepts used by the authors in this definition. By state of a class,
we refer to class definition and the program code of its methods, i.e., a version of
the class implementation. The Class Level Coupling (CLC) represents the coupling
resulting from state dependencies between classes during the development life cycle.
The metric refers to the case of class level coupling CLC in the context of unstable
server classes. In the sequel, CC will signify the dependent client class and SC
the server class being changed. In order to define the CDBC attribute, we have to
investigate the possible relationship types. This can be synthesized into Table 2.1.
The maturity of the SC also plays an important role in the definition of the CDBC
attribute as the value is only relevant for those parts of SC that are subject to
change. If SC represents a mature abstraction, its interface is assumed to be more
stable than its implementation. Therefore a factor k was introduced (0 ≤ k ≤ 1)
corresponding to the stability of SC’s interface. Using the notions already intro-
CHAPTER 2. RELATED WORK 39
α = Number of methodsDescription of CC potentially affected
by a change
SC is not used by CC at all 0
SC is the class of an instance variable of CC n
Local variables of type SC are used jwithin j methods of CC
SC is a superclass of CC n
SC is the parameter type of j methods of CC j
CC accesses a global variable of class SC n
Table 2.1: Relationship Types Between CC and SC and Their corresponding Contributionα to Change Dependency.
duced, the degree of CDBC can be expressed mathematically as follows :
A =m1∑
implement=1
αi + (1− k)m2∑
interface=1
αi
where the first sum in the relation represents the sum of values corresponding to
the m1 accesses of CC to the implementation of the SC class. The second sum in
the relation represents the sum of a value corresponding to the m2 accesses of CC
to the interface of the SC. Because the SC class has a stability degree of k this term
of the expression is multiplied with (1−k) representing the instability degree of the
SC class. Knowing A, CDBC value is defined as :
CDBC(CC, SC) = min(n,A)
The Change Dependency Between Classes metric (CDBC) determines the potential
amount of follow-up work to be done in a client class CC when the server class SC
is being modified in the course of some maintenance activity. The CDBC metric
was not very much discussed in the literature. In fact this is already a deficiency
CHAPTER 2. RELATED WORK 40
of the metric. Although it has some interesting aspects it was not validated until
now by the specialists. Another deficiency of this metric is the calculation of the
stability degree k of the class. This factor is a very important, but there are no
concrete indications given by the authors of this metric on how to compute it. Thus
it must be determined empirically. Following this conclusion, we can affirm that
the stability degree k of a class has to be provided by the designer of the class. This
is a big disadvantage in a re-engineering process as in most of the cases those who
re-design the system do not know very well the design details and history of that
system.
• Locality of Data (LD). This metric represents an attribute directly connected
with the quality of the abstraction embodied in the class. The Locality of Data
(LD) metric is defined by relating the amount of data local to the class to the total
amount of data used by the that class [88]. The LD value for a class C can be
mathematically expressed by the relation :
LD =
∑ni=1 |Li|
∑ni=1 |Ti|
with Mi(l ≤ i ≤ n) methods of class C, but excluding all trivial read/write methods
for instance variables; Ti(l ≤ i ≤ n) the set of all variables used in Mi, except for
non-static local variables defined in Mi; Li(l ≤ i ≤ n) the set of class-local vari-
ables accessed in Mi, directly or via read/write methods. The authors include the
following variables in the category of class-local ones : non-public instance variables
of class C, inherited protected instance variables of its superclasses, static variables
defined locally in Mi. We have to make this observation : for the sake of robustness
of the measure all the non-static local variables defined in Mi are not counted, as
they don’t play a major role in the design.
CHAPTER 2. RELATED WORK 41
The Locality of Data metric (LD) influences the class reuse potential. Classes with
high data locality are more self-sufficient than those with low data locality. This
metric also influences another external attribute : the testability of the class. The
higher the LD value the easier it is to test the class. We should note that the
main point of this metric is the notion of self-sufficiency. A class with a high self-
sufficiency, means that the class uses very few data that are not “local” to it. In
fact the “non-local” data that can be accessed by the methods of a class are : global
variables and public instance variables of the class, or of the superclasses. The
LD metric was not very much discussed in the literature. In fact this is already a
weakness of the metric. Like the CDBC metrics, although it has some interesting
aspects it was not validated until now by the specialists.
Cohesion Metrics
Another important aspect in the object-oriented design is the level of cohesion for each
class. The role of this category of metrics is to detect the classes with a low cohesion
level, as these classes represent possible flaws in the design. These classes might be the
subject of a redesign process, in most of the cases by splitting. It is mostly desirable to
have classes with a high level of cohesion.
• Lack of Cohesion in Methods (LCOM). Consider a class C1 with n methods
M1, M2, ..., Mn. Let {Li} represent the set of instance variables used by method
Mi. There are n such sets {I1}, ..., {In}.
Let P = {(Ii, Ij) | Ii ∩ Ij = ∅}
and Q = {(Ii, Ij) | Ii ∩ Ij 6= ∅}
CHAPTER 2. RELATED WORK 42
If all n sets {I1}, ..., {In} are ∅ let P = ∅. Then :
LCOM = |P | − |Q|, if |P | > |Q|
= 0, otherwise
In other words the LCOM value represents the difference between the number of
pairs of methods in class C that uses common instance variables and the number
of pairs of methods that do not use any common variables.
Cohesiveness of methods within a class is desirable, as it promotes encapsulation.
Lack of cohesion implies classes should probably be split into two or more subclasses.
Any measure of disparateness of methods helps to identify flaws in the design. Low
cohesion increases complexity, thereby increasing the likelihood of errors during the
development process.
This metric has been criticized by Hitz and Montazeri in [87]. The two authors
demonstrate that Chidamber and Kemerer’s definition for LCOM does not obtain
coherent results for similar cases and exhibits some anomalies regarding the intu-
itive understanding of the attribute of cohesiveness. Although they agree with the
definition of LCOM presented in [109], they propose a graph theoretic formulation,
which they hope to be more precise. Their new definition leads to an improved ver-
sion of LCOM which helps to differentiate among the ties in cases of LCOM = 1.
We will present this metric later in this section. Another critic to this metric comes
from Bieman and Kang in [25]. According to them, LCOM is effective at identi-
fying the most non-cohesive classes, but it is not effective at distinguish between
partially cohesive classes. LCOM indicates lack of cohesion only when, compared
pairwise, fewer than half of the paired methods use the same instance variables. In
CHAPTER 2. RELATED WORK 43
this paper, the authors present two cohesion measures that are sensitive to small
changes in order to evaluate the relationship between cohesion and reuse. We will
present the two alternative metrics proposed by Bieman and Kang later.
As already mentioned, Hitz and Montazeri propose an improvement of the LCOM
metric [86]. Let X denote a class, Ix the set of instance variables for class X, and
Mx the set of methods. We will also consider a simple, undirected graph Gx(V,E)
with V = Mx and
E = {(m,n) ∈ V × V | ∃i ∈ Ix : (m accesses i) ∧ (n accesses i)}
that signifies exactly those vertices are connected that in the graph that have at
least one common instance variable. We can now define LCOM(X) as the number of
connected components of Gx, that is the number of “clusters” operating on disjoint
sets of instance variables.
One of the criticism on LCOM mentioned in [86] was the lack of differentiation
between the classes with LCOM = 1. Among these classes there are still more and
less cohesive classes possible. Especially for big classes, it might be desirable to
refine the measure to tell the structural difference between the members of the set
of classes with LCOM = 1. The two extreme cases are this :
– Sequential Cohesion. This case is described in Figure 2.5. In this case each
method has a set of common instance variable with two other methods. This
case corresponds to a minimum cohesive class design with LCOM = 1. The
cardinality of E for this case is :
|E| = n− 1
CHAPTER 2. RELATED WORK 44
Figure 2.5: Sequential Cohesion.
– Maximal Cohesion. This case is described in Figure 2.6. In this case all n
methods access the same set of instance variables. This case is mapped to the
complete graph with the cardinality of E taking the value :
|E| = n(n− 1)
2
Thus we can break many of the ties in the set of classes yielding LCOM = 1.
The more edges in the graph Gx, the higher the cohesion of the class. For
convenience we map |E| into the interval [0, 1] :
C = 2|E| − (n− 1)
(n− 1)(n− 2)
Figure 2.6: Maximal Cohesion.
For classes with more than two methods, C can be used to discriminate among those
cases with LCOM = 1 as C gives us a measure of the deviation of a given graph from
CHAPTER 2. RELATED WORK 45
the minimal cohesive case. Consider a set of methods {Mi} (i = 1, ...,m) accessing
a set of attributes {Aj} (j = 1, ..., a). Let µ(Aj) be the number of methods which
reference attribute {Aj}. Then :
LCOM =
1a
((
∑aj=1 µ(Aj)
)
−m)
(1−m)
• Tight Class Cohesion (TCC). Bieman and Kang propose in [25] a set of two
metrics on cohesion, that should eliminate the weaknesses that they observed on
LCOM. In order to understand the definition of the Tight Class Cohesion (TCC)
metric we have to list some of the concepts the authors use in this article. Class co-
hesion is defined in terms of relative number of connected methods in the class. The
authors identify two mechanisms by which individual methods are tied together :
i) the MIV relations that involves communication between methods through shared
instance variables, ii) call relations that involve the sending of messages directly
(or indirectly) from one method to another. A client class can access only visible
components of the class. In this model, invisible components of a class are included
only indirectly through the visible ones. Therefore, class cohesion is modeled as the
MIV relations among all visible methods (not including constructor or destructor
functions) in the class.
There are three options to evaluate cohesion of a subclass : i) include all inherited
components in the subclass, ii) include only methods and instance variables defined
in the subclass, iii) include only inherited instance variables.
A method is represented as a set of instance variables directly or indirectly used
by the method. The representation of a method is called abstract method AM.
DU(M) is the set of instance variables directly used by a method M. IU(M) is the
CHAPTER 2. RELATED WORK 46
set of instance variables indirectly used by a method M.
A class can be represented as a collection of abstract methods(AM) where each
AM corresponds to a visible method in the class. The abstract method set for a
method M is the reunion of the set of instance variables directly used by M and
the set of instance variables indirectly used by M . Based on the notations we made
above, the set of abstract methods for method M can be formally defined using set
operators as :
AM(M) = DU(M) ∪ IU(M)
The representation of a class using abstract methods is called an abstracted class(AC).
An abstracted class corresponding to a class C can be formally expressed as :
AC(C) = ‖AM(M) | M ∈ V (C)‖
where V (C) is the set of all visible methods in a class C and in the ancestors of
C. The AM ’s of different methods can be identical thus there can be duplicated
elements in AC. Therefore, AC is a multi-set (denoted by ‖ and ‖). A local
abstracted class (LAC) is a collection of AM ’s where each AM corresponds to a
visible method defined only within the class :
LAC(C) = ‖AM(M) | M ∈ LV (C)‖
where LV (C) are the visible methods defined only within the class C. The authors
define two measures of class cohesion based on the direct and indirect connections
of method pairs. Let NP (C) to be the total number of pairs of abstract methods
in AC(C). NP is the maximum possible number of direct or indirect connections
CHAPTER 2. RELATED WORK 47
in a class. If there are n methods in class C, then :
NP (C) =n(n− 1)
2
Let NDC(C) to be the number of direct connections and NIC(C) be the number of
indirect connections in AC(C). Tight class cohesion (TCC) is the relative number
of directly connected methods. Formally this can be expressed as :
TCC(C) =NDC(C)
NP (C)
TCC indicates the degree of connectivity between visible methods in a class.
2.3 Software Architecture
The software architecture of a program or computing system is the overall structure of
the system, in terms of its software components, the externally visible properties of those
components, and the relationships among them.
By “externally visible” properties, we are referring to those assumptions other compo-
nents can make of a component, such as its provided services, performance characteristics,
fault handling, shared resource usage, and so on. The intent of this definition is that a
software architecture must abstract away some information from the system (otherwise
there is no point looking at the architecture, we are simply viewing the entire system)
and yet provide enough information to be a basis for analysis, decision making, and hence
risk reduction.
The implemented architecture of a software system typically exists only in artifacts
such as source code, makefiles and occasionally designs that are directly realized as code
CHAPTER 2. RELATED WORK 48
(through, for example, the use of an architecture description language). In addition, it
is infrequent that an implementation language provides explicit mechanisms for the rep-
resentation of architectural constructs. Therefore, facilities for the reconstruction of a
software architecture from these artifacts are critical for identifying the as implemented
architecture. The ability to identify the architecture of an existing system that has suc-
cessfully met its quality goals fosters reuse of the architecture in systems with similar
goals. As known, architectural reuse is the cornerstone practice of product line develop-
ment.
2.3.1 Architecture Reconstruction
Architecture reconstruction [108] is the process where the as-built architecture of an
implemented system is obtained from an existing legacy system. This is done through a
detailed system analysis using tool support. These tools extract information about the
system and aid in building successive levels of abstraction. Architecture reconstruction
is an iterative and interactive process, comprising four phases [101]. The first phase
is the information extraction, from implementation artifacts (including source code and
dynamic information such as event traces), of a set of extracted views that represent the
system’s fundamental structural and behavioural elements. The second phase is the view
fusion that creates fused views that augment or improve the extracted views. During
the third phase, namely reconstruction phase, the analyst iteratively and interactively
develops and applies patterns to the fused views to reconstruct architecture-level derived
views. In this area of research, patterns provide the medium for an analyst to express their
understanding of a system’s architecture as structural and attribute-based relationships
among its components. Also, the derived views may be explored for the purposes of
evaluating architectural conformance, identifying targets for re-engineering or reuse and
analyzing the architecture’s qualities.
CHAPTER 2. RELATED WORK 49
The reconstruction process can be most effectively supported by the integration of
existing tools and techniques into a workbench. In such a workbench, software trans-
formational steps may lead to addressing contradictory requirements (i.e., increasing
performance while decreasing maintainability). For this reason, we need to discuss how
design and source code programming patterns may assist on such selection of the trans-
formational steps that need to be applied in any given re-engineering scenario.
2.3.2 Architectural Patterns and Design Patterns
A “pattern” has been defined as an idea that has been useful in one practical context and
will probably be useful in others [70]. Patterns offer the promise of helping the architect
identify combinations of architectural and/or solution building blocks that have been
proven to deliver effective solutions in the past, and may provide the basis for effective
solutions in the future.
Pattern techniques are generally acknowledged to have been established as a valuable
architectural design technique by Christopher Alexander, a buildings architect, who de-
scribed this approach in his book “The Timeless Way of Building” [5] which provides
an introduction to the ideas behind the use of patterns, description of the features and
benefits of a patterns approach to architecture. Software and buildings architects have
many similar issues to address, and so it was natural for software architects to take an
interest in patterns as an architectural tool.
In [37], the authors define these three types of patterns as follows :
• An architectural pattern expresses a fundamental structural organization or schema
for software systems. It provides a set of predefined subsystems, specifies their
responsibilities, and includes rules and guidelines for organizing the relationships
among them.
CHAPTER 2. RELATED WORK 50
• A design pattern provides a scheme for refining the subsystems or components of a
software system, or the relationships among them. It describes commonly recurring
structure of communicating components that solves a general design problem within
a particular context.
• An idiom is a low-level pattern specific to a programming language. An idiom
describes how to implement particular aspects of components or the relationships
between them using the features of the given language.
2.3.3 Patterns in Software Re-engineering
Object-oriented legacy systems frequently require restructuring in order to become more
amenable to future changes in requirements. In re-engineering an object-oriented legacy
system, it is frequently useful to introduce design patterns [72]. This addition may help to
add clarity to the system and thus facilitate further program evolution. This restructuring
can be performed either by hand or through the use of automated tools [23]. In the latter
case, the designer usually specifies certain operations to be carried out (e.g., to extract a
method from existing code or to move a method from one class to another), and the tool
handles the mundane details of performing the transformation itself.
Moreover, researchers are interested in developing (semi-)automated support for pro-
gram transformations that use a more sophisticated target structure than that of the
examples just mentioned. One interesting category of higher level transformation that a
designer may wish to apply comprises those transformations that relates to the application
of design patterns. Design patterns aim on reducing the coupling between program com-
ponents thus enabling certain types of program evolution to occur with minimal change
to the whole application.
Improving an object-oriented system often involves both redesign and source code
CHAPTER 2. RELATED WORK 51
modification. Programmers often do not distinguish between these two activities and
intertwine them freely. It has been found that it is useful to perform improvements by
first transforming the design while preserving the program behaviour, and then extending
the better functionality of designed system [39, 40]. This approach allows the designer
to validate the new design separate from the added functionality. Furthermore, if the
designer uses automatic tools to transform the design while ensuring that program be-
haviour is preserved, then the extensions are the only possible source of additional error
and the only portion of the system that must be validated.
A growing number of researchers consider design patterns to be a promising approach
to object-oriented systems development [20, 37, 50, 53, 72, 140, 153]. The main idea
behind design patterns is to support the reuse of design information, thus allowing
developers to communicate design information for a subject system more effectively.
New design patterns are constantly being specified, and applied by several research
groups [54, 70, 112, 115, 146, 179]. Moreover, numerous development tools that sup-
port the design pattern approach are currently being developed [34, 62, 63, 68, 103, 175].
In this context, several studies have been presented in the literature that aim at
detecting design patterns in object-oriented software based on structural descriptions in
the reverse engineering [7, 36, 103, 104, 107] but the goal here is applying them in the
context of forward engineering.
Gert Florijn and his group have developed a tool that provides a broad range of
support for a programmer working with patterns [68, 118]. Their focus is on the repre-
sentation of design patterns within the tool itself and the maintenance of the constraints
associated with a design pattern (i.e., checking that changes to the program do not vio-
late any of the design patterns present in the code). Their work also deals with pattern
CHAPTER 2. RELATED WORK 52
application, but the starting point of their transformations is the green field situation, so
the issues of behaviour preservation and reorganization of existing relationships as part
of the transformation process do not arise.
Similarly, Eden and his group have developed a prototype technique called the pat-
terns wizard that can apply a given design pattern to an Eiffel program [62]. This work is
very similar to our goal. It takes a meta-programming approach and organizes the trans-
formations into four levels : design pattern, micro-pattern, idioms, and abstract syntax
tree.
Finally, Schulz [152] merged refactoring work [132] with so called design pattern op-
erators to produce behaviour preserving transformations that introduce design patterns.
Their published work to date presents only their initial ideas.
To re-engineer an object-oriented software system, we need to consider several analysis
and transformation techniques. This section provides a summary of the techniques that
can be helpful for assessing the quality characteristics of a software system both at the
design level and at the source code level.
2.4 Summary
In this chapter, we have described the three principle research fields upon which this thesis
is founded : software re-engineering, non-functional requirements, and design patterns.
The aim of this chapter is to provide a general background to existing and ongoing
research in these areas. In subsequent chapters, we present our own contributions in
more detail, and also present detailed analysis of our approach in comparison to closely
related work.
Chapter 3
Quality-Driven Re-engineering
Framework
You can’t control what you can’t measure.
Tom DeMarco
Over the past few years, legacy system re-engineering has emerged as a business critical
activity. Software technology is evolving by leaps and bounds, and legacy software systems
need to operate on new computing platforms and take advantage of new functionality.
Moreover, organizations are changing at rates that pose ever-changing demands on the
software systems that support their day-to-day operation. Given the amount of human
effort required to manually re-engineer even a medium-sized system, most re-engineering
methodologies have come to rely extensively on tools in order to reduce human effort
requirements. Not surprisingly, the topic of software re-engineering has been researched
heavily for some time, leading both to a variety of commercial tool-sets for particular
re-engineering tasks [55, 157], and to research prototypes [67, 106, 120].
In most cases, software re-engineering tasks have to conform to hard and soft quality
constraints (or non-functional requirements) such as “the re-engineered system must run
53
CHAPTER 3. QUALITY-DRIVEN RE-ENGINEERING FRAMEWORK 54
as fast as the original”, or “the new system should be more easily maintainable than the
original”. For example, the Open Group identifies in [133] a number of evolution qual-
ities for software systems, which range from increasing user productivity, to improving
portability and scalability, improving vendor independence, enhancing security, manage-
ability, and more. These desired qualities (or, more precisely, desired deltas on software
qualities) should play a fundamental role in defining the re-engineering process and the
tools that support it. Unfortunately, there is little understanding of what this role is and
how to fit it in the re-engineering process. In this thesis, we are interested in developing a
framework that uses quality requirements to define and guide the re-engineering process.
This research develops a software re-engineering model that is driven by specific non-
functional requirements. More specifically, the major theme of the proposed approach is
to exploit the synergy between requirements analysis [183], software architecture [74], and
reverse engineering [42]. Understanding the architecture of an existing system aids in
predicting the impact evolutionary changes may have on specific quality characteristics
of the system [162]. Requirements analysis techniques, in turn, suggest what concepts
are most useful in understanding how an existing system works and how it should evolve.
This research builds on this synergy by developing a re-engineering model that can be
applied at architectural level.
3.1 Software Re-engineering Life Cycle
In this section, we present the phases of the re-engineering life-cycle as these could be
adapted from the Waterfall Model [75, 141]. We can regard re-engineering to be an
evolutionary process consisting of the following six phases as illustrated in Figure 3.1.
CHAPTER 3. QUALITY-DRIVEN RE-ENGINEERING FRAMEWORK 55
Risk Analysis
PhaseAnalysis
Source Code
Remediation
Phase
Phase
Verify
Risk Analysis
Risk Analysis
Risk Analysis
Risk Analysis
Risk Analysis
Verify
Verify
Verify
Verify
Verify
PhaseAnalysis
Requirement
Model Analysis Phase
Transformation
Assessment and Adoption
Phase
Figure 3.1: The Re-engineering Life-Cycle.
• Requirements Analysis Phase : refers to the identification of concrete re-engineering
goals for a given re-engineering project. The specification of the criteria should be
specified for the new re-engineered system and must be fulfilled (for example, faster
performance). Violations that need to be repaired are also identified in this phase.
• Model Analysis Phase : refers to documenting and understanding the architecture
and the functionality of the legacy system being re-engineered. In order to under-
stand and to manipulate a legacy system, it is necessary to capture its design, its
architecture and the relationships between different elements of its implementation.
A common problem in legacy systems is the lack of documentation. As a conse-
quence, a preliminary model is required in order to document the system and the
rationale behind its design. This requires reverse engineering the legacy system in
order to extract design information from the code.
• Source Code Analysis Phase : refers to the identification of the parts of the code
that are responsible for violations of requirements originally specified in the system’s
analysis phase. This task encompasses the design of methods and tools to inspect,
CHAPTER 3. QUALITY-DRIVEN RE-ENGINEERING FRAMEWORK 56
measure, rank and visualize software structures. Detecting error prone code that
deviates from its initial requirement specifications requires a way to measure where
and by how much these requirements are violated. Problem detection can be based
on a static analysis of the legacy system (i.e., analyzing its source code or its design
structure), but it can also rely on a dynamic usage analysis of the system (i.e., an
investigation of how programs behave at run-time).
• Remediation Specification Phase : refers to the selection of a target software struc-
ture that aims to repair a design or a source code defect with respect to a target
quality requirement. Because legacy applications have been evolved in such a way
that classes, objects and methods may heavily depend on each other, a detected
problem may have to be decomposed into elementary sub-problems.
• Transformation Phase : consists of physically transforming software structures ac-
cording to the remediation strategies selected previously. This requires methods
and tools to manipulate and edit software systems, to re-organize and re-compile
them automatically, to debug and check their consistency, and to manage different
versions of software being re-engineered.
• Assessment and Adoption Phase : refers to the process of assessing the new system
as well as, establishing and integrating the revised system throughout the corporate
operating environment. This might involve the need for training and possibly the
adoption of a new improved business process model.
This means that our re-engineering approach should consist of : i) requirements anal-
ysis phase to identify specific re-engineering goals, ii) model analysis phase to understand
the system’s design and architecture, iii) source code analysis phase to understand a
system’s implementation, iv) remediation specification phase to examine the particular
CHAPTER 3. QUALITY-DRIVEN RE-ENGINEERING FRAMEWORK 57
problem and to select the optimal transformation for the system, v) transformation phase
to apply transformation rules in order to re-engineer a system in a way that complies with
specific quality criteria, and vi) evaluation phase to assess whether the transformation has
addressed the specific requirements set.
3.2 Problem Definition
We assume the following scenario : an existing object-oriented legacy system is being re-
engineered in order to conform with a new requirement (i.e., performance enhancement).
After studying the code and the desired requirement, it is concluded that the existing
structure of the program makes the desired extension difficult to achieve, and that the
application of some design patterns or source code transformations would help to achieve
the desired property. In this context, we provide support for the developer to decide what
design pattern or transformation to apply towards achieving a specific non-functional
requirement for the new system (e.g., performance enhancement).
To specify the problem more precisely, we assume that the re-engineering process
consists of a series of transformations t1, t2, ..., tn on the abstract syntax tree AST (S) [3]
of a software system S. We also assume that for each quality of interest, say Q, there is a
metric MQ which measures how well a software system (or system fragment) fares with
respect to the quality. Examples of software properties for the migrant system include
“The target application should run on NT platforms”, while examples of qualities include
“time and space characteristics”, “maintainability”, “portability”, “customizability”, and
the like. A quality-based re-engineering problem is defined as follows :
CHAPTER 3. QUALITY-DRIVEN RE-ENGINEERING FRAMEWORK 58
Given a software system S, relevant quality metrics MQ1,MQ2, ...,MQn, a
desired software property P , and a set of constraints C1, C2, ..., Ct on the soft-
ware qualities Q1, Q2, ..., Qn, find a sequence of transformations t1, t2, ..., tn
such that the new re-engineered system S ′ = tn(tn−1(...(t1( AST (S)...) is such
that P (S′) and the constraints C1(S′), C2(S
′), ..., Ct(S′) are satisfied.
To address the problem presented above in a more systematic fashion, we need to
resolve several research issues, namely :
• We need to compose a list of software transformations which relate to particular
software qualities.
• We need to investigate the mutual impact these transformations have on two or
more qualities.
• We need to devise a method to quantitatively assess the impact of a particular
transformation on a particular quality in terms of metrics or quantitative software
indices.
3.3 Quality-Driven Object-Oriented Re-engineering
The re-engineering of legacy systems has become a major concern in today’s software
industry. Traditionally, most re-engineering efforts were focused on systems written in
traditional programming languages such as Fortran, COBOL, and C [4, 10, 19, 121, 155].
Unfortunately, non of them have guided the re-engineering process in the context of non-
functional or quality requirement as a goal. The problem of coping with qualities or
non-functional requirements during re-engineering has been experimentally tackled by
developing a number of tools that met particular quality requirements. In [67], a tool-set
CHAPTER 3. QUALITY-DRIVEN RE-ENGINEERING FRAMEWORK 59
has been developed that assists on the migration of PL/IX legacy code to C ++ while
maintaining comparable time performance. The work in [135] presents a re-engineering
tool that supports the transformation of C code to C + + code that is consistent with
object-oriented programming principles. In both cases, the approach was experimental.
First, a tool has been built to perform the re-engineering task, then a trial-and-error
strategy was used to select a particular set of transformations which ensured that the
re-engineered code satisfied given quality constraints.
However, not much effort has been invested for systematically documenting quality
attributes as a guide for the software re-engineering process. In this context, this thesis
proposes a re-engineering framework which allows for specific quality requirements for the
migrant system to be modelled as a collection of soft-goal graphs and for the selection
of the transformational steps that need to be applied at source code level of the legacy
system being re-engineered.
Software re-engineering processes can be applied at different levels. At the lowest
levels, migration takes the form of transforming (or “transliterating”) the code from one
language into another. At higher levels, the structure of the system may be changed as
well, to make it, for instance, more object-oriented. At even higher levels of abstraction,
the global architecture of the system may be changed as part of the migration process.
For this research work, we adopt an incremental and iterative re-engineering process
model that is driven by the soft-goal interdependency graphs which will be presented
in the following sections. It means that the proposed re-engineering process model will
be applied iteratively before achieving the desired requirements for the target migrant
system.
The re-engineering process includes the following steps as illustrated in Figure 3.2.
CHAPTER 3. QUALITY-DRIVEN RE-ENGINEERING FRAMEWORK 60
Final SystemCodeRepresentationSource CodeHigh-Level
EvaluationSource CodeNew
ASG, AST, RSF, ...UML Diagrams
TransformationRules
Non-FunctionalRequirementsGoal-Driven
Figure 3.2: The Block Diagram of the Quality-Based Re-engineering Process.
First, the source code is represented as an Abstract Syntax Tree [3]. The tree is further
decorated using a linker, with annotations that provide linkage, scope, and type informa-
tion. In a nutshell, once software artifacts have been understood, classified and stored
during the reverse engineering phase, their behaviour can be readily available to the sys-
tem during the forward engineering phase. Then, the forward engineering phase aims to
produce a new version of a legacy system that operates on the target architecture and
aims to address specific non-functional requirements (i.e., maintainability or performance
enhancements). Finally, we use an iterative procedure to obtain the new migrant source
code by selecting and applying a transformation which leads to performance or maintain-
ability enhancements. The transformation is selected from the soft-goal interdependency
graphs. The resulting migrant system is then evaluated and the step is repeated until
quality requirements are met.
3.4 Soft-Goal Interdependency Graphs
To represent information about different software qualities, their interdependencies, and
the software transformations that may affect them, we adopt the NFR framework pro-
CHAPTER 3. QUALITY-DRIVEN RE-ENGINEERING FRAMEWORK 61
posed in [43, 44, 125]. In the NFR framework, quality requirements are treated as poten-
tially conflicting or synergistic goals to be achieved, and are used to guide and rationalize
the various design decisions taken during system/software development. Because qual-
ity requirements are soft and subjective by nature, they are often achieved not in an
absolute sense, but to a sufficient or satisfactory extent. Accordingly, the NFR Frame-
work introduces the concept of soft-goals whose achievement judged by the sufficiency of
contributions from other (sub-) soft-goals. A soft-goal interdependency graph is used to
support the systematic, goal oriented process of architectural design.
According to the framework, software qualities are represented as soft-goals, i.e., goals
that can be partially achieved. The leafs of the soft-goal interdependency graph represent
design decisions which fulfil or contribute positively/negatively to soft-goals above them.
Given a quality constraint for a re-engineering problem, one can look up the soft-goal
interdependency graph for that quality, and examine how it relates to other soft-goals,
and what are additional design decisions or software transformations that may affect the
desired quality positively or negatively. In this thesis, we have chosen maintainability
and performance enhancement as the re-engineering requirements for the new migrant
system.
In addition to performance, maintainability is another important requirement. It has
been argued that maintainability can be partially achieved with the use of design patterns.
For example, the State design pattern makes it easier to add new states in a system
without altering the functionality of existing states. Ironically, experience drawn from
software engineering practice reports that improved methods during system maintenance
and evolution may result in higher maintainability indicators. Hence, it is important to
consider how and by what means one can improve maintainability during re-engineering.
CHAPTER 3. QUALITY-DRIVEN RE-ENGINEERING FRAMEWORK 62
Performance is a vital quality factor in real-time, transaction-based, or interactive
systems. Such systems have to handle incoming data and transactions, provide an inter-
face with external users, and maintain persistent storage. Without good performance,
such systems would be practically unusable, leading to lack of service, lack of informa-
tion, dissatisfied users, and ultimately corporate loss. Hence, it is important to consider
performance requirements during re-engineering such systems.
3.4.1 Maintainability Soft-Goal Graph
Maintainability is defined as the quality of a software system that relates with the ease
of adding new functionality named perfective maintenance, porting the system from one
platform to another named adaptive maintenance, or fixing errors named corrective main-
tenance [75]. Maintainability can be evaluated by the system revision history and source
code measurements. Also, it can be measured as a quantification of the time necessary
to make maintenance changes to the product, or as a percentage of code affected by a
specific change [80, 131] when a code fix or modification is applied. Maintainability as
a re-engineering requirement is quite broad and abstract. Various researcher teams have
determined numerous attributes and characteristics of software systems that relate to
maintainability. To effectively model how software attributes and characteristics relate
to maintainability, we must provide a comprehensive and formal classification framework.
Such a framework can be defined in terms of a semantic net of non-functional requirements
that we call “soft-goals”.
The initial maintainability requirement is quite broad and abstract. Researchers have
determined numerous and varied attributes of software which might affect maintainability.
To effectively deal with such a broad requirement, this NFR needs to be broken down into
more specific soft-goals that contribute towards satisficing the top-level NFR softgoal. It is
CHAPTER 3. QUALITY-DRIVEN RE-ENGINEERING FRAMEWORK 63
important to note that in this work we only describe soft-goals relevant to the source code
of the target system. It is also possible to identify maintainability-related soft-goals that
do not depend directly on source code properties. However, identifying such heuristics
would require knowledge about specific environmental factors (such as management and
process modelling issues) and are outside the scope of the work presented here.
Figure 3.3 shows a comprehensive soft-goal interdependency graph for maintainability
decomposition. This graph attempts to represent and organize a comprehensive set of
software attributes that relate to software maintainability. The graph was compiled after
a thorough review of the literature [73, 80, 131, 134]. In the figure, AND relations are
represented with a single arc, and OR relations with a double arc.
High Maintainability
High Documentation Quality
High Data Structure Quality
Low Data CouplingLow I/O Complexity
High Data Consistency
High Control Structure Quality
High HighModule Reuse
Low Control
High Control Flow Consistency
High Source Code Quality
Cohesion
Low ControlFlow Complexity Flow Coupling
High EncapsulationHigh Modularity
Figure 3.3: Maintainability Soft-Goal Decomposition.
For our work, we have classified the maintainability non-functional requirements
(NFR) soft-goal graph into two major areas namely, attributes that relate to source code
quality [80], and attributes that relate to the documentation quality. Thus, the main-
CHAPTER 3. QUALITY-DRIVEN RE-ENGINEERING FRAMEWORK 64
tainability interdependency graph can be decomposed into two soft-goals : i) high source
code quality, and ii) high documentation quality which has been depicted in Figure 3.3.
In this case, both softgoals are needed together to meet the maintainability requirement.
This is referred to as an AND contribution of the offspring softgoals towards their parent
softgoal. The high source code quality softgoal can be further decomposed into the sub-
softgoals : i) high control structure quality, and ii) high data structure quality [51, 131].
Now we want to focus on each of these sub-softgoals individually. The high control
structure quality softgoal can further be decomposed into the sub-softgoals that source
code must be characterized by the following attributes with an OR contribution :
1. High Cohesion - Cohesion or module strength is the degree which the tasks per-
formed by a single software module are related to one another.
2. Low Control Flow Complexity - Control flow complexity is the degree to which a
system has a design or implementation that is difficult to understand and verify.
3. High Modularity - Modularity is the degree to which a system or program is com-
posed of discrete components such that a change to one component has minimal
impact on other components.
4. High Control Flow Consistency - Control flow consistency is the degree of unifor-
mity, standardization, and freedom from contradiction of the logical process flow
within the parts of a system or component.
5. High Encapsulation - Encapsulation is a software development technique that con-
sists of isolating system function or a set of data, and operations on those data,
within a module and providing precise specifications for the module.
6. Low Control Flow Coupling - Control flow coupling is the degree of interdependence
CHAPTER 3. QUALITY-DRIVEN RE-ENGINEERING FRAMEWORK 65
between software modules.
7. High Module Reuse - Module reuse is the degree to which a software module can
be used in more than one location in a program or system.
The high data structure quality soft-goal can further be decomposed into the sub-
softgoals that source code must be characterized by the following attributes with an OR
contribution :
1. High Data Consistency - Data consistency is the degree of uniformity, and freedom
from contradiction among the inter-modular data types and structures of a system.
2. Low Data Coupling - Data coupling is the degree of interdependence between soft-
ware modules.
3. Low I/O Complexity - I/O complexity is the degree of complication of a system
component, determined by factors such as the number and intricacy of interfaces,
the number and intricacy of conditional branches, the degree of nesting, the types
of data structures, and other local characteristics.
The complete process of the decompositions is illustrated in Figure 3.3.
3.4.2 Performance Soft-Goal Graph
Similar to maintainability, performance-related requirements and their interdependencies
are represented in terms of a soft-goal interdependency graph. Figure 3.4 shows this
decomposition. The graph was compiled after a thorough review of the literature [14, 24,
74, 84, 105, 129]. High performance soft-goal is decomposed with an AND contribution
into : i) time performance, and ii) space performance [129].
CHAPTER 3. QUALITY-DRIVEN RE-ENGINEERING FRAMEWORK 66
Good Performance
Good TimePerformance
Low Response Time Low
Main MemoryUtilization
Low Secondary Storage Utilization
Good Space Performance
Low CPU Time
High Throughput
Low I/OActivities
RunningLow Time
Low System CPU Time
Low User CPU Time
Figure 3.4: Performance Soft-Goal Decomposition.
In turn, the space performance soft-goal can be decomposed into the following sub-
softgoals : i) low main memory utilization, and ii) low secondary storage utilization. As
shown in Figure 3.4, this is also an AND contribution, which means both sub-softgoals
must be satisficed to achieve the good space performance soft-goal. The time performance
soft-goal can be decomposed into the following sub-softgoals with an OR contribution :
i) low response time, and ii) high throughout.
As shown in Figure 3.4, the low response time soft-goal can also be decomposed
into the following sub-softgoals with an OR contribution : i) low CPU time, ii) low
I/O activities, and iii) low time running. Finally, the low CPU time soft-goal can be
decomposed into the following sub-softgoals : i) low user CPU time, and ii) low system
CPU time. As shown in Figure 3.4, this is also an OR contribution.
Up to now, we have been provided the precise interpretations of what the initial NFRs
of maintainability and performance signify. However, we have not yet provided the precise
means by which one could achieve maintainability and performance in a system. At this
CHAPTER 3. QUALITY-DRIVEN RE-ENGINEERING FRAMEWORK 67
point, we need to identify software transformations or design decisions that actually
satisfice the top-level NFR soft-goals and then to select the best solution for the target
system. Then, the next steps are : i) the design and development of a comprehensive
catalogue of transformations that can be modelled in the soft-goal interdependency graphs
and can be applied at the source code level of an object-oriented legacy system to address
specific re-engineering objectives which Chapter 4 deals with these issues, and ii) the
design and development of an analysis methodology that allows for the identification
of error prone architectural design and source code programmatic patterns that can be
“repaired” according to the transformational steps identified by the soft-goal graphs which
Chapter 6 discusses these aspects of the research.
3.5 Summary
We have proposed a quality-driven framework for software re-engineering. The framework
uses desirable qualities for the re-engineered code to define and guide the re-engineering
process. This framework devises a workbench in which re-engineering activities do not
occur in a vacuum, but can be evaluated and fine-tuned in order to address specific quality
requirements for the new target system such as, enhancements in maintainability, and
performance.
Chapter 4
Software Transformation Algebra
As a program is evolved its complexity increases
unless work is done to maintain or reduce it.
Meir M. Lehman
In the previous chapter, we described the quality-driven re-engineering framework. In this
chapter, we identify design decisions that actually satisfice the top-level NFR soft-goals.
In Section 4.1, we discuss the role of design patterns in software re-engineering and
in the context of the quality-driven framework. Specifically, we present a classification
of the relationships between design patterns which can lead to a new categorization of
the GoF design patterns [72] into different layers. Section 4.2 describes our approach to
define transformation rules based on a layered architecture while Section 4.3 discusses an
algebra for composing such transformation rules. Finally, Section 4.4 gives a summary of
this chapter.
68
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 69
4.1 Role of Design Patterns in Software Re-engineering
Design patterns have been widely adopted and well investigated by the software engi-
neering community over the past decade. However, their primary use is still associated
with forward engineering and the design phase of the software life-cycle. In this section,
we would like to examine design patterns from a different perspective namely, their clas-
sification and usage for software re-engineering and restructuring. It means that we are
interested to investigate design patterns and their relationships as a means to restructure
an object-oriented legacy system so that the new system conforms with specific design
patterns and meets specific non-functional requirement (NFR) criteria. For achieving
this goal, we need to develop a catalogue of specific design patterns and refactoring oper-
ations [71] that can be used to enhance specific software qualities during re-engineering,
namely maintainability and performance.
Figure 4.1 provides an overview on how the design pattern approach is related to
several other concepts of object-oriented software development as we plan to use in the
proposed quality-driven object-oriented re-engineering framework. As Figure 4.1 depicts
the components or source code features that can be directly extracted from the object-
oriented legacy system provide important information for guiding the developers to detect
and apply candidate patterns in a way that can improve the quality of target system.
As discussed in Section 3.1, the proposed re-engineering life cycle consists of six stages.
In a nutshell, we can relate these stages to the role of design patterns in this context as
follows : i) requirements analysis phase to identify specific re-engineering goals, ii) model
analysis phase to understand the system’s design and architecture which Design Rules
provided by reverse engineering gives proper information, iii) source code analysis phase
to understand a system’s implementation through extracted components and features,
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 70
Engineering
Reverse
Engineering
Reverse
helps to
find starting
can be combined to can be combined to or Features
ExtractedComponents
DesignPatterns
RulesDesign
in serves
Metric
Object-Oriented Legacy System
serve as a basic for the correct use of
Analysis
serve as
points for
used
are often derived from
are
OperationsRefactoring
Design
as goals for
forhints
give
assess quality
of
improves the quality of the
blocksreusable building
Figure 4.1: On the Role of Design Patterns in Re-engineering Context.
iv) remediation specification phase to examine the particular problem through refactoring
operations and to select the optimal transformation for the system, v) transformation
phase to apply transformation rules in order to re-engineer a system in a way that complies
with specific quality criteria, and vi) adoption or evaluation phase to assess via metrics
analysis whether the applied transformations have achieved the specific requirements.
Once software artifacts have been understood, classified, and stored during the reverse
engineering phase, their behaviour can be readily available to the system during the
forward engineering phase. The forward engineering phase aims to produce a new version
of an object-oriented legacy system that operates on the target architecture and meets
specific non-functional requirements (i.e., maintainability or performance enhancements).
The proposed process is iterative and incremental in nature. It means that at each
iteration cycle, the evaluation procedure is applied to ensure that each transformation
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 71
step conforms with the requirements set for the new system.
4.1.1 Overall Structure of GoF Catalogue
Design patterns were discussed by Christopher Alexander, an architect, in order to de-
scribe techniques for town planning, architectural designs, and building construction tech-
niques [5]. Each design pattern description contains a section where relationships to other
patterns of a higher or of a lower granularity level are presented. These relationships in-
fluence the construction process. A classification for the patterns was given, however their
mutual relationships have not been provided. Frameworks [96, 184] are also considered
as high-level design patterns, usually consisting of many interrelated design patterns of
lower levels.
Booch [28] also discussed that design patterns are ranging from idioms to frame-
works. In [50], several design patterns are combined in an exemplary application, but the
relationships are not investigated further.
In [72], a catalogue of design patterns is presented. The catalogue not only lists a
description of the patterns but also presents how patterns are related. Furthermore, the
catalogue presents a classification of all design patterns according to two criteria : jurisdic-
tion (class, object, compound) and characterization (creational, structural, behavioral).
However, these relationships in [72] are described informally and each relationship appears
to be different in its formalization from the other ones.
The relationships between object-oriented design patterns were first analyzed in [37]
where three kinds of relationships between patterns are described. These include : i) use -
one pattern can use another pattern, ii) variant - one pattern can be a variant of another
pattern, iii) combine - two patterns can be used in combination to solve a problem.
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 72
Similarly, Mesazaros and Doble [119] identified five relationships between patterns, a
pattern can use, be used by, generalize, specialize, or provide an alternative to another
pattern.
As a part of this thesis, we have carefully analyzed the existing patterns presented
by the “Gang of Four” [72] to determine their relationships and their usage in the re-
engineering area. The classification scheme for relationships between patterns presented
in this section was developed to support the wider goal of improving the quality and the
design of migrant code while maintaining its original functionality (behaviour preserving
transformations). Specifically, twenty three design patterns originally presented in the
“Gang of Four” book are re-classified for re-engineering purposes.
Table 4.1 is a tabular presentation in alphabetic order of the design patterns and
their relationships that can be found in [72]. Table 4.1 provides an overview of the
structure of the proposed catalogue. It serves as a reference point as it contains the
most detailed information about the pattern relationships. This table also serves as the
starting point for the further classification and the revision of the relationships. On the
basis of Table 4.1, we build our proposed classification scheme.
4.1.2 Classifying Relationships
Our classification scheme is based on the following relationships between any pairs (X,Y )
of design patterns found from the description in Table 4.1 :
• X Uses Y
When building a solution for the problem addressed by X, one subproblem is similar
to the problem addressed by Y . Therefore, the design pattern X uses the design
pattern Y in its solution [5, 37, 72]. Thus, the solution of Y represents one part
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 73
Pattern (X) Description of Relationship Pattern (Y)Abstract Factory Are often implemented with Factory Methods.
Can also be implemented using Prototype.Adaptor Has a structure similar to Bridge.Bridge Is similar to Adaptor.Builder Is similar to Abstract Factory.Chain of Uses Decorator.ResponsibilityCommands Uses Composite.Composite Is used for a Chain of
Responsibility.Can be used to implement Commands.Creates composite Builder.Defines simple instance of Interpreter.
Decorator Supports recursive composition, not possible with Adaptor.Is often used with Composite.Have similar implementation as Proxies.
Facade Is similar to Mediator.Factory Method Is usually called within Template Methods.Flyweight Lets you share components such as Composite.Interpreter traverses the structure by using Iterator.Iterator Can used to traverse Composites.
Can be combined with Visitor.Mediator Is similar to Facade.Memento Can keep state to undo its effect using Command.
Is often used in conjunction with Iterator.Observer Can use Singleton.Prototype Is often a Singleton.
Is competing pattern in some way with Factory Method.Proxy Defines a representative for another object without Adaptor.
changing the interface in the comparison withSingleton Is used by Observer.State Is similar to Strategy.Strategy Is often best to implement as Flyweight.Template Method Often calls Factory Method.Visitor Localizes operations that would be distributed across Composite.
Can be used to maintain the behaviour of Interpreter.
Table 4.1: Overall Structure of the Design Pattern Catalogue.
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 74
of the solution for X. It means that a pattern which has a larger or more global
impact on a design will use patterns which have smaller or more local impacts.
For example, Chain of responsibility uses Decorator. Tools supporting the design
pattern approach can benefit from this information as such a relationship can be
checked in existing designs. Also design patterns like Y can be visualized as blocks
without internal implementation details in order to raise the abstraction level. The
uses relationship can also be used to simplify the descriptions of more complex
patterns by composition.
We can also consider the used by (Y used by X) relationship which is the inverse
of the uses relationship (X uses Y ) and can be analyzed in the same way as that
relationship. For example, because Interpreter uses Iterator, Iterator is used by
Interpreter.
• X Refines Y
A specific pattern X refines a more abstract pattern Y if the specific pattern’s full
description is a direct extension of the more general pattern Y [119]. That is, the
specific pattern X must deal with a specialization of the problem the general pattern
Y addresses, and must have a similar (but more specialized) solution structure.
To make an analogy with object-oriented programming, the uses relationship is
similar to composition, while the refines relationship is similar to inheritance. For
example, Factory Method refines Template Method, because Factory Methods are
effectively Hook Methods [72] which are used by subclasses to specify the class of
an object the Template Method in the superclass will create. In the description
of Factory Method pattern, one of the main forces addressed by the pattern is the
use of naming conventions to illustrate the particular method is in fact a Factory
Method.
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 75
We can also consider that the refined by or generalizes relationship (Y is refined by
X) is the inverse of the refines relationship (X refines Y ) and can be analyzed in the
same way as that relationship. For example, as Factory Method refines Template
Method then Template Method is refined by Factory Method.
• X Conflicts with Y
The third fundamental relationship between patterns in our classification scheme is
conflicts which denotes that the two or more patterns provide mutually exclusive
solutions to similar problems. Most pattern forms do not provide an explicit section
to record this relationship but it is often expressed in the related pattern section
along with the uses relationship.
For example, Prototype and Factory Method patterns conflict because they provide
two alternative solutions to the problem of subclasses redefining the class of objects
created in superclasses. When reading or applying a pattern, this relationship can
be exploited in two ways. When looking for patterns, if a pattern seems as if it
may be applicable, then the conflicting patterns should be examined because they
present alternative choices but once a pattern has been chosen the other conflicting
patterns can be ignored.
• X is Similar to Y
This relationship is often used to describe patterns which are similar because they
address the same problem [37]. The similarity relationship seems to be much broader
than just conflicts, and as it is also used to describe patterns which have a similar
solution technique such as Strategy and State. These can be treated as refining a
more abstract pattern, or occasionally related by the uses relationship.
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 76
• X Combines with Y
Patterns of Software Architecture [37] introduces a combines relationship in the case
where two patterns are combined to solve a single problem which is not addressed
directly by any other pattern.
In simple cases, we can model this relationship directly by the uses relationship
where one pattern is a larger scale pattern that addresses the whole problem and
the other pattern is a smaller scale pattern which provides a solution to a sub-
problem. For example, Composite and Decorator are often used together in ap-
plications [180]. There are also other kinds of relationships between them. For
example, when looking at the solution aspect, Decorator can be seen as a degener-
ated Composite. When considering the pattern scope, they both support recursively
structured objects whereby Decorator focuses on attaching additional properties to
objects. Thus, the design patterns in this category are somehow similar but it
is difficult to state this relationship more precisely. Therefore, we only insert a
relationship of type “Combines with” and neglect the other ones.
In more complex cases, we consider that this relationship really points to a lack
in the patterns themselves. Although these patterns can be combined to provide
a solution to a problem, the actual problem and the way these patterns are com-
bined to solve it, is being represented by the combines relationship and it is not
captured explicitly in a pattern. In these cases, we ensure that the problem is iden-
tified explicitly by locating an existing pattern or introducing a new pattern which
addresses the problem directly, outlines the whole solution and uses the patterns
that combine to solve it. For example, Iterator traverses Composite structures and
Visitor centralizes operations on object structures. Depending upon the necessary
degree of flexibility, one typically combines two or all three design patterns, for
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 77
instance Interpreter.
• X Requires Y
We say that one pattern requires a second pattern if the second pattern is a prerequi-
site for solving the problem addressed by the first pattern. For example, Composite
can be used to implement Command. It means that Command pattern requires
Composite pattern before it can be implemented successfully.
In general, we consider that this relationship can be modelled quite adequately by
the uses relationship. The distinction between requires and uses seems to be based
primarily on the order in which the patterns should be applied. If one pattern
requires a second pattern, the second pattern must be applied before the first one
can be used to produce its solution. This is also the case with the general uses
relationship, since if one pattern uses a second pattern, the second pattern must be
applied before the solution described by the first pattern will be completed. This is
the reason that we can model the requires relationship with the uses relationship.
Based on our classification scheme, we can categorize those design pattern relation-
ships one level further as follows :
1. Primary Relationships
Our classification scheme can be based on three primary relationships such as : i) a
pattern uses another pattern, ii) a more specific pattern refines a more general
pattern, iii) one pattern conflicts with another pattern when they both propose
solutions to a similar problem.
2. Secondary Relationships
Our scheme also describes three secondary relationships between patterns such as :
i) two patterns are being similar, ii) two patterns are combining to solve a single
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 78
problem, iii) a pattern requires the solution of another pattern. We classify these
relationships as secondary relationships because we have been able to express them
in terms of the primary relationships as discussed before.
4.1.3 Modifying Relationships
Now, we examine the proposed classification of the design patterns relationships further.
This process results in some modifications to existing relationships. The organization of
the relationships in different categories is sometimes difficult because it partly depends
upon subjective criteria. The difference between “X Uses Y ” or “X Combines With
Y ” depends upon the subjective assessment whether the usage of Y is seen as a central
part of the solution X, or if it is more of a combination of two autonomous design
patterns. Furthermore, two design patterns might be related in different ways. Decorator
or Composite, and Abstract Factory or Prototype are pairs of design patterns which can
be combined and are also similar. In this paper, each relationship is assigned to the most
adequate category.
Based on the catalogue, Factory Method does not use Template Method but it is often
called (refine) by Abstract Factory in a Template Method. It means that Factory Method
often plays the role of a primitive in a Template Method. Thus, if an Abstract Factory uses
Factory Method in its solution, then it really uses the design pattern Template Method.
Therefore, we do not need to consider Factory Method as a separate design pattern but as
a “X Uses Y” relationship between Abstract Factory and Template Method. By removing
the Factory Method design pattern, we need to modify the relationship between this
pattern and Prototype appropriately. It means that from now on, the Prototype design
pattern has a conflict relationship with Template Method instead of Factory Method.
The integration of the above modifications as well as the introduction of the primary
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 79
Pattern (X) Relationship Pattern (Y)
Abstract uses Template.Factory refines Prototype.
Adaptor is used by Bridge.
Bridge uses Adaptor.
Builder uses Abstract Factory.
Chain of uses Decorator.Responsibility
Commands uses Composite.
Composite refines Chain ofResponsibility.
conflicts with Builder.refines Interpreter.
Decorator refines Adaptor.uses Composite.refines Proxy.
Facade is refined by Mediator.
Flyweight uses Composite.
Interpreter uses Iterator.uses Visitor.
Iterator uses Composites.uses Visitor.uses Memento.
Mediator refines Facade.
Memento uses Command.
Observer uses Singleton.
Prototype uses Singleton.conflicts with Template.
Proxy conflicts with Adaptor.
Singleton is used by Observer.
State refines Strategy.
Strategy uses Flyweight.
Visitor refines Composite.
Table 4.2: Revised Classification.
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 80
Structural
Behavioral
Command
Memento
Iterator
Responsibility
InterpreterDecorator
Visitor
Flyweight
Chain ofAdaptor
Proxy
Bridge
Strategy
State
Observer
PrototypeTemplateMethod
AbstractFactory
Facade
Mediator
Uses
Refines
Creational
Singleton
CompositeConflicts By
Builder
Legend:
Figure 4.2: Classified Structure of Design Pattern Catalogue.
relationships after expressing the secondary relationships in terms of primary ones into
Table 4.1 results in Table 4.2. In this context, Figure 4.2 is a graphical illustration of
Table 4.2, and our proposed classification scheme.
4.1.4 Design Patterns in a Layered Architecture
Up to now, we have classified the relationships between the design patterns and modified
a few of them. As one can see in Figure 4.2, “X Uses Y ” is the most frequent relationship.
Therefore, we try to arrange the patterns according to this predominant relationship.
The graph defined by the primary relationships is acyclic. This property allows us to
arrange the design patterns in different layers as shown in Figure 4.3.
In [20], it is indicated that “Patterns can be used at many levels, and what is derived at
one level can be considered a basic pattern at another level”. Furthermore, it is stated that
“This is probably typical of most architects; some patterns will be generic and some will
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 81
be specific to the problem domain” which also confirms the organization depicted in our
proposed layers in Figure 4.3. These layered design structure techniques are useful in the
reverse engineering context for extracting architecture as well as in forward engineering
context for improving the design or enhancing non-functional requirements of existing
code. These two different layers are discussed below.
Legend:
Creational Structural Behavioral Uses Conflicts ByRefines
DecoratorAdaptorMementoCompositeTemplateMethodSingleton
ResponsibilityChain ofPrototypeObserver
State
Strategy
Flyweight
Interpreter
AbstractFactory
Command
Visitor
Bridge
Iterator
Builder
ProxyFacadeMediator
Primary
of DPsLayer
SecondaryLayer
of DPs
Figure 4.3: Arrangement of Design Pattern Catalogue in Layers.
Primary Layer of Design Patterns
This layer contains the design patterns which are heavily used in the design patterns
of higher level and in object-oriented systems in general. Table 4.3 gives a list of these
patterns in alphabetic order and their respective purpose. The Composite design pattern
seems to be the most important one as it is used by eight other design patterns. It is a
basic pattern in the sense that the addressed problem of handling recursively structured
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 82
objects is a basic problem in many contexts.
Pattern PurposeAdaptor Adopting a protocol of one class to the
protocol of another class.Composite Single and multiple, recursively
composed objects can be accessed bythe same protocol.
Decorator attaching additional properties to objects.Facade Encapsulating s subsystem.Mediator Managing collaboration between objects.Memento Encapsulating a snapshot of the internal
state of an object.Proxy Controlling access to an object.Singleton Providing unique access to services
or variables.Template Objectifying behaviour.
Table 4.3: Primary Level of Design Patterns.
The problem addressed by these design patterns occurs again and again when devel-
oping object-oriented systems. The design patterns are thus proven to be very general.
When building a system, one would often look upon them more as basic design techniques
than as patterns. The intentions of these design patterns are very general and applicable
to a broad range of problems occurring in the design of object-oriented systems.
Secondary Layer of Design Patterns
This layer comprises design patterns which are used for more specific problems in the
design of software. These design patterns are not used in the design patterns from the
primary layer, but in patterns from the same layer. Design patterns in this layer are the
most specific and they can often be assigned to one or more application domains.
Builder, Prototype and Abstract Factory address problems with the creation of ob-
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 83
jects, Iterator traverses object structures, Command objectifies an operation and so on.
The proposed arrangement of design patterns into two layers is one of the possible
separation of concerns for design patterns. As more design patterns are described or
new application area are considered, the proposed scheme should be revised to meet new
requirements. For example, when considering the restructuring and re-engineering of
distributed systems the proposed classification scheme is not fully adequate.
Currently, such a classification allows for the understanding of the overall structure
of the catalogue, and for relating new design patterns to existing ones. This arrangement
also groups design patterns according to their typical combinations and plays an impor-
tant role as typical combinations can be used as building blocks in software design. At
the moment, it helps us to grasp and to understand the overall structure of GoF cata-
logue, and to relate new design pattern to existing one. It is also an aid for traversing
or learning design patterns, as the user can choose between a bottom-up or a top-down
traversal.
The jurisdiction and characterization criteria [72] are also orthogonal with our pro-
posed criteria, and result in several clusters of design patterns with a similar intent. We
believe that this arrangement can help for the retrieval and selection of an appropriate
design pattern for a specific problem at hand.
In a nutshell, we have presented a classification of the relationships between design
patterns which can lead to a new categorization of the GoF design patterns into different
layers. The proposed classification can assist software engineers with : i) understanding
better the complex relationships between design patterns, ii) organizing existing design
patterns as well as categorizing and describing new design patterns, iii) building tools
which support the application of design patterns during restructuring.
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 84
The next steps focus on : i) the formal description of the source code transformations
required for the migrant system to conform with the proposed design pattern classification
scheme, and ii) the formalization of the impact different transformations have on the
migrant system with respect to maintainability and performance enhancements.
4.2 A Software Transformation Framework
It has been argued in the software engineering community that the use of design pat-
terns [37, 72, 78, 79] has a positive effect on system qualities. The process of devising and
composing transformations that introduce such design patterns in an ill-designed object-
oriented system poses an investigating challenge for the re-engineering of such systems.
The process is both a top-down for higher level transformations, and a bottom-up for the
lower level design motifs.
In developing a transformation for a particular design pattern, we consider existing
work in the design patterns and refactorings literature. Examining the design pattern
catalogue [37, 72, 78, 79] and our proposed classification of the relationships between
design patterns in Section 4.1.2, it is clear that certain motifs occur repeatedly across the
catalogue. For example, a class registers another class only via an interface. It has been
also presented in Figure 4.3 that specific design motifs can be combined in various ways
to produce a wide variety of existing design patterns.
The process of devising and composing transformations to introduce design patterns
in an ill-designed object-oriented system is both a top-down one for higher level transfor-
mations, and a bottom-up one for the lower level design motifs. The importance of such
techniques lies in the fact that they may allow us to implement a design pattern trans-
formation as a composition of lower level design motifs. The transformation framework
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 85
proposed in this thesis is defined in a layered model as illustrated in Figure 4.4. The
rationale behind this proposed layered architecture of transformations is further elabo-
rated.
Primitive DPs
Transformations
Investigavtive
Functions
Complex DPs
Transformations
Supporting
Functions
Positioning
Transformations
**
<<Check>>
<<Check>><<Check>>
<<Check>>
1..6
1..* Contribute
Contain
*
*
Use
Figure 4.4: Meta-Model of the Transformations.
In defining a transformation, it is necessary to specify sets of preconditions and conse-
quently assertions should be made about the program, such that a certain class exists or
a given name-space is not already in use. For this purpose, we define a set of investigative
functions to enable these assertions to be made as shown in Figure 4.4. Investigative
functions serve two related roles. First, they are implemented as actual operations that
can be applied to an object-oriented program to extract some information about the pro-
gram. Second, they are used as predicates examining whether a specific transformation
can be applied in a specific source code context. Examples include : i) to test whether
a method is in a certain class, ii) to test whether there is a given class in the program.
Investigative functions are described further in Section 5.2.
In describing a transformation, it may be necessary to extract richer content from
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 86
the program code than the information provided by the investigative functions. For this
purpose, we define supporting functions as shown in Figure 4.4. For example, we may
wish to build an interface from a class based on the signatures of its public methods.
Supporting functions can be used to perform this type of task. Examples from this
category of functions include : i) construct and return an empty class, ii) construct and
return an interface that reflects all the public methods of a given class. Supporting
functions are elaborated further in Section 5.3. Investigative and supporting functions
are proper functions without any functional side-effects on the program behaviour.
A positioning transformation as shown in Figure 4.4 aims to introduce refactor-
ings [132] to the original system towards achieving the desired target requirement (e.g.,
enhance the maintainability). Most of them are standard and would be part of any
refactoring suite [71, 132], such as addClass [71] operation. More explanations about
the positioning transformations will be discussed in Section 5.4. Each of the supporting
functions and positioning transformations has the following structure :
• Preconditions. These are assertions, written in first-order predicate logic. They
pertain to the examination of the source code features that must be present for
the transformation to be applied [162]. In defining these preconditions, assertions
should be made about the program, such as a certain class exists or a given name
is not already in use. Investigative functions as shown in Figure 4.4 enable us to
make these assertions.
• Postconditions. These pertain to mappings from investigative functions to inves-
tigative functions.
In developing a transformation related to a particular design pattern, we aim to reuse
previously defined transformations. For example, a class may register another class only
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 87
via an interface (we call ABSTRACTION). These design motifs lead to primitive de-
sign pattern transformations as shown in Figure 4.4. By focusing on the development of
primitive design pattern transformations, we are able to build a library of useful transfor-
mations that can be reused. Each of the primitive design pattern transformation which
will be further elaborated in Section 5.5 has the following structure :
• Preconditions. They must hold in order to be able to apply a transformation.
Investigative functions as shown in Figure 4.4 enable us to make these assertions.
• Transformation Process. This is a concise, step-by-step description on how to
carry out and implement transformations. The proposed transformation process
is facilitated by the application of the investigative functions, supportive functions,
and positioning transformations.
• Postconditions. These pertain to mappings from investigative functions to inves-
tigative functions. They denote specific conditions that must hold after a transfor-
mation is applied.
• Possible Effect on Soft-goals. The goal is to formalize and automate the ap-
plication of transformations that affect the specific target quality for the migrant
system. This part associates each transformation to one or more non-functional
requirement.
Consequently, the primitive design pattern transformations can be combined to pro-
duce complex transformations related to different design patterns as shown in Figure 4.4.
A complete list of the complex design pattern transformations will be presented in Sec-
tion 5.7.
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 88
4.3 Algebra for Composing Software Transformations
In order to reason about a subject, a representation of its various elements is required.
If the reasoning is to be carried out with mathematical rigor, the representation must be
a formal model of the subject. Such a model must satisfy three requirements [111] : i) it
must be complete with respect to the essential aspects of the subject being modelled,
ii) it must be predictive and the conclusions drawn from the model must correspond to
the result obtained by observing the subject itself, iii) it must be well formed and sound
in the sense that the model should not permit fallacious and inconsistent reasoning.
The representation we choose is that of a state space that is a collection of named
abstract objects, each capable of holding a value taken from a predefined set of legitimate
values. Then, we need to define an abstract machine which is defined by abstract objects
and abstract operations on these objects. An abstract machine M is defined by a pair
M = (d, F ) where d is the state of M , and F is a set of transformations for affecting
state changes. The transformations fi ∈ F act upon a set of data objects {O1, ..., On}.
The state d is given by the states of object Oj .
An object O is defined by a triple O = (n, v, t) where n is its name, v is its value, and t
is its type. The name of an object may be used to reference the object in a transformation
description. The value of an object defines the state of the object. The type of an object
defines the form of its value and the operations that may legitimately be performed upon
it. The set of transformations F of an abstract machine M may be embedded into an
abstract language. Then the state d of an abstract machine M is given by the values
of objects that can be created, given a name, and assigned a value, using this abstract
language. That is, the state d at a specific instant is given by the values vi of the objects
of a program written in the abstract language. That is d = (v1, ..., vn). In addition, the
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 89
state space D of a program may be defined as the Cartesian product D = D1× ...×Dn of
the sets Di of the legitimate states (value ranges) of all the objects Oi references by that
program. Legitimate input-output values may then be identified by defining subspaces
of the state space D.
4.3.1 Approaches for Defining Semantics
Having realized that our concern is with transformation semantics, we must now review
the various approaches to the formal definition of the semantics of language constructs.
Work in this field fits into one of three major categories namely operational, denotational,
and axiomatic approaches [161]. The three approaches are depicted in Figure 4.5, where
P denoted a program written in a programming language and D denotes the state space
of that program.
With the operational approach, a program P is translated into a program T (P ) written
in the abstract language of a more primitive abstract machine. As a consequence, the
program state space D is mapped onto the state space T (D) of the program T (P ).
Program T (P ) semantics are implicitly defined by the semantics of the programming
constructs in T (P ), which are assumed to be unambiguous and obvious. In order to
explicitly define the semantics of P , test cases TC for program P are defined. These test
cases T (TC) that are based on T (D). The semantics of program P can then be defined
explicitly by executing program T (P ) for the test cases T (TC).
With the denotational approach, an appropriate value space V must be defined onto
which the state space D can be mapped. The program P is then transformed into a pro-
gram V (P ) in a programming language that allows an association between programming
constructs and values in V to be established. Finally, semantic valuation functions are
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 90
V(P) V
SemanticValuation
DeductionP D
ImplicitDefinition
T(P) T(D) TC
T(TC)
Denotational
Operational
Approach
Axiomatic
Approach
Approach
Execution
Figure 4.5: Comparison of Approaches.
defined that associate the programming constructs in V (P ), and V (P ) itself, with the
appropriate subspaces of the value space V . Hence, the semantics of the program V (P )
are explicitly defined. The semantics of program P are indirectly defined by virtue of the
conversion of program P to program V (P ).
The axiomatic approach is the most straightforward. With it the programming con-
structs in a program are directly mapped onto a state space D by the explicitly defined
semantics of the program P . The idea of axiomatic approach is to associate semantics
of language constructs with logical assertions of two kind. The first, an input assertion,
is assumed true prior to execution of a transformation, and form it and the nature of
the construct a second assertion, the output assertion, is derived that is true after execu-
tion of the construct. The pair of assertions thus characterize legitimate construct input
and output states and hence the effect of the construct. Assertions are derived from the
construct space and the construct.
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 91
4.3.2 An Algebraic Framework for Transformations
The framework presented in this section consists of a specification language for transfor-
mations, algebraic semantics for program transformations, and compositional techniques
for transformations of programs. The goal of this section is to provide a suitable frame-
work for verifying and deriving transformations based on the software transformation
framework which was discussed in Section 4.2. A hierarchy of this specification language
is depicted in Figure 4.6.
As depicted in Figure 4.6, investigation functions are boolean expressions in our lan-
guage in the form of preconditions or postconditions. Also, we were able to fit our
transformations in two different categories, namely quality dependent and quality altering
based on the proposed software transformation framework in Section 4.2.
As shown in Figure 4.6, we have discovered that there are four operators in which we
can compose transformations as follows :
1. Choice (+) is a selection operator that allows for a transformation to be selectively
applied among alternative ones based on the validity of its preconditions which is
computed by the source code features.
2. Sequential Composition (;) is where a sequence of transformations are applied one
after the other. For example, the following chain adds methods foo and bar to the
class c.
addMethod(c,foo) ; addMethod(c,bar)
3. Parallel Composition (‖) is where a set of transformations are performed concur-
rently.
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 92
Operators
Transformations
Expressions
Quality Altering
Quality Independent
Positioning Transformations
Supporting Functions
Primitive Transformations
Numerical Expression
Measurement
Arithmetic
Composite WFF
Precondition
Postcondition
Boolean Expression
Predicates (Investigating Functions)
General Purpose Function (Sorting)
Complex Transformations
Chioce (+)
Parallel Composition (||)
Iteration (*)
Sequential Composition (;)
Algebraic Framework
Figure 4.6: Specification Language for Software Transformation Framework.
4. Iteration (*) is where a transformation or a chain of transformations is performed
on a set of program elements. For example, the following set iteration copies all the
methods of the class a to the class b (e.g., (addMethod)∗).
ForAll m:Method, if classOf(m)=a then {addMethod(b,m)}
The language is given as an extended process calculus with the following constructors.
This is because process calculi provide a well-founded basis for analyzing this type of
computation. The other constructions of this calculus are basically inherited from those
of existing process calculi [89, 122].
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 93
• Let A be a finite domain denoting predicates which are investigation functions from
our transformation framework. Its elements are denoted as a, b, ...
• Let A be a finite domain complementary to A. Its elements are denoted as a, b, ...
where a is the complementary function (i.e., negated) with respect to a.
• Let L ≡ A ⋃ A be a set of boolean expression names. Elements of the set are
written as `, `′, ...
• Let τ denote any composite well-formed formula (wff).
• Let√
denote a program termination.
• Let Act ≡ L ⋃ {τ} be the set of boolean expressions. Its elements are denoted
as α, β, ...
It is worth mentioning that the calculus is designed as just a specification language
for describing transformations. The set T of transformations of the calculus, ranging over
T1, T2, ... is defined recursively by the following abstract syntax :
T ::= 0 | (π) | if π then T1 else T2 | while π do T1 | T1;T2 | T1‖T2 | T1 + T2 | T1∗ | A
π ::= ` | ¬π1 | π1 ∧ π2 | π1 ∨ π2
A is a variable and is always used in the form Adef= T . We assume that in A
def= T , T is
always closed, and each occurrence of A in P is only within some subexpressions, (π);A
where π is not empty. In (`1 | ... | `n), `1, ...`n are distinct and we denote (π) as () when
π is empty. In Adef= T , we have L(T ) ⊆ L(A). We describe an empty element of L(T ) as
ε. The intuitive meanings of some basic expressions in the calculus are as follows :
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 94
• 0 represents a terminated transformation.
• (`1 | `2);T represents that a transformation performs either `1 followed by `2 and
then T , or `2 followed by `1 and then T .
• T1 ; T2 denotes the the sequential composition of two transformations T1 and T2.
If the application of T1 terminates then the execution of T2 follows that of T1.
• T1 ‖ T2 expresses that T1 and T2 can apply in parallel. Note that T1 does not
contain all predicates included T2 and vice versa.
• T1∗ denotes that T1 can apply iteratively. This can be implemented as a conditional
branch, for example an if-then-else statement or a while-loop given in the form of
inference rules for the transformations.
• T1 + T2 can apply either T1 or T2 nondeterministically provided the appropriated
preconditions hold.
• Adef= T has an identifier A and occurrences of A in expressions are interpreted as T .
The operational semantics of the calculus is defined as a labelled behavioral transition
rules [122] written as :
µ−→(−→⊆ T × (A⋃
{√})× T )
This defines the semantics of functional behaviours of transformations. For example,
T µ−→T ′ means that T performs boolean expression and then behaves as T ′. The def-
inition of the semantics also uses a structural congruence (≡) over expressions in T as
studied in [122]. ≡ is defined as follows :
(1) T1; (T2;T3) ≡ (T1;T2);T3
0;T ≡ T
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 95
(2) T1‖T2 ≡ T2‖T1T‖0 ≡ T
T1‖(T2‖T3) ≡ (T1‖T2)‖T3
(3) T1 + T2 ≡ T2 + T1
T + T ≡ T
(4) A ≡ T if Adef= T
(5) () ≡ 0
π1 ∧ π2 ≡ π2 ∧ π1
π1 ∨ π2 ≡ π2 ∨ π1
The algebra is a labelled transition system
⟨
T , A⋃
{√},{
µ−→ ⊆ T × T | µ ∈ A⋃
{√}} ⟩
The transition relation −→ is defined by the following structural induction rules as
given below :
(1) −
(`1|...|`i|...|`n)`i−→(`1|...|`i−1|`i+1|...|`n)
(2) −
0√−→ε
(3) −
T1+T2τ−→T1
(4) T1α−→T1
′
T1;T2α−→T1
′;T2
(5) T1α−→T1
′
T1‖T2α−→T1
′‖T2
(6) T1`−→T1
′ T2`−→T2
′
T1‖T2τ−→T1
′‖T2′
(7) T1≡T2 T1α−→T1
′ T1′≡T2
′
T2α−→T2
′
CHAPTER 4. SOFTWARE TRANSFORMATION ALGEBRA 96
where α ∈ Act and ` ∈ L, π is not empty, ε is an empty symbol of T and α is a
boolean algebra in A.
In this section, we have shown how an algebraic framework can be used to specify
the transformations commonly occurring during software maintenance. The next chapter
describes the application of the algebra given in this section to produce a catalogue of
source-code improving transformations.
4.4 Summary
Building on related work on refactoring [71], we have proposed a classification scheme of
the standard design patterns [72] in a way that we believe can assist software maintainers
to better assess the impact of these design patterns when applied to object-oriented soft-
ware restructuring. This scheme is based on three primary relationships between patterns
such as : i) a pattern uses another pattern, ii) a pattern refines another pattern, iii) a
pattern conflicts with another pattern as well as three secondary relationships between
patterns such as : i) a pattern is similar to another one, ii) two patterns combine to solve
a single problem, iii) a pattern requires the solution of another pattern. These classifi-
cations motivate us to update the catalogue and organize the design patterns into two
layers representing different abstraction levels.
The framework presented in this chapter also consisted of a specification language
for transformations, algebraic semantics for program transformations, and compositional
techniques for transformations of programs.
Chapter 5
Code-Improving Transformations
Catalogue
A complex system that works is invariably found to
have evolved from a simple system that worked.
John Gall
As discussed, we have considered a class of transformations where a program is trans-
formed into another program in the same language (source-to-source transformations)
and that the two programs may differ in specific qualities such as performance and main-
tainability. It is generally such differences and enhancements that motivate program
transformations.
In this chapter, we define transformations, stating their preconditions and postcondi-
tions, and their possible impact on non-functional requirements. Section 5.1 explains the
usage of first-order predicate logic as the mathematical notations for specifying precondi-
tions and postconditions in the catalogue of transformations. While Sections 5.2, and 5.3
explain proposed functions in this research work, Sections 5.4, 5.5, and 5.7 discuss each
transformation in detail using first-order predicate logic (FOPL) notation. Section 5.6
97
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 98
presents the impact of the transformations on soft-goal interdependency graphs. Finally,
Section 5.8 gives a summary of this chapter.
5.1 Mathematical Notations
In this research work, we specify preconditions and postconditions in first-order predicate
logic (FOPL) [111]. In addition to the standard logic symbols {¬,∧,∨,→,≡,=, ∃, ∀},
FOPL includes a set of extralogical symbol that specify the various functions and pred-
icates. A basic for predicate logic is a pair B = (F, P ) where F is the set of function
symbols and P is a set of predicate symbols. The functions and predicates that we have
mentioned in Section 4.2 make up the basis that we use. Since a well-formed formula
(WFF) in FOPL has no meaning apart from an interpretation, we must also define what
interpretation we will be using to assign meanings to well-formed formulae. An interpre-
tation of FOPL, I = (D, I0), is a pair where D is the domain of discourse and I0 is a
mapping which assigns values from within D to the symbols within F and P [111].
In our application, the domain D consists of program elements. In particular, it
contains the classes,variables, and methods of the program that is being transformed.
The predicate and functions symbols represent various program analysis that can be
computed for the program.
We use the following notation based on [111] and also used in [149]. This will be used
extensively in this section where it will be necessary to be precise about the effect of a
transformation on a program.
• P : This is the program to be transformed or refactored.
• IP : Denotes an interpretation of first-order predicate logic where the universe of
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 99
discourse comprises the program elements of P, and the functions and predicates
of the calculus reflect the investigating functions as applied to the program P.
• |= IPpreR : Denotes the evaluation of the precondition of the transformation R on
the program interpretation IP .
• postR(IP) : Denotes the program interpretation IP , rewritten with the postcondi-
tion of the transformation R.
• f [x/y] : Denotes a function which maps the element x to y. This syntax is used in
postconditions to describe the effect of the transformation on the functions. Note
that the name of a new function produced as the result of applying a transformation
is written with a prime (′), so stating that the function f is updated with the new
element (x, y) would be written thus : f ′ = f [x/y].
• ⊥ : Uses in a postcondition to mean an undefined value. For example, if a trans-
formation removes a method called m, the updating of the classOf investigation
function to indicate that m no longer belongs to any class would be written thus :
classOf ′ = classOf [m/ ⊥].
5.2 Investigative Functions
As explained, these functions serve two related roles in our work. Firstly, they are imple-
mented as actual operations that can be applied to an object-oriented program to extract
some information about the program. Secondly, they are used as predicates examining
whether a specific transformation can be applied in a specific source code context. For
example, to test whether a method is in a certain class or to find the signature of a given
method. The relationship between these two roles is that the latter is the implementation
of the former.
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 100
In describing a refactoring or its precondition, it is necessary to refer to various pro-
gram elements : classes, methods, interface, etc. The principle elements that we make
use of, and their interrelationships, are depicted by a UML diagram model illustrated in
Figure 5.1. Other program entities that are used in defining refactorings and investiga-
tive functions are : Interface, Argument, ObjectReference, Field, Parameter, Expression,
Variable, and MethodInvocation.
Class
Method
Signature
Constructor
1 *
1
*
1
*
0..* 0..1
*
1
*
1
*
1
classCreated
contains
sigOfsigOf
createsSameObject
contains constructorInvoked
ObjectCreationExpr
Figure 5.1: Principle Program Entities and Their Relationships.
As we described before, these functions are used to extract information from the
program being transformed. For each investigative function, we specify its name, return
type, argument types, and provide a brief textual description of what its purpose is.
Table 5.1 shows a list of proposed investigative functions in this research work, however
they are described with more details in an alphabetic order on Appendix A.
The investigative functions are not completely unrelated and this is unavoidable. For
example, it is important to know whether one class defines a subtype of another class,
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 101
No. Name Purpose
Inv1 argument An argument from a given method.
Inv2 classCreation A class that can be created by a given constructor.
Inv3 classOf A class to which the given method belongs.
Inv4 containClass A class that contains a given object reference.
Inv5 containMethod A method that contains a given object reference.
Inv6 contstructorInv A constructor that is invoked by a given object.
Inv7 createsObject True if a method creates a new object of the same class.
Inv8 creates True if a method creates an object of the same class.
Inv9 declares True if a class contains a method in its interface.
Inv10 defines True if a concrete method contains in a (super)class.
Inv11 equalInterface True if two interfaces declare the same public methods.
Inv12 implmInterface True if there is a link from an interface to another.
Inv13 initializes True if a method initializes the field to the expression.
Inv14 isAbstract True if a class/method is declared to be abstract.
Inv15 isClass True if there is a given class in the program.
Inv16 isInterface True if there is a given interface in the program.
Inv17 isPrivate True if a method/field is a private member of its class.
Inv18 isPublic True if a method/field is a public member of its class.
Inv19 isStatic True if a method/field is a static member of its class.
Inv20 isSubtype True if the type defined by class1 is a subtype of thetype defined by class2.
Inv21 localVars A set of the local variables
Inv22 methodsInv Returns the set of invoked methods.
Inv23 name Name of a given class/interface/method/constructor.
Inv24 noOfArg Returns the number of the arguments.
Inv25 noOfPar Returns the number of the parameters.
Inv26 par Returns a parameter.
Inv27 returnsObject True if a method returns an object of a class.
Inv28 returnType Returns the class/interface of a method.
Inv29 sigOf Signature of a given method/constructor.
Inv30 superClass Direct superclass relationship of a class.
Inv31 type Returns the class/interface of a given reference.
Inv32 uses True if a method directly reference a field or invokedby another method or object reference.
Table 5.1: A List of Investigative Functions.
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 102
as this affects what type of refactorings are possible involving these classes. It is also
important to be able to determine if one class has an extends link to another class. If
we determine that the class B extends the class A, then we know that B must also be
a subtype of A. It is important to note these relationships and to use them in proofs as
necessary. The relationship between the investigative functions we use are as follows :
• If a method is in a class, that class defines the method directly and vice versa :
∀ c : Class,m : Method, classOf(m) = c ⇐⇒
defines(c, name(m), sigOf(m), direct)
• If a class defines a method, it declares it as well :
∀ c : Class,m : Method, defines(c, name(m), sigOf(m))⇒
declares(c, name(m), sigOf(m))
• If a method and constructor return the same object, they must have the same
signature :
∀ m : Method, c : Constructor, returnsObject(c,m)⇒ sigOf(m) = sigOf(c)
• Two classes/interfaces have the same interface if each one is a subtype of the other :
∀ e1 : Class/Interface, e2 : Class/Interface, equalInterface(e1, e2) ⇐⇒
isSubtype(e1, e2) & isSubtype(e2, e1)
• If a class/interface implements another interface, it must be a subtype of that
interface :
∀ e : Class/Interface, i : Interface, implmInterface(e, i)⇒ isSubtype(e, i)
• If a class extends another class, it must be a subtype of that class :
∀ c1 : Class, c2 : Class, superclass(c1) = c2 ⇒ isSubtype(c1, c2)
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 103
• If a class is abstract, it must declare a method that is does not define :
∀ c : Class, isAbstract(c) ⇐⇒ ∃ m : Method such that
declares(c,m) & ¬defines(c,m)
• One class creates another if there is an object creation expression contained in the
first class (or any superclass) that creates an instance of the second class :
creates(c1, c2) ⇐⇒ ∃ o : ObjectCreationExprn,m : Method such that
classCreation(o) = c2 ∧ containMethod(o) = m ∧
classOf(m) ∈ c1⋃
superclass(c1)
• If a method creates and returns the same object as a constructor, it also returns it :
∀ c : Constructor,m : Method, createsObject(c,m)⇒ returnsObject(c,m)
5.3 Supporting Functions
In describing a transformation, it may be necessary to extract richer content from the
program code than is provided by the investigative functions. For example, we may
wish to build an interface from a class based on the signatures of its public methods.
Supporting functions are used to perform this type of task. Because they are not at
the primitive level of the investigative functions, we provide them with a precondition
and postcondition. Supporting functions are proper functions without side-effects on
the program, so the postcondition invariably involves the return value of the supporting
function itself. Table 5.2 shows a list of proposed supporting functions in this research
work, however they are described with more details in an alphabetic order on Appendix B.
5.4 Positioning Transformations
The positioning transformations or primitive refactoring that are used in this work are
presented in this section. Most of them are standard and would be part of any refactoring
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 104
No. Name Purpose Pre-cond Post-cond
Sup1 abstractClass Construct and return an 1) Inv15 1) (Inv16interface that reflect ∧all the public methods Inv11)of a given class. 2) Inv23
Sup2 abstractMethod Construct and return a 1) True 1) (Inv14 ∧a method that has the Inv23 ∧same signature as a method. Inv29)
Sup3 emptyClass Construct and return 1) True 1) (Inv23 ∧an empty class. ¬Inv3)
Sup4 makeAbstract Returns a method creates 1) True 1) (Inv7the same object as a ∧constructor. Inv23)
Sup5 wrapperClass Creates a wrapper class. 1) ¬Inv16 1) Inv232) (¬Inv15 2) (Inv3 ∧
∧ Inv26 ∧¬Inv16) Inv13)
3) Inv134) (Inv3 ∧
Inv23)5) Inv27
Table 5.2: A List of Supporting Functions.
suite, for example, addClass [71]. Others are quite particular to this work, for example,
replaceObject which replaces a given object creation expression with an invocation of a
given method using the same argument list. Table 5.3 shows a list of proposed positioning
transformations in this research work, however they are described with more details in
an alphabetic order on Appendix C.
5.5 Primitive Design Pattern Transformations
Six primitive design pattern transformations have been identified. They are the design
motifs that occur frequently; in this way it is similar to design patterns but these are
lower level constructs. The key aspect of this approach is that the decision of what trans-
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 105
No. : Name Purpose Precondition PostconditionPos1: Removes a 1) Inv25 1) Inv25
absorbParameter parameter 2) (Inv22 ∧ Inv1) 2) (Inv21 ∧from a method. Inv23 ∧ Inv31)
3) Inv13
Pos2: Makes public 1) (Inv3 ∧ Inv15) 1) (Inv10 ∧abstractMethodFromClass a method/field Inv32 ∧ Inv18)
from a class.Pos3: addClass Adds a class. 1) (¬Inv15 ∧ Inv16) 1) Inv15
2) Inv30 2) Inv30
3) (Inv9 ∧ ¬Inv10 ∧Inv23 ∧ Inv29)
4) Inv10
5) ¬Inv17
6) (¬Inv17 ∧ Inv23)Pos4: addGetMethod Adds a method 1) Inv15 ∧ Inv3 1) Inv3 ∧ Inv23
to a concrete class 2) (Inv9 ∧ Inv23) 2) Inv27
Pos5: Adds a link from a 1) (Inv15 ∧ Inv16) 1) Inv12
addImplementsLink class to an interface. 2) (Inv9 ∧ Inv10)Pos6: addInterface Adds an interface. 1) ¬Inv15 ∧ ¬Inv16 1) Inv16
Pos7: addMethod Adds a method. 1) (Inv15 ∧ ¬Inv10) 1) Inv3
2) Inv11
Pos8: Adds a static 1) Inv30 1) Inv3
addSingletonMethod field and method 2) Inv23 2) Inv23
to a class. 3) Inv17 3) Inv27 ∧4) ¬ Inv10 Inv25
5) Inv25
Pos9: Adds a new 1) Inv15 1) (Inv31 ∧createExclusiveComponent component to a 2) (Inv30 ∧ Inv23)
class. ¬ Inv17 ∧ Inv23) 2) Inv13
Pos10: Makes constructors 1) Inv15 1) Inv3
makeConstructorProtected protected. 2) (Inv2 ∧ Inv30) 2) Inv11
Pos11: moveMethod Moves a method. 1) Inv15 ∧ Inv31 1) Inv3
2) (Inv32 ∧ Inv18) 2) (Inv3 ∧3) (Inv31 ∧ Inv23 ∧ Inv29
Inv23 ∧ Inv29) Inv32)Pos12: Moves the 1) Inv15 ∧ Inv16 1) (Inv35 ∧parameterizeField initialization 2) Inv31 Inv31)
of a field. 3) Inv13 2) Inv25
Pos13: Moves a method. 1) Inv10 1) Inv3
pullUpMethod 2) (¬Inv18 ∧ 2) Inv9
Inv23) 3) Inv3
Pos14: Changes type 1) Inv16 ∧ Inv12 1) Inv31
replaceClassWithInterface of an object. 2) ¬ Inv32
Pos15: replaceObject Replaces an object. 1) Inv7 ∨ Inv27 1) Inv5
Pos16: Updates client 1) Inv15 ∧ Inv11 1) Inv31
useWrapperClass class. 2) Inv27 2) Inv28
Table 5.3: A List of Positioning Transformations.
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 106
formation rule should apply and where to apply it, depends on the desired improvement
of quality which a developer has as a goal. We have formalized the application of trans-
formations that affect quality. Also, our aim is to remove the burden of tedious and error
prone code reorganization from the developer to improve the quality in a re-engineering
environment. Each transformation in this category comprises a precondition, and algo-
rithmic description, a postcondition, and its impact on quality. While the body of this
section analyzes the process for each of the these transformations which is also shown in
Table 5.4, their complete structures in the form of precondition, transformation process,
postcondition are presented on Appendix D.
5.5.1 ABSTRACTION Transformation
This transformation aims to add an interface to a class. This enables another class to
take a more abstract view of the first class by accessing it via the newly added interface.
It requires two parameters namely : i) the name of the class to be abstracted (c), and
ii) the name of the new interface to be created (newInterface).
For the applicability of the transformation, we need first to evaluate preconditions in
the source code using investigative functions as follows : 1) the class c exists and 2) no
class or interface with the name newInterface exists.
Then, the transformation entails the following steps : 1) an interface to be created
using abstractClass supporting function that reflects the public methods of this class,
2) the addition of this interface to the program using positioning transformations such as
addInterface(newInterface), and 3) the addition of an implements link from the class to
the newly created interface using a positioning transformation.
Finally, the following conditions must hold after applying the transformation : 1) a
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 107
new interface called newInterface exits, 2) the class c and the new interface have the
same public interface, and 3) an implements link exists from the class c to the interface
newInterface. The detailed process of this transformation based on our proposed process
algebra are depicted in Table 5.4.
5.5.2 EXTENSION Transformation
This transformation aims to construct an abstract class from an existing class and to
create an extends relationship between the two classes. It is related to ABSTRACTION
transformation but rather than building a completely abstract interface from the class,
it builds an abstract class where only certain specified methods are declared abstractly.
This transformation requires three parameters namely : i) the name of the existing class
(oldClass), ii) the name of the class to be created (newClass), and iii) the name of the
methods to be abstracted (abstractMethods).
For the applicability of the transformation, we need first to evaluate preconditions in
the source code features using investigative functions as follows : 1) no class or interface
with the name newClass may exist, 2) the oldClass must exist, and 3) any fields used by
methods that are to be pulled up must not be public.
Then, the transformation requires for its application the following steps : 1) to create
an empty class called newClass using the emptyClass supporting transformation, 2) to
insert the newly created class into the inheritance hierarchy just above the oldClass using
the addClass positioning transformation, 3) to add for each method in abstractMeth-
ods to this new class using addMethod positioning transformation, and 4) to move any
methods not in abstractMethods from the oldClass to the newly created class using the
pullUpMethod positioning transformation.
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 108
Name Preconditions Transformation Process PostConditionsABSTRACTION Inv15 ∧ Inv16 Sup1 ; Pos6 ; Pos5 Inv23 ∧ Inv16 ∧
Inv11 ∧ Inv12
¬Inv15 ∧ ¬Inv16 ∧ Sup3 ; Pos3 ; Inv15 ∧ Inv11 ∧EXTENSION (¬Inv32 ∨ ¬17) (Sup2 ;Pos7)
∗ ; (Pos13)∗ Inv3 ∧ Inv9 ∧
Inv30 ∧ Inv32
¬Inv15 ∧ Inv16 ∧ Pos3 ; Pos9 ; Inv15 ∧ Inv31 ∧MOVEMENT (Inv17 ∨ (Pos2 ; Pos11)
∗ Inv23 ∧ Inv10 ∧¬(Inv23 ∧ Inv30)) Inv32 ∧ Inv18
(Sup2 ; Pos7 )∗; Inv5 ;ENCAPSULATION Inv15 ∧ ¬Inv10 (Pos15)
∗ Inv23 ;Inv10
Inv15 ∧ Inv16 ∧ Inv31 ∧BUILDRELATION Inv12 ∧ Inv19 ∧ (Pos14)
∗ Inv4 ∧Inv31 ∧ ¬Inv32 Inv23
¬Inv15 ∧ ¬Inv16 ∧ Inv15 ∧WRAPPER Inv4 ∧ Inv12 ∧ Sup5 ; Pos3 ; (Pos16)
∗ Inv12 ∧ Inv31 ∧Inv32 ∧ Inv9 Inv4 ∧ Inv2
Table 5.4: A List of Primitive Design Pattern Transformations.
Finally, these conditions must hold after the application of the transformation : 1) a
new class called newClass exists, 2) the oldClass and its new superclass define precisely the
same type, 3) all methods in oldClass not in abstractMethods are moved to the superclass,
4) any method in abstractMethods will have an abstract method declared in the class called
newClass, and 5) any fields used by the moved methods are also moved to the superclass.
The detailed process of this transformation based on our proposed process algebra are
depicted in Table 5.4.
5.5.3 MOVEMENT Transformation
This transformation aims to move parts of an existing class to a component class, and
to set up a delegation relationship from the existing class to its component. This one
requires three parameters namely : i) the name of the existing class (oldClass), ii) the
name of the new class to be created (newClass), and iii) the name of the methods to be
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 109
moved (moveMethod).
For the applicability of the transformation, we need to evaluate preconditions in the
source code features using investigative functions as follows : 1) the oldClass must exist,
2) the name of the newClass must not be used, and 3) the methods to be moved must
belong to the oldClass,
Then, the transformation requires the following steps for its implementation : 1) an
empty class to first be added to the program using addClass positioning transformation,
2) an exclusive component of this class to be added to the oldClass, 3) each method to be
moved first to be “abstracted” using the abstractMethod supporting function, 4) at this
point, the moveMethods positioning transformation may be invoked to move the method
to the new class.
Finally, these conditions must hold after applying the transformation : 1) a new class
called newClass has been added to the program, 2) the class oldClass has a field called
“movement”, 3) all methods or fields defined directly or indirectly in oldClass that are
used by a method in moveMethod are now public, 4) the given methods have been moved
to the newClass, and 5) the oldClass delegates invocations of the moved methods to
methods that exhibit the same behaviour in the newClass. The detailed process of this
transformation based on our proposed process algebra are depicted in Table 5.4.
5.5.4 ENCAPSULATION Transformation
This transformation aims to be applied when one class creates instances of another,
and it is required to weaken the association between the two classes by packaging the
object creation statements into dedicated methods. This transformation requires three
parameters namely : i) name of the class to be updated (creator), ii) name of the product
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 110
class (product), and iii) name of the new constructor method (createProduct).
For the applicability of the transformation, we need to evaluate preconditions in the
source code features using investigative functions as follows : 1) the class creator exists and
2) the creator class defines no method called createProduct that have the same signature
as a constructor in the class product.
Then, the transformation requires the following steps to be implemented : 1) for every
constructor in the product class, a new method called createProduct is created using
makeAbstract supporting function which performs this construction and to be added to
the creator class using the supporting functions, 2) all product objects created in the
creator class are replaced with invocations of the appropriate createProduct method using
a positioning transformation to replace the given object creation expression e with an
invocation of the method createProduct using the same argument list.
Finally, these conditions must hold after applying the transformation : 1) for every
product object creation expression in the creator class, a method called creatorProduct that
creates the same object is added to the creator class, and 2) every product object creation
expression in the creator class that is not contained in a method called createProduct
is deleted. The detailed process of this transformation based on our proposed process
algebra are depicted in Table 5.4.
5.5.5 BUILDRELATION Transformation
This transformation is appropriate when one class (c1) uses, or has knowledge of, another
class (c2), and the relationship between the classes to operate in a more abstract fashion
via an interface is required. This transformation requires four parameters namely : i) the
name of the class to be used (c2), ii) the name of the super class (c1), iii) the name of the
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 111
abstract interface to be used (usedInterface), and iv) the name of methods (methodName).
For the applicability of the transformation, we need to evaluate preconditions in the
source code features using investigative functions as follows : 1) the interface usedInterface
and the classes c1 and c2 exist, 2) an implements link exists from the class c2 to the
interface usedInterface, 3) any static methods in the c2 class are not referenced through
any of the object references to be updated, and 4) any public fields in the c2 class are
not referenced through any of the object references to be updated.
Then, the transformation requires the following steps to be implemented : 1) to regis-
ter each object reference in the class c1 that is of the type c2, 2) to exclude any references
that are contained in any method called methodName, 3) to modify their existing types
from the class c2 to the usedInterface.
Finally, these conditions must hold after applying the transformation : 1) all references
to the c2 class in the c1 class not in methodName have been changed to refer instead to the
usedInterface and 2) the initial conjuncts of the precondition simply ensure that referenced
classes and interface exist and have the proper relationship. The detailed process of this
transformation based on our proposed process algebra are depicted in Table 5.4.
5.5.6 WRAPPER Transformation
This transformation aims to “wrap” an existing receiver class with another class, in such
a way that all requests to an object of the wrapper class are passed to the receiver object
it wraps, and similarly any results of such requests are passed back by the wrapper. It
requires two parameters namely : i) the name of a single receiver class or a set of receiver
classes to be wrapped (client), ii) the name of an interface that reflects how the receivers
are used in the client classes (interfaceName), and iii) the name of the wrapper class
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 112
(wrapperName).
For the applicability of the transformation, we need to evaluate preconditions in the
source code features using investigative functions as follows : 1) the given interface must
exist and 2) the name for the new wrapper class is not in use.
Then, the transformation requires the following steps to be implemented : 1) the
wrapper class is created and added to the program and 2) the wrapper class is used to
wrap each of the receiver classes and, consequently, any clients that use these receiver
classes are updated to wrap each construction of a receiver class with an instance of the
wrapper class.
Finally, the following conditions must hold after applying the transformation : 1) the
wrapper class has been added to the program, 2) all object references to receiver classes
in client have been changed to wrapperName, and 3) all creations of receiver of objects in
the client have been updated. The detailed process of this transformation based on our
proposed process algebra are depicted in Table 5.4.
5.6 Modifications on SIGs with Transformations
While the soft-goal graphs as presented in Sections 3.4.1 and 3.4.2 provide specific in-
terpretation of what the initial non-functional requirement (NFR) of Maintainability and
Performance mean, they do not yet provide means for guiding the transformation process
and actually achieving the desired quality.
At some point, when the non-functional requirements have been sufficiently refined,
one must be able to identify and associate actions for achieving these NFR (which are
treated as NFR softgoals) and then assess the specific solutions for the target system.
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 113
������������������
������������������
������������������
������������������
������
������������������
� � ������
High Maintainability
High ControlQuality
ModularityHigh
CohesionHigh
High ModuleReuse
High Structure Quality
High Source Code Quality High Documentation Quality
Structure
BUILDRELATION ABSTRACTION MOVEMENT EXTENSION ENCAPSULATION
High
Low Data CouplingLow I/O Complexity
Encaps.High
+
-
_
++
+++ _ +
++ +++
-
+++
-
++
ConsistencyFlow
ControlHigh
WRAPPER
++--
+
+
+
LowControl
FlowCoupling Data Consistency
Legend
: NFR Soft-Goal
: Operationalization
: Contribution Link
Figure 5.2: Relating Primitive Design Patterns Transformations to Maintainability Soft-Goal Graph.
It is important to note that there is a “gap” between NFR softgoals and development
techniques. This section associates primitive design pattern transformations with the
maintainability and performance soft-goal graphs as shown in Figures 5.2 and 5.3. We
call these associations operationalizations of the NFR soft-goals [44]. Like other softgoals,
operationalizing softgoals makes a contribution, positive or negative, towards parent soft-
goals in terms of relations such as AND, OR, +, ++, or −, −−.
The proposed primitive design pattern transformations provide a body of knowledge
to modify soft-goal dependency graph for maintainability as shown in Figure 5.2. For
example, let us consider the challenge of achieving “High Cohesion” for a module in order
to satisfy “High Maintainability” as the top level target goal. One possible alternative is to
use the ABSTRACTION primitive design patterns transformation as shown in Figure 5.2.
In this case, ABSTRACTION is a development technique or operationalization that can
be implemented. It is a candidate for the task of meeting the high cohesion NFR as
a positive positive contribution (++). This is contrasted with “High Cohesion”, which
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 114
is still a software quality attribute, i.e., a non-functional requirement. We say that the
ABSTRACTION transformation operationalizes high cohesion. We also say that the high
cohesion NFR is operationalized by ABSTRACTION transformation. Operationalizing
softgoals are drawn as filled circles and are just another type of soft-goal graph nodes.
����
������������������
������������������
������������������
������������������
������������������
������������������������������
��������
� � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � � �
!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!!�!�!�!�!�!�!�!�!�!�!�!�!�!�!
"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�""�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"�"
#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�##�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#�#
$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$$�$�$�$�$�$�$�$�$�$�$
%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%%�%�%�%�%�%�%�%�%�%
&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&�&
'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�''�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�''�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�''�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�''�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�''�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�''�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�''�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�''�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�''�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�''�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�''�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�''�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�''�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�''�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'�'
(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�((�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(�(
)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�))�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)�)
*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�**�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*�*
+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�++�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+�+
,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,�,
-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�--�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-�-
.�.�.�.�.�..�.�.�.�.�..�.�.�.�.�..�.�.�.�.�..�.�.�.�.�..�.�.�.�.�..�.�.�.�.�..�.�.�.�.�..�.�.�.�.�..�.�.�.�.�..�.�.�.�.�..�.�.�.�.�..�.�.�.�.�..�.�.�.�.�..�.�.�.�.�..�.�.�.�.�.
/�/�/�/�//�/�/�/�//�/�/�/�//�/�/�/�//�/�/�/�//�/�/�/�//�/�/�/�//�/�/�/�//�/�/�/�//�/�/�/�//�/�/�/�//�/�/�/�//�/�/�/�//�/�/�/�//�/�/�/�//�/�/�/�/
0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�00�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�00�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�00�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�00�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�00�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�00�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�00�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�00�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�00�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�00�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�00�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�00�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�00�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�00�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0�0
1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�11�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�11�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�11�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�11�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�11�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�11�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�11�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�11�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�11�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�11�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�11�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�11�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�11�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�11�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1�1
2�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�22�2�2
3�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�33�3�3
44444444444444444444444
55555555555555555555555
6�6�6�6�6�6�6�6�66�6�6�6�6�6�6�6�66�6�6�6�6�6�6�6�66�6�6�6�6�6�6�6�66�6�6�6�6�6�6�6�66�6�6�6�6�6�6�6�66�6�6�6�6�6�6�6�66�6�6�6�6�6�6�6�66�6�6�6�6�6�6�6�66�6�6�6�6�6�6�6�66�6�6�6�6�6�6�6�66�6�6�6�6�6�6�6�66�6�6�6�6�6�6�6�66�6�6�6�6�6�6�6�6
7�7�7�7�7�7�7�7�77�7�7�7�7�7�7�7�77�7�7�7�7�7�7�7�77�7�7�7�7�7�7�7�77�7�7�7�7�7�7�7�77�7�7�7�7�7�7�7�77�7�7�7�7�7�7�7�77�7�7�7�7�7�7�7�77�7�7�7�7�7�7�7�77�7�7�7�7�7�7�7�77�7�7�7�7�7�7�7�77�7�7�7�7�7�7�7�77�7�7�7�7�7�7�7�77�7�7�7�7�7�7�7�7
8�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�88�8�8�8�8�8�8�8�8�8�8
9�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�99�9�9�9�9�9�9�9�9�9�9
:�:�:�::�:�:�::�:�:�::�:�:�::�:�:�::�:�:�::�:�:�::�:�:�::�:�:�::�:�:�::�:�:�::�:�:�::�:�:�::�:�:�::�:�:�::�:�:�::�:�:�::�:�:�::�:�:�::�:�:�::�:�:�::�:�:�::�:�:�:
;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;;�;�;�;
<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<<�<�<
=�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�==�=�=
>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>>�>�>�>�>�>�>�>�>�>�>�>
?�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�??�?�?�?�?�?�?�?�?�?�?�?
@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@�@
A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�AA�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A�A
B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�BB�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B�B
C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�CC�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C�C
D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�DD�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D�D
E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�EE�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E�E
F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�FF�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F�F
G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�GG�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G�G
Good Performance
Performance
Low Secondary Storage Utilization
Good Space Performance
High Throughput
+
+
-
Good Time
: NFR Soft-Goal
: Operationalization
: Contribution Link
Legend:
MOVEMENT EXTENSION WRAPPERABSTRACTION
++
+
-
++
++
-
+
-
++
ENCAPSULATION BUILDRELATION
+
+++
++
-
+
+
Low Time Running
Low CPU Time
Main MemoryLow
Utilization
Low Response
Time
Low User CPU Time
Low System CPU Time
Low I/OActivities
Figure 5.3: Relating Primitive Design Patterns Transformations to Performance Soft-Goal Graph.
5.7 Complex Design Pattern Transformations
In this section we discuss how design patterns in the GoF book [72] can be defined
as a composition of the primitive design pattern transformations which were discussed
so far. While we discuss the creation of a subset of the GoF patterns in the body of
this section, Table 5.5 shows the transformation process for each pattern based on our
proposed algebra.
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 115
HIHHIHHIHJIJJIJJIJ
KIKKIKKIKLILLILLIL
MIMMIMMIMNINNINNIN
OIOOIOOIOPIPPIPPIP
QIQIQQIQIQRIRIRRIRIR
SISISSISISSISISTITTITTIT
UIUUIUUIUVIVVIVVIV
High Maintainability
High ControlQuality
ModularityHigh
CohesionHigh
High ModuleReuse
High Structure Quality
High Source Code Quality High Documentation Quality
Structure
BUILDRELATION ABSTRACTION MOVEMENT EXTENSION ENCAPSULATION
High
Low Data CouplingLow I/O Complexity
Legend
Encaps.High
: Operationalization
: NFR Soft-Goal
: Target
+
-
_
++
++
++
Control Low
+ _ +++ +++
+
-
+++
-
Flow Coupling++
ConsistencyFlow
ControlHigh
: Design Target Link
: Contribution Link
DP Generator
Composite orPrototype
Factory Method orAbstract FactoryDP Generator DP Generator
Decorator or ProxyBuilder or Adaptor or State or
StrategyDP Generator
SingletonDP DP
GeneratorGenerator
Bridge
DP Generator
Chain ofResponsibility
WRAPPER
Template Method DPGenerator
MementoDPGenerator
IteratorDPCommands
DPGenerator Generator
Data Consistency
--
++
+
Figure 5.4: Relating Transformations to Maintainability Soft-Goal Graph.
Some of the fundamental and commonly used GoF patterns that we may consider
are the “Factory Method” from Creational Patterns category, the “Composite” from
Structural Patterns category, and the “Iterator” from Behavioral Patterns category. These
are sufficiently complex to illustrate the use of the proposed transformation composition.
Figure 5.4 depicts the level of reuse of the primitive transformations for these three
design patterns of the Gamma et al catalogue. As it can been seen, a considerable level
of reuse was achieved. As shown in Figure 5.4, when a primitive transformation (also is
called operationalization which is a possible design alternative for meeting NFRs in the
target system [44]) makes a contribution towards one or more parent soft-goals, it is re-
lated to the latter in terms of a link labelled +, ++, or −, −−. A simple example of this
interdependency graph is that the transformation “Factory Method Design Pattern Gen-
erator” contributes very positively (++) to the soft-goal high control flow consistency and
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 116
negatively (−) to the soft-goal low I/O complexity using “BUILDRELATION” primitive
design pattern transformation (a type of operationalization which can be implemented
directly).
Generator Name Transformation ProcessAbstractFactoryGen Sup3 ; Pos3 ;
(ABSTRACTION ; BUILDRELATION ; ENCAPSULATION)∗;SingletonGen ; (Pos15)
∗
BuilderGen ABSTRACTION ; WRAPPER ; BUILDRELATION ;(Pos1)
∗ ; Pos12
FactoryMethodGen ABSTRACTION ; ENCAPSULATION ;BUILDRELATION ; EXTENSION
PrototypeGen Pos9 ; ABSTRACTION ;BUILDRELATION ; (Pos15)
∗
SingletonGen EXTENSION ; Pos8 ;(Pos15)
∗ ; Pos10
AdaptorGen WRAPPER ; ABSTRACTION ; BUILDRELATIONBridgeGen WRAPPERCompositeGen ABSTRACTION ; Pos5 ; BUILDRELATIONDecoratorGen ABSTRACTION ; BUILDRELATION ; WRAPPERFacadeGen ENCAPSULATION ; WRAPPERFlyweightGen WRAPPER ; CompositeGenProxyGen WRAPPER ; ABSTRACTION ; BUILDRELATION
ChainofRespGen WRAPPER ; BUILDRELATIONCommandGen Sup5 ;ABSTRACTION ; Pos16
InterpreterGen CompositeGen ; IteratorGenIteratorGen MOV EMENT ; ABSTRACTION ; ENCAPSULATIONMediatorGen ENCAPSULATION ; FacadeGenMementoGen MOV EMENT ; BUILDRELATIONObserverGen SingletonGen ; MediatorGenStateGen MOV EMENT ; ABSTRACTION ; BUILDRELATION ;
(Pos6 ; Pos7)∗
StrategyGen MOV EMENT ; ABSTRACTION ; BUILDRELATIONTemplateMethodGen EXTENSION ; BUILDRELATIONVisitorGen CompositeGen ; EXTENSION
Table 5.5: A List of Generators for Complex Design Pattern Transformations.
The intent of the Factory Method pattern is to define an interface for creating an ob-
ject, but let subclasses decide which class to instantiate [72]. The Factory Method Design
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 117
Pattern Generator lets a class defer its instantiation to subclasses. The transformation
consists of the following steps : 1) the application of the “ABSTRACTION” primitive
design pattern transformation to generate an interface that reflects how the creator class
uses the instances of the product that it creates, 2) the application of the “ENCAPSU-
LATION” primitive design pattern transformation so that the construction of product
objects can be encapsulated inside dedicated, overridable methods in the creator class,
3) the application of the “BUILDRELATION” primitive design pattern transformation
so that the creator class can register the product class only via the interface created
in the previous step, 4) the application of the “EXTENSION” primitive design pattern
transformation so that the creator class can be inherited from an abstract class where
the construction methods are declared abstractly.
The intent of the Composite pattern is to enable a client class to treat a single compo-
nent object or a composition of objects in a uniform fashion [72]. The result of Composite
Design Pattern Generator transformation is that the client class uses the component class
through its interface. It is also easy to extend the client so that it uses compositions of
components in place of the single component instances. The transformation consists of
the following steps : 1) the application of the “ABSTRACTION” primitive design pat-
tern transformation on the component class in order to produce the component interface,
2) the application of the “BUILDRELATION” primitive design pattern transformation
in order to abstract the client class from the component class and use the component
interface instead.
The intent of the Iterator pattern is to enable sequential access to the elements of an
aggregate object without exposing the underlying representation of the object [72]. The
Iterator Design Pattern Generator allows for multiple concurrent iterations over the aggre-
gate object in a way that the underlying structure of the aggregation is not exposed. The
CHAPTER 5. CODE-IMPROVING TRANSFORMATIONS CATALOGUE 118
transformation consists of the following steps : 1) the application of the “MOVEMENT”
primitive design pattern transformation to copy the iteration methods and fields to the
new iteration class, which is parameterized with an instance of the aggregate class and
delegates any internally generated, more iterator requests to this instance, 2) the appli-
cation of the “ABSTRACTION” primitive design pattern transformation on the iterator
class in order to produce an iterator interface, 3) the application of the “ENCAPSULA-
TION” primitive design pattern transformation to add an construction method for the
iterator to the aggregate class.
5.8 Summary
We have proposed a layered software transformation framework to support object-oriented
software re-engineering. The layered framework based on a proposed algebra enables
for the transformations to be modelled in the quality driven re-engineering framework.
We believe that this transformation framework is noteworthy as devises a workbench in
which re-engineering activities do not occur in a vacuum, but can be evaluated and fine-
tuned in order to address specific quality requirements for the new target system such as,
enhancements in maintainability or performance.
Chapter 6
Software Transformation Process
It is better not to proceed at all, than to proceed without method.
Rene Descartes
In the previous chapter, we presented a software transformation catalogue based on soft-
goal interdependency graphs. We considered a class of transformations where a program
is transformed into another program in the same language (source-to-source transforma-
tions) and that the two programs may differ in specific qualities such as performance
and maintainability. This chapter discusses a search algorithm that determines a set
of source-code improving transformations among several applicable transformations for
achieving multi-objective non-functional requirements.
In Section 6.1, we discuss how a soft-goal interdependency graph can be modelled
as a directed graph. Section 6.2 proposes a framework where a catalogue of object-
oriented metrics can be used as indicators for automatically detecting prospects where
a particular transformation can be applied to improve the quality of an object-oriented
legacy system. Section 6.3 develops a multi-objective heuristic search algorithm whose
objective is to identify the set of transformation rules that can be applied on any given
step of a transformation process so that the migrant system will possibly have the desired
119
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 120
quality characteristics. An example that illustrates the usage of the proposed algorithm
is also presented. Finally, Section 6.4 provides a summary of this chapter.
6.1 A Model for a SIG Representation
Each soft-goal interdependency graph (SIG) for a non-functional requirement can be
considered as a directed graph (digraph) D represented as a set R of a 3-tuple elements
< N,E,L > where N is a set of vertices or nodes, divided into NFR soft-goal nodes
and transformation operationalization nodes. The set of nodes or vertices is called the
vertex-set of D, denoted by N = V (D). There is also a special node called the entry
node. E is a set of edges or arcs which is a list of ordered pair of the nodes. The list of
arcs is called the arc-list of D, denoted by E = A(D). If ni and nj are vertices, then an
arc of the form ninj is said to be directed from ni to nj , or to join ni to nj . In this case,
node nj is said to be a successor of node ni and node ni is said to be a parent of node nj .
Finally, L is a labelling of N × E which assigns to each node a node of D, and to each
edge an impact rule as it will be elaborated later.
6.1.1 Types of Contributions in SIGs
As discussed in Section 3.4 for decomposition of soft-goal interdependency graphs, devel-
opment proceeds by repeatedly refining parent soft-goals into offspring soft-goals. In such
refinements, the offspring can contribute fully or partially, and positively or negatively,
towards satisficing of the parent goal node as follows :
• AND(G, {G1, G2, ..., Gn}) – soft-goal G is fulfilled when all of G1, G2, ..., Gn are
fulfilled and there is no negative evidence against it.
• OR(G, {G1, G2, ..., Gn}) – soft-goal G is fulfilled when one of G1, G2, ..., Gn is ful-
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 121
filled and there is no negative evidence against it.
• +(G1, G2) – soft-goal G1 contributes positive to the fulfilment of soft-goal G2.
• ++(G1, G2) – soft-goal G1 contributes positive-positive to the fulfilment of soft-goal
G2.
• −(G1, G2) – soft-goal G1 contributes negative to the fulfilment of soft-goal G2.
• − − (G1, G2) – soft-goal G1 contributes negative-negative to the fulfilment of soft-
goal G2.
For the purpose of the QDR framework, the arcs of directed graph for each SIG are
labelled by the above rules. A soft-goal interdependency graph is given by the start node
called s, representing the top level requirement state, and the above rules associate goals
(parent nodes) and sub-goals (children nodes). It is convenient to model the above rules
in terms of contribution operators.
In reference to Figure 5.4, Table 6.1 presents the contribution operators describing
how satisficing the offspring (or failure thereof) contributes to satisficing the parent goal.
Recall that soft-goal satisficing suggests that the generated source code is expected to
satisfy non-functional requirements within acceptable limits, rather than absolutely. In
this respect, if a soft-goal is considered to be acceptably satisficeable then it is deemed
as satisficeable. If, however, soft-goal is considered to be potentially unsatisficeable then
it is deemed as deniable.
As depicted in Table 6.1, the first two contribution operators, AND, and OR, relate
a group of offsprings to a parent. To keep track of the information regarding these two
contribution operators, we will build an adjacency matrix, namely Soft-Goal Adjacency
Matrix, which will be elaborated in Section 6.1.2. For AND contribution, the parent is
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 122
Operator Name Notation Example
ANDAND Single Arc (High Source Code Quality,
High Documentation Quality)SATISFICE High Maintainability
OROR Double Arc (Low I/O Complexity, High Data Consistency,
Low Data Coupling)SATISFICE High Data Structure Quality
MAKE ++ ABSTRACTION MAKES High Cohesion
HELP + BUILDRELATION HELPS Low Control Flow Coupling
HURT − ENCAPSULATION HURTS High Data Consistency
BREAK −− WRAPPER BREAKS Low I/O Complexity
Table 6.1: A Catalogue of Contribution Operators.
satisficed if all the offspring are satisficed. For OR contribution, the parent is satisficed
if any of the offsprings is satisficed.
Let’s turn to the contribution operators involving a single offspring. MAKE and
BREAK provide sufficient support, MAKE being positive and BREAK being negative.
MAKE is defined as : if the offspring is satisficed, then the parent is satisficeable. BREAK
is defined as : if the offspring is satisficed, then the parent is deniable. HELP and HURT
provide partial support, HELP being positive, and HURT being negative. HURT is de-
fined as : if the offspring is denied, then the parent is satisficeable. HELP is defined
as : if the offspring is denied then the parent is deniable. To keep track of the informa-
tion regarding these contribution operators, we will build an incidence matrix, namely
Transformation Impact Matrix, which will be elaborated in Section 6.1.3.
Now, we can proceed to define two matrices for each soft-goal interdependency graph,
namely Soft-Goal Adjacency Matrix (SAM) and Transformation Impact Matrix (TIM)
which are elaborated later in the following sections.
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 123
6.1.2 Soft-Goal Adjacency Matrix (SAM)
Let n1 and n2 be vertices of a SIG. If n1 and n2 are joined by an arc e with any of AND
or OR contribution operator, then n1 and n2 are said to be adjacent with the defined
rule. If the arc e is directed from n1 to n2, then the arc e is said to be incident from n1
and incident to n2.
LetD to be a SIG in digraph form with n vertices or soft-goal nodes, N = {d1, d2, ..., dn}.
The simplest graph representation scheme uses an n × n matrix SAM (Soft-Goal Adja-
cency Matrix) of &’s, |’s, and 0’s given by :
SAM i,j =
&, when AND(di, {dj})
|, when OR(di, {dj})
0, otherwise
that is, the (i, j)th element of the matrix is not equal to 0 only if di −→ dj is an edge
in D with a contribution operator. For example, the SAM for the following digraph is as
follows :
21
4
3
6
5
1 2 3 4 5 6
1 0 | | | 0 0
2 0 0 0 0 0 0
3 0 0 0 0 0 0
4 0 0 0 0 & &
5 0 0 0 0 0 0
6 0 0 0 0 0 0
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 124
Clearly, the number of entries which is not equal to zero in the SAM is equal to
the number of edges in a soft-goal interdependency graph. One advantage of using an
adjacency matrix is that it is easy to determine the sets of edges with their contribution
operators emanating from a given vertex. Each non-zero entry in the ith row corresponds
to an edge with its contribution operator that emanates from vertex di. Conversely, each
non-zero entry in the ith column corresponds to an edge incident on vertex di.
Since SAM has |N |2 entries, the amount of the space needed to represent the edges and
their corresponding contribution operators of a SIG is O(|N |2), regardless of the actual
number of edges in the graph. If a graph contains relatively few edges, |E| ¿ |N |2, then
most of the elements of the SAM will be zero as the above example shows. A matrix in
which most of the elements are 0 is a sparse matrix. One technique that is often used for a
sparse graph uses link lists. The link list for vertex di with its corresponding contribution
operator. As a result, the lists are called adjacency list. While this is an issue that we
will deal with at the implementation phase, we will refer to it as SAM in wherever we
need in this chapter.
Now, we discuss an algorithm to generate an adjacency matrix for n soft-goals. We
call it Generate Adjacency Matrix (GAM). The process for a goal node GOAL, consisting
of a set of start soft-goal nodes G1, G2, ..., Gi, can be informally described as shown in
Figure 6.1.
The control strategy for GAM selects a sub-soft-goal component, S∗, in Step 4 and
a rule based on the contribution operator, R, to apply in Step 6. Whatever the form of
this strategy is, in order to satisfy Step 3, it must ultimately select all the elements in
{Si}. For any S∗ selected, though, it is also necessary to select all applicable rules.
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 125
Algorithm 5.1. GAM(Gi,Gj , C,R) =Input :
R : A set of rules with a 3-tuple 〈pNode, sNode, r〉Gi,Gj : Non-functional requirement goals.C : Contribution operator among two goals.
Output :SAM: A complete adjacency matrix for the above goals.
Variables :L: A list of visited nodes.
Method :
1. SAMGoal,Gi= C; SAMGoal,Gj
= C; SAMGoal,Goal = 0;
2. Si ← {Gi,Gj}; /* The individual Si are now regarded as separate goals */
3. while Si is not empty, do begin
4. select S∗ and remove S∗ from Si;
5. if S∗ 6∈ L then SAMS∗,S∗ = 0; add S∗ to L as a Visited Node;
6. while r ∈ R that can be applied to S∗, do begin
7. S ← result of applying r to S∗;
8. si ← decomposition of S;
9. for each ni ∈ si
10. if ni 6∈ L, then begin
11. append ni to {Si};
12. SAMni,ni = 0;
13. end-if
14. update SAMni,∗ entries based on r;
15. end-for
16. end-while
17. end-while
Figure 6.1: Generate Adjacency Matix Algorithm.
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 126
6.1.3 Transformation Impact Matrix (TIM)
As mentioned before, there are two types of nodes in a SIG, namely NFR soft-goal nodes
and transformation operationalization nodes. In practice, a transformation node is con-
sidered for the purpose of implementing a subset of the NFR soft-goals. Thus, each NFR
soft-goal is associated with a set of transformations that have been associated to it ac-
cording to what features of the source code a transformation affects, and according to the
associating of these features with the specific allocating a soft-goal node is representing.
The NFR soft-goal allocation is not necessarily one-to-one – that is, a single soft-goal may
be associated to more than one transformation. Using UML, the relationship between
soft-goals and transformations can be illustrated in Figure 6.2.
TransformationNFR Soft-Goal
0..* 1
1..*1..*
Impacts on
Associated to
Figure 6.2: Non-Functional Soft-Goal, Transformations and Their Relationships.
As we can observe, NFR soft-goals and transformations play alternative roles in the
processing step, as follows :
• Once a set of NFR soft-goals are present, a set of transformations is assigned to
implement them. The selected transformations are expected to affect a goal node by
altering features that positively or negatively affect the specific node and to provide
an appropriate way to measure this impact.
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 127
• In order to satisfy their allocated non-functional requirements, transformations may
generate additional NFR soft-goals to be implemented during subsequent steps.
These additional NFR soft-goals will be allocated to future transformations.
Let n1 be a soft-goal node and n2 a transformation or operationalization node. If
n1 and n2 are joined by an arc e with any of MAKE, HELP , HURT , or BREAK
contribution operator, then n1 and n2 are said to be adjacent with the defined rule. The
arc e which is directed from n2 to n1 is said to be incident from n2 and incident to
n1. Let S be a set nodes, S = {s1, s2, ..., sn}, representing soft-goals and T is a of set
operationalization nodes, T = {t1, t2, ..., tm}, representing transformations. The simplest
impact representation scheme uses an m×n matrix TIM (Transformation Impact Matrix)
of ++’s, +’s, −−’s, −’s, and 0’s given by :
TIM i,j =
++, when (ti, sj ,MAKE)
+, when (ti, sj , HELP )
−, when (ti, sj , HURT )
−−, when (ti, sj , BREAK)
0, otherwise
that is, the (i, j)th element of the matrix is not equal to 0 only if ti −→ sj is an edge
in D with a contribution operator. For example, the TIM for the following digraph is as
follows :
WWXX
YYZZ
1 2 3
t t’
HELP MAKE MAKE
BREAK
HURT
1 2 3
t ++ 0 −−
t′ + − ++
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 128
Clearly, the number of entries which is not equal to zero in the TIM is equal to the
number of edges in a soft-goal interdependency graph at the operationalization level. One
advantage of using an impact matrix is that it is easy to determine the sets of edges with
their contribution operators emanating from a given transformation. Each non-zero entry
in the ith row shows the impact on soft-goal nodes for a given transformation. Conversely,
each non-zero entry in the ith column shows the allocated transformations on a soft-goal
node. This corresponds to the way that we have already described in Figure 6.2.
As discussed in Chapters 3 , 4, and 5, the building process of a goal graph can be
divided into two steps. First, the initial goal will be split into sub-goals. Rules based on
contribution operators can be applied to each of these sub-soft-goals independently. The
result of these applications can also be split and so on until there is no further splitting
possible based on the information existed. This step, namely Generate Adjacency Ma-
trix, was elaborated in Section 6.1.2. Second, we can define another algorithm, namely
Generate Impact Matrix, to incorporate soft-goals, transformations, and their relation-
ships based on our definition of transformation impact matrix (TIM). The process can
be described as shown in Figure 6.3.
The control strategy for GIM selects a soft-goal node from the generated soft-goal
adjacency matrix in Step 3 and is based on the existing rules in Step 4 the impact will
be applied on all corresponding rows in TIM, Step 5 to Step 11 illustrated in Figure 6.3.
The main role which is played by the GIM algorithm in the representation of a SIG
is to hold the traceability information required when a transformation selection search
algorithm is applied.
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 129
Algorithm 5.1. GIM(SAM,R) =Input :
SAM : Soft-Goal Adjacency Matrix (n× n).R : A set of rules with a 3-tuple 〈transNode, softNode, impact〉.
Output :T IM: An impact matrix (m× n) for the generated SAM.
Variables :L: A list of visited transformation nodes.i: An index for keeping track of number of soft-goal nodes.j: An index for keeping track of number of transformation nodes.
Method :
1. initialize i to 1 and L to ∅;
2. while i ≤ n, do begin
3. SName = NAME(SAMi,∗);
4. while r ∈ R & rsoftNode = SName do begin
5. if rtransNode 6∈ L then begin
6. add rtransNode to {L};
7. append rtransNode as row j to T IM;
8. T IMj,∗ = 0;
9. end-if
10. else j = NUMBER(rtransNode);
11. T IMj,i = rimpact;
12. end-while
13. increment i by 1;
14. end-while
Figure 6.3: Generate Impact Matrix Algorithm.
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 130
6.2 A Model for Quality Assessment
Our work on improving the quality of object-oriented legacy systems includes : i) building
soft-goal interdependency graphs as a means to model the associations of maintainability
and performance with design decisions and source code features, and ii) proposing a
software transformation framework based on SIGs. The next step is to assign object-
oriented metrics to software features and correspondingly to the transformations that
affect these features in a systematic manner in order to identify the transformations that
may be appropriate in improving quality as this is estimated by the selected metrics. The
next section addresses this issue.
6.2.1 A Classification of OO Design Flaws
Design defects can be recognized in the early stages of software development or during
system evolution. They cause the system to exhibit low maintainability, low reuse, high
complexity and faulty behaviour. Specifically, for object-oriented legacy systems which
have been faced with frequent modifications, detection and correction of such design flaws
is a complex task. We propose a classification of object-oriented design flaws which is a
step towards discovering recurring detection and correction methods.
Design properties are tangible concepts that can be directly assessed by examining
the internal and external structure, relationships, and functionality of the system com-
ponents, attributes, methods, and classes. An evaluation of the class definition and its
external relationships (inheritance type) with other classes as well as, the examination of
its internal components, attributes, and methods can be used to reveal significant infor-
mation that objectively captures the structural and functional characteristics of a class
and its elements.
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 131
Overall, a design could deteriorate for several reasons. Specifically, a class may have
been designed taking into account all principles of object-oriented design (i.e., encapsula-
tion, information hiding, data abstraction) in the initial stages of development but lost its
integrity among other reasons due to : i) addition of methods/data members, ii) trying as
a base class to accomplish too much for its derived classes, iii) attempting to handle too
many different situations, grouping what should be several different derived classes into
a single class, iv) increasing number of relationships and associations with other classes
and abstract data types.
By introducing a classification of design flaws, we aim to discover generic detection
and correction methods. This classification will ease the assessment of new re-engineering
techniques and tools. Sorting and classifying design flaws is a complex task because of the
multiple points of views that can be considered. We propose the following classification
obtained from the literature [35, 46, 70, 123, 185] based on the scope of design flaws inside
an object-oriented application. The classification can distinguish among i) design flaws
involving the internal structure of a class, ii) design flaws involving interactions among
classes, and iii) design flaws relating to the application semantics. We retain these three
categories because they represent three distinct levels of abstraction and thus must rely
on different detection and correction techniques.
These three categories are not orthogonal and several design flaws do not fit simply
in a single category. We can define four additional categories as depicted in Figure 6.4
which are included in the intersections of the three previous ones. Thus, evolving from
the three main categories, we can introduce seven categories to classify the design flaws.
These categories which allow a finer-grain classification of the design flaws are as follows :
• Structural Flaws (SF) : This category includes any design flaws related to the
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 132
ArchitecturalFlaws
(AF)
SB
SAB
SA AB
Structural
Flaws
(SF)
Flaws
(BF)
Behavioral
Figure 6.4: Design Flaws Classification.
internal structure of a class. It embodies style and syntactic flaws which are design
defects in the structure of the class and its members. For example, methods with
too many invocations are error-prone and difficult to maintain or extend [71].
• Architectural Flaws (AF) : This category considers any design flaws related to
the external structure of the classes (their public interface) and their relationships.
All design flaws in the application architecture belong to this category. For exam-
ple, mixing different algorithms within a single data structure is an architectural
flaw. The reason is that the algorithms outweigh the data structure and any data
structure extension is not easy because it requires possibly complex modifications
every time a new algorithm is considered [72].
• Behavioural Flaws (BF) : This category encompasses all the design flaws related
to the application semantics. For example, the “The Year 2000 Problem” (due
to the storage of years on only two digits) is a typical behavioural design flaw.
Another example of behavioural design flaws concerns changes in the environment
of a system.
• Intersection of SF and AF (SA) : This category includes design flaws related
to both the internal and external structures of the classes. There are some internal
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 133
design flaws for which corrections imply changes to the application architecture. For
example, duplicated code among classes reveals a need to change the architecture
to factor out the duplicated code. Also, there are some architectural design flaws
involving changes to the internal structures of the classes. For example, the usage
of the Composite Pattern [72] when a specialized object creates a meaningful new
object where we can attach behaviour. If we have the data hierarchy of a composite,
but no shared operations, we are in a situation similar to a “data bag”. We may
want to observe what clients do with the class - perhaps there’s functionality that
belongs in the Composite rather than its client.
• Intersection of SF and BF (SB) : This category considers design flaws involving
both the semantics of the class and its internal structure. There are some defects
in the behaviour of the class which in order to be corrected imply changing its
structure and defects in the internal structure of the class which in order to be
corrected imply changing its behaviour.
• Intersection of AF and BF (AB) : This category encompasses design flaws
related to both architectural and behavioural of the classes. There is a set of design
flaws related to the application architecture which in order to be corrected imply
changing the semantics of its classes. For example, a “God” class [147] is a sign of
a bad architecture that for its improvement requires changing the semantic of at
least the “God” class. Also, there are some design flaws in the behaviour of classes
which in order to be corrected recursive changes in their architecture.
• Intersection of SF, AF, and BF (SAB) : The last category includes the set of
all the design flaws implying the structure, semantics, and the architecture of the
application.
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 134
Based on our proposed classification, it is possible to distinguish among design flaws
relative to any combination of syntactic, structural, semantic, or architectural defects.
These categories also allow differentiating among design flaws that stem from one category
and imply changes in another one. For example, duplicate code across classes is detected
into internal structures (SF) of the classes, but resulting flaws appear in both internal
structures (SF) and their architecture (AF). Our concern for improving the quality of
object-oriented design of legacy systems is related to apply the changes which preserve
the behaviour of the system. It means that the behavioural flaws are out of the scope of
this research work. Due to this assumption, we only focus on SF, AF, and the intersections
between them which can cause decreasing the design quality.
6.2.2 Role of Design Flaws in the QDR Framework
During the development of object-oriented legacy systems, an incremental approach is
used [32, 142]. The initial design model created in the first increment may have good
design properties. However, over subsequent increments, the quality may be deteriorated.
It means that there is a risk that the class design will deteriorate in quality with each
increment [143]. Over time, such classes may become difficult to maintain and become
prone to errors. Consequently, we need to devise a technique not only for detecting these
design flaws but also for correcting them.
Figure 6.5 shows the proposed re-engineering strategy using object-oriented metrics
to assess the impact transformations have on soft-goals. As it is known, an object model
has several levels of representation, including application level, subsystem level, class level,
and function level. While design flaws can occur at any level, our focus here is on class
level deterioration. We believe that this is the most fundamental level that constitutes a
system. Improving deteriorated classes should help to keep object-oriented legacy systems
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 135
Classes in Object Model
OO MetricsDetected
Design FlawsRe-engineered
Classes
OO Metrics
Results
Apply Metrics Transformations Apply Metrics
ImprovementEvaluate (from Detected Design Flaws)
Metrics Data(From Re-engineered Classes)Metrics Data
Apply
Figure 6.5: Re-engineering Strategy for Design Flaws.
operational. After extracting an object model at class level through reverse engineering,
the proposed strategy as depicted in Figure 6.5 employs the following steps :
• Step 1 : To select, measure, and record the specific object-oriented metrics in order
to detect classes for which quality has deteriorated. While there are several reasons
for a design to lose quality over time, here the focus is on detecting the classes that
have high complexity and high coupling. For detecting such classes, there is a need
to have a classification of object-oriented metrics which relate to different categories
of design quality and source code features. In Section 6.2.3, we will propose and
discuss a useful catalogue of such metrics.
• Step 2 : To re-engineer detected design flaws using proper transformations. For
correcting such design flaws through software transformations, we need to study
the impact of specific transformations have on specific metrics. In Section 6.2.4,
we discuss the impact of the proposed software transformation framework on the
selected object-oriented metrics. Based on the preconditions for each transformation
and the source code features, we identify all possible transformations that can be
applied at any given point of the transformation process.
• Step 3 : To re-apply and record the same object-oriented metrics to the re-engineered
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 136
classes and finally compare the recorded results to evaluate design and source code
improvement as well as compliance with the desired requirements. Once the trans-
formation and the role of the class are determined, it is necessary to verify that a
transformation contributes in the particular context of the application.
One way to detect design flaws at the class level is to identify violations of a “good”
object-oriented software design by performing source code analysis. However, some guide-
lines and principles exist [147] to build a “good” design, but there is no consensus on what
a “good” design really is. While there are several reasons for a class to lose quality over
time, here the focus is on the classes that have high coupling and low cohesion. These
characteristics often result in loss of abstraction and encapsulation. They are those highly
coupled classes that often loose cohesion during the course of development. Based on this
assumption, two fundamental quality design heuristics will be proposed to detect design
flaws at the class level as follows :
• Key Classes Heuristic (KCH) : A proper way to detect design flaws at the
class level is to identify which classes implement the key concepts of the system.
Usually, the most important concepts of a system are implemented by very few key
classes [18] which can be characterized by the specific properties. These classes
which we called them as key classes manage a large amount of other classes or use
them in order to implement their functionality. The key classes are tightly coupled
with other parts of the system. Additionally, they tend to be rather complex,
since they implement much of the legacy system’s functionality. Finding these
classes is a starting point in the proposed framework to detect potential design
flaws and correct them properly based on the proposed software transformation
framework. Figure 6.6 illustrates such an analysis. The classes of the object-oriented
legacy system are ranked according to their complexity and coupling measurements.
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 137
Classes that are complex and tightly coupled with the rest of the system fall into the
upper right corner and are good candidates for these key classes. Mathematically,
we can combine the two metrics by computing the distance d of a class from the
origin of the coordinate system. If x denotes the complexity metrics vector value of
a class c, and y its coupling metrics vector value, we compute the combined value
dc as :
dc(x, y) = max(dc(x, y)), ∀ x ∈ x, y ∈ y (6.1)
where dc(x, y) =√
x2 + y2. In some cases, if the metrics use a very different scale,
some normalization might be required and we can then use the following formula
instead :
dc(x, y) =
√
(
x
xmax
)2
+
(
y
ymax
)2
(6.2)
This combined value allows for class comparison. Classes with higher values for d
are better candidates to be considered key classes of the system than classes with
lower values for d. The value of d provides a good means to identify the key classes
of the system that may represent design flaws which needs to be taken care of.
• One Class-One Concept Heuristic (OC2H) : A very basic principle in object-
oriented software engineering states that a class should implement one single concept
of the application domain. Some violations of this principle can be detected by using
these assumptions : i) a class that implements more than one concept, has probably
low cohesion measurements, since these concepts can be implemented separately,
ii) a class that by itself does not implement one concept (the implementation of
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 138
Class 3
tightly coupled with other partsof the system.
Classes that are tightly coupled with otherparts of the system. Class 4
Classes that are rather complex.
Class 1 Class 5
Class 6Class 2
Complexity
Coupling
Core classes are complex and
Figure 6.6: Key Classes in an Object-Oriented Legacy System.
the concept is distributed among many classes) is probably tightly coupled to other
classes. Therefore, by collecting cohesion and coupling values of an object-oriented
legacy system, possible violations of the principle “one class - one concept” can
be found. These classes tend to have either low cohesion values or high coupling
values. The classes that have very low cohesion values can often be split [132].
Sometimes this leads to a more flexible design, since the two separate classes are
easier to understand and are more reusable. Low cohesion values also indicate
deteriorated classes. These classes are not implementing a self contained object
from the application domain, they just group methods together, acting as a module.
6.2.3 Assigning Object-Oriented Metrics to Soft-Goals
Each of the design flaws identified in Section 6.2.1 and each of the quality rules for
detecting these flaws are modelled as an attribute or a characteristic of a design. These
characteristics are sufficiently well defined to be objectively assessed by using one or
more object-oriented metrics. Metrics are particularly suitable to check, whether the
object-oriented legacy system adheres to design principles or contains violations of these
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 139
principles.
In this section, we select object-oriented metrics that will be used to assess object-
oriented system qualities in our quality-driven re-engineering framework. In order to
make a selection, we first need to establish s set of criteria that should guide the selection
process. Establishing these criteria requires to consider a central part of the study which is
to identify which of the metrics can be successfully used in order to assess the improvement
of the quality of migrant system and to collect proper transformations based on the source
code features. In this respect, we will focus on two criteria : i) the theoretical evaluation
of the definition of the metric, and ii) the aspects of design flaws that we plan to detect
and correct.
The proposed selection of the object-oriented metrics is classified according to four
major metrics categories [172] : complexity metrics, coupling metrics, cohesion metrics,
and inheritance metrics as discussed in Section 2.2.2. While Table 6.2 illustrates these
metrics along with their relation to soft-goal nodes, we further describe them in a more
details as follows :
• Complexity Metrics : We consider these metrics because they may give indica-
tions about the level of complexity for a given class. One of the well established
metrics to measure the complexity of a class isWMC (Weighted Methods per Class)
measures the complexity of a class by adding up the complexities of the methods de-
fined in the class [41, 64]. A special case ofWMC (which is very simple to compute)
is NOM (Number Of Methods) as well as RFC (Response Set For A Class) met-
ric [41] which measure the complexity of a class by counting the number of methods
defined in that class [83]. Such metrics measure the attributes of the objects in the
class and express the potential communication between the class that is measured
with other classes i.e., how many methods local to the class and methods from other
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 140
classes can be potentially invoked by invoking methods from the class. Complex-
ity measurements for methods are usually given by code complexity metrics like
LOC or the McCabe Cyclomatic complexity [116]. The Class Definition Entropy
(CDE) [13] metric identifies complex classes in an object-oriented system. Classes
with higher values of CDE can be expected to have a complex implementation and
a more than average number of errors and changes. Obviously, complexity metrics
play an important role when re-engineering software systems as classes with high
complexity measurements are difficult to understand and consequently difficult to
change.
• Coupling Metrics : Another important aspect when dealing with an object-
oriented legacy system is the coupling level between classes. A class is coupled
to another class, if it depends on that class, for example by accessing variables of
that class, or by invoking methods from that class. Classes that are tightly coupled
cannot be seen as isolated parts of the system. Understanding or modifying them
requires that other parts of the system must be inspected as well. Conversely, if
other parts of a system change, classes with high coupling measurements are more
likely to be affected by these changes. Additionally, classes with high coupling tend
to play key roles in the system, making them a good starting point when trying to
understand an unfamiliar object-oriented legacy system. Analyzing the viewpoints
suggested for the different coupling metrics, one is able to reason on the level of reuse
and maintainability of a class. Specifically, DAC (Data Abstract Coupling) mea-
sures coupling between classes that results from attribute declarations [87, 88, 109].
DAC counts the number of abstract data types defined in a class. Essentially, a
class is an abstract data type, therefore DAC reflects the number of declarations
of complex attributes (i.e., attributes that have another class of the system as a
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 141
Metric Category Definition Soft-Goal Nodes
CDBC [88](ChangeDepen-dencyBetweenClasses)
Coupling CDBC determines the potential amount offollow-up work to be done in a client class CCwhen the server class SC is being modified in thecourse of some maintenance activity and definedas: CDBC(CC,SC) = min(n,A) where A =∑m1
implement=1αi + (1− k)
∑m2
interface=1αi.
Low Control Flow Coupling,High Encapsulation, HighControl Flow Consistency
CDE [13](ClassDefinitionEntropy)
Complexity CDE computes a decimal number to indicatea class definition complexity based on the us-age and frequency of different name strings ina class declaration. Consider n1 is the num-ber of unique name strings, N1 is the totalnumber of name strings, fi for 1 ≤ i ≤ n1
is the frequency of occurrence, then CDE =−∑n1
i=1(fi/N1)log(fi/N1).
Low Control Flow Complexity,High Cohesion, High Encapsu-lation
DAC [109](Data Ab-stractionCoupling)
Coupling The metric which measures the coupling com-plexity caused by ADT’s is called Data Abstrac-tion Coupling (DAC) and is defined as numberof ADT’s defined in a class.
Low Data Coupling, High DataConsistency, High Encapsula-tion
DIT [109](Depthof Inheri-tance)
Inheritanceand Cou-pling
DIT represents the length of the tree from thatclass to the root of the inheritance tree. In casesinvolving multiple inheritance, value is maxi-mum length from that node to the root of thetree.
High Module Reuse, High En-capsulation, High Modularity
LCOM [83](Lack ofCohesion inMethods)
Cohesion Consider a class C, its set M of m methodsM1, ...,Mm, and its set A of a data membersA1, ..., Aa accessed by M . Let µ(Ak) be thenumber of methods that access data attributeAk where 1 ≤ k ≤ a. Then, LCOM(C(M,A)) =(
1a
∑
a
j=1µ(Aj)
)
−m
1−m.
High Cohesion, High DataConsistency, Low I/O Com-plexity, High Modularity, HighModule Reuse
LD [88](Localityof Data)
Coupling LD metric is defined by relating the amount ofdata local to the class to the total amount of dataused by the that class. It can be mathematically
expressed by the relation: LD =
∑
n
i=1|Li|
∑
n
i=1|Ti|
.
Low Data Coupling, High DataConsistency, High Encapsula-tion
NOC [109](Num-ber OfChildren)
Inheritanceand Cou-pling
NOC represents the number of immediate sub-classes subordinated to a class in the class hier-archy. The number of children gives an idea ofthe potential influence a class has on the design.
High Module Reuse, High En-capsulation, High Modularity
NOM [109](Num-ber OfMethods)
Complexityand Cou-pling
Since the local methods in a class constitute theinterface increment of the class, NOM serves thebest as an interface metric. Then NOM number
of local methods in a class.
Low I/O Complexity, High Co-hesion, High Modularity
RFC [41](ResponseFor aClass)
Complexityand Cou-pling
The Response Set for a Class (RS) is a set ofmethods that can be potentially executed in re-sponse to a message received by an object ofthat class. RFC is the cardinality of the re-sponse set for that class. Then, mathematicallyRFC = |RS|.
Low Control Flow Coupling,Low Control Flow Complex-ity, Low I/O Complexity, HighControl Flow Consistency
TCC [25](TightClassCohesion)
Cohesion Let NP (C) to be the total number of pairs ofabstract methods in AC(C). Let NDC(C) tobe the number of directed connection in AC(C),then TCC is the relative number of directlyconnected methods which can be expressed as :TCC(C) = NDC(C)/NP (C).
High Cohesion, High Modular-ity, High Module Reuse
WMC [41](WeightedMethodsper Class)
Complexity Consider a class C1, with methods M1, ...,Mn
and c1, ..., cn are the static complexity of themethods, then : WMC =
∑n
i=1ci.
Low Control Flow Complex-ity, High Control Flow Consis-tency, Low I/O Complexity
Table 6.2: Selected Object-Oriented Metrics and Their Relationships with Soft-Goals.
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 142
type). CDBC (Change Dependency Between Classes) is another interesting metric
that directly addresses an important aspect in re-engineering that is maintenance
effort.
• Cohesion Metrics : The cohesion of a class describes how closely the entities of a
class (such as attributes and methods) are related. Often, cohesion is measured by
establishing relationships between methods of the class in the case where the same
instance variables are accessed. A useful metric measuring this property is TCC
(Tight Class Cohesion) [25, 65, 87, 88] which measures the cohesion of a class as
the relative number of directly connected methods, where methods are considered
to be connected when they use at least one common instance variable. In the
literature, several formulas have been introduced to compute Lack of Cohesion [41,
83, 109]. We adopted a definition in [83] which measures dissimilarity among all the
methods of a class except the inherited methods but including overloaded methods.
The LCOM value denotes the number of pairs of methods without shared instance
variables, minus the number of pairs which do share instance variable.
• Inheritance Metrics : This category of metrics attempts to provide indicators
on the quality of the class hierarchy layout of an object-oriented legacy system. A
useful metric measuring this property is DIT (Depth of Inheritance) [41]. Basili
et. al [16] argued in their report that the information that they obtained from this
metric were completely useful on reasoning about the quality of the class. The
Number of Children (NOC) [109] represents the number of immediate subclasses
subordinated to a class in the class hierarchy. The greater the number of children,
the greater the reuse, since inheritance is a form of reuse. An immediate conclusion
is that the classes with a greater number of children have to provide more services
in different contexts, and thus they should be more flexible. An assumption that
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 143
can be made is that such classes will introduce more complexity in the design.
The goal of this assignment which is drawn in Table 6.2 was to find a reasonably
small set of metrics which contain sufficient information to allow accurate determination
of source code features and design properties.
6.2.4 Mapping Software Transformations to a Metrics Suite
Once a source code fragment as a candidate for re-engineering is detected using the
suggested object-oriented metrics, the next step is to propose possible transformations
that improve the quality of the program while preserving its behaviour. We establish
a cause-to-effect relationship between some combinations of metrics and a poor design
quality. It means that we associate changes of the code that improve the values of certain
metrics to the quality of an application or program. The problem to address is what
transformations and code changes should be applied to improve the corresponding metrics
and therefore the corresponding system quality. An intuitive solution is to identify which
transformation (or a set of transformations) allows changing the value of a particular
metric (or a set of metrics). To respond to such a kind of question, we need to consider
two steps : i) propose a catalogue of transformations as a predefined set of transformations
that can be applied both at the internal and the external structures of the classes, and
ii) analyze the impact of each transformation on the predefined set of metrics. The first
step was completely discussed in Section 5.5 and a comprehensive list of transformations
is provided in Appendix D.
In this context, there is a synergy between design heuristics and design patterns.
Design heuristics can highlight a problem in one facet of a design while patterns can
provide the solutions. In this work, the proposed transformations alter the design with
the purpose to improve the quality of a system while preserving its behaviour. These
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 144
transformations modify the structure of a program which will possibly modify in a pos-
itive way the values of the metrics related with the quality being improved. As we are
interested in class level metrics, we study the metric variations for all classes involved in
a transformation. The possible impact of applying each transformation on metrics for the
classes involved is shown in Table 6.3. Note that ‘+’ means that there is a positive impact,
‘−’ means that there is a negative impact, and ‘NI’ means that there is no impact.
Metric Name
TransformationCDBC
CDE
DAC
DIT
LCOM
LD
NOC
NOM
RFC
TCC
WMC
ABSTRACTION + + + NI + + NI + + + −EXTENSION + + − + + − + + NI + NI
MOVEMENT − NI NI + + NI + + − + NI
ENCAPSULATION + + + + − + + NI NI NI NI
BUILDRELATION + + NI NI − NI NI − + NI +
WRAPPER + + NI NI − NI NI − NI + −
Table 6.3: Impact of the Transformations on OO Metrics Suite.
Several authors have addressed the particular problem of class hierarchy design and
maintenance. In their work, transformations are most often used to abstract common
behaviour into new classes. Work in the context of the Demeter System has addressed
the design of class hierarchies using an optimization process [110]. The objective function
used in the optimization process is a global class hierarchy metric that measures the overall
complexity of the class hierarchy. Godin and Mili [77] proposed the use of concept (Galois)
lattices and derived structures as a formal framework for dealing with class hierarchy
design or re-engineering that guarantees maximal factorization of the common properties
including polymorphism. The GURU tool [123] dealt with refactoring of methods and
class hierarchy in an integrated manner.
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 145
However, not much effort has been invested for systematically documenting object-
oriented metrics as a guide not only for the detection design flaws in the reverse engi-
neering process but also for correction through proper transformations in the forward en-
gineering process. This work is therefore a first step in using metrics to guide the choice
of useful transformations. In this context, the compiled catalogue of object-oriented
metrics and the proposed transformation framework allow for achieving specific quality
requirements in the migrant system.
Consider, AC to be a set of classes in an object model extracted from an object-
oriented legacy system. We need to calculate the metric values from the predefined cat-
alogue and apply quality heuristics rules to detect design flaws and deteriorated classes
in the legacy system being analyzed. In this process, the first step is to apply the key
classes (KCH) rule by using both a complexity and coupling metrics. A very high level
quality goal for a software system could be maintainability, thus coupling measurements
should not be high in order to ensure that changes to the system do not trigger changes
throughout the system. Therefore, monitoring DAC values can be promising. When a
significant number of classes evolves to higher DAC measurements, some refactoring oper-
ations [71] or meta-pattern transformations [166, 164] of the system could be appropriate,
to reduce coupling.
Moreover, good object-oriented design styles usually require that classes have high
cohesion, since they should encapsulate concepts that belong together. Classes with low
cohesion often represent violations to a flexible, extensible or a reusable design. All of
these are issues that must be dealt with during the object-oriented re-engineering process.
Therefore, by applying cohesion metrics like TCC and coupling metrics like DAC and RFC
to the object-oriented legacy system, possible violations of the principle one class - one
concept (OC2H) rule can be found. These classes tend to have either low TCC values or
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 146
high DAC and high RFC values. For example, classes that have very low TCC values, can
often be split [71]. Sometimes this leads to a more flexible design, since the two separate
classes are easier to understand and are more reusable. Low TCC measurements may
indicate classes that have not been designed in an object-oriented way. These classes are
not implementing a self contained object from the application domain, they just group
methods together, acting as a module. If a class exhibits low method cohesion, it indicates
that the design of the class has probably been partitioned incorrectly. In this case, the
design could be improved if the class was split into more classes with individual higher
cohesion. The LCOM metrics helps to identify such design flaws.
6.3 A Multi-Objective Search Algorithm for SIGs
Up to now, this research work on improving the quality of object-oriented legacy sys-
tems has included : i) devising a quality-driven re-engineering framework, ii) proposing
a software transformation framework based on soft-goal interdependency graphs to en-
hance quality, and iii) investigating the usage of metrics for detecting potential design
flaws. In this section, we are particularly interested to determine a proper set of trans-
formations among several alternative transformations that can be applied on a system
as means to restructure its object-oriented source code so that the new migrant system
conforms with specific non-functional requirement enhancements. Most of the efforts in
this research direction concentrated on the definition of transformations and their imple-
mentation [6, 19, 22, 38, 156, 177]. To the best of our knowledge, there is no effort on
the automatic detection of the situation where a sequence of these source-code improving
transformations can be applied in an object-oriented legacy system to improve a specific
quality or address a specific requirement.
As it is known, most non-functional requirements involve multiple and conflicting
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 147
objectives which relate to various alternative design decisions [44]. The task of adequately
modelling and analyzing such problems has been the subject of the multi-attribute utility
theory [102]. However, accurately and confidently describing preference in the context
of multiple objectives using a scalar criterion can be difficult. In order to avoid this
potential difficulty, we can search for the set of so-called non-dominated solutions [159]
which represent the multiple-objective approach to problem solving.
Definition 1 : A Transformation Path is T1 op T2 op ... Tn where op can be ;, ‖, +, ×
obtained from the algebra.
Definition 2 : A transformation path T is said to be non-dominated among a set of
transformations if there are no other transformations in the set that are at least as “good”
as T with respect to all the non-functional objectives and is strictly “better” than any
other transformation with respect to at least one of the non-functional objectives, where
“good” and “better” are defined in terms of an impact-valued criterion associated with
each of the multiple non-functional objectives under consideration.
Thus, instead of seeking a single optimal solution, one seeks the set of non-dominated
solutions. Determination of the most preferred alternative from the set of non-dominated
alternatives depends on the developer’s selection and the nature of the target systems.
Many problem-solving approaches can be interpreted as procedures for iteratively
searching through a set of predetermined or progressively determined solution alternatives
until a satisfactory, perhaps in some sense optimal solution is found [128]. Most reasonably
complete formulations of real-world problems involve multiple, conflicting objectives. The
task of adequately modelling such problems using a single valued criterion has been the
subject of considerable research as discussed by [102] and other researchers in the area of
multi-attribute utility theory (MAUT). The multi-objective search model was introduced
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 148
by Stewart in [160] as a unified framework for solving search problems involving multiple
objectives. In this research work, we present a multi-objective generalization of heuristic
search algorithm A∗. The algorithm identifies a set of all non-dominated paths [159] from
a specified start node to a given set of goal nodes in a graph.
6.3.1 Soft-Goal Evaluation Procedure
In the proposed quality-driven re-engineering framework, we need to identify a list of
potential transformations among several possible ones that can assist on achieving the
desired non-functional requirements. When a source-code improving transformation in a
SIG is selected, we need an evaluation procedure which is activated to propagate labels
from offsprings to parents. This determines the degree to which non-functional require-
ments are achieved by this set of the selected transformations. Figure 6.7 illustrates these
contribution operator impact types in a spectrum, ranging from sufficient negative support
(“−−”) on the left to sufficient positive support (“++”) on the right.
HURT UNKNOWN HELP MAKE
--
BREAK
? + ++-
Figure 6.7: A Catalogue of Impact Links.
Given a SIG, one can determine whether each soft-goal or interdependency is satis-
ficed. This is done through the assignment of a label. Using the notion of satisficeable and
deniable, a soft-goal or interdependency in the graph is labelled as follows for depicting
the desired objectives :
• satisficed (√ or S) if it is satisficeable and not deniable,
• weakly satisficed (W+) if it is representing inclusive positive support for a parent,
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 149
• denied (× or D) if it is deniable or not satisficeable,
• weakly denied (W−) if it is representing inclusive negative support for a parent,
• conflicting (\ or C) if it is both satisficeable and deniable,
• undetermined (U or U) if it is neither satisficeable nor deniable.
Undecide (U) Satisficed (W+)Weakly
Satisficed (S)Denied (D) Denied (W-)Weakly
Conflict (C)
Figure 6.8: A Catalogue of Objectives Based on Label Values.
The U label represents a situation where there is no positive or negative support. At
the time a soft-goal is newly introduced, it is given a U label by default. Figure 6.8 shows
a catalogue of label values. The spectrum ranges from denied to satisficed. Unknown and
conflicting values are shown in the middle.
Then, the Soft-Goal Evaluation (SGE) algorithm illustrated in Figure 6.9 consists of
two basic steps. For each soft-goal or interdependency in a SIG, the procedure first com-
putes the individual impact of each source-code improving transformation which we call it
Generate Individual Label (GIL). Secondly, the individual impacts of all interdependen-
cies are combined into a single label which we call it Combine Generated Labels (CGL).
Details of the each step of the procedure will be elaborated in the following sections.
6.3.2 Impact Analysis : Generate Individual Label (GIL)
In the first step, we determine the “individual impact” of an offspring’s contribution
towards its parent. For AND and OR contributions, we treat all of the offsprings as one
group with a single “individual impact”, defined as follows :
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 150
Algorithm 5.3. SGE(AC,DSG, T IM,SAM,VIC) =Input :
AC : A set of classes in an object-oriented legacy system.DSG : A List of Desired Soft-Goals.T IM : Transformation Impact Matrix.SAM : Soft-Goal Adjacency Matrix.
Output :VIC: A set of Vector-Impact Cost for AC.
Variables :COMi: Complexity Metrics Vector for class i.COHi: Cohesion Metrics Vector for class i.COU i: Coupling Metrics Vector for class i.
Method :
1. for each class C in AC do begin
2. COHC = NIL; COUC = NIL; COMC = NIL;
3. calculate the metrics values fromMC;/* Detect design flaws based on metric value by applying the evaluating rules */
4. append(COUC , DAC);
5. append(COMC , RFC); /* apply KCH Rule */
6. append(COHC , TCC); /* apply OC2H Rule */
7. .... /* Other rules using metrics fromMC can also be applied here */
8. if C is a deteriorated class based on dC(COUC , COMC) then begin
9. for each applicable transformation Ti do begin
10. find the satisfaction level for each DSG;
11. GIL (SAM, T IM, Ti);
12. CGL (SAM, T IM, Ti);
13. combine all satisfaction level as VIC;
14. end-for
15. end-if
16. end-for
Figure 6.9: Soft-Goal Evaluation Algorithm.
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 151
• If offspring1 AND ... AND offspingn SATISFICE parent then
label(parent) = mini(label(offpringi))
• If offspring1 OR ... OR offspingn SATISFICE parent then
label(parent) = maxi(label(offpringi))
where the labels are ordered in increasing order as follows :
× ≤ U ≈ \ ≤ √ (6.3)
Now, we need to consider the individual impact for some of the other contribution
types. Here are some rules for propagation of labels from an offspring to its parent which
are depicted in Table 6.4 in more detail :
• MAKE propagates√
from offspring to parent. It also propagates × to the parent.
• BREAK inverts the “sign” of an offspring’s√
label into × for the parent.
• HELP keeps the same direction, but “weakens” it. That is,√
in the offspring is
weakly propagated to W+ in the parent. However, × in the offspring is propagated
as × in the parent, as × is already the lower limit in the label set.
• HURT inverts the direction, and weakens it. That is,√
in the offspring is weakly
inverted to W− in the parent, and × in the offspring is weakly inverted to W+ in
the parent.
• UNKNOWN (“?”) always contributes U .
• An undetermined offspring (U) always propagates U , regardless of the contribution
type.
• A conflicting offspring (\) propagates \, unless the contribution type is UNKNOWN
in which case a U label is propagated.
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 152
Table 6.4 shows the individual impact of an offspring upon its parent during the
first step. Parent labels are shown in the table entries. It is interesting to compare
rows of entries of Table 6.4 with the label catalogue of Figure 6.8 which has a left-to-
right ordering. In Table 6.4, looking left-to-right at the individual impacts for satisficed
offspring (labelled√), there is a left-to-right progression through the label catalogue.
For individual impacts of denied offspring (labelled ×), there is a right-to-left progression
through the label catalogue. Also, it may be noted that Table 6.4 does not have entries
for other offspring, such as W+ and W−. In a nutshell, this step generates labels for a
parent given the labels of its offsprings. As we discuss below, the second step, namely
the Combine Generated Labels (CGL), amalgamates such values in a single label. We
will also discuss a possible extension to retain such values as outputs of the CGL step,
and inputs to the GIL step.
Label of Contribution Successors
Offspring’s Label BREAK HURT ? HELP MAKE
× W+ W+ U × ×\ \ \ U \ \
U U U U U U√ × W− U W+ √
Table 6.4: The Individual Impact of An Offspring.
6.3.3 Objective Analysis : Combine Generated Labels (CGL)
Once all contributing labels have been generated for a given parent, the second step of
the evaluation procedure combines them into a single label. The labels that contribute
to a parent are placed in a “bag” (a collection which allows duplicate entries, unlike a
set). The possible label values in the bag are ×, W−, \, U , W+, and√. A bag is used
because duplicate labels are useful as for the instance, where several positive supporting
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 153
contributions indicated by several W+ labels may be combined into a√
label.
The W+ and W− labels in the bag are first combined into one or more√, ×, \.
Specifically, W+ values alone in a bag result in√, and W− values alone result in ×.
Moreover, U labels depend on the nature of the target system. A mixture of W+ and
W− values produce√, × or \. The resulting set of labels is then combined into a single
one, by choosing the minimal label of the bag, with a label ordering :
\ ≤ U ≤ × ≈ √ (6.4)
If there are both√
and × values present, the result will be a conflict (\), and the
developer will have to deal with the conflict. For the purposes of this step, there is no
specific ordering relationship between√
and ×; instead they are both greater than other
label values.
By having W+ and W− as output values after the current step (CGL), they would
also have to be considered as inputs to subsequent first steps (GIL). This would require
Table 6.4 to be extended by adding rows for W+ and W− as offspring. Informally, we
can consider some possible propagation values : 1) W+ OR W+ could result in W+ for
the parent, 2)W− AND any value could result in denying the parent, 3) AW+ offspring
and a HELP or MAKE contribution could result inW+ for the parent, 4) AW+ offspring
and a BREAK or HURT contribution could result in W− for the parent. In this way, we
could consider modifying the evaluation procedure so that values such as W+ and W−
could appear as outputs of this step (CGL) instead of being eliminated. If this is the
case, this step (CGL) would use the following ordering :
\ ≤ U ≤ W− ≈ W+ ≤ × ≈ √ (6.5)
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 154
6.3.4 Problem Formulation : A Graph Search Approach
After applying the Soft-Goal Evaluation (SGE) algorithm including GIL and CGL, we
obtain a list of potential transformations with the evaluation of their impact on each
desired soft-goal. In this step, we present how to select a sequence of transformations
among several possible ones, that may yield the desired properties for the migrant system.
Such a problem can be formulated as a search in the space of alternative transformations.
Let G = (N(G), A(G)) to be a directed graph, N(G) to be the set of nodes in G that
are transformations, and A(G) be the set of arcs in G. Thus, A(G) ⊆ N(G) × N(G).
For each arc α = (ni, nj), node nj is referred to as the head of α and ni as the tail of α.
Furthermore, each node ni in the graph is labelled with a vector of impact values :
K(ni) = (impact1(ni), ..., impactq(ni)) (6.6)
where impactu(ni) , u = 1, 2, ..., q relates to the impact of associated transformations on
the corresponding non-functional requirement u. impactu(n) is defined as CostBenefit which
needs to be minimized by maximizing Benefit and minimizing Cost as will be elaborated
further.
Any transformation in the QDR Framework performs operations such as : i) com-
prehending/understanding source code for the application of transformation that can be
done by using investigation functions, ii) adding and/or deleting source code entities,
and iii) modifying source code entities. By these considerations, the Cost for applying a
transformation ti in QDR Framework can be measured as follows :
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 155
Cost(ti) = # of points of investigation (pre− and post− conditions) +
# of source code features added+
# of source code features deleted+
# of source code features modified (6.7)
We consider that each transformation makes some changes to the source code features
that affect directly the cost of the transformation. For defining what a source code feature
is, we have to take in account : 1) class specialization (is a) that means code and structure
reuse, 2) class association (is part of) that means class or system structure definition, and
3) class aggregation (is referred by) that means dynamic managing of objects. This
classification helps us to define a feature as the summation of # of classes/interfaces,
# of methods/constructors, # of variables. The section of a transformation process can
give us the exact number for such features.
As discussed in 4.3.2, we have discovered that there are operators (e.g., choice, se-
quential composition, parallel composition, and iteration) in which we can compose trans-
formations. Now, we need to define the Cost for such operators. Let ci be the cost for a
transformation ti, then the Cost for such compositional transformations can be defined
as follows :
• Cost for a Sequence Composition : Cost(t1; t2) = c1 + c2
• Cost for a Parallel Composition : Cost(t1‖t2) = c1 + c2
• Cost for a Choice Composition : Cost(t1 + t2) = min(c1, c2)
• Cost for a Loop : Cost(while(x) do ti) = cx + ci + Cost(while(x) do ti)
• Cost for a Condition : Cost(if x then t1 else t2) = cx +max(c1, c2)
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 156
In order to measure the Benefit for a potential transformation to be applied, a
summary of proposed metrics needs to be evaluated both before and after applying the
transformations. Let Mb = 〈m1,m2, ...,mn〉, (mi 6= 0), be a vector of metrics showing
different features of the source code before applying a candidate transformation and
Ma = 〈m′1,m
′2, ...,m
′n〉, (m′
i 6= 0), be a vector of metrics showing the same features of
the source code after applying the transformation, then for maximizing Benefit we need
to find the difference which is calculated as follows :
(Ma −Mb) > 0, ∀ ti, (m′i −mi) > 0
For the metrics that their decreasing values provide more benefit, we need to consider
1mi
instead of mi. Then Benefit can be defined as :
Benefit(n) = (m′
1 −m1
min(m′1,m1)
+ ...+m′
n −mn
min(m′n,mn)
)/n
Then, the search problem can be represented by a unique node in G called start node
s ∈ N(G) and Γ ≤ N(G) a set of goal nodes. We consider this search problem to be an
instance of the class of multi-objective search problems [102]. We can therefore formulate
the selection of source-code improving transformations as a multi-objective graph search
algorithm as depicted in Figure 6.10.
Let G be a graph where an initial node s and a set of goal nodes Γ have been selected.
The vector 〈f1∗(nk), f2∗(nk), ..., fq∗(nk)〉 gives the actual cost of the optimal transforma-
tion path from n to goal t ∈ Γ for any given requirement u = 1, 2, ..., q where
fi∗(nk) = gi
∗(nk) + hi∗(nk), i = 1, 2, ..., q (6.8)
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 157
Given Problem :
• A problem state-space, represented as a finite directed graph, where transformationsare nodes in the graph,
• A single start node in the graph,
• A finite set of goal nodes and end nodes in a path of source-code improving trans-formations that can introduce GoF design patterns [72] in the graph,
• A vector of impact-valued criterion associated with each arc in the graph,
• For each node, a set of vectors for heuristic functions providing information onimpact to be accrued along a portion of a solution graph.
• A preference among paths on their impacts.
Find Solution :
• The set of all non-dominated solution graphs (potential source-code improvingtransformations) in the graph.
Figure 6.10: Multi-objective Search Problem Formulation.
gi∗(nk) is the minimal cumulative impact in space i for a path from s to n; and hi
∗(nk)
is the actual remaining cost in requirement space i from n to any goal node. fi∗(nk) is
generally not known when the search is conducted, but can be approximated by a path
evaluation function fi(nk) of the type :
fi(nk) = gi(nk) + hi(nk), i = 1, 2, ..., q (6.9)
where gi(nk) is the cumulative impact in requirement space i of the best path known so far
from s to n. gi(nk) is defined as the cumulative cost of impact(n1)+ ...+ impacti(nk). As
discussed above, impacti(nk) can be calculated by maximizing Benefit and minimizing
Cost. This assumption modifies the path evaluation function fi(nk) as follows :
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 158
fi(nk) =j=k∑
j=1
impacti(nj) + hi(nk), i = 1, 2, ..., q (6.10)
Now, we need to calculate hi(n) which is an admissible heuristic function for each
transformation which means that :
∀ n ∀ i, hi(n) ≤ h∗i(n)
This function can be easily calculated as a distance from goal. Such a value can be
consider as the number of transformations that need to be applied from n to the goal
node which will be obtained from definition for each transformation based on the proposed
algebra.
6.3.5 Select Transformation Path (STP)
This section presents a multi-objective graph search approach to identify the set of all
non-dominated solution graphs in SIGs for selecting the source-code improving transfor-
mations. This algorithm can be considered as an adaptation of A∗ algorithm [128]. The
description of the proposed algorithm which is depicted in Figures 6.11 will be elaborated
further.
As a reminder, we defined that a transformation path T is said to be non-dominated
among a set of transformations A if there are no other transformation in the set A
that are at least as “good” as T with respect to all the non-functional objectives and
is strictly “better” than any other transformation with respect to at least one of the
non-functional objectives, where “good” and “better” are defined in terms of an impact-
valued criterion associated with each of the multiple non-functional objectives under
consideration. Thus, instead of seeking a single optimal solution, one seeks the set of
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 159
Page 1 of 3Algorithm 5.4. STP (PSP,GN ,NDS,AC,DSG, T IM,SAM) =
Input :PSP : A finite directed graph with transformations as nodes.GN : A finite set of goal paths in the graph.AC : A set of classes in an object-oriented legacy system.DSG : A List of Desired Soft-Goals.T IM : Transformation Impact Matrix.SAM : Soft-Goal Adjacency Matrix.
Output :NDS: A set of all non-dominated solution graphs.
Variables :OPEN : A set of potential transformation nodes for expansion.CLOSED: A set nodes that have been generated, but not in OPEN .SOLUTION : A set of solution paths discovered prior to current state.SOLUTION GOALS: A set of non-dominated goals associated with paths.SOLUTION IMPACTS: A set of non-dominated solution path impacts.LABEL: A set of accrued impacts of paths.Iteration: A variable keeps tracking of iteration number.VIC: A set of Vector-Impact Cost for each arc in the graph.
Method :
1. Initialize by setting OPEN to a set contains start node from PSP;
2. Initialize the following sets :
(a) CLOSED = ∅;(b) SOLUTION = ∅;(c) SOLUTION IMPACTS = ∅;(d) SOLUTION GOALS = ∅;(e) LABEL = ∅;
3. SGE(AC,DSG, T IM,SAM,VIC);
Continue in the Next Page ...
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 160
Page 2 of 3Algorithm 5.4. STP (PSP,GN ,NDS,AC,DSG, T IM,SAM) =
4. while (VIC 6∈ SOLUTION IMPACTS & GN ∈ OPEN) do begin
5. if ND = ∅ then begin
6. set SOLUTION GOALS to s;
7. append solution path impacts to SOLUTION IMPACTS;
8. append VIC to LABEL sets;
8. append solution paths to SOLUTION ;
9. end-if-then
9. else begin
10. choose a node n from ND based on CGL;
11. remove n from OPEN ;
12. append n to CLOSED;
13. end-if-else
14. update accrued impacts LABEL based on n;
15. if n ∈ GN , then begin
16. append n to SOLUTION GOALS;
17. append nimpact to SOLUTION IMPACTS;
18. remove any dominated members of SOLUTION IMPACTS.
19. Go to Step 44.
20. end-if-then
21. Generate the successors of n, using proposed algebra.
22. if n has no successors then Go to Step 44;
Continue in the Next Page ...
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 161
Page 3 of 3Algorithm 5.4. STP (PSP,GN ,NDS,AC,DSG, T IM,SAM) =
23. else begin
24. for all successors n′ ∈ n, do begin
25. if n′ is a newly generated node, then begin
26. establish a back-pointer from n′ to n;
27. set G(n′) = LABEL(n′, n);
28. compute node selection values, F (n′), using G(n′);
29. compute heuristic function values at n′, H(n′);
30. append n′ to OPEN ;
31. end-if-then
32. else do begin
33. while n′ 6= ∅ do begin
34. append nimpact′ to LABEL(n′, n);
35. update NDS based on G(n′);
36. if n′ 6∈ G(n′), then begin
37. delete associated path with n′ from LABEL(n′, n);
38. if n′ ∈ CLOSED then add n′ to OPEN ;
39. end-if-then
40. end-while
41. end-if-else
42. end-for-all
43. end-if-else
44. increment Iteration counter by 1;
45. end-while
Figure 6.11: Selection Transformation Path Algorithm.
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 162
non-dominated solutions. Determination of the most preferred alternative from the set
of non-dominated alternatives depends on the developer’s selection and the nature of the
target systems. The use of sets OPEN and CLOSED for control of the search is typical
in heuristic search work. SOLUTION and SOLUTION GOALS are introduced to help
collect multiple solutions.
Definition 3 : OPEN is a set of source-code improving transformation nodes that
are considered as potential candidates for expansion by the multi-objective algorithm.
Definition 4 : The CLOSED set is used in the algorithm to keep track of source-code
improving transformation nodes that have been generated, but are not on OPEN .
Definition 5 : A source-code improving transformation node n ∈ N(G) is said to be
generated if its vector is computed from that of one of its parents in SIGs.
Definition 6 : A source-code improving transformation node is said to be expanded
when all its successors have been generated.
Definition 7 : An arc is said to be traversed if the source-code improving transforma-
tion node at its head has been generated from the source-code improving transformation
node at its tail.
The necessary generalization of the various functions related to node evaluation to
allow for a set of evaluation at any given node results in the use of the sets G, H, and
F . G is a vector of cost to benefit (g1(n), g2(n), ..., gq(n)) of an efficient path from s
to n. This returns a set of non-dominated accrued impacts for a source-code improving
transformation node. H is a vector (h1(n), h2(n), ..., hq(n)) of an optimistic estimate of the
cost of a path from n to some goal nodes.This returns is a set of all non-dominated paths
impacts associated with a potion of at least one non-dominated solution path, specifically,
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 163
the impact of the potion between n and Γ. F is a vector (f1(n), f2(n), ..., fq(n)) of the
estimated values of the cost of a path that goes through n from the initial node s to some
goal nodes. This returns a set of source-code improving transformation node selection
values for a node n.
The requirement for accommodating possible multiple back-pointers at a node results
in the use of the LABEL sets which include accrued impacts of paths from s through n
to n′. SOLUTION is a collection of solution paths that have been discovered prior to the
start of the current state. SOLUTION GOALS is a set of non-dominated goals associ-
ated with paths in SOLUTION . SOLUTION IMPACTS is necessary in our general
case to account for the fact that there may be a number of non-dominated paths with
distinct costs or impacts. SOLUTION IMPACTS is a set of non-dominated solution
path impacts associated with goals in SOLUTION GOALS. Finally, ND is introduced
as a subset of OPEN to be identified for particular attention in the process of selecting a
node for expansion.
6.3.6 Usage of the Proposed Multi-Objective Algorithm : An Example
This section illustrates the operation of the proposed algorithm in Section 6.3 on a simple
state-space graph. The purpose of the example is to present an overview of the general
behaviour of the algorithm.
A state space graph is shown in Figure 6.12 which also shows the values of the arc costs
that refer to the impact of associated transformation on the corresponding non-functional
requirements. The value of M (number of objectives) for this example is 2 which means
two non-functional requirements or soft-goals can be considered for improving in the
target system. However, we need to clarify that the search is performed at one dimension
at a time.
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 164
T1
T2
T3
Goal Nodeswhich introduce
DPs
s
t1
t2
t3
(1 2)
(2 1)
(2 1)
(2 1)
(3 1)
(1 2)
(1 3)
(1 2)
Figure 6.12: State Space Graph for the Example.
Operation of the algorithm is followed using the sequence of the graphs that are
illustrated in Figure 6.13 and the corresponding trace presented in Table 6.5.
Each graph illustrates the state of the search for an iteration of the algorithm pro-
posed in Section 6.3. Arcs of the initial state-space graph are shown as dashed lines.
As the arcs are traversed during the search, they are represented as solid lines in fig-
ures. Final solution paths are shown as additional numbered dotted lines in the graphs.
Source-code improving transformation nodes of the initial problem state-space graph are
shown as circled nodes. OPEN source-code improving transformation nodes are shown
with double circles. Non-dominated members of OPEN ; that is, source-code improv-
ing transformation nodes of ND, are shown in large darkened circles. The source-code
improving transformation node selected for expansion in each iteration is depicted with
three circles. Finally, CLOSED source-code improving transformation nodes may be
identified by the fact that they are single solid circles for which at least one incoming arc
is no longer dashed.
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 165
Goal Nodeswhich introduce
DPs
(1 2)
(2 1)
(2 1)
(2 1)
(3 1)
(1 2)
(1 3)
(1 2)
T1
T2
T3
Goal Nodeswhich introduce
DPs
s
t1
t2
t3
(1 2)
(2 1)
(2 1)
(2 1)
(3 1)
(1 2)
(1 3)
(1 2)
Goal Nodeswhich introduce
DPs
(1 2)
(2 1)
(2 1)
(2 1)
(3 1)
(1 2)
(1 3)
(1 2)
Goal Nodeswhich introduce
DPs
(1 2)
(2 1)
(2 1)
(2 1)
(3 1)
(1 2)
(1 3)
(1 2)
t1
T1
T2
T3
t3
t2s
s
t1
T1
T2
T3
t2
t3
s
t1
t2
t3
T1
T2
T3
(c) (d)
(a) (b)
Figure 6.13: Graphical Trace of the Operation of the Proposed Multi-Objective Algo-rithm. (a) Iteration 1, (b) Iteration 2, (c) Iteration 3, (d) Iteration 4.
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 166
Iter. OPEN Back-pointer Adj. SOLUTION IMPACTS andNo. n G(n) F (n) n′ LABEL(n′, n) CLOSED SOLUTION GOALS0 s∗∗ (0 0) (1 2)(3 1) ∅ ∅
t∗∗1 (1 2) (2 4)(3 3) s (1 2)1 t∗2 (3 1) (5 2) s (3 1) s ∅
t3 (1 3) (2 5) s (1 3)t∗2, t
∗∗3
2 T1 (3 3) (3 3) t1 (3 3) s, t1 ∅T2 (2 4) (2 4)(5 2) t1 (5 2)
3 t∗∗2 , T1, T ∗2
T3 (2 5) (2 5) t3 (2 5) s, t1, t3 {(3 3)}, {T1}T1
4 T ∗∗2 (5 2) (5 2) t2 (5 2) s, t1, t2, t3 {(3 3), (5 2), (5 2)}, {T1, T2, T3}T ∗3 (5 2) (2 5)(5 2) t2 (5 2)
Table 6.5: Numerical Trace of the Operation of Multi-Objective Algorithm.
Table 6.5 traces the evolution of the critical quantities and sets as the search pro-
gresses. Elements of the sets G, F , and LABEL are only shown if they have been altered
in an iteration. Nodes in ND are marked with an asterisk in the first column and the node
selected for expansion is marked with a second asterisk in the same column. Nodes were
selected for expansion from ND based on the evaluation procedures described in Sec-
tion 6.3.1. Note that specific heuristic selection rules should be developed for particular
domains of application in target systems.
The search ends at the 5th iteration after finding the following three non-dominated
solution paths and their associated impact costs :
P1∗ = {s, t1, T1} c(P1
∗) = (3 3)
P2∗ = {s, t2, T2} c(P2
∗) = (5 2)
P3∗ = {s, t2, T3} c(P3
∗) = (5 2)
6.4 Summary
This chapter presented an algorithmic process that can be applied to introduce refac-
toring operations and design patterns into an object-oriented system for which cohesion
and coupling indicators have deteriorated under excessive and prolonged maintenance.
CHAPTER 6. SOFTWARE TRANSFORMATION PROCESS 167
The introduction of design patterns and other refactoring operations is achieved by the
application of a collection of quality improving transformations. An evaluation method
allows for the assessment of the impact these transformations have on the qualities of the
system that is improved.
This chapter also proposed a framework whereby object-oriented metrics can be used
as indicators for automatically detecting situations for particular transformations to be
applied in order to improve specific design quality characteristics. The process was based
both on modelling the dependencies between design qualities and source code features,
and on analyzing the impact various transformations have on software metrics that quan-
tify the design qualities being improved.
A multi-objective graph search algorithm to identify the set of all non-dominated
solution graphs in SIGs for selecting the source-code improving transformations allows
for the selection of a non-dominated path of the transformations. This algorithm can be
considered as an adaptation of A∗ algorithm. Three types of heuristics are used in the
algorithm : i) a node evaluation heuristic (GIL), ii) a node selection heuristic , and iii) a
solution based graph selection heuristics (CGL).
The proposed approach can assist a software engineer to select the proper transforma-
tions when re-engineering an object-oriented system and also assist the software engineer
to apply the transformations incrementally on specific error prone parts of the system.
We believe that the proposed framework is useful to restructure and maintain good qual-
ity object-oriented systems. This strategy can be used to prevent loss of maintainability
or restore it through re-engineering.
Chapter 7
Case Studies
The art of drawing conclusions from experiments and observationsconsist in estimating whether they are sufficiently great or numerousenough to constitute the proofs.
Antoine L. Lavoisier
This chapter presents a set of case studies related to the time complexity, space com-
plexity, and assessment of the quality-driven re-engineering technique introduced in this
thesis. The proposed technique has been implemented in a prototype that aims to improve
the quality of medium to large legacy systems implemented in object-oriented languages
like Java or C++.
7.1 Objectives and Scopes
Basili and Selby in [15] have proposed four paradigms for experimentation and empirical
studies in software engineering that are meant as guidelines for setting up and conduct-
ing experimentation. These paradigms consist of : i) improvement paradigm, ii) goal-
question-metric paradigm, iii) experimentation framework paradigm, and iv) classification
paradigm. In this respect, the case studies in this Chapter belong to the “experimenta-
168
CHAPTER 7. CASE STUDIES 169
tion framework paradigm” that consists of four categories corresponding to the phase of
the experimentation process, namely : “definition”, “planning”, “operation”, and “inter-
pretation”. The definition of the group of experimentations is presented below and the
other three phases will be elaborated further in this chapter. The experimentations in
this Chapter have been organized to:
• Demonstrate the generality of the proposed approach by experimenting with sys-
tems in different domains such as public libraries, expert systems, Java packages,
and monolithic applications.
• Evaluate the time and space complexity of quality-driven re-engineering technique
as a function of source code size.
• Evaluate the usefulness of the proposed approach in terms of quality and accuracy
of the proposed transformation process.
7.1.1 Experimentation Suite
The experiments are performed on six (ranging from small-size to large-size) open source
software systems. Table 7.1 presents the source code related characteristics of the exper-
imentation suite. The experiments for each system involve :
1. WELTAB Election Tabulation System [181] which was built in the late 1970s to
support the collection, reporting, and certification of election results by city and
county clerks’ offices in the State of Michigan. It was originally written in an
extended version of Fortran on IBM and Amdahl mainframes under the University
of Michigan’s MTS operating system, then was converted to C and run on PCs under
MS/DOS (non-GUI, pre-Windows) in late 1980. Finally, the Object-Orientation
CHAPTER 7. CASE STUDIES 170
Migration Tool [135] has been applied to it in order to migrate the original C
source code to new object-oriented C ++ code.
System Written Source Code Number of Number ofName Language (KLOC) Files Classes
WELTAB C++ 6.7 18 11
AVL C++ 8.4 23 17
NetBeans JavaDoc Java 14.4 101 98
JESS Java 21.6 112 72
Eclipse Ant Java 34.8 178 100
Eclipse JDTCore Java 147.6 741 258
Table 7.1: Source Code Statistics of the Case Study Software Systems.
2. GNU AVL Library [76] which is a public domain library written in C for sparse
arrays, AVL, Splay Trees, and Binary Search Trees. The library also includes
code for implementing single and double linked lists. The original system was
organized around C structs and an elaborate collection of macros for implementing
tree traversals, and simulating polymorphic behaviour for inserting, deleting and
tree re-balancing operations. Also, there were slightly more complex constructs
which built on top of the basic ones. These included sparse arrays and data caches.
The GNU AVL has been migrated in the previous project to C ++ [135].
3. Java Expert System Shell [94] which is a rule engine and scripting environment
written entirely in Sun’s Java language by Ernest Friedman-Hill at Sandia National
Laboratories [151]. JESS was originally inspired by the CLIPS expert system shell,
but has grown into a complete, distinct, dynamic environment of its own. Using
JESS, one can build Java applets and applications that have the capacity to pertain
inferences using a knowledge base in the form of declarative rules and facts. The
core JESS language is still compatible with CLIPS, in that many Jess scripts are
CHAPTER 7. CASE STUDIES 171
valid CLIPS scripts and vice-versa. Like CLIPS, JESS uses the Rete algorithm [69]
to process rules, a very efficient mechanism for solving the difficult many-to-many
matching problem.
4. NetBeans JavaDoc [127] which supports the JavaDoc standard for Java documen-
tation - both viewing it and generating it. JavaDoc is the Java programming lan-
guage’s tool for generating API documentation. The NetBeans IDE [126] is a devel-
opment environment - a tool for programmers to write, compile, debug and deploy
programs. It is written in Java - but can support any programming language. It
is a free product with no restrictions on how it can be used. NetBeans JavaDoc
gives the developers a solid documentation tool when working with code that the
IDE lets us integrate API documentation for the code we are working on into the
IDE itself. Jar files of classes imported by NetBeans JavaDoc are tools.jar and
netbeans-support.jar.
5. Eclipse Ant Package [60] provides support for running the Apache Ant [8] build tool
in the platform. Apache Ant is a Java-based build tool. In theory, it is kind of like
Make, but without Make’s wrinkles. Ant is different. Instead of a model where it is
extended with shell-based commands, Ant is extended using Java classes. Instead
of writing shell commands, the configuration files are XML-based, calling out a
target tree where various tasks get executed. Each task is run by an object that
implements a particular Task interface. Eclipse Ant Package defines a number
of task and data types and various infrastructure pieces which make Ant in the
platform easier and more powerful. Jar files of classes imported by Eclipse Ant are
j2ee.jar, jakarta-oro-2.0.5.jar and log4j-core.jar.
6. Eclipse JDTCore Package [61] which the Java model is the set of classes that model
the objects associated with creating, editing, and building a Java program. This
CHAPTER 7. CASE STUDIES 172
package contains the Java model classes which implement Java specific behaviour
for source and further decompose Java resources into model elements. Jar files
of classes imported by Eclipse JDTCore are ant.jar, jakarta-ant-1.4.1-optional.jar,
resources.jar, runtime.jar and xerces.jar.
7.1.2 Experimentation Hardware Platform
We use the Re-engineering Tool Kit for Java [145] for extracting facts from the Java source
code in order to provide a high-level view of the systems. For our analysis approach for
detecting design flaws, and performing proper transformations of any kind, the Java
source code and/or the Java class file must be parsed. The Re-engineering Tool Kit for
Java parses the source code (JavaML) and generates XML documents that are easier to
read and work with. Also, for collecting software metrics, we use the Datrix Tool [57].
Our experiments were carried on a SUN Ultra 10 440MHZ, 256M memory, 512 swap disk.
7.2 A Prototype for QDR Framework
As a part of this work, the proposed quality-driven re-engineering approach has been
implemented in a prototype which offers an interactive and incremental environment for
improving the quality of an object-oriented system 1. The architectural design of this
prototype consists a number of components with simple interface and with a pipe and
filter architectural style. Each component (filter) processes its input data in the form
of a file (pipe) and stores the results in another file for the next component. Figure 7.1
illustrates the architecture of this prototype with its components which are elaborated
further.
1The current version of the QDR Framework prototype consists of 6KLOC written in Java language.
CHAPTER 7. CASE STUDIES 173
Soft-GoalEvaluation
M2
Select PathTransformation
M3
Source Code
Parser
R1 R2
R3
AnalyzerDatrix
Key ClassDetector
M1
Code Generator Extractor
MetricR4 R5
CompiledMetrics
C1 C2
C3
C4
Parsing Phase
Metric Extractor Phase
Evaluation PhaseC4:
C3:
C2:
C1:
Evaluated results
Target code
Indirect metrics
R4:
R5:
R3:
level metricsClass/FileR2:
Parsed codeR1:M1:
M2:
M3:
Key classes to be transformed
Potentail transformationas a finite directed graph
A set of non-dominatedsolution graph
Memory Repository Components
New Target Code
SAM
DSG
TIMTIM
SAM
DSG
C2
Model Analysis Phase
Quality Improvement
Figure 7.1: The Architectural Design of the Prototype for QDR Framework.
CHAPTER 7. CASE STUDIES 174
7.2.1 Pre-Process Components
These components are composed of two phases which are described as follows :
• Parsing Phase : Program representation plays an important role on building tools
that facilitate software analysis and software maintenance. One of the most popular
representations is the Abstract Syntax Tree (AST) [3]. We have used Ret4J [145]
for building ASTs as a program representation scheme. Ret4J defines a language
model in terms of a Java language DTD and automatically annotates source code
with XML tags. The benefit of using XML in this context is that the corresponding
tree conforms with the language domain model as defined in the corresponding
language DTD. The advantage of this method is that the complete document exists
in memory and it can be easily processed and manipulated. The disadvantage is
that working with large XML documents imposes a large memory requirement.
This phase has been depicted, namely C1, on the left hand-side of Figure 7.1.
• Metric Extractor Phase : Metrics are not indications of bugs, but high metric num-
bers often indicate how complex, fragile, or sensitive to regressions a class may be.
Classes or methods with high metric values may be good candidates for refactoring
and software transformations. It is therefore useful for a us to monitor metrics and
investigate those metrics which seem out of line. Datrix [57] which is a tool for
software evaluation and a trademark of Bell Canada helps us in this respect. This
phase is done in two stages. First, direct class metrics (37 in total) are extracted
from the source code using Datrix Metric Analyzer. Second, the selected indirect
metrics which were discussed in Section 6.2.3 can be computed based on the first
step running some written scripts, as a part of the prototype, which is the most
attractive feature of Shell Programming. This phase including the two steps has
been depicted, namely C2, on the right hand-side of Figure 7.1.
CHAPTER 7. CASE STUDIES 175
7.2.2 Analysis Components
The major tasks of the prototype are performed by three analysis components as shown
in the middle part of Figure 7.1, namely C3. After parsing the source code and extracted
the selected metrics, it is the time to improve the quality of the parsed object-oriented
system. An object model has several levels of representation, including application level,
subsystem level, class level, and function level [32]. While design flaws can occur at any
level, our focus here is on class level deterioration. While there are several reasons for a
design to lose quality over time, here the focus is on detecting the key classes, using Key
Class Detector, that have high complexity and high coupling, and low cohesion. On the
other side, the re-engineering activities need to be done based on specific non-functional
requirements that are represented as a list of Desired Soft-Goals (DSG). Soft-Goal Evalu-
ation component builds a search graph of potential transformations based on i) Soft-goal
Adjacency Matrix (SAM) which was discussed in Section 6.1.2, ii) Transformation Impact
Matrix (TIM) which was discussed in Section 6.1.3, iii) the proposed algebraic framework
for the proposed layered transformation framework which was discussed in Section 4.3.2,
and iv) the list of DSG. The evaluation algorithm was elaborated in Section 6.3.1. The
final step in this phase (C3) is responsible for identifying the set of all non-dominated
solution graphs for selecting source-code improving transformations. Based on the pre-
conditions for each transformation and the source code features, we identify all possible
transformations that can be applied at any given point of the transformation process. A
snapshot of the QDR framework is depicted in Figure 7.2.
7.2.3 Post-Process Components
Once the transformations are determined and applied, it is necessary to verify that they
contribute towards the desired target qualities. The last step of the implemented proto-
CHAPTER 7. CASE STUDIES 176
type as shown in Figure 7.1, namely C4, takes care of these requirements. Code Generator
component uses XML2Java from Ret4J [145] to covert back XML representation to a valid
Java source file. Also, there is a need to re-apply and record the same object-oriented
metrics to the re-engineered classes and finally compare the recorded results to evaluate
design and source code improvement as well as compliance with the desired requirements
which can be computed using the described Metric Extractor Component.
Figure 7.2: A Snapshot of the Quality-Driven Re-engineering Framework.
CHAPTER 7. CASE STUDIES 177
7.3 Detailed Process of QDR Prototype
For the analyzing and improving the qualities of the case studies, we have applied the
proposed QDR framework using the incremental steps as describing in the following steps :
• Step 1 : After parsing the source code, we measure and record the specific object-
oriented metrics in order to detect classes for which quality has deteriorated. While
there are several reasons for a design to lose quality over time, here the focus is
on detecting the classes that have high complexity and high coupling. For detect-
ing such classes, there is a need to have a classification of object-oriented metrics
which relate to different categories of design quality and source code features. In
Section 6.2.3, we proposed such a catalogue of metrics.
• Step 2 : After detecting design flaws automatically, we need to re-engineer the
classes using proper transformations. On the other side, the re-engineering activ-
ities need to be done based on specific non-functional requirements that are rep-
resented as a list of Desired Soft-Goals (DSG). For correcting such design flaws
through software transformations, we look at the impact specific transformations
have on specific metrics as discussed in Section 6.2.4. Soft-Goal Evaluation compo-
nent builds a search graph of potential transformations based on SAM, TIM, the
proposed algebraic framework for the proposed layered transformation framework,
and the list of DSG. Based on this search space, a set of all non-dominated solution
graphs is identified for selecting source-code improving transformations. Now, we
can look at the operation of the the proposed A* algorithm in Chapter 6. What
we need to do is start with the goal state and then generate the graph downwards
from there. Obviously we need to consider two things : i) the best transformation
nodes and search those first, and ii) not to expand the same state repeatedly. We
start with the OPEN list. This is where we consider which nodes we haven’t yet
CHAPTER 7. CASE STUDIES 178
expanded. The CLOSED list is a list of nodes that we have expanded. Using the
OPEN and CLOSED list lets us be more selective about what we look at next in the
search. We want to look at the best transformation nodes first. We give each trans-
formation node a score on how good we think it is. This score should be thought
of as the cost of getting from the transformation node to the goal plus the cost of
getting to where we are. The details of these scores in terms of functions fi, gi, and
hi were discussed in Section 6.3.4. Using these function values the multi-objective
algorithm will be directed, subject to pre-conditions and postconditions we will look
at further on towards the goal. Based on the preconditions for each transformation
and the source code features, all selected transformation paths are identified using
the STP algorithm.
• Step 3 : After applying transformations, we need to re-apply and record the same
object-oriented metrics to the re-engineered classes and finally compare the recorded
results to evaluate design and source code improvement as well as compliance with
the desired requirements.
7.3.1 Selected Criteria for Implementing Transformations
As depicted in Figure 7.2, a subset of the proposed code improving transformations
catalogue discussed in Chapter 5 has been implemented in the prototype. In this section,
we explain our criteria for selecting such a subset of transformations to be implemented
within the scope of the thesis.
First for the restructuring transformations, we have considered a pattern from “Pri-
mary Layer of DPs” namely, the Composite design pattern which is the most popular one
as it is used by four other design patterns and is refined by three other design patterns
as shown in Figure 4.3. It means that we have started from Structural Patterns because
CHAPTER 7. CASE STUDIES 179
they are concerned with how classes and objects are composed to form larger structures.
The Composite pattern describes how to build a class hierarchy that is made up of dif-
ferent kinds of objects. In this category, another design pattern for re-architecting a
software system into subsystems and helping minimize the communication and data flow
dependencies between subsystems is the Bridge design pattern. This pattern decouples
an abstraction from its implementation so that the two can vary independently. This can
not only extend the abstraction and implementor hierarchy independently but also shield
clients from implementation details.
Second, we have considered the “Secondary Layer of DPs” that can be built on top of
the Composite design pattern as shown in Figure 4.3. As far as, the Behavioural Patterns
are concerned with the algorithms and the assignment of the responsibilities between
objects, we consider with two of them namely, Iterator and Visitor. The Iterator pattern
allows access to an aggregate object’s contents without exposing its internal represen-
tation. The pattern also supports multiple traversals of aggregate objects. Providing a
uniform interface for traversing different aggregate structures is another reason to use
this pattern that supports polymorphic iteration. On the other hand, the Visitor pattern
helps making the migrant system more maintainable because a new operation over an
object structure can be modified simply by adding a new visitor class. An explanation
is that as a restructuring operation, Visitors help in applying operations to objects that
don’t have a common parent class.
Third, we have considered creational patterns as they are concerned with the class
instantiation process. They become more important as systems evolve to depend more
on object composition than class inheritance. As that happens, emphasis shifts away
from hard-coding a fixed set of behaviours toward defining a smaller set of fundamental
behaviours that can be composed into any number of more complex ones. There are two
CHAPTER 7. CASE STUDIES 180
common ways to parameterize a system by the classes of objects it creates. One way
is to subclass the class that invokes the appropriate constructors. This corresponds to
using the Factory Method patterns. The other way to parameterize a system relies more
on object composition. Specifically, the pattern allows for the definition of a class that
supports constructors that can be parameterized. This is a key aspect of Abstract Factory
patterns which involve creating a new “factory object” whose responsibility is to create
product objects by invoking their corresponding constructors.
The above selection criteria also lead us to implement all six primitive design trans-
formations which are considered as the design motifs in the proposed layered architecture
depicted in Figure 4.4. Investigation Functions 5.2, Supporting Functions 5.3, and Posi-
tioning Transformations 5.4 were also implemented based on their demands according to
the proposed algebraic framework for transformations.
7.4 Some Statistics of the Subject Software Systems
In this section, we evaluate the time and space complexity of quality-driven re-engineering
technique as a function of source code size. Also, the usefulness of the proposed approach
is evaluated in terms of quality and accuracy of the proposed transformation process.
7.4.1 Time and Space Complexity
In Table 7.2, we have summarized the results collected from Java source codes in pre-
process phase. We can see that the output file which is based on the JavaML represen-
tation [145] is much larger than the input file which is plain Java source files. A closer
examination of the Java grammar used [114] provides a good explanation of this. In the
DTD for JavaML [114, 145], we observe that expressions are nested in such a way, so that
every kind of expression is described in terms of other expressions. This means that to
CHAPTER 7. CASE STUDIES 181
represent a unary expression, there is a need to store many levels of other expressions in
the XML file.
Source AST Parsing Stored ExtractingCode XML Time Metrics Metrics Time
System Name (KLOC) (MB) (min : sec) (KB) (sec)
NetBeans JavaDoc 14.4 35.9 4 : 45 619.7 72
JESS 21.6 43.1 5 : 25 739.3 98
Eclipse Ant 34.8 58.4 8 : 37 765.8 173
Eclipse JDTCore 147.6 402.2 40 : 14 2528.4 258
Table 7.2: Some Time and Space Statistics of the Case Study Software Systems.
In terms of time requirements, in Figure 7.3 we also graph the relationship between
system size, AST XML size, and parsing time. Overall, the parsing of Java source files is
reasonable, even when large systems are considered as seen in the last row in Table 7.2.
0 50 100 1500
100
200
300
400
500
Siz
e of
AS
T X
ML
(MB
)
Size of Source Code (KLOC)
Size
0 50 100 1500
500
1000
1500
2000
2500
Par
sing
Tim
e (s
ec)
Time
Figure 7.3: Graph of Parsing Time and Size Results for the Case Studies.
In the last two columns of Table 7.2, we have summarized the results collected for
metrics in terms of time and space. First, direct class metrics (37 in total) are extracted
CHAPTER 7. CASE STUDIES 182
from the source code using Datrix Metric Analyzer [57]. Second, the selected indirected
metrics which were discussed in Section 6.2.3 can be computed based on the first step
running some written scripts.
0 50 100 150500
1000
1500
2000
2500
3000S
ize
of S
tore
d M
etric
si (
KB
)
Size of Source Code (KLOC)
Size
0 50 100 15050
100
150
200
250
300
Ext
ract
ig M
etric
s T
ime
(sec
)
Time
Figure 7.4: Graph of Extracting Metrics Time and Size Results for the Case Studies.
From Table 7.2, we can see that the space for metrics is based on the input files which
are plain Java source files. In terms of time requirements, in Figure 7.4 we also graph
the relationship between system size, size of stored metrics, and time for extracting the
metrics. Overall, the time for extracting the metrics from Java source files is very fast,
even when very large systems are considered as seen in the last row in Table 7.2.
7.4.2 Impact of Applied Transformations on Soft-Goals
In this section, we summarize the collected results from case studies after applying the
transformations and discuss their impacts on soft-goal nodes.
In Table 7.3, we have summarized the results collected from case studies after applying
the transformations on the object-oriented metrics suite which are proper indicators for
CHAPTER 7. CASE STUDIES 183
maintainability. As shown in Table 7.3, there are two sets of transformations with their
impacts on the quality of target systems. While the first six rows of Table 7.3 show the
collected results for the primitive design pattern transformations, the columns third to
thirteen of the same table show the impacts of the corresponding primitive design pattern
transformations on the proposed object-oriented metrics suite.
Good object-oriented design recommends that classes be as lightly coupled as possi-
ble, so high CDBC [88], DAC [109], and LD [88] metric values may indicate poor design.
Experimental results for the “ABSTRACTIONS” transformation indicates an improve-
ment for low coupling by its positively impacts on CDBC [88] at the level of 12% on
average, on DAC [109] at the level of 10% on average, and on LD [88] at the level of 18%
on average as shown in Figure 7.5. Similarly, this transformation allows for performance
enhancement as well because it enables a class to take a more abstract view of the other
class by accessing it via the added interface. Our experimental results confirm this fact
for an average performance increase of 10% as shown in Figure 7.6.
CDBC CDE DAC DIT LCOM LD NOC NOM RFC TCC WMC−20
−10
0
10
20
30
40
Object−Oriented Metrics Suite
Per
cent
age
of C
hang
es (
%di
ff)
AbstractionExtensionMovementEncapsulationBuildRelationWrapper
Figure 7.5: Impact of Applying Primitive Transformations on Maintainability.
CHAPTER 7. CASE STUDIES 184
MetricName(%
diff)
SystemNames
Transform
ation
C D B C
C D E
D A C
D I T
L C O ML D
N O C
N O M
R F C
T C C
W M CWELTAB
17.21
2.03
15.87
03.79
13.73
0.02
4.09
3.65
7.93
−9.65
AVL
Abstraction
2.73
13.07
8.53
0.01
9.71
16.32
01.12
3.73
19.13
1.81
NetBeansJavaD
oc
12.02
2.98
7.17
019
.21
3.12
0.01
17.36
5.89
1.03
−9.07
JESS
9.73
2.15
3.59
0.02
11.41
24.70
03.66
2.57
5.72
−11
.38
WELTAB
7.05
14.76
−3.76
19.47
1.73
−11
.54
8.09
4.77
0.04
11.07
0NetBeansJavaD
oc
Extension
9.06
17.51
−5.32
7.92
13.21
−9.86
3.37
5.76
06.66
0.01
JESS
12.41
7.62
−2.9
8.76
8.32
−5.47
12.54
4.79
0.01
18.32
0.03
AVL
1.65
0.01
0.02
17.87
12.54
01.99
3.09
−9.43
8.65
0NetBeansJavaD
oc
Movem
ent
−11
.43
00.01
2.65
11.37
0.02
1.09
6.95
−4.75
10.54
0.01
Eclipse
Ant
−8.35
0.04
08.23
17.61
01.06
4.07
−3.06
13.76
0.02
WELTAB
23.32
13.76
9.56
11.87
−1.76
1.54
4.98
0.01
0.01
0.03
0.02
AVL
Encapsulation
18.37
11.43
2.54
1.06
−4.56
13.76
3.76
0.04
00.01
0NetBeansJavaD
oc
5.43
23.76
1.87
15.43
−3.21
6.43
3.76
00.02
00.01
JESS
19.65
17.87
5.32
5.76
−10
.55
1.07
13.98
0.07
0.03
0.01
0.02
WELTAB
BuildRelation
13.49
12.98
0.05
0.01
−4.29
0.02
0−7.87
4.73
0.02
14.54
JESS
25.60
3.64
0.02
0.04
−28
.62
00.03
−7.82
7.77
015
.81
JESS
Wrapper
33.29
42.91
0.02
0.05
−9.53
0.03
0−14
.11
017
.40
−9.93
Eclipse
JDTCore
20.34
17.65
00.02
−17
.45
00.02
−13
.37
0.02
6.87
17.13
WELTAB
AbsFacGen.
7.82
6.48
8.44
3.23
−4.78
−1.17
1.65
−3.22
−1.20
12.32
−2.09
JESS
14.65
8.17
1.43
2.54
−10
.39
−7.43
6.26
−2.11
0.06
3.83
1.07
WELTAB
FactM
ethGen.
7.04
3.44
3.23
7.56
−1.94
−3.76
3.89
−3.70
−7.39
7.50
−1.19
JESS
4.17
5.71
6.34
7.83
−4.19
−11
.91
2.59
−0.39
−2.31
10.01
−2.43
JESS
BridgeGen
25.73
18.44
00.01
−8.31
0.01
0.03
−2.97
−1.32
9.61
−3.26
Eclipse
JDTCore
11.14
6.12
0.10
0.23
−9.82
00.14
−8.14
0.34
3.91
−7.61
WELTAB
Com
posGen.
15.35
8.55
5.83
0.02
−4.53
3.47
0.03
−1.24
2.72
3.69
5.18
JESS
15.17
13.78
1.98
0.01
−9.52
10.31
0.02
−3.79
1.11
2.86
4.21
AVL
IteratorGen
4.78
7.72
5.39
12.43
3.44
9.58
1.09
0.52
−1.37
10.96
0.13
NetBeansJavaD
oc
7.72
17.95
1.97
10.36
15.06
2.07
1.93
17.54
1.43
2.16
−3.07
WELTAB
VisitorGen
11.08
10.87
1.37
6.54
−1.88
−5.04
3.52
−2.81
0.43
7.44
3.17
JESS
10.76
17.84
−1.21
1.79
−1.73
1.39
6.32
−0.09
1.01
10.28
1.91
Table 7.3: Impact of Applied Transformations on OO Metric Suite for the Case Studies.
CHAPTER 7. CASE STUDIES 185
High CDE [13] and NOM [109] metric values may indicate unnecessary complexity.
Experimental results for the “EXTENSION” transformation indicates an improvement
for complexity by its positive impact on CDE [13] at the level of 15% on average, and
on NOM [109] at the level of 7% on average as shown in Figure 7.5. However, the incor-
poration of this transformation has been shown to decrease performance by an average
of almost 3% as shown in Figure 7.6. This is a typical case of conflict in NFR soft-goal
interdependency graph.
ABS EXT MOV ENC BRL WRP AFG FMG BDG CPG IRG VSG−20
−10
0
10
20
30
40
Applied Primitive/Complex Transformations
Per
cent
age
of P
erfo
rman
ce C
hang
es (
%di
ff)
AVL GNUWELTABNetBeans JavaDocJESS
Figure 7.6: Impact of Applying Different Transformations on Performance.
Classes with many superclasses, yielding high DIT [41] and NOC [109] metric values,
have their behaviour scattered in many places, requiring more effort to maintain. This
is the hidden cost of subclassing, often overlooked in OO designs. Experimental results
for the “ENCAPSULATION” transformation show an improvement for inheritance by
its positive impact on these metric values at the level of 8% on average as shown in
Figure 7.5. Similarly, this transformation allows for performance enhancement for an
average increase of 23% as shown in Figure 7.6.
CHAPTER 7. CASE STUDIES 186
The cohesion of a class describes how closely the entities of a class (such as at-
tributes and methods) are related. Often, cohesion is measured by establishing rela-
tionships between methods of the class in the case where the same instance variables are
accessed. TCC [25] and LCOM [83] are proper indicators for this non-functional require-
ment. Experimental results for the “MOVEMENT” primitive transformation shows an
improvement for cohesion by its positive impact on at the level of 12% on average and on
LCOM [83] at the level of 15% on average as shown in Figure 7.5. However, the incorpo-
ration of this transformation has been shown to decrease performance by an average of
almost 7% as shown in Figure 7.6.
The last six rows of Table 7.3 show the collected results for the complex design pattern
transformations, the columns third to thirteen of the same table show the impacts of the
corresponding complex design pattern transformations on the proposed object-oriented
metrics suite. The results and the impact on performance and maintainability of such
complex design pattern transformations are also illustrated in Figures 7.6 and 7.7.
CDBC CDE DAC DIT LCOM LD NOC NOM RFC TCC WMC−10
−5
0
5
10
15
20
Object−Oriented Metrics Suite
Per
cent
age
of C
hang
es (
%di
ff)
AbstractFactoryGenFactoryMethodGenBridgeGenCompositeGenIteratorGenVisitorGen
Figure 7.7: Impact of Applying Some Complex Transformations on Maintainability.
CHAPTER 7. CASE STUDIES 187
The IteratorGen transformation allows access to an aggregate object’s contents with-
out exposing its internal representation. The pattern also supports multiple traversals of
aggregate objects. Providing a uniform interface for traversing different aggregate struc-
tures is another reason to use this pattern that supports polymorphic iteration. Our
experimental results indicate an increase of maintainability with respect to positive im-
pact on all object-oriented metrics as depicted in Figure 7.7. However, this complex
transformation reduces the performance by almost 20% because of more than traversal
can be pending on an aggregate object.
The CompositeGen transformation describes how to build a class hierarchy that is
made up of two kinds of objects : primitives and composites. It means that the key to
this complex design pattern transformation is an abstract class that represents both prim-
itives and their containers. This transformation is found to reduce complexity because it
allows for component sharing. Experimental results indicate a complexity improvement
on CDE [13] at the level of 12% on average and on WMC [41] at the level of 5% as shown
in Figure 7.7. Similarly, this transformation allows for performance enhancement as well,
because it allows for explicit superclass references and simplifies component interfaces.
Our experimental results confirm this result for an average performance increase of 25%
as illustrated in Figures 7.6.
7.5 Discussion on QDR Framework Evaluation
In this section, some of the case studies are analyzed in more detail. Using the trans-
formations described in Chapter 5, we have collected experimental results in order to
evaluate the impact of particular implemented transformations. The results and the im-
pact on performance and maintainability by applying selected transformations for the
case studies are illustrated in Figure 7.5 to 7.7.
CHAPTER 7. CASE STUDIES 188
JESS can be considered as one of the case studies to be discussed. Three classes were
detected by the assessment strategy as a deteriorated design from the maintainability
point of view according to one class-one concept heuristic (OC2H) rule. These three
classes are called respectively, Deffacts, Deffunction, and Defglobal. Deffacts is a public
class which extends Java.lang.Object and implements java.io.Serializable. This part of
JESS system is depicted as a UML diagram in Figure 7.8. Rete class is also the reasoning
engine and executes the built Rete network, and coordinates many other activities. This
is also a public class that extends java.lang.Object and implements java.io.Serializable
<<interface>> Visitable
Deffacts Deffunction
accept Visitor(v)...
...getModule()getFact (int idx)getDocString()accept Visitor(v) accept Visitor(v)
addAction(Funcall fc)addValue(Value cal)getDocString()...
reset(Rete engine)getInitializationValue()accept Visitor(v)
getName()...
Defglobal
Rete
addDeffacts(Deffacts df)
findDefglobal(java.lang.string name)listDeffacts()listDefglobals()listFunctions()...
findDeffacts(java.lang.string name)
Figure 7.8: A Part of Object Model of Java Expert System Shell (JESS).
One can create deffact objects and add them to a Rete engine using Rete.addDeffacts().
Deffunction is a public class which extends java.lang.Object and implements Userfunction
and java.io.Serializable. One can create such objects and add them to a Rete engine us-
ing Rete.addUserfunction. Defglobal is a public class which extends java.lang.Object and
implements java.io.Serializable. One can create Defglobals type objects and add them to
a Rete engine using Rete.addDefglobal.
The values for the object-oriented metrics suite of these classes are given in Table 7.4.
CHAPTER 7. CASE STUDIES 189
Metrics Deffacts Deffunction Defglobal
CDE 3.794 3.374 2.321
DAC 0 2 1
LCOM 9 5 5
NOM 9 9 5
RFC 30 15 24
TCC 11.3 25.7 34.6
WMC 16 30 50
Table 7.4: Object-Oriented Metrics for Three classes of JESS.
To avoid that the KCH rule applies for each of the three classes, we have to increase
the value of TCC, to decrease the value of DAC and to decrease the value of RFC. As
Figure 7.8 shown, Rete class make use of Visitable interface that has been implemented
in three different implementation classes, namely Deffacts, Deffunction, and Defglobal.
The weakness of this structure becomes apparent if the programmer wants to extend the
interface in some way. Then, for each existing implementation class, a new class will have
to be added.
After applying the STP algorithm as discussed in 6.3.5, the following sequences of
potential transformations are proposed to apply for correcting such design flaws :
• Path 1 : Sup5 ; Pos3 ; (Pos16)∗
• Path 2 : Sup3 ; Pos3 ; (Sup2 ; Pos7)∗ ; (Pos13)
∗
• Path 3 : Sup1 ; Pos6 ; Pos5
The first path is a “WRAPPER” transformation which enables the Visitable interface
to be extended separately from its implementation. This transformation can create an
abstract class for the three classes. As these three classes have common methods (such
CHAPTER 7. CASE STUDIES 190
as accept, getDocString), the RFC and DAC do not change which is sufficient to avoid
the application of “WRAPPER” transformation. This transformation is appropriate
according to the context of the application. In considering “WRAPPER” primitive design
pattern transformation, it is clear that the theme of delegation is involved. A new wrapper
class is to be added between the existing Rete class and the implementation classes. The
effect of applying the “WRAPPER” transformation is depicted as a UML diagram in
Figure 7.9. The duty of this class is to delegate all the requests it receives from the client
(Rete) to the appropriate implementation object.
Rete
addDeffacts(Deffacts df)
findDefglobal(java.lang.string name)listDeffacts()listDefglobals()listFunctions()...
findDeffacts(java.lang.string name) accept Visitor(v)...
Visitable<<interface>>
accept Visitor(v)getInitializationValue()reset(Rete engine)getName()...
Defglobal
accept Visitor(v)addAction(Funcall fc)addValue(Value cal)getDocString()...
DeffunctionDeffacts
accept Visitor(v)getDocString()getFact (int idx)getModule()...
(Visitable object)...
WrapperVisitable
WrapperVisitable
getobject(Visitor)
Figure 7.9: The Same Part of JESS After Applying WRAPPER Meta-Pattern Transfor-mation.
As illustrated in Figure 7.9, the “WRAPPER” transformation is used to “wrap” an
existing receiver class with another class, in such a way that all requests to an object of
the wrapper class are passed to the receiver object it wraps, and similarly any results
of such requests are passed back by the wrapper object. This requires that all existing
instantiations of the receiver class be also wrapped with an instantiation of the wrapper
class itself. The overall effect of this transformation is to add a certain flexibility to the
relationship between a client object and the receiver object it uses by increasing the value
CHAPTER 7. CASE STUDIES 191
of TCC and decreasing the values of LCOM and NOM. All communication now goes via
the wrapper object (WrapperVisitable), which means that run-time replacement of the
receiver object classes becomes possible without the client object (Rete) being aware of
the change. Experimental results confirm such maintainability improvement in terms of
reducing complexity and coupling measurement as shown in Table 7.3. Application of
this primitive transformation also allows for performance enhancement for an average 5%
as illustrated in Figures 7.6. A Similar situation was detected and applied for Eclipse
JDTCore as shown in Table 7.3. Both of these systems could be improved further by the
application of BridgeGen complex transformation.
The second path can be the application of the “EXTENSION” transformation for
these three classes in JESS which proposes the creation a set of specialized subclasses
for each class. The three classes Deffacts, Deffunction, and Defglobal are small and are
already pretty much specialized, then thus this transformation and it corresponding path
can be omitted. The third path is the application of “ABSTRACTION” transformation
for these three classes of JESS system. This can not be performed because of violating
the preconditions based on the source code features for this part of system.
We consider AVL GNU as another case study to be discussed further in this section.
AVL object model is depicted in Figure 7.10. Two classes were detected by the assessment
strategy as a deteriorated design from the maintainability point of view according to
one class-one concept heuristic (OC2H) rule. These two classes are called respectively,
ubi cacheEntry and ubi cachRoot. After applying STP algorithm as discussed in 6.3.5,
this sequence of potential transformations is proposed to apply for correcting such design
flaws : Pos3 ; Pos9 ; (Pos2 ; Pos11)∗ ; Sup1 ; Pos6 ; Pos5 ; (Sup2 ; Pos7)
∗ ; (Pos15)∗
This sequence of transformations introduces IteratorGen complex transformation which
CHAPTER 7. CASE STUDIES 192
Figure 7.10: Object Model of AVL GNU Library System.
accesses an aggregate object’s contents without exposing its internal representation. This
transformation also supports multiple traversals of aggregate objects. Providing a uniform
interface for traversing different aggregate structures is another reason to use this transfor-
mation that supports polymorphic iteration. Applying this transformation to AVL system
build “Cache”class as illustrated in Figure 7.11. An aggregate object such as a “cache”
can provide a way to access its elements (e.g., “ubi cacheRoot” and “ubi cacheEntry”)
without exposing its internal structure. This may result to a system that is more main-
tainable because of the simplification of the aggregate interface. Our experimental results
indicate an increase of the maintainability as shown in Table 7.3. However, this trans-
formation reduces the performance by almost 10%, as depicted in Figure 7.6, because of
more than one traversal can be pending on an aggregate object. Similar situation was
applicable for NetBeans JavaDoc.
CHAPTER 7. CASE STUDIES 193
Figure 7.11: Object Model of AVL After Applying Transformations.
We consider WELTAB as another case study to be discussed further in this section.
The WELTAB object model is depicted in Figure 7.12. The “REPORT” class was de-
tected by the assessment strategy as a deteriorated design from the maintainability point
of view according to key class heuristic (KCH) rule. This class aims to support multiple
printed reports. Different reports have different appearances and headers for printing.
To be portable across different report style sheets, After applying the STP algorithm as
discussed in 6.3.5, this sequence of potential transformations is proposed to apply for
correcting such design flaws :
ABSTRACTION ; ENCAPSULATION ; BUILDRELATION ; EXTENSION
This sequence of transformations actually introduces FactoryMethodGen complex
transformation which can solve the addressed problem by defining an abstract “Report-
CHAPTER 7. CASE STUDIES 194
Figure 7.12: Object Model of WELTAB Election Tabulation System.
Gen” class that declares an interface for creating each kind of reports as illustrated in
Figure 7.13. This class acts as an Factory Method pattern. Our result for this system
indicates that this transformation reduces the performance by almost 7%, possibly due to
the dynamic nature of selecting an invoking the proper constructors. However, the incor-
poration of this pattern has been shown to improve coupling by an average of almost 5%
and to decrease complexity by an average of almost 4%. This is a typical case of conflicts
in the NFR soft-goal interdependency graph (performance vs. complexity and coupling).
Table 7.3 summarizes all these results with respect to maintainability enhancements while
Figure 7.6 shows this transformation impacts on performance.
CHAPTER 7. CASE STUDIES 195
Figure 7.13: Object Model of WELTAB After Applying Transformations.
7.6 Summary
The design and implementation of supporting tools are fundamental requirements to
assess the practical use of a re-engineering approach. In this chapter, the important
aspects of the proposed quality-driven re-engineering framework were tested through a
series of experiments.
This framework provides an incremental environment for improving specific system
qualities, namely maintainability and performance, in an object-oriented target system.
The proposed toolkit environment consists of three main phases namely pre-process com-
ponents, analysis components, and post-process components. The experiments were per-
formed on six open source object-oriented systems.
Chapter 8
Future Directions and Conclusions
Attempt the end, and never stand to doubt;Nothing is so hard, but research will find it out.
Robert Herrick
In this chapter, we summarize the findings of this thesis and present future directions
that stem from this research. In Section 8.1, we present the contributions of the thesis
and in Section 8.2, we discuss future work that would extend this research.Finally, in
Section 8.3, we make some concluding remarks.
8.1 Contributions
The principle contributions of this thesis were also stated in Chapter 1. Here we discuss
them in more detail and in the light of the material already presented. These include :
• The design and development of a collection of comprehensive soft-goal interdepen-
dency graphs as they pertain to performance and maintainability of large object-
oriented legacy systems. The essence of our methodology has been published in
summary form in [163, 170], and more completely in [171].
• The design and development of a comprehensive catalogue of transformations as
196
CHAPTER 8. FUTURE DIRECTIONS AND CONCLUSIONS 197
these have been modeled in soft-goal interdependency graphs and can be applied
at source code level of an object-oriented legacy system to address specific re-
engineering objectives. In [165], we examined design patterns from a different
perspective namely, their classification and usage for software re-engineering and
restructuring. Specifically, twenty three GoF design patterns were re-classified in
terms of a layered model that is denoted by six different relations. We also discussed
how the classification scheme can be useful for the re-engineering and restructuring
of object-oriented systems. This classification was developed to support the wider
goal of improving the quality and the design of migrant code while maintaining its
original functionality. This step helped to propose a layered model whereby the
transformation process is based on investigative functions for evaluating precondi-
tions, supportive functions for positioning the system to a form that a transforma-
tion can be applied, primitive design pattern transformations, and complex design
pattern transformations. This layered model of software transformations has been
published in [166]. The application of this model in full rigor to AVL GNU Library
System [76] has been published in [164].
• The design and development of a framework by which the new migrant code can be
measured and assessed on whether it meets the quality requirements initially set.
We proposed a framework where a catalogue of object-oriented metrics can be used
as indicators for automatically detecting situations where a particular transforma-
tion can be applied to improve the quality of an object-oriented legacy system. The
improvement process is based on analyzing the impact of various transformations
on object-oriented metrics and was discussed in [167].
• The design and development of an analysis methodology that allows for the identi-
fication of error prone architectural design and source code programmatic patterns
CHAPTER 8. FUTURE DIRECTIONS AND CONCLUSIONS 198
that can be “repaired” according to the transformational steps identified by the soft-
goal graphs. We proposed algorithms for incrementally re-engineering the source
code by applying the identified transformation rules. The essence of our methodol-
ogy has been submitted for publication [168].
• The design and development of a prototype system that assists on automating
the re-engineering process for re-engineering tasks that pertain to enhancements of
the performance and maintainability of the migrant system. An extensive set of
transformations has been designed and implemented.
8.2 Future Work
Several new research questions have arisen from this research thesis. Possible future work
is presented below :
• Quality-Driven Component-Based Software Engineering : Automated component-
based development is emerging as a field of study in software engineering. There
are many open issues that need to be resolved before a component-based develop-
ment approach can make a significant impact on mission-critical software. Methods
must be developed that allow measurement and prediction of non-functional char-
acteristics such as availability, adaptability, security, and performance. Automatic
analysis and design methodologies although increasingly in use, are still lacking the
required formalization. Middleware technologies such as Microsoft’s .NET and Sun
Microsystem’s EJB are slowly moving into the domain of automated component-
based software engineering. However, their emphasis is typically on generation, such
as middleware code generation or user-interface generation, and their support for
quality control is only beginning to develop. Therefore, the ability to model and rea-
son about the non-functional characteristics of component-based systems formally
CHAPTER 8. FUTURE DIRECTIONS AND CONCLUSIONS 199
is vital to any endeavor to automate the process of component development, adap-
tation, integration and deployment. The proposed quality-driven re-engineering
framework presented in this thesis can serve as a foundation to build such a model
for component-based systems.
• Measuring Quality of Service in Distributed Object Systems : Distributed appli-
cations are difficult to build and maintain and are even more difficult when the
applications are distributed over wide area networks or heterogeneous platforms.
Distributed object computing middleware has emerged to simplify the building of
distributed applications by hiding implementation details behind functional inter-
faces. However, critical applications need to comply with non-functional require-
ments, such as real-time performance, dependability, or security, that are as im-
portant as the functional requirements, but are also hidden by the middleware.
Because current distributed object middleware does not support these aspects of
critical applications, application developers often find themselves bypassing the dis-
tributed object systems, effectively gaining little or no advantage from the middle-
ware. There is a need to develop Quality Objects Framework for including Quality
of Service in distributed object applications. This framework can support the speci-
fication of quality of service contracts between clients and service providers, runtime
monitoring of contracts, and adaptation to changing system conditions. A crucial
aspect of developing such a framework is a suite of Quality Description Languages
for describing states of quality of service, system elements that need to be mon-
itored to measure the current quality of service, and notification and adaptation
to trigger when the state of quality of service in the system changes. The taxon-
omy proposed in this thesis for building non-functional requirements in the form of
interdependency soft-goal graphs can be a step towards developing such a quality
CHAPTER 8. FUTURE DIRECTIONS AND CONCLUSIONS 200
description language for measuring quality of service in distributed object systems.
• Incorporating Non-functional Requirements into Software Architectures : During the
software development process, functional requirements are usually incorporated into
the software artifacts step by step. At the end of the process, all functional require-
ments must have been implemented in such a way that the software satisfies the
requirements designed at the early stages. Non-Functional Requirements (NFRs),
however, are not implemented in the same way as functional ones. The introduction
of NFRs into the software architecture is an important step in the software design.
In order to formalize NFRs, we need to develop an approach where we first select
which NFRs are considered in the formalization, design a strategy for specifying the
NFRs in a formal language, and finally specify the NFRs. This focuses on a fact
that the specification of non-functional requirements such as performance must be
expressed in terms of sets, operations and constraints on a formal language which
is based on a set theory. Essentially, first-order logic expressions combined with the
definition of sets are sufficient for modeling NFRs, instead of temporal logic or first
order predicates. The use of such a formal model enables us to verify properties of
the software in the early stages of the software design. In terms of dynamic sys-
tems, it assumes a very important role because at configuration time it is possible
to check when two components have compatible non-functional properties. Also,
such a conceptual model will be proposed using some heuristics to make UML as a
standard notation for modeling the software systems suitable to handle NFRs. The
proposed process algebra for the layered software transformations to build design
pattern discussed in this thesis builds a bridge towards incorporating NFRs into
software architecture.
CHAPTER 8. FUTURE DIRECTIONS AND CONCLUSIONS 201
8.3 Conclusion
This thesis addresses the issue of developing a re-engineering methodology and its associ-
ated architecture for migrating an object-oriented legacy system to a new target system.
The methodology allows for specific design and quality requirements of the target migrant
system to be considered during the re-engineering process that is applied on iterative and
incremental steps. The focal point is to recover an object model from the source code and
incrementally refine it, taking into consideration design and quality requirements for the
migrant system. This includes the identification and classification of refactoring opera-
tions and design patterns that will allow for quality enhancements to be achieved during
the migration process. Refactoring operations and design patterns have been proposed
only in the context of forward engineering but we believe that the classifying and devel-
oping patterns for reverse engineering and quality based re-engineering is an important
research task and a novel idea.
Overall, this research work is important for two reasons. Firstly, it attempts to
address a problem that has challenged the research community for several years, namely
the maintenance of object-oriented systems. Secondly, it aims to devise a workbench in
which re-engineering activities do not occur in a vacuum, but can be evaluated and fine-
tuned in order to address specific quality requirements for the new target system such as
enhancements in maintainability and performance.
Appendix A
Investigative Functions Catalogue
• Inv1: Argument argument(MethodInvocation/ObjectCreationExpr invocation, int i)
Returns the ith argument to the given method invocation or object creation expres-
sion or ⊥ if no such argument exists.
• Inv2: Class classCreation(ObjectCreationExpr e)
Returns the class that can be created by the given constructor expression.
• Inv3: Class classOf(Constructor/Method/Field a)
Returns the class to which the given constructor/method/field belongs. The condi-
tion classOf(a) = c is also written as a ∈ c.
• Inv4: Class containClass(ObjectReference o)
Returns the class that contains the given object reference.
• Inv5: Method containMethod (ObjectReference/ObjectCreationExpr e)
Returns the method containing the given object reference or object expression.
• Inv6: Constructor contstructorInv (ObjectCreationExpr e)
202
APPENDIX A. INVESTIGATIVE FUNCTIONS CATALOGUE 203
Returns the constructor that is invoked by the given object creation expression. This
can be determined based on the static types of the arguments to the constructor.
• Inv7: Boolean createsObject (Constructor c, Method m)
Returns true if the method m creates and returns a new object of the same class
and in precisely the same state as would be created by c, given the same argument
list. m must have no other side-effects; in particular it must neither access any
variables other than its parameters, nor send a message to another object.
• Inv8: Boolean creates(Class c1, Class c2)
Returns true if a method in the class c1 creates an instance of the class c2.
• Inv9: Boolean declares(Class c, String n, Signature s)
Returns true of the class c contains a method named n of signatures s in its interface.
An implementation need not to be provided, and the declaration of n(s) may appear
as an abstract method in a superclass or as an element of an interface that c
indirectly/directly implements. The parameter direct is added if the test is only to
refer to the class c itself, and for simplicity, a method may be provided as parameter
instead of the method name and signature. The parameter c may also to be an
interface with the natural interpretation.
• Inv10: Boolean defines(Class c, String n, Signature s)
Returns true if a concrete method called n of signature s is contained in the class
c or one of its superclasses. If no signature is provided, it simply tests if a method
named n is contained in the class c or one of its superclasses. Again, the parameter
direct is added if the test is only to refer to the class c itself, and, for simplicity, a
method may be provided as parameter instead of the method name and signature.
APPENDIX A. INVESTIGATIVE FUNCTIONS CATALOGUE 204
• Inv11: Boolean equalInterface(Class/Interface c1, Class/Interface c2)
Returns true is c1 and c2 declare precisely the same public methods. Public fields
and static methods are not included in the comparison.
• Inv12: Boolean implmInterface(Class/Interface e, Interface i)
Returns true if there is an implements link from the class/interface e to the interface
i.
• Inv13: Boolean initializes(Method/Constructor m, Field/Variable f, Expr e)
Returns true if the method/constructor m initializes the field/variable f to the
expression e.
• Inv14: Boolean isAbstract(Class/Method x)
Returns true if the class/method x is declared to be abstract.
• Inv15: Boolean isClass(Class c)
Returns true if c is a class. If given a string as argument, it tests if a class of the
given name exists in the program.
• Inv16: Boolean isInterface(Interface i)
Returns true i is an interface in the program. If given a string as argument, it tests
if an interface of the given name exists in the program.
• Inv17: Boolean isPrivate(Method/Field e)
Returns true if the method/field e is a private member of its class.
• Inv18: Boolean isPublic(Method/Field e)
Returns true if the method/field e is a public member of its class.
APPENDIX A. INVESTIGATIVE FUNCTIONS CATALOGUE 205
• Inv19: Boolean isStatic(Method/Field e)
Returns true if the method/field e is a static member of its class.
• Inv20: Boolean isSubtype(Class/Interface e1, Class/Interface e2)
Returns true if the type defined by the class/interface e1 is a subtype of the type
defined by the class/interface e2. This is based on the normal syntactic notion of
subtyping [47], but does not depend on their being an explicit implements/extends
relationship between the entities.
• Inv21: SetOfVariable localVars(Method/Constructor m)
Returns the set of the local variables that are defined within the given method or
constructor, regardless of the block scope they are in.
• Inv22: SetofMethod methodsInv(MethodInvocation i)
Returns the set of methods that could be invoked by the method invocation i.
• Inv23: String name(Class/Interface/Method/Constructor x)
Returns the name of the given class/interface/method/constructor.
• Inv24: int noOfArg(MethodInvocation/ObjectCreationExpr e)
Returns the number of the arguments to the given MethodInvocation or object
creation expression.
• Inv25: int noOfPar(Method/Constructor m)
Returns the number of the parameters of the given method/constructor.
• Inv26: Parameter par(Method/Constructor m, int i)
Returns the ith parameter of the given method/constructor, or null if the given
parameter does not exist.
APPENDIX A. INVESTIGATIVE FUNCTIONS CATALOGUE 206
• Inv27: Boolean returnsObject(Constructor c, Method m)
Returns true if the method m returns an object of the same class and in precisely
the same state as would be created by c, given the same argument list. m must have
no other side-effects; in particular it must neither access any variables other than its
parameters, nor send a message to another object. Note that the methods m need
not actually create a new object. See also the stronger condition, createsObject.
• Inv28: Class/Interface returnType(Method m)
Returns the class/interface that is the return type of the method m.
• Inv29: Signature sigOf(Method/Constructor x)
Returns the signature of the given method or constructor.
• Inv30: Class superclass(Class c)
Returns the direct superclass (based on the extends relationship) of the class c, or
null if none exists. It can be also applied to a constructor, method or field in which
case the superclass of the class of the given element is returned.
• Inv31: Class/Interface type(ObjectReference o)
Returns the class/interface of the given object reference (field, parameter or local
variable).
• Inv32: Boolean uses(Method m, Field f)
Returns true if the method m directly reference the field f.
Appendix B
Supporting Functions Catalogue
• Sup1: Interface abstractClass(Class c, String newName)
Construct and return an interface called newName that reflects all the public meth-
ods of the given class c.
Precondition :
The class c must exist : isClass(c)
Postcondition :
The returned interface inf declares the same public methods as the class c :
isInterface′ = isInterface[inf/true]
equalInterface′ = equalInterface[(c, inf)/true]
The name of the returned interface is newName :
name′ = name[inf/newName]
• Sup2: Method abstractMethod(Method m)
Construct and return an abstract method that has the same name and signature
as the given method m.
207
APPENDIX B. SUPPORTING FUNCTIONS CATALOGUE 208
Precondition :
This may be used in any state : True
Postcondition :
The returned method meth is abstract and has the same name and signature as the
given method m :
isAbstract′ = isAbstract[meth/true]
name′ = name[meth/name(m)]
sigOf ′ = sigOf [meth/sigOf(m)]
• Sup3: Class emptyClass(String name)
Construct and return an empty class called name.
Precondition :
This may be used in any state : True
Postcondition :
An empty class called name is returned where returned is the class returned by this
function :
name′ = name[returned/name]
∀ e : Method/F ield/Constructor,¬classOf(e) = returned
• Sup4: Method makeAbstract(Constructor c, String newName)
Returns a method called newName that, given the same arguments, will create the
same object as the constructor c. The method signature is obtained by copying
that of the constructor, and the method is given a body that is simply an object
creation expression that invokes the given constructor, using the arguments to the
method as its own argument.
APPENDIX B. SUPPORTING FUNCTIONS CATALOGUE 209
Precondition :
This may be used in any state ; True
Postcondition :
A method called newName is returned that, given the same argument list, creates
the same object as the constructor c, where returned is the returned method :
createsObject′ = createsObject[(c, returned)/true]
name′ = name[returned/newName]
• Sup5: Class wrapperClass(Interface iface, String Wrappername, String fieldName)
Creates a class called Wrappername that provides the same interface as iface and
implements all its methods by delegating them into a private field of the type iface,
called fieldName. The class is given a constructor that accepts an object of the
type iface and initializes the field fieldName to this object. A method called “get”
+ fieldName is also added that returns the contents of this field (i.e., returns the
wrapped object).
Precondition :
The given interface must exist : isInterface(iface)
The name of the class to be added is not in use :
¬isClass(wrapperName) ∧ ¬isInterface(wrapperName)
Postcondition :
A class called wrapperName is returned :
name′ = name[returned/wrapperName]
The returned class has a filed of type iface called fieldName :
APPENDIX B. SUPPORTING FUNCTIONS CATALOGUE 210
∃ f : Field such that
classOf ′ = classOf [f/returned]
type′ = type[f/iface]
name′ = name[f/fieldName]
The constructors of returned initialize this field with the first parameter :
∀ c : Constructor, classOf(c) = returned,
initializes′ = initializes[c, f, par(c, 1)]
The class wrapper has a method called “get” + fieldName :
∃ m : Method such that
classOf ′ = classOf [m/wrapper]
name′ = name[m/“get” + fieldName]
This method returns the contents of the field ]em fieldName :
returnsObject′ = returnsObject[m/fieldName]
Appendix C
Positioning Transformations
Catalogue
• Pos1: void absorbParameter(Method/Constructor m, int paramNumber)
Removes the specified parameter from the method/constructor m, converting the
parameter into a local variable in the method, and initializing it with the expression
given for the argument. This is similar to, but more flexible that, the removeParam-
eter refactoring described by Fowler in [71]. In [71] assumes the parameter is not in
use but here we allow it to be in use once it is always passed the same argument.
Precondition : The parameter exists in the given method :
noOfPar(m) ≥ paramNumber
All invocations of m take the same expression (which must be independent of con-
text) as an argument for the specified parameter :
∃ exprn : Exprn such that
∀ i : MethodInvocation,m ∈ methodsInv(i),
argument(i, paramNumber) = exprn
211
APPENDIX C. POSITIONING TRANSFORMATIONS CATALOGUE 212
Postcondition : The parameter list for m has been reduced by 1 :
noOfPar′ = noOfPar[m/noOfpar(m)− 1]
m now defines a new local variable of the same name and type as the parameter
that has been removed :
localV ars′ = localV ars[m/localV ars(m) ∪ v] where
name(v) = name(par(m, paramNumber))∧
type(v) = type(par(m, paramNumber))
This new local variable is initialized to the expression that was previously passed
in as an argument :
initializes′ = initializes[(m, v, exprn)/true]
• Pos2: void abstractMethodFromClass(Method m)
Makes public any method or field that is (i) a member of the same class that m
belongs to or a superclass, and (ii) is used by m. This refactoring is usually used as
a preparation for moving the method m to a component of its current class. Prior
to pulling out m, everything it refers to its current class must be made public. If m
is in fact a cohesive member of its class, this refactoring is likely to severely damage
the encapsulation of the class and its superclasses.
Precondition :
The class referred to exists and m is a member of this class :
isClass(classOf(m)) ∧m ∈ classOf(m)
Postcondition :
All methods/fields defined directly or indirectly in classOf(m) that m uses have
been made public :
APPENDIX C. POSITIONING TRANSFORMATIONS CATALOGUE 213
∀ x : Field/Method, defines(classOf(m), x), uses(m,x),
isPublic′ = isPublic[x/true]
• Pos3: void addClass(Class c, Class super, SetOfClass subclasses)
Adds the class c to the program. If a superclass is given, a extends links is added
from the class c to this superclass. If subclasses are given, an extends link is added
from each one to the class c.
Precondition :
The name of the class to be added is not in use :
¬isClass(name(c)) ∧ ¬isInterface(name(c))
Any given subclasses must exit :
∀ s ∈ subclasses, isClass(s)
If the superclass exists, it must be a superclass of all the subclasses :
if isClass(super) then ∀ s ∈ subclasses, superclass(s) = super
If c is a concrete class, then any abstract methods declared in super or its super-
classes must be defined in c :
if ¬ is Abstrcat(c) then
∀ m : Methods, declares(super,m) ∧ ¬defines(super,m),
defines(c, name(m), sigOf(m))
The class c must not contain any method that overrides one declared (in)directly
in the superclasses :
∀ n : String, s : Signature, if declares(super, n, s)then
¬defines(c, n, s, direct)
The class c must not contain any field that redefines one declared in any of its
(in)direct superclasses :
APPENDIX C. POSITIONING TRANSFORMATIONS CATALOGUE 214
∀ f : Field, f ∈ c, ¬isPrivate(f),
∀ g : Field, g ∈ sup, where sup ∈ superclasses(c), ¬isPrivate(g),
name(f) 6= name(g)
Postcondition :
c is a class in the program :
isClass′ = isClass[c/true]
An extends link exists from the class c to the class super :
superclass′ = superclass[c/super]
• Pos4: void addGetMethod(Class concrete, String fieldName)
Adds a method to the concrete class that returns the contents of the field called
fieldName.
Precondition :
The class concrete exists and has a field called fieldName :
isClass(concrete) ∧ classOf(fieldName) = concrete
The class concrete does not declare a method called “get” + fieldName :
∀ m : Method, declares(concrete,m), name(m) 6= “get” + fieldName
Postcondition :
The class concrete has a method called “get” + fieldName :
∃ m : Method such that classOf ′ = classOf [m/concrete]
name′ = name[m/“get” + fieldName]
This method returns the contents of the field fieldName :
returnsObject′ = returnsObject[m/fieldName]
APPENDIX C. POSITIONING TRANSFORMATIONS CATALOGUE 215
• Pos5: void addImplementsLink(Class concrete, Interface inf)
Adds an implements link from the class concrete to the interface int. The class
concrete must not be abstract, it means that it must implement all the abstract
methods that are declared in inf.
Precondition :
The class concrete and the interface inf must exist :
isClass(concrete) ∧ isInterface(inf)
The class concrete must be a subtype of the interface inf :
concrete ⊆ inf
The class concrete must implement all the method that are declared in inf :
∀ m : Method, declares(inf,m), defines(concrete,m, direct)
Postcondition :
An implements link had been added from the class concrete to the interface inf :
implmInterface′ = implmInterface[(concrete, inf)/true]
• Pos6: void addInterface(Interface i)
Adds the interface i to the program. A class or interface with this name must not
already exist.
Precondition :
No class or interface with the name name(i) exists :
¬isClass(name(i)) ∧ ¬isInterface(name(i))
Postcondition :
i is a new interface in the program :
APPENDIX C. POSITIONING TRANSFORMATIONS CATALOGUE 216
isInterface′ = isInterface[i/true]
• Pos7: void addMethod(Class c, Method m)
Adds the method m to the class c. A method with this signature must not already
exist in this class or its superclasses. This refactoring extends the external interface
of the class.
Precondition :
The class c exists and does not define any method with the same name and signature
as m :
isClass(c) ∧ ¬defines(c, name(m), sigOf(m))
Postcondition :
The method m has been added to the class c :
classOf ′ = classOf [m/c]
Any class or interface that previously had the same interface as c does not have the
same interface anymore :
∀ a : Class, a 6= c, if equalInterface(a, c) then
equalnterface′ = equalInterface[(a, c)/false]
• Pos8: void addSingletonMethod
(Class singletonClass, Class concreteSingleton, String methodName, String fieldName)
Adds a static field named fieldName of type singletonClass to the class singleton-
Class. Also adds a static method named methodName that gives access to this field
and instantiates it lazily as a concreteSingleton object when necessary [72]. If the
last two parameters are omitted, we assume them to be named “getInstance” and
“instance” respectively.
APPENDIX C. POSITIONING TRANSFORMATIONS CATALOGUE 217
Precondition :
The first two parameters must be classes and the class singletonClass must be a
superclass of concreteSingleton :
singletonClass ∈ superclass(concreteSingleton)
The class singletonClass can have no field called fieldName :
∀ f : Field, f ∈ singletonClass, name(f) 6= fieldName
A non-private field called fieldName cannot be defined in any superclass of single-
tonClass :
if f : Field ∈ cls, cls ∈ superclass(singletonClass),
name(f) = fieldName then isPrivate(f)
A method called methodName cannot be defined in the class singletonClass :
¬defines(singletonClass,methodName)
The class concreteSingleton must have a no-arg constructor :
∃ c : Constructor ∈ concreteSingleton such that noOfPar(c) = 0
Postcondition :
A new methodm has been added to the class singletonClass, with certain properties :
classOf ′ = classOf [m/singletonClass]
The name of m is methodName :
name′ = name[m/methodName]
The method m returns an object of the class concreteSingleton, in the same state
as would be returned by the no-arg constructor :
returnsObject′ = returnsObject[(c,m)/true]
where c : Constructor ∈ concreteSingleton ∧ noOfPar(c) = 0
APPENDIX C. POSITIONING TRANSFORMATIONS CATALOGUE 218
• Pos9: void createExclusiveComponent
(Class context, Class component, String fieldName)
Adds a new component to the class context, called fieldName, of type component.
All constructors in context are updated to instantiate this field as well.
Precondition :
The classes must exist :
isClass(context) ∧ isClass(component)
Neither the class context nor any of its superclasses may have a non-private field
called fieldName :
∀ f : Field, f ∈ sup, where sup ∈ superclass(context) ∪ context,
¬isPrivate(f), name(f) 6= fieldName
Postcondition :
The class context has a field called fieldName of type component :
∃ f : Field, f ∈ context such that type′ = type[f/component]
name′ = name[f/fieldName]
All constructors of context initialize this field :
∀ c : Constructor, c ∈ context,
initializes′ = initializes[(c, fieldName, “new component()”)/true]
• Pos10: void makeConstructorProtected(Class c)
Makes all constructors of the class c protected. If the class has no explicit construc-
tors, a no-arg one is added and made protected.
Precondition :
The class c exists : isClass(c)
Creations of objects of the class c occur only in c and its subclasses :
APPENDIX C. POSITIONING TRANSFORMATIONS CATALOGUE 219
∀ e : ObjectCreationExprn, classCreation(e) = c,
e ∈ c ∨ c ∈ superclass(contaniClass(e))
Postcondition :
The method m has been added to the class c :
classOf ′ = classOf [m/c]
Any class or interface that previously had the same interface as c does not have the
same interface anymore :
∀ a : Class, a 6= c, if equalInterface(a, c) then
equalInterface′ = equalInterface[(a, c)/false]
• Pos11: void moveMethod(Class context, Field component, Method meth)
Moves the method meth from the class context to the class of the field component
The existing method is replaced by one that delegates the same request to the
component field. The moved method is given an extra parameter that refers to
the context object it has been moved from, and any references it makes to this
(implicitly or explicitly) are sent back to this context object.
Precondition :
The class referred to exist :
isClass(context) ∧ isClass(type(component))
meth is a method of the class context :
meth ∈ context
Every method/field in context that is used by meth must be public :
∀ c : Method/F ield, x ∈ context, uses(meth, x), isPublic(x)
A similar method to meth cannot be defined in the component class :
APPENDIX C. POSITIONING TRANSFORMATIONS CATALOGUE 220
∀ m : Method ∈ type(component), name(meth) = name(m),
sigOf(meth) 6= sigOf(m)
Postcondition :
The method meth is now a member of the class of the component field :
classOf ′ = classOf [meth/classOf(component)]
The class context delegates invocations of the moved method to a method that
exhibits the same behavior in the class of the component field :
∃ m : Method such that classOf ′ = classOf [m/context]
name′ = name[m/name(meth)]
sigOf ′ = sigOf [m/sigOf(meth)]
uses′ = uses[(m,meth)/true]
• Pos12: void parameterizeField(Class client, Class/Interface product)
Moves initialization of the field of type product in the class client outside the con-
structor of the class, so the initial value for this field is now passed as an argument
to the client class constructor.
Precondition :
The given interface/classes exist :
isClass(client) ∧ (isClass(product) ∨ isInterface(product))
The client class has a single field of type product :
∃ f : Field, f ∈ client such that type(f) = product
This field is initialized to a context free expression, exprn, in all constructors :
∃ exprn, ∀ c : Constructor, c ∈ client, initializes(c, f, exprn)
APPENDIX C. POSITIONING TRANSFORMATIONS CATALOGUE 221
Postcondition :
Each client constructor has a new parameter of type product :
∀ c : Constructor, c ∈ client
noOfPar′ = noOfPar[c/noOfPar(c) + 1]
type′ = type[par(c, noOfPar(c) + 1)/product]
The field f is initialized with this parameter rather than exprn :
initializes′ = initializes[(c, f, exprn)/false]
initializes′ = initializes[(c, f, par(c, noOfPar(c) + 1)/true]
All creations of client objects now take the expression exprn as an extra argument :
∀ e : ObjectCreationExprn, classCreation(e) = client,
noOfArg′ = noOfArg[e/noOfArg(e) + 1]
argument′ = argument[(e, noOfArg(e) + 1)/exprn]
• Pos13: void pullUpMethod(Method m)
Moves the method m from its current class to its superclass. All fields directly
reference by m are moved to the superclass as well. An abstract method dec-
laration is added to the superclass for any method referenced by m that is not
directly/indirectly declared in the superclass.
Precondition :
The class must have a superclass to which to move the method :
superclass(m) 6=⊥
m must not be defined in the superclasses :
¬defines(superclass(m), name(m), sigOf(m))
Any field m uses must not be public and must not clash with fields in the super-
classes :
APPENDIX C. POSITIONING TRANSFORMATIONS CATALOGUE 222
∀ f : Field, f ∈ classOf(m), if uses(m, f) then
(¬isPublic(f) ∧ ∀ g : Field, g ∈ superclass(m),
name(f) 6= name(g))
Postcondition :
m is moved from its existing class to its superclass :
classOf ′ = classOf [m/superclass(m)]
Any methods m uses that are not declared in its superclass are declared there now :
∀ n : Method, n ∈ classOf(m),m 6= n,
if uses(m,n) ∧ ¬declares(superclass(m), n) then
declares′ = declares[(superclass(m), n, direct)/true]
Any fields m uses are moved to the superclass :
∀ f : Field, f ∈ classOf(m) if uses(m, f) then
classOf ′ = classOf [f/superclass(m)]
• Pos14: void replaceClassWithInterface(ObjectReference o, Interface inf)
Changes the type of the object reference o to the interface inf.
Precondition :
The interface inf exists : isInterface(inf)
The class of the object reference o must have an implements link to the interface
inf :
implmInterface(type(o), inf)
Any static methods or fields in the class of the object reference o are not accessed
through the object reference o :
APPENDIX C. POSITIONING TRANSFORMATIONS CATALOGUE 223
∀ m : Method, classOf(m) = type(o)
if isStatic(m) then ¬uses(o,m)∧
∀ f : Field, classOf(f) = type(o), ¬uses(o, f)
Postcondition :
The type of the object reference o if inf :
type′ = type[o/inf ]
• Pos15: void replaceObject(ObjectCreationExpr e, Method m)
Replaces the given object creation expression e with an invocation of the method
m using the same argument list.
Precondition :
The object creation expression e and the method m must both, given the same
argument list, create and return the same object, or they must both simply return
the same object, and this must be the only instance of the class :
createsObject(constructorInv(e),m)∨
(returnsObject(constructorInv(e),m)
The object creation expression e must be in the method m :
containMethod(e) 6= m
Postcondition :
The object creation expression e has been removed :
contanMethod′ = containMethod[e/ ⊥]
• Pos16: void useWrapperClass
(Class client, Class wrapper, Class receiver, String getterMethod)
APPENDIX C. POSITIONING TRANSFORMATIONS CATALOGUE 224
Updates the client class so that any construction of the receiver class is replaced by
a construction of the wrapper class, taking the corresponding receiver object as an
argument. All variables of the type receiver in the client classes are also renamed to
wrapper. Any methods in client whose return type is receiver are updated to return
the wrapped receiver object by delegating to the getterMethod in wrapper.
Precondition :
The specified classes exist : isClass(client)∧ isClass(wrapper)∧ isClass(receiver)
The classes support the same interface : equalInterface(wrapper, receiver)
The method getterMethod in wrapper returns the wrapped receiver object :
returnsObject((newwrapper(e)).getterMethod(), e)
Postcondition :
All object references to receiver in client have been changed to wrapper :
∀ o : ObjectRef ∈ client, type(o) = receiver,
type′ = type(o/wrapper)
Methods in client that return a receiver object are updated to return the wrapped
receiver object by delegating to the getterMethod :
∀ m : Method,m ∈ client, returnType(m) = receiver
uses′ = uses[m/getterMethod]
Appendix D
Primitive DP Transformations
Catalogue
• ABSTRACTION Transformation
Precondition :
(a) isClass(c)
(b) ¬isClass(newInterface) ∧ ¬isInterface(newInterface)
Transformation Process :
ABSTRACTION(Classc, StringnewName)
{
Interfaceinf = abstractClass(c, newName)
addInterface(inf)
addImplementsLink(c, inf)
}
225
APPENDIX D. PRIMITIVE DP TRANSFORMATIONS CATALOGUE 226
Postcondition :
(a) name′ = name[tmp/newInterface]
(b) isInterface′ = isInterface[tmp/true]
(c) equaleInterface′ = equaleInterface[(c, tmp)/true]
(d) implmInterface′ = implmInterface[(c, tmp)/true]
Possible effect on non-functional requirements (quality) :
(a) High Control Flow Consistency(+)
(b) High Cohesion(++)
(c) High Data Consistency(++)
(d) Low I/O Activities(−)
(e) Low I/O Complexity(−)
(f) Low Main Memory Utilization(+)
(g) Low System CPU Time (+)
(h) Low Time Running(++)
• EXTENSION Transformation
Precondition :
(a) ¬isClass(newName) ∧ ¬isInterface(newName)
(b) ∀ f : Field,m : Method, f ∈ concrete,m ∈ concrete,
(c) m 6∈ abstractMewthods, if uses(m, f) then ¬isPublic(f)
APPENDIX D. PRIMITIVE DP TRANSFORMATIONS CATALOGUE 227
Transformation Process :
EXTENSION(Classconcrete, StringnewName, SetOfStringabstractMethod)
{
Classabstract = emptyClass(newName)
addClass(abstract, superclass(concrete), concrete)
For All m : Method,m in concrete, name(m) in abstractMethods
{
MethodabsMethod = abstractMethod(m)
addMethod(abstract, absMethod)
}
For All m : Method,m in concrete,
name(m) not in abstractMethods
{
pullUpMethod(m)
}
}
Postcondition :
(a) isClass′ = isClass[newName/true]
(b) superclass′ = superclass[concrete/newName][newName/superclass(concrete)]
(c) equaleInterface′ = equalInterface[(concrete, superclass′(concrete))/true]
(d) ∀ m : Method,m ∈ concrete,m 6∈ abstractMethods,
(e) classOf ′ = classOf [m/superclass′(concrete)]
(f) ∀ m : Method,m ∈ abstractMethods,
APPENDIX D. PRIMITIVE DP TRANSFORMATIONS CATALOGUE 228
(g) declares′ = declares[(superclass(concrete),m, direct)/true]
(h) ∀ m : Method,m ∈ concrete,m 6∈ abstractMethods,
(i) ∀ f : Field, f ∈ concrete, uses(m, f),
(j) classOf ′ = classOf [f/superclass(concrete)]
Possible effect on non-functional requirements (quality) :
(a) High Control Flow Consistency(+)
(b) High Cohesion(++)
(c) High Module Reuse(++)
(d) High Throughput(++)
(e) Low Data Coupling(−)
(f) Low I/O Activities(−)
(g) Low System CPU Time (+)
(h) Low Time Running(++)
• MOVEMENT Transformation
Precondition :
(a) isClass(context)
(b) ¬isClass(movementClass) ∧ ¬isInterface(movementClass)
(c) ∀ m ∈ moveMethods,m ∈ context
(d) ∀ f : Field, f ∈ context, nameOF (f) 6∈ “movement”
(e) if f : Field ∈ cls, cls ∈ superclasses(context),
(f) name(f) = “movement” then isPrivate(f)
APPENDIX D. PRIMITIVE DP TRANSFORMATIONS CATALOGUE 229
Transformation Process :
MOV EMENT (Classcontext, SetOfMethodmoveMethods, StringmovementName)
{
addClass(emptyClass(movementName))
createExclusiveComponent(context,movementName, “movement”)
ForAllm : Method,minmoveMethods
{
abstractMethodFromClass(m)
moveMethod(context, “movement”,m)
}
}
Postcondition :
(a) isClass′ = isClass[movementName/true]
(b) ∃ f : Field, f ∈ context such that
(c) type′ = type[f/movementName]
(d) name′ = name[f/“movement”]
(e) ∀ m : Method ∈ moveMethod,
(f) ∀ x : Field/Method, defines(context, x), uses(m,x)
(g) isPublic′ = isPublic[x/true]
(h) ∀ m : Method ∈ moveMthods, classOf ′ = classOf [m/movementName]
(i) ∀ m : Method ∈ moveMethods,
(j) ∃ n : Method, classOf ′(n) = context,
APPENDIX D. PRIMITIVE DP TRANSFORMATIONS CATALOGUE 230
(k) name′(n) = name(m),
(l) sigOf ′(n) = sigOf(m) such that
(m) uses′ = uses[(n,m)/true]
Possible effect on non-functional requirements (quality) :
(a) High Modularity(++)
(b) High Module Reuse(+)
(c) High Throughput(−)
(d) Low Control Flow Coupling(−)
(e) Low System CPU Time (+)
(f) Low Time Running(−)
• ENCAPSULATION Transformation
Precondition :
(a) isClass(creator)
(b) ∀ c : Constructor, c ∈ product
(c) ¬define(craetor, createProduct, sigOf(c))
Transformation Process :
ENCAPSULATION(Classcreator, Classproduct, StringcreateProduct)
{
For All c : Constructor, classOf(c) = product
{
Method m = makeAbstract(c, createProduct)
APPENDIX D. PRIMITIVE DP TRANSFORMATIONS CATALOGUE 231
addMethod(creator,m)
}
For All e : ObjectCreationExprn,
classCreation(e) = productand
containClass(e) = creatorand
name(containethod(e)) = createProduct
{
replaceObject(e, createProduct)
}
}
Postcondition :
(a) ∀ e : ObjectCreationExprn, classCreation(e) = product,
(b) containClass(e) = creator, ∃ m : Method such that
(c) createsObject′ = createsObject[(constructorInv(e),m)/true]
(d) name′ = name[m/createProduct]∧
(e) defines′ = defines[(creator,m)/true]
(f) ∀ e : ObjectCreationExprn, classCreation(e) = product,
(g) containClass(e) = creator,
(h) name(containMethod(e)) 6= createProduct,
(i) containMethod′ = containMethod[e/ ⊥]
Possible effect on non-functional requirements (quality) :
(a) High Data Consistency(−)
APPENDIX D. PRIMITIVE DP TRANSFORMATIONS CATALOGUE 232
(b) High Encapsulation(++)
(c) High Throughput(++)
(d) Low Control Flow Coupling(+)
(e) Low Data Coupling(++)
(f) Low I/O Activities(+)
(g) Low Main Memory Utilization(++)
• BUILDRELATION Transformation
Precondition :
(a) isInterface(inf) ∧ isClass(context) ∧ isClass(concrete)
(b) implmInterface(concrete, inf)
(c) ∀ m : Method,m ∈ concrete, isStatic(m),
(d) ∀ o : ObjectRef, type(o) = concrete,
(e) containClass(o) = context,¬uses(o,m)
(f) ∀ f : field, f ∈ concrete, isPublic(f)
(g) ∀ o : ObjectRef, type(o) = concrete,
(h) containClass(o) = context,¬uses(o, f)
Transformation Process :
BUILDRELATION(Classcontext, Classconcrete,
Interfaceinf, SetOfStringskipMethods)
{
For All o : ObjectRef, type(o) = concrete,
APPENDIX D. PRIMITIVE DP TRANSFORMATIONS CATALOGUE 233
containClass(o) = context,
name(containMethod(o)) in skipMethods
{
replaceClassWithInterface(o, inf)
}
}
Postcondition :
(a) ∀ o : ObjectRef, type(o) = concrete, containClass(o) = context,
(b) name(containMethod(o)) inskipMethods, type′ = type[o/inf ]
Possible effect on non-functional requirements (quality) :
(a) High Control Flow Consistency(++)
(b) Low Control Flow Coupling (+)
(c) Low I/O Activities(++)
(d) Low I/O Complexity (−)
(e) Low Time Running(+)
• WRAPPER Transformation
Precondition :
(a) isInterface(iface)
(b) ¬isClass(wrapperName) ∧ ¬isInterface(wrapperName)
(c) ∀ o : ObjectRef, containClass(o) ∈ clinets,
(d) implmIneterface(type(o), iface)
APPENDIX D. PRIMITIVE DP TRANSFORMATIONS CATALOGUE 234
(e) ∀ m : Method, uses(o,m), declares(iface,m)
Transformation Process :
WRAPPER(SetOfClassclient, Interfaceiface, StringwrapperName)
{
Classwrapper = wrapperClass(iface, wrapperName, “receiver”);
addClass(wrapper);
For All c : Class, implmInterface(c, iface)
{
useWrapperClass(clients, wrapper, c, “getReciever”);
}
}
Postcondition :
(a) isClass′ = isClass[wrapper/true]
(b) ∀ o : ObjectRef, containClass(o) ∈ clients,
(c) implmInterface(type(o), iface), type′ = type[o/wrapper]
(d) ∀ e : ObjectCreationExprn, implmInterface(classCreation(e), iface),
(e) containClass(e) ∈ clients, classCreation′ = classCreation[r/wrapper]
(f) ∀ c : Class, implmInterface(c, iface),
(g) ∀ e : ObjectCreationExprn, classCreation(e) = c,
Possible effect on non-functional requirements (quality) :
(a) High Cohesion (+)
APPENDIX D. PRIMITIVE DP TRANSFORMATIONS CATALOGUE 235
(b) High Control Flow Consistency(+)
(c) High Throughput (+)
(d) Low Control Flow Coupling (+)
(e) Low I/O Activities (+)
(f) Low I/O Complexity (−−)
(g) Low Secondary Storage Utilization (−)
Bibliography
[1] Fernando B. Abreu and Rogerio Carapuca. Candidate metrics for object-oriented
software within a taxonomy framework. The Journal of Systems and Software,
26(1):87–96, 1994.
[2] Rade Adamov and Lutz H. Richter. A proposal for measuring the structural com-
plexity of programs. Journal of Systems and Software, 23(12):55–70, 1990.
[3] Alfred V. Aho, Ravi Sethi, and Ullman Jeffrey. Compilers : Principles, Techniques,
and Tools. Addison-Wesley, 1988.
[4] Peter Aiken, Alice Muntz, and Russ Richards. A framework for reverse engineering
dod legacy information systems. In Proceedings of the IEEE Working Conference
on Reverse Engineering (WCRE), pages 180–191, Baltimore, Maryland, USA, May
1993.
[5] Christopher Alexander. A Pattern Language. Oxford University Press, 1977.
[6] Paola Antonini, Gerardo Canfora, and Aniello Cimitile. Re-engineering legacy sys-
tems to meet quality requirements : An experience report. In Proceedings of the
IEEE International Conference on Software Maintenance (ICSM), pages 146–153,
Victoria, BC, Canada, September 1994.
236
BIBLIOGRAPHY 237
[7] Giuliano Antoniol, Roberto Fiutem, and Luca Cristoforetti. Design pattern recov-
ery in object-oriented software. In Proceedings of the International Workshop on
Program Comprehension, pages 153–160, Ischia, Italy, June 1998.
[8] Apache ant. URL = http://ant.apache.org/.
[9] A. W. Appel. Modern Compiler Implementation in ML. Cambridge University
Press, 1998.
[10] Robert S. Arnold. Software Re-engineering. IEEE Computer Society Press, 1993.
[11] Felix Bachmann, Len Bass, Gary Chastek, Patrick Donohoe, and Fabio Peruzzi.
The architecture based design method. Technical Report CMU/SEI-2000-TR-001
ADA375851, Software Engineering Institute, Carnegie Mellon University, Pitts-
burgh, PA, USA, 2000.
[12] William G. Bail and Marvin V. Zelkowitz. Program complexity using hierarchical
abstract computers. Computer Languages, 13(3/4):109–133, March/April 1988.
[13] Jagdish Bansiya, Carl Davis, and Letha Etzkorn. An entropy-based complexity mea-
sure for object-oriented designs. Theory and Practice of Object Systems, 5(2):111–
118, 1999.
[14] Mario R. Barbacci, Robert Ellison, Judith A. Stafford, Charles B. Weinstock, and
William G. Wood. Quality attribute workshops. Technical Report CMU/SEI-2001-
TR-010, Software Engineering Institute, Carnegie Mellon University, Pittsburgh,
PA, USA, May 2001.
[15] Victor R. Basili. Paradigms for experimentation and empirical studies in software
engineering. Reliability Engineering and System Safety, 32(1–2):171–191, 1991.
BIBLIOGRAPHY 238
[16] Victor R. Basili, Lionel C. Briand, and Walcelio L. Melo. A validation of object-
oriented design metrics as quality indicators. IEEE Transactions of Software En-
gineering, 22(10):751–761, October 1996.
[17] Len Bass, Paul Clements, and Rick Kazman. Software Architecture in Practice.
Addison-Wesley, 2003.
[18] Markus Bauer. Analyzing software systems using combinations of metrics. In Oliver
Ciupke and Ducasse Stiphane, editors, Proceedings of the ECOOP Workshop on
Experiences in Object-Oriented Re-Engineering, Lisbon, Portugal, May 1999.
[19] Ira Baxter and Christopher Pidgeon. Software change through design maintenance.
In Proceedings of the IEEE International Conference on Software Maintenance
(ICSM), pages 250–259, Bari, Italy, October 1997.
[20] Kent Beck. Patterns and software development. Dr. Dobbs Journal, 19(2):18–23,
1993.
[21] Kent Beck. Extreme Programming Explained : Embrace Change. Addison-Wesley,
2000.
[22] PerOlof Bengtsson and Jan Bosch. Scenario-based software architecture re-
engineering. In Proceedings of the IEEE International Conference on Software
Reuse (ICSR), pages 308–317, Victoria, BC, Canada, June 1998.
[23] Keith H. Bennett. Do program transformations help reverse engineering? In
Proceedings of the IEEE International Conference on Software Maintenance, pages
247–254, Bethesda, Maryland, USA, November 1998.
[24] John Bergey, Mario Barbacci, and Wood William. Using quality attribute work-
shops to evaluate architectural design approaches in a major system acquisition : A
BIBLIOGRAPHY 239
case study. Technical Report CMU/SEI-2000-TN-010, Software Engineering Insti-
tute, Carnegie Mellon University, Pittsburgh, PA, 2001.
[25] James M. Bieman and Byung-Kyoo Kang. Cohesion and reuse in an object-oriented
system. In Proceedings of ACM Symposium for Software Re-usability (SSR), pages
259–262, 1995.
[26] Barry W. Boehm et al. Characteristics of Software Quality. Elsevier North-Holland
Publishing Company, Inc., 1980.
[27] Barry W. Boehm and Hon In. Identifying quality requirement conflicts. IEEE
Software, pages 25–35, March 1996.
[28] Grady Booch. Patterns. Object Magazine, 3(2), 1993.
[29] Grady Booch. Object-oriented analysis and design with applications. Ben-
jamin/Cummings Pub. Co., 1994.
[30] M. G. J. Brand, H. Jong, P. Klint, and P. Olivier. Efficient annotated terms.
Software, Practice & Experience, 30(3):259–291, 2000.
[31] M. G. J. Brand and E. Visser. Generation of formatters for context-free languages.
ACM Transactions on Software Engineering and Methodology, 5(1):1–41, January
1996.
[32] Eric J. Braude. Software Engineering : An Object-Oriented Perspective. Addison-
Wesley, 2001.
[33] Lionel C. Briand, Sanro Morasca, and Victor R. Basili. Defining and validating
measures of object-based high-level design. IEEE Transactions of Software Engi-
neering, 25(5):722–743, September/October 1999.
BIBLIOGRAPHY 240
[34] Kyle Brown. Design reverse engineering and automated design patterns detection in
smalltalk. Master’s thesis, Department of Computer Engineering, North Carolina
State University, 1996.
[35] William Brown, Raphael Malveau, Hays McCormickIII, and Thomas Mowbray.
Anti-Patterns : Refactoring Software, Architectures, and Projects in Crisis. Addi-
son Wesley, 1998.
[36] Frank J. Budinsky, Marilyn A. Finnie, John M. Vlissides, and Pasty S. Yu. Auto-
matic code generation from design patterns. IBM Systems Journal, 35(2):151–171,
1996.
[37] Frank Buschmann et al. Pattern-Oriented Software Architecture : A System of
Patterns. John Wiley and Sons, 1999.
[38] Gerardo Canfora, Anna R. Fasolino, and Maria Tortorella. Towards re-engineering
in reuse re-engineering processes. In Proceedings of the International Conference
on Software Maintenance (ICSM), pages 147–156, Maryland, DC, USA, November
1998.
[39] Eduardo Casais. Managing Evolution in Object-Oriented Environments : An Algo-
rithmic Approach. PhD thesis, University of Geneva, 1991.
[40] Eduardo Casais. An incremental class reorganization approach. In Ole
Lehrmann Madsen, editor, Proceedings of the European Conference on Object-
Oriented Programming (ECOOP), pages 114–132, Utrecht, The Netherlands, June
1992.
[41] Shyam R. Chidamber and Chris F. Kemerer. A metrics suite for object-oriented
design. IEEE Transactions on Software Engineering, 20(6):476–493, June 1994.
BIBLIOGRAPHY 241
[42] Elliot J. Chikofsky and James H. CrossII. Reverse engineering and design recovery :
A taxonomy. IEEE Software, 7(1):13–17, January 1990.
[43] Lawrence K. Chung. Representing and Using Non-Functional Requirements : A
Process Oriented Approach. PhD thesis, Department of Computer Science, Univer-
sity of Toronto, 1993.
[44] Lawrence K. Chung, Brain A. Nixon, Eric Yu, and John Mylopoulos. Non-
Functional Requirements in Software Engineering. Kluwer Publishing, 2000.
[45] Neville I. Churcher and Martin J. Shepperd. A metrics suite for object-oriented
design. IEEE Transactions on Software Engineering, 21(3):263–265, March 1995.
[46] Oliver Ciupke. Automatic detection of design problems in object-oriented re-
engineering. In Proceedings of the IEEE Technology of Object-Oriented Languages
and Systems - TOOLS 30, pages 18–32, 1999.
[47] Craig J. Cleaveland. An Introduction to Data Types. Addison-Wesley, 1986.
[48] Paul Clements, Felix Bachmann, Len Bass, David Garlan, James Ivers, Reed Little,
Robert Nord, and Judith Stafford. Documenting Software Architectures: Views and
Beyond. Addison-Wesley, 2002.
[49] Clone doctor (clonedr). URL = http://www.semdesigns.com/Products/.
[50] Peter Coad. Object-oriented patterns. Communications of ACM (CACM),
35(9):153–159, September 1993.
[51] Don Coleman, Bruce Lowther, and Paul Oman. The application of software main-
tainability models in industrial software systems. The Journal of Systems and
Software, 29(1):3–16, 1995.
BIBLIOGRAPHY 242
[52] C. Collberg, C. Thomborson, and D. Low. Manufacturing cheap, resilient and
stealthy opaque constructs. In ACM SIGPLAN-SIGACT Symposium on Principles
of Programming Languages (POPL), pages 184–196, San Diego, CA, USA, January
1998.
[53] James O. Coplien. Advanced C++ Programming Styles and Idioms. Addison-
Wesley, 1992.
[54] James O. Coplien and Douglas Schmidt, editors. Pattern Languages of Program
Design. Addison-Wesley, 1994.
[55] James R. Cordy and Ian H. Carmichael. The txl programming language syntax
and semantics version 7. Technical Report 93-355, Department of Computing and
Information Sciences, Queen’s University, Kingston, Canada, June 1993.
[56] Krzysztof Czarnecki and Ulrich W. Eisenecker, editors. Generative Programming :
Methods, Tools, and Applications. Addison-Wesley, 2000.
[57] Datrix metric reference manual, version 4.1. Bell Canada, 2000.
URL = http://www.iro.umontreal.ca/labs/gelo/datrix.
[58] Tom DeMarco. Controlling Software Projects : Management, Measurement and
Estimation. Prentice-Hall, 1982.
[59] Arie van Deursen, P. Klint, and F. Tip. Origin tracking. Journal of Symbolic
Computation, 15(56):523–546, 1993.
[60] Eclipse ant package. URL = http://dev.eclipse.org/viewcvs/index.cgi/ome/main.html.
[61] Eclipse jdt core package. URL = http://www.eclipse.org/documentation/html/plugins/org.eclipse.jdt.doc.isv/doc/reference/api/org/eclipse/jdt/core/package-
summary.html.
BIBLIOGRAPHY 243
[62] Amnon H. Eden, Joseph Gil, and Amiram Yehudai. Automating the application of
design patterns. Journal of Object Oriented Programming, 10(2):44–46, May 1997.
[63] Amnon H. Eden, Amiram Yehudai, and Joseph Gil. Precise specification and au-
tomatic application of design patterns. In Proceedings of the IEEE Automated
Software Engineering (ASE), pages 143–152, Lake Tahoe, CA, USA, November
1997.
[64] Letha H. Etzkorn, Jagdish Bansiya, and Carl Davis. Design and code complexity
metrics for oo classes. Journal of Object Oriented Programming, 12(1):35–40, March
1999.
[65] Letha H. Etzkorn, Carl Davis, and Wei Li. A practical look at the lack of cohesion in
methods metric. Journal of Object Oriented Programming, 11(5):27–34, September
1998.
[66] Clive Finkelstein, Peter G. Aiken, and John A. Zachman. Building Corporate Por-
tals with XML. McGraw-Hill, 1999.
[67] Patrick Finnigan et al. The software bookshelf. IBM Systems Journal, 36(4):564–
593, November 1997.
[68] Gert Florijn, Marco Meijers, and Pieter Winsen. Tools support in design patterns.
In Proceedings of the ACM European Conference on Object-Oriented Programming
(ECOOP), volume 1241, pages 427–495, Jyvdskyld, Finland, June 1997.
[69] Charles L. Forgy. Rete : A fast algorithm for the many pattern/ many object
pattern match problem. Artificial Intelligence, 19:17–37, 1982.
[70] Martin Fowler, editor. Analysis Patterns. Addison-Wesley, 1997.
BIBLIOGRAPHY 244
[71] Martin Fowler. Refactoring : Improving the Design of Existing Code. Addison-
Wesley, 1999.
[72] Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Design Patterns :
Elements of Reusable Object-Oriented Software. Addison-Wesley, 1995.
[73] David Garlan, Gail E. Kaiser, and David Notkin. Using tool abstraction to compose
system. IEEE Computer, 25(6):30–38, June 1992.
[74] David Garlan and Mary Shaw. An Introduction to Software Architecture. World
Scientific Publishing Co., 1993.
[75] Carlo Ghezzi, Mehdi Jazayeri, and Dino Mandrioli. Fundamentals of Software
Engineering. Prentice Hall, 2003.
[76] Gnu avl libraries, 1999. URL = http://www.interads.co.uk/˜crh/ubiqx.
[77] Robert Godin and Mili Hafedh. Building and maintaining analysis-level class hier-
archies using galois lattice. In Proceedings of the ACM 8th Annual Conference on
Object-Oriented Programming Systems, Languages, and Applications (OOPSLA),
pages 394–410, Washington, DC, USA, September 1993.
[78] Mark Grand. Patterns in Java, volume 1. John Wiley & Sons, 1998.
[79] Mark Grand. Patterns in Java, volume 2. John Wiley & Sons, 1999.
[80] Jack R. Hagemeister. A Metric Approach to Assessing the Maintainability of Soft-
ware. PhD thesis, Department of Computer Science, University of Idaho, 1992.
[81] Maurice Halstead. Elements of Software Science. Elsevier North-Holland Inc., 1977.
[82] Warren Harrison. A entropy-based measure of software complexity. IEEE Trans-
actions on Software Engineering, 18(11):1025–1029, 1992.
BIBLIOGRAPHY 245
[83] Brian Henderson-Sellers. Object-Oriented Metrics : Measures of Complexity. Pren-
tice Hall, 1996.
[84] John L. Hennessy and David A. Patterson. Computer Architecture : A Quantitative
Approach. Morgan Kaufman, 1990.
[85] Sallie Henry and Dennis Kafura. Software structure metrics based on information
flow. IEEE Transactions on Software Engineering, 7(5):510–518, September 1981.
[86] Martin Hitz and Behzad Montazeri. Measuring coupling and cohesion in object-
oriented systems. In Proceedings of the International Symposium on Applied Cor-
porate Computing, pages 75–76, Monterrey, Mexico, October 1995.
[87] Martin Hitz and Behzad Montazeri. Chidamber and kemerer’s metrics suits : A
measurement theory perspective. IEEE Transactions on Software Engineering,
22(4):267–271, April 1996.
[88] Martin Hitz and Behzad Montazeri. Measuring coupling in object-oriented systems.
Object Currents, 1(4), 1996.
[89] Charles Antony Richard Hoare. Communicating Sequential Processes. Prentice
Hall, 1985.
[90] G. Huet and B. Lang. Proving and applying program transformations expressed
with second order patterns. Acta Informatica, 11:31–55, 1978.
[91] Injectj. URL = http://injectj.fzi.de.
[92] Intellij idea 3.0. URL = http://www.intellij.com/idea.
[93] International organization for standardization (iso). Information Technology, Soft-
BIBLIOGRAPHY 246
ware Product Evaluation, Quality Characteristics and Guidelines for Their Use,
ISO/IEC 9126, 1996.
[94] Java expert system shell (jess). URL = http://www.sandia.gov/jess/.
[95] jfactor. URL = http://www.instantiations.com/jfactor/.
[96] Ralph E. Johnson and Vincent F. Russo. Reusing object-oriented designs. Technical
Report UIUCDCS 91-1696, University of Illinois, May 1991.
[97] Simon P. Jones. Haskell 98 Language and Libraries. Cambridge University Press,
2003.
[98] Jrefactory. URL = http://jrefactory.sourceforge.net.
[99] Rick Kazman, Len Bass, Gregory Abowd, and Mike Webb. Saam: A method for
analyzing the properties of software architectures. In Proceedings of the Interna-
tional Conference on Software Engineering (ICSE), pages 81–90, Sorrento, Italy,
May 1994.
[100] Rick Kazman, Mark Klein, and Paul Clements. Attam : Method for architecture
evaluation. Technical Report CMU/SEI-2000-TR-004 ADA382629, Software Engi-
neering Institute, Carnegie Mellon University, Pittsburgh, PA, USA, 2000.
[101] Rick Kazman, Liam O’Brien, and Chris Verhoef. Architecture reconstruction guide-
lines, 2nd edition. Technical Report CMU/SEI-2002-TR-034 ESC-TR-2002-034,
Software Engineering Institute, Carnegie Mellon University, Pittsburgh, PA, USA,
2002.
[102] Ralph L. Keeney and Howard Raiffa. Decision with Multiple Objectives : Preferences
and Value Tradeoffs. John Wiley and Sons, 1976.
BIBLIOGRAPHY 247
[103] Rudolf K. Keller, Reinhard Schauer, Sebastien Robitaille, and Patrick Page.
Pattern-based reverse engineering of design components. In Proceedings of the
IEEE International Conference on Software Engineering (ICSE), pages 226–235,
Los Angeles, CA, USA, May 1999.
[104] Ismail Khriss and Rudolf Keller. Transformations for pattern-based forward-
engineering. In Proceedings of the International Workshop on Software Transfor-
mation Systems (STS), pages 50–58, Los Angeles, CA, USA, May 1999.
[105] Mark Klein, Len Bass, and Rick Kazman. Attribute-based architecture styles.
Technical Report CMU/SEI-99-TR-022 ADA371802, Software Engineering Insti-
tute, Carnegie Mellon University, Pittsburgh, PA, 1999.
[106] Kostas Kontogiannis. Evaluation experiments on the detection of programming
patterns using software metrics. In Proceedings of the Working Conference on
Reverse Engineering (WCRE), pages 44–54, Amsterdam, The Netherlands, October
1997.
[107] Christian Kramer and Lutz Prechelt. Design recovery by automated search for
structural design patterns in object-oriented software. In Proceedings of the Working
Conference on Reverse Engineering (WCRE), pages 208–215, Monterey, CA, USA,
November 1996.
[108] Rene L. Krikhaar. Software Architecture Reconstruction. PhD thesis, University of
Amsterdam, Amsterdam, The Netherlands, 1999.
[109] Wei Li and Sallie Henry. Object-oriented metrics that predict maintainability.
Journal of Systems and Software, 23(2):111–122, 1994.
[110] Karl J. Lieberherr, Paul Bergstein, and Ignacio Silva-Lepe. From objects to classes :
BIBLIOGRAPHY 248
Algorithms for optimal object-oriented design. IEEE Journal of Software Engineer-
ing, 6(4):205–228, 1991.
[111] Jaques Loeckx and Kurt Sieber. Foundation of Program Verification. Wiley & Sons,
1987.
[112] David H. Lorenz. Tiling design patterns - a case study using the interpreter pattern.
In Proceedings of the ACM SIGPLAN Conference on Object-Oriented Programming,
Systems, Languages and Applications (OOPSLA), pages 206–217, Atlanta, Georgia,
USA, 1997.
[113] Mark Lorenz and Jeff Kidd. Object-Oriented Software Metrics : A Practical Ap-
proach. Prentice-Hall, 1994.
[114] Evangelos Mamas. Design and Implementation of an Integrated Software Mainte-
nance Environment. PhD thesis, Depertment of Electrical and Computer Engineer-
ing, University of Waterloo, Ontario, Canada, 2000.
[115] Robert C. Martin, Dirk Riehle, and Buschmann Frank, editors. Pattern Languages
of Program Design, volume 3. Addison-Wesley, 1998.
[116] Thomas McCabe. A complexity measure. IEEE Transactions on Software Engi-
neering, 2(4):308–320, 1976.
[117] Thomas McCabe and Butler Charles W. Design complexity measurement and
testing. Communications of the ACM, 32(12):1415–1425, 1989.
[118] Marco Meijers. Tool support for object-oriented design patterns. Master’s thesis,
Department of Computer Science, Rijksuniversiteit Utrecht, 1996.
[119] Gerard Meszaros and Jim Doble. A pattern language for pattern writing. In
BIBLIOGRAPHY 249
Robert C. Martin, Dirk Riehle, and Buschmann Frank, editors, Pattern Languages
of Program Design, volume 3, pages 529–574. Addison-Wesley, 1998.
[120] Hausi Muller, Mehmet Orgun, Scott Tilley, and James Uhl. A reverse engineering
approach to subsystem identification. Software Maintenance and Practice, 5(4):181–
204, 1993.
[121] Howard W. Miller. Re-engineering legacy software systems. Digital Press, 1998.
[122] Robin Milner. Communicating and Concurrency. Prentice Hall, 1989.
[123] Ivan Moore. Automatic inheritance hierarchy restructuring and method refactoring.
In Proceedings of the ACM 11th Annual Conference on Object-Oriented Program-
ming Systems, Languages, and Applications (OOPSLA), pages 235–250, San Jose,
California, October 1996.
[124] S. S. Muchnick. Advanced Compiler Design and Implementation. Morgan Kaufmann
Publishers, 1997.
[125] John Mylopoulos, Lawrence K. Chung, and Brain Nixon. Representing and using
non-functional requirements : A process-oriented approach. IEEE Transactions on
Software Engineering, 18(6):483–497, 1992.
[126] Netbeans ide. URL = http://www.netbeans.org/.
[127] Netbeans javadoc. URL = http://javadoc.netbeans.org/.
[128] Nils J. Nilsson. Principles of Artificial Intelligence. Tiago Publishing Company,
1980.
[129] Brian A. Nixon. Dealing with performance requirements during the development
BIBLIOGRAPHY 250
of information systems. In Proceedings of the IEEE International Symposium on
Requirements Engineering (RE), pages 42–49, San Diego, CA, USA, January 1993.
[130] Roland Olssoni. Inductive functional programming using incremental program
transformation. Artificial Intelligence, 74(1):55–83, March 1995.
[131] Paul Oman and Jack Hagemeister. Constructing and testing of polynomials predict-
ing software maintainability. The Journal of Systems and Software, 24(3):251–266,
1994.
[132] William Opdyke. Refactoring Object-Oriented Framework. PhD thesis, University
of Illinois, 1992.
[133] Open group architecture framework version 4.
URL = http://www.opengroup.org/public/arch.
[134] David L. Parnas. On the criteria to be used in decomposing systems into modules.
Communications of the ACM, 15:1053–1058, 1972.
[135] Prashant Patil. Migration of procedural systems to object oriented architectures.
Master’s thesis, Department of Electrical and Computer Engineering, University of
Waterloo, 1999.
[136] Dewayne Perry and Alexander L. Wolf. Foundations for the study of software
architecture. ACM SIGSOFT Software Engineering Notes, 17(4):40–52, 1992.
[137] Shari L. Pfleeger, Ross Jeffery, Bill Curtis, and Barbara Kitchenham. Status report
on software measurement. IEEE Software, 14(2):33–43, 1997.
[138] A. M. Pitts and M. J. Gabbay. Proceedings of the 5th international conference on
mathematics of programme construction (mpc). In R. Backhouse and N. Oliveira,
BIBLIOGRAPHY 251
editors, A Metalanguage for Programming with Bound Names Modulo Renaming,
volume 1837, pages 230–255. Lecture Notes in Computer Science, Ponte de Lima,
Portugal, July 2000.
[139] Alan Pope. The CORBA Reference Guide : Understanding the Common Object
Request Broker Architecture. Addison-Wesley, 1998.
[140] Wolfgang Pree. Meta patterns : A means for capturing the essentials of reusable
object-oriented design. In Proceedings of the ACM European Conference on Object-
Oriented Programming (ECOOP), volume 0821, pages 150–162, Bologna, Italy,
1994.
[141] Roger S. Pressman. Software Engineering : A Practitioner’s Approach. McGraw
Hill, 2000.
[142] Vaclav T. Rajlich and Kieth H. Bennett. A staged model for the software life cycle.
IEEE Computer, 33(7):66–71, 2000.
[143] Vaclav T. Rajlich and Prashant Gosavi. A case study of unanticipated incremental
change. In Proceedings of the IEEE International Conference on Software Mainte-
nance (ICSM), pages 442–451, Montreal, Canada, October 2002.
[144] Recoder. URL = http://recoder.sourceforge.net.
[145] Reengineering tool for java (ret4j). URL = http://www.alphaworks.ibm.com/tech/ret4j.
[146] Dirk Riehle. Composite design patterns. In Proceedings of the ACM SIGPLAN
Conference on Object-Oriented Programming, Systems, Languages and Applications
(OOPSLA), pages 218–228, Atlanta, Georgia, USA, 1997.
[147] Arthur J. Riel. Object-Oriented Design Heuristics. Addison-Wesley, 1996.
BIBLIOGRAPHY 252
[148] Don Roberts, John Brant, and Ralph Johnson. A refactoring tools for smalltalk.
Theory and Practice of Object Systems, 3(4):253–263, 1997.
[149] Donald Roberts. Eliminating Analysis in Refactoring. PhD thesis, University of
Illinois at Urbana-Champaign, Department of Computer Science, 1999.
[150] James Rumbaugh, Ivar Jacobson, and Grady Booch. The Unified Modeling Lan-
guage: Reference Manual. Addison-Wesley, 1999.
[151] Sandia national laboratories, livermore, ca. URL = http://www.sandia.gov/.
[152] Benedikt Schulz. Design patterns as operators implemented with refactoring. In
Proceedings of the Workshop on Experiences in Object-Oriented Re-Engineering,
European Conference on Object-Oriented Programming (ECOOP), Brussels, Bel-
gium, July 1998.
[153] Mary Shaw. Heterogeneous design idioms for software architecture. In Proceedings
of the Sixth International Workshop on Software Specification and Design, pages
158–165, Como, Italy, October 1991.
[154] D. R. Smith. Kids : A semiautomatic program development system. IEEE Trans-
actions on Software Engineering, 16(9):1024–1043, 1990.
[155] Harry Sneed and Erika Nyary. Down-sizing large application programs. Journal of
Software Maintenance: Research and Practice, 6(5):105–116, 1994.
[156] Harry M. Sneed. Transforming procedural program structures to object-oriented
class structures for the purpose of populating a common software repository. In Pro-
ceedings of the IEEE International Conference on Software Maintenance (ICSM),
page 286, Montreal, Canada, October 2002.
BIBLIOGRAPHY 253
[157] Software refinery, reasoning systems. URL = http://www.reasoning.com.
[158] Ian Sommerville. Software Engineering. Addison-Wesley, 2001.
[159] Ralph E. Steuer. Multiple Criteria Optimization : Theory, Computation, and Ap-
plication. John Wiley and Sons, 1986.
[160] Bradley S. Stewart and White Chelsea C. Multi-objective a∗. Journal of Association
for Computing Machinery, 38(4):775–814, 1991.
[161] Joseph E. Stoy. Denotational Semantics : The Scott-Strachey Approach to Program-
ming Language. The MIT Press, 1977.
[162] Ladan Tahvildari, Richard Gregory, and Kostas Kontogiannis. An approach for
measuring software evolution using source code features. In Proceedings of the IEEE
Asia-Pacific Software Engineering (APSEC), pages 10–17, Takamatsu, Japan, De-
cember 1999.
[163] Ladan Tahvildari and Kostas Kontogiannis. A workbench for quality based soft-
ware re-engineering to object oriented platforms. In Proceedings of the ACM In-
ternational Conference in Object Oriented Programming, Systems, Languages, and
Applications (OOPSLA) - Doctoral Symposium, pages 157–158, Minneapolis, Min-
nesota, USA, October 2000.
[164] Ladan Tahvildari and Kostas Kontogiannis. A methodology for developing transfor-
mations using the maintainability soft-goal graph. In Proceedings of the IEEE 9th
International Working Conference on Reverse Engineering (WCRE), pages 77–86,
Richmond, Virginia, USA, November 2002.
[165] Ladan Tahvildari and Kostas Kontogiannis. On the role of design patterns in
quality-driven re-engineering. In Proceedings of the IEEE 6th European Conference
BIBLIOGRAPHY 254
on Software Maintenance and Re-engineering (CSMR), pages 230–240, Hungary,
Budapest, March 2002.
[166] Ladan Tahvildari and Kostas Kontogiannis. A software transformation framework
for quality-driven object-oriented re-engineering. In Proceedings of the IEEE Inter-
national Conference on Software Maintenance (ICSM), pages 596–605, Montreal,
Canada, October 2002.
[167] Ladan Tahvildari and Kostas Kontogiannis. A metric-based approach to enhance
design quality through meta-pattern transformations. In Proceedings of the IEEE
7th European Conference on Software Maintenance and Re-engineering (CSMR),
pages 183–192, Benevento, Italy, March 2003.
[168] Ladan Tahvildari and Kostas Kontogiannis. Improving design quality using meta-
pattern transformations : A metric-based approach. Journal of Software Mainte-
nance and Evolution : Research and Practice, to appear, 25 pages.
[169] Ladan Tahvildari and Kostas Kontogiannis. Computer aided software engineering.
In John G. Webster, editor, Encyclopedia of Electrical and Electronics Engineering.
John Wiley & Sons, to appear, 35 pages.
[170] Ladan Tahvildari, Kostas Kontogiannis, and John Mylopoulos. Requirements-
driven software re-engineering. In Proceedings of the IEEE 8thInternational Work-
ing Conference on Reverse Engineering (WCRE), pages 71–80, Stuttgart, Germany,
October 2001.
[171] Ladan Tahvildari, Kostas Kontogiannis, and John Mylopoulos. Quality-driven soft-
ware re-engineering. Journal of Systems and Software, Special Issue on : Software
Architecture - Engineering Quality Attributes, 66(3):225–239, June 2003.
BIBLIOGRAPHY 255
[172] Ladan Tahvildari and Ajit Singh. Categorization of object-oriented software met-
rics. In Proceedings of the IEEE Canadian Conference on Electrical and Computer
Engineering, pages 235–239, May 2000.
[173] David P. Tegarden, Steven D. Sheetz, and David E. Monarchi. Effectiveness of
traditional metrics for object-oriented system. In Proceedings of the Twenty-Fifth
Hawaii International Conference on System Sciences, pages 7–10, January 1993.
[174] Lance Tokuda and Don Batory. Evolving object-oriented designs with refactorings.
In Proceedings of the IEEE 14th International Conference on Automated Software
Engineering (ASE), pages 174–181, Cocoa Beach, Florida, October 1999.
[175] Paolo Tollena and Giulio Antoniol. Object-oriented design patterns inference.
In Proceedings of the IEEE International Conference on Software Maintenance
(ICSM), pages 230–238, Oxford, England, UK, September 1999.
[176] Transmogrify. URL = http://transmogrify.sourceforge.net.
[177] Chris Verhoef. How to implement the future? In Proceedings of the 26th IEEE Eu-
romicro Conference, volume 1, pages 32–47, Maastricht, The Netherlands, October
2000.
[178] Eilco Visser. Meta-programming with concrete object syntax. In Don Batory,
Charles Consel, and Walid Taha, editors, Generative Programming and Component
Engineering (GPCE), volume 2487 of Lecture Notes in Computer Science, pages
299–315, Pittsburgh, PA, USA, October 2002. Springer-Verlag.
[179] John M. Vlissides, James O. Coplien, and Norman L. Kerth, editors. Pattern
Languages of Program Design, volume 2. Addison-Wesley, 1996.
BIBLIOGRAPHY 256
[180] Andre Weinand, Erich Gamma, and Ralph E. Johnson. et++ : An object-oriented
application framework in c++. In Proceedings of the ACM SIGPLAN Conference on
Object-Oriented Programming, Systems, Languages and Applications (OOPSLA),
pages 46–57, San Diego, CA, USA, 1988.
[181] Weltab election tabulation system. URL = http://pathbridge.net/reproject/cfp2.htm.
[182] Scott A. Whitmire. Object-Oriented Design Measurement. John Wiley & Sons,
1997.
[183] Roel Wieringa. Requirements Engineering : Frameworks for Understanding. John
Wiley & Sons, 1996.
[184] Rebecca J. Wirfs-Brock and Ralph E. Johnson. Surveying current research in
object-oriented design. Communications of ACM (CACM), 33(9):105–123, Septem-
ber 1990.
[185] Steven G. Woods, Alexander E. Quilici, and Qiang Yang. Constraint-Based Design
Recovery for Software Re-engineering. Kluwer Academic Publishers, 1998.