Some Theory and Practice on Patterns – In Practice Yann-Gaël Guéhéneuc

Some Theory and Practice on
Patterns – In Practice
Yann-Gaël Guéhéneuc
NII, Tokyo, Japan
12/02/14
This work is licensed under a Creative
Commons Attribution-NonCommercialShareAlike 3.0 Unported License
Patterns
 Patterns
document reusable solutions to
recurring problems
– Architecture
• Architectural styles
– Design
• Design patterns
• Design anti-patterns
– Implementation
• Idioms
2/169
Examples
 Do
you know
– C++?
– Java?
– Lisp?
– Prolog?
– Smalltalk?
3/169
C++
class Dog {
string name;
Dog(const Dog* dog) : name(dogname) {}}
class Kennel { Dog* dog; string name; }
if (&kennel != this) {
thisdog =
new Dog(kennel.dog);
thisname = kennel.name;
}
return *this;
Bruce Eckel ; Thinking in C++ ; Volume 2, pages 551–553, Planet PDF, 2nd Edition, 2000.
4/169
C++
class Dog {
string name;
Dog(const Dog* dog) : name(dogname) {}}
class Kennel { Dog* dog; string name; }
if (&kennel != this) {
thisdog =
new Dog(kennel.dog);
thisname = kennel.name;
}
return *this;
?
Bruce Eckel ; Thinking in C++ ; Volume 2, pages 551–553, Planet PDF, 2nd Edition, 2000.
5/169
C++
class Dog {
string name;
Dog(const Dog* dog) : name(dogname) {}}
class Kennel { Dog* dog; string name; }
if (&kennel != this) {
thisdog =
new Dog(kennel.dog);
thisname = kennel.name;
}
return *this;
Overriding of
operator =
?
Bruce Eckel ; Thinking in C++ ; Volume 2, pages 551–553, Planet PDF, 2nd Edition, 2000.
6/169
Java
final Object oldListOfEntities =
this.listOfEntities();
this.fireVetoableChange(
"RemoveEntity",
oldListOfEntities,
anEntity);
this.removeEntity(anEntity);
this.firePropertyChange(
"RemoveEntity",
oldListOfEntities,
anEntity);
7/169
Java
final Object oldListOfEntities =
this.listOfEntities();
this.fireVetoableChange(
"RemoveEntity",
oldListOfEntities,
anEntity);
this.removeEntity(anEntity);
this.firePropertyChange(
"RemoveEntity",
oldListOfEntities,
anEntity);
?
8/169
Java
final Object oldListOfEntities =
this.listOfEntities();
this.fireVetoableChange(
"RemoveEntity",
oldListOfEntities,
anEntity);
this.removeEntity(anEntity);
this.firePropertyChange(
"RemoveEntity",
oldListOfEntities,
anEntity);
Veto protocol
of JavaBeans
?
9/169
Lisp
(define (square ls)
(if (null? ls)
'()
(cons ((lambda(x) (* x x))
(car ls))
(square (cdr ls)))))
10/169
Lisp
(define (square ls)
(if (null? ls)
'()
(cons ((lambda(x) (* x x))
(car ls))
(square (cdr ls)))))
?
11/169
Lisp
(define (square ls)
(if (null? ls)
'()
(cons ((lambda(x) (* x x))
(car ls))
(square (cdr ls)))))
?
Map
12/169
Prolog
checkLt0(LA, LT, LD, NNLA, NNLT, NNLD) :nextEvent(
[],
E),
interpretEvent(E, IE),
checkLt1(IE, LA, LT, LD, NLA, NLT, NLD),
!,
(
(IE = programEnd,
NNLA = NLA,
NNLT = NLT,
NNLD = NLD)
;
checkLt0(NLA, NLT, NLD, NNLA, NNLT, NNLD)
).
13/169
Prolog
checkLt0(LA, LT, LD, NNLA, NNLT, NNLD) :nextEvent(
[],
E),
interpretEvent(E, IE),
checkLt1(IE, LA, LT, LD, NLA, NLT, NLD),
!,
(
(IE = programEnd,
NNLA = NLA,
NNLT = NLT,
NNLD = NLD)
;
checkLt0(NLA, NLT, NLD, NNLA, NNLT, NNLD)
).
?
14/169
Prolog
checkLt0(LA, LT, LD, NNLA, NNLT, NNLD) :nextEvent(
[],
E),
interpretEvent(E, IE),
checkLt1(IE, LA, LT, LD, NLA, NLT, NLD),
!,
(
(IE = programEnd,
NNLA = NLA,
NNLT = NLT,
NNLD = NLD)
;
checkLt0(NLA, NLT, NLD, NNLA, NNLT, NNLD)
).
?
Conditional
15/169
Smalltalk
Integer>>+ aNumber
^aNumber addInteger: self
Float>>+ aNumber
^aNumber addFloat: self
Integer>>addInteger: anInteger
<primitive: 1>
Float>>addFloat: aFloat
<primitive: 2>
Integer>>addFloat: aFloat
^self asFloat addFloat: aFloat
Float>>addInteger: anInteger
^self addFloat: anInteger asFloat
Kent Beck ; Smalltalk – Best practice patterns ; Pages 55–57, Prentice Hall, 1997, ISBN 0-13-476904-X.
16/169
Smalltalk
Integer>>+ aNumber
^aNumber addInteger: self
Float>>+ aNumber
^aNumber addFloat: self
Integer>>addInteger: anInteger
<primitive: 1>
Float>>addFloat: aFloat
<primitive: 2>
Integer>>addFloat: aFloat
^self asFloat addFloat: aFloat
Float>>addInteger: anInteger
^self addFloat: anInteger asFloat
?
Kent Beck ; Smalltalk – Best practice patterns ; Pages 55–57, Prentice Hall, 1997, ISBN 0-13-476904-X.
17/169
Smalltalk
Integer>>+ aNumber
^aNumber addInteger: self
Float>>+ aNumber
^aNumber addFloat: self
Integer>>addInteger: anInteger
<primitive: 1>
Float>>addFloat: aFloat
<primitive: 2>
Integer>>addFloat: aFloat
^self asFloat addFloat: aFloat
Float>>addInteger: anInteger
^self addFloat: anInteger asFloat
Double
dispatch
?
Kent Beck ; Smalltalk – Best practice patterns ; Pages 55–57, Prentice Hall, 1997, ISBN 0-13-476904-X.
18/169
Conclusion on the Examples
 The
examples showed idioms in the given
pieces of source code
– These idioms are recurring motifs in a program
source code
– These motifs connote a recognized,
acknowledge style of programming
19/169
Outline
 Definition
 Quality
 Form
 Example
 Catalogue
 Practice
 Conclusion
20/169
Outline
 Definition
 Quality
 Form
 Example
 Catalogue
 Practice
 Conclusion
21/169
Definition

Context
– 1977 et 1979: architecture
• Christopher Alexander
• A Pattern Language: Towns, Buildings,
Construction and the idea of generative patterns
• The Timeless Way of Building and the idea of
perfection in architecture
– 1990: object-oriented design
• Erich Gamma, Richard Helm, Ralph Johnson,
and John Vlissides†
• Design Patterns drawn from experience
22/169
Definition
A
Pattern Language:
Towns, Buildings, Construction
– 253 patterns
– Generative grammar
– “At the core... is the idea that people should
design for themselves their own houses, streets
and communities. This idea... comes simply
from the observation that most of the wonderful
places of the world were not made by architects
but by the people.”
23/169
Definition
“Each pattern describes a problem which occurs over and
over again in our environment, and then describes the core
of the solution to that problem, in such way that you can
use this solution a million times over, without ever doing it
the same way twice.”
—Christopher Alexander, 1977
“Each pattern is a three part rule, which express a relation
between a context, a problem, and a solution.”
—Christopher Alexander, 1977
24/169
盈進学園 東野高等学校
http://eishin.ac/
25/169
Definition
 Design
Patterns:
Elements of Reusable OO Software
– 23 patterns
– Not a language?
– “Dynamic, highly parameterized software is
harder to understand and build than more static
software.”
26/169
Definition
“The strict modeling of the real world leads
to reflect today’s realities but not necessarily
tomorrow’s. The abstractions that emerge
during design are key to making a design
flexible.”
—Erich Gamma, 1994
27/169
JHotDraw
http://www.jhotdraw.org/
http://www.javaworld.com/article/2074997/swing-gui-programming/
become-a-programming-picasso-with-jhotdraw.html
28/169
Definition
A
pattern is a general reusable solution to a
commonly occurring problem within a given
context in software development, operation,
and maintenance
29/169
Definition
A
pattern is a general reusable solution to a
commonly occurring problem within a given
context in software development,
operation, and maintenance
– Patterns have been identified for
•
•
•
•
Different phases of software development
Different levels of abstraction
Different technologies
…
30/169
Definition
A
pattern is a general reusable solution to a
commonly occurring problem within a
given context in software development,
operation, and maintenance
31/169
Definition
A
pattern is a general reusable solution to a
commonly occurring problem within a
given context in software development,
operation, and maintenance
– Problem faced by three people at three different
times in a similar context
– Particular problems are not included, except if
they occur more than three times…
32/169
Definition
A
pattern is a general reusable solution to a
commonly occurring problem within a given
context in software development, operation,
and maintenance
33/169
Definition
A
pattern is a general reusable solution to a
commonly occurring problem within a given
context in software development, operation,
and maintenance
– Essentially, a solution must describe steps to
solve the problem
• Architecture
• Design
• Implementation
34/169
Definition
A
pattern is a general reusable solution to a
commonly occurring problem within a given
context in software development, operation,
and maintenance
35/169
Definition
A
pattern is a general reusable solution to a
commonly occurring problem within a given
context in software development, operation,
and maintenance
– The solution must not be particular
– The solution can be adapted
– The solution must be adapted
36/169
Definition
A
pattern is a general reusable solution to a
commonly occurring problem within a given
context in software development, operation,
and maintenance
– The solution must not be particular
– The solution can be adapted
– The solution must be adapted
• Forces
• Variants
37/169
Recall the C++ Example
class Dog {
string name;
Dog(const Dog* dog) : name(dogname) {}}
class Kennel { Dog* dog; string name; }
if (&kennel != this) {
thisdog =
new Dog(kennel.dog);
thisname = kennel.name;
}
return *this;
Bruce Eckel ; Thinking in C++ ; Volume 2, pages 551–553, Planet PDF, 2nd Edition, 2000.
38/169
Recall the C++ Example
class Dog {
string name;
Dog(const Dog* dog) : name(dogname) {}}
class Kennel { Dog* dog; string name; }
if (&kennel != this) {
thisdog =
new Dog(kennel.dog);
thisname = kennel.name;
}
return *this;
Bruce Eckel ; Thinking in C++ ; Volume 2, pages 551–553, Planet PDF, 2nd Edition, 2000.
39/169
Recall the C++ Example
class Dog {
string name;
Dog(const Dog* dog) : name(dogname) {}}
class Kennel { Dog* dog; string name; }
if (&kennel != this) {
thisdog =
new Dog(kennel.dog);
thisname = kennel.name;
}
return *this;
Development, operation, and
maintenance
Bruce Eckel ; Thinking in C++ ; Volume 2, pages 551–553, Planet PDF, 2nd Edition, 2000.
40/169
Recall the C++ Example
class Dog {
string name;
Dog(const Dog* dog) : name(dogname) {}}
class Kennel { Dog* dog; string name; }
if (&kennel != this) {
thisdog =
new Dog(kennel.dog);
thisname = kennel.name;
}
return *this;
Development, operation, and
maintenance
Commonly occurring problem
within a given context
Bruce Eckel ; Thinking in C++ ; Volume 2, pages 551–553, Planet PDF, 2nd Edition, 2000.
41/169
Recall the C++ Example
class Dog {
string name;
Dog(const Dog* dog) : name(dogname) {}}
class Kennel { Dog* dog; string name; }
if (&kennel != this) {
thisdog =
new Dog(kennel.dog);
thisname = kennel.name;
}
return *this;
Development, operation, and
maintenance
Commonly occurring problem
within a given context
General reusable solution
Bruce Eckel ; Thinking in C++ ; Volume 2, pages 551–553, Planet PDF, 2nd Edition, 2000.
42/169
Outline
 Definition
 Quality
 Form
 Example
 Catalogue
 Practice
 Conclusion
43/169
Quality
A
means to enhance the reusability
– Of the code written using the pattern
– Of the problem and its solution




44/169
Quality
A
means to enhance the reusability
– Of the code written using the pattern
– Of the problem and its solution
A
means to encapsulate design experience



45/169
Quality
A
means to enhance the reusability
– Of the code written using the pattern
– Of the problem and its solution
A
means to encapsulate design experience
 A common vocabulary among designers


46/169
Quality
A
means to enhance the reusability
– Of the code written using the pattern
– Of the problem and its solution
A
means to encapsulate design experience
 A common vocabulary among designers
A
means to have that
“quality without a name”
47/169
Quality Without a Name



48/169
Quality Without a Name
“there is a point you reach in tightening a nut, where you
know that to tighten just a little more might strip the thread,
but to leave it slightly looser would risk having the hut
coming off from vibration. If you've worked with your hands
a lot, you know what this means, but the advice itself is
meaningless.”
—Robert Pirsig, circa. 1972
49/169
Quality Without a Name
“there is a point you reach in tightening a nut, where you
know that to tighten just a little more might strip the thread,
but to leave it slightly looser would risk having the hut
coming off from vibration. If you've worked with your hands
a lot, you know what this means, but the advice itself is
meaningless.”
—Robert Pirsig, circa. 1972
“[T]oo often software developers spend their days
grinding away for pay at programs they neither need
nor love. But not in the Linux world - which may
explain why the average quality of software
originated in the Linux community is so high.”
—Eric Raymond, 1998
50/169
Quality Without a Name
51/169
Quality Without a Name
ニワトリのヒナの雌雄鑑別
(chick sexing)


http://discovermagazine.com/2011/sep/18-your-brain-knows-lot-more-than-you-realize
52/169
Quality Without a Name
ニワトリのヒナの雌雄鑑別
(chick sexing)
“The master would stand over the
apprentice and watch. The student
would pick up a chick, examine its
rear, and toss it into one bin or the
other. The master would give
feedback: yes or no.”
—Eagleman, 2011
http://discovermagazine.com/2011/sep/18-your-brain-knows-lot-more-than-you-realize
53/169
54/169
Practice, practice
and practice more
55/169
56/169
Quality
 Rationale
– “Software design is widely recognised as being
a “wicked” or “ill-structured” problem,
characterised by ambiguous specifications, no
true/false solutions (only ones that are “better” or
“worse” from a particular perspective), the lack
of any “stopping rule” to determine when a
solution has been reached, and no ultimate test
of whether a solution meets the requirements.”
—Zhang and Budgen, 2012
57/169
Quality
“Important assumptions
– That patterns can be codified in such a way that
they can be shared between different designers
– That reuse will lead to “better” designs. There is
an obvious question here of what constitutes
“better”, but a key measure is maintainability”
—Zhang and Budgen, 2012
(With minor adaptations)
58/169
Quality
“Advantages:
– Using patterns improves programmer
productivity and program quality
– Novices can increase their design skills
significantly by studying and applying patterns
– Patterns encourage best practices, even for
experiences designers
– Design patterns improve communication, both
among developers and from developers to
maintainers”
59/169
Outline
 Definition
 Quality
 Form
 Example
 Catalogue
 Practice
 Conclusion
60/169
Form
 Several
books, articles
– “Theoretical”
– With examples
– Among others…
61/169
Form
 Several
books, articles
– “Theoretical”
– With examples
– Among others…
62/169
Form
 Several
books, articles
– “Theoretical”
– With examples
– Among others…
63/169
Form
 Several
books, articles
– “Theoretical”
– With examples
– Among others…
64/169
Form
 Several
books, articles
– “Theoretical”
– With examples
– Among others…
65/169
Form
 Several
books, articles
– “Theoretical”
– With examples
– Among others…
66/169
Form
 Several
books, articles
– Amazon.com
• Books › Computers & Technology › Programming ›
Software Design, Testing & Engineering › ObjectOriented Design › "patterns"
• 224 results on May 31, 2013
67/169
Form
 Several
books, articles
– Amazon.com
• Exclusion
– Unreleased books
– Specific to a technology or frameworks
» e.g., MVVM Unleashed by Michael Brown
– Process oriented, user-interface, programming languages
» e.g., Process Patterns: Building Large-Scale Systems
Using Object Technology by Scott W. Ambler and
Barbara Hanscome
– Proceedings of conferences
– Unrelated to software engineering
68/169
Form
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
Pattern-Oriented Software Architecture, Patterns for Concurrent and Networked Objects: Volume 2 (Wiley Software...
by Douglas C. Schmidt, Michael Stal, Hans Rohnert and Frank Buschmann
Pattern-Oriented Software Architecture, Patterns for Resource Management: Volume 3 (Wiley Software Patterns
Series... by Michael Kircher and Prashant Jain
Pattern-Oriented Software Architecture, A System of Patterns: Volume 1 (Wiley Software Patterns Series) by Frank
Buschmann, Regine Meunier, Hans Rohnert and Peter Sommerlad
Pattern-Oriented Software Architecture For Dummies (For Dummies (Computers)) by Robert Hanmer
Web Security Patterns by Ramesh Nagappan and Christopher Steel
Safe C++ by Vladimir Kushnir
Programming in the Large with Design Patterns by Eddie Burris
Elemental Design Patterns by Jason McC. Smith
Java Application Architecture: Modularity Patterns with Examples Using OSGi (Robert C. Martin Series) by Kirk
Knoernschild
Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions (Addison-Wesley
Signature... by Gregor Hohpe and Bobby Woolf
Patterns of Enterprise Application Architecture (Addison-Wesley Signature Series (Fowler)) by Martin Fowler
Cognitive Patterns: Problem-Solving Frameworks for Object Technology by Robert K Konitzer, Bobbin Teegarden,
Alexander Rush and Karen M Gardner
Service Design Patterns: Fundamental Design Solutions for SOAP/WSDL and RESTful Web Services by Robert
Daigneau
The ACE Programmer's Guide: Practical Design Patterns for Network and Systems Programming by Stephen D.
Huston, James CE Johnson and Umar Syyid
Patterns for Parallel Software Design (Wiley Software Patterns Series) by Jorge Luis Ortega-Arjona
Design Patterns in Object-oriented ABAP by Igor Barbaric
Object-Oriented Reengineering Patterns by Oscar Nierstrasz, Stéphane Ducasse and Serge Demeyer
Dependency Injection by Dhanji R. Prasanna
Object-Oriented Software Engineering Using UML, Patterns, and Java (3rd Edition) by Bernd Bruegge and Allen H.
Dutoit
J2EE Design Patterns by William Crawford and Jonathan Kaplan
Applying UML and Patterns: An Introduction to Object-oriented Analysis and Design and Iterative Development by
Craig Larman
Object-oriented Analysis and Design Using Umlan Introduction to Unified Process and Design Patterns by Mahesh P.
Matha
C++ Design Patterns and Derivatives Pricing (Mathematics, Finance and Risk) by M. S. Joshi
Effective Java (2nd Edition) by Joshua Bloch
Patterns for Fault Tolerant Software (Wiley Software Patterns Series) by Robert Hanmer
Implementation Patterns by Kent Beck
Patterns for Computer-Mediated Interaction (Wiley Software Patterns Series) by Till Schummer and Stephan Lukosch
Pattern Oriented Software Architecture Volume 5: On Patterns and Pattern Languages by Frank Buschmann, Kevlin
Henney and Douglas C. Schmidt
Object-Oriented Analysis and Design with Applications (3rd Edition) by Grady Booch, Robert A. Maksimchuk, Michael
W. Engle and Bobbi J. Young
Head First Object-Oriented Analysis and Design by Brett D. McLaughlin, Gary Pollice and Dave West
Agile Principles, Patterns, and Practices in C# by Robert C. Martin and Micah Martin
Design Patterns For Dummies by Steve Holzner
Pattern Languages of Program Design 5 by Dragos Manolescu, Markus Voelter and James Noble
Design Patterns in Java(TM) (Software Patterns Series) by Steven John Metsker and William C. Wake
Object-Oriented Design and Patterns by Cay S. Horstmann
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
Object-Oriented Modeling and Design with UML (2nd Edition) by Michael R. Blaha and James R Rumbaugh
Remoting Patterns: Foundations of Enterprise, Internet and Realtime Distributed Object Middleware (Wiley
Software... by Markus Völter, Michael Kircher and Uwe Zdun
Software Factories: Assembling Applications with Patterns, Models, Frameworks, and Tools (Wiley Application
Development... by Jack Greenfield, Keith Short, Steve Cook and Stuart Kent
Refactoring to Patterns by Joshua Kerievsky
Architecting Enterprise Solutions: Patterns for High-Capability Internet-based Systems (Wiley Software Patterns...
by Paul Dyson and Andrew Longshaw
Enterprise Patterns and MDA: Building Better Software with Archetype Patterns and UML by Jim Arlow and Ila
Neustadt
Data Access Patterns: Database Interactions in Object-Oriented Applications by Clifton Nock
Domain-Driven Design: Tackling Complexity in the Heart of Software by Eric Evans
Pattern-Oriented Analysis and Design: Composing Patterns to Design Software Systems by Sherif M. Yacoub,
Hany H. Ammar, Sherif Yacoub and Hany Ammar
Java Extreme Programming Cookbook by Eric M. Burke and Brian M. Coyner
J2EE Best Practices: Java Design Patterns, Automation, and Performance (Wiley Application Development
Series) by Darren Broemmer
Real-Time Design Patterns: Robust Scalable Architecture for Real-Time Systems by Bruce Powel Douglass
Design Patterns Java¿ Workbook by Steven John Metsker
EJB Design Patterns: Advanced Patterns, Processes, and Idioms by Floyd Marinescu
Streamlined Object Modeling: Patterns, Rules, and Implementation by Jill Nicola, Mark Mayfield and Mike Abney
Design Patterns Explained: A New Perspective on Object-Oriented Design by Alan Shalloway and James Trott
Small Memory Software: Patterns for systems with limited memory (Software Patterns Series) by James Noble
and Charles Weir
AntiPatterns in Project Management by William J. Brown, Hays W. "Skip" McCormick III and Scott W. Thomas
Pattern Languages of Program Design 4 (Software Patterns Series) by Brian Foote, Neil Harrison and Hans
Rohnert
Testing Object-Oriented Systems: Models, Patterns, and Tools by Robert V. Binder
Design Patterns and Contracts by Jean-Marc Jezequel, Michel Train and Christine Mingins
Object-Oriented Software Development Using Java: Principles, Patterns, and Frameworks (1/e) by Xiaoping Jia
Refactoring: Improving the Design of Existing Code by Martin Fowler, Kent Beck, John Brant and William Opdyke
More Process Patterns: Delivering Large-Scale Systems Using Object Technology (SIGS: Managing Object
Technology... by Scott W. Ambler
Pattern Hatching: Design Patterns Applied by John Vlissides
AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis by William J. Brown, Raphael C. Malveau,
Hays W. "Skip" McCormick and Thomas J. Mowbray
A Little Java, A Few Patterns (Language, Speech, & Communication) by Matthias Felleisen, Daniel P. Friedman
and Ralph E. Johnson
Pattern Languages of Program Design 3 (v. 3) by Robert C. Martin, Dirk Riehle and Frank Buschmann
Object Models: Strategies, Patterns, and Applications (2nd Edition) by Peter Coad, David North and Mark Mayfield
Analysis Patterns: Reusable Object Models by Martin Fowler
Patterns of Software: Tales from the Software Community by Richard P. Gabriel
Pattern Languages of Program Design 2 (v. 2) by John Vlissides, James O. Coplien and Norman L. Kerth
Software Patterns by James Coplien
Software Architecture: Perspectives on an Emerging Discipline by Mary Shaw and David Garlan
Adaptive Object-Oriented Software: The Demeter Method with Propagation Patterns: The Demeter Method with
Propagation... by Karl Lieberherr
Pattern Languages of Program Design by James O. Coplien and Douglas C. Schmidt
69/169
Form
“Each pattern is a three part rule, which
express a relation between a context, a
problem, and a solution.”
—Christopher Alexander, 1977
70/169
Form
 General
form as for the GoF
also inspired by Coplien’s form
– Name
– Problem(s)
– Solution
– Consequences
71/169
Form (Extended)
 General
form as for the GoF
also inspired by Coplien’s form
– Name
– Problem(s)
– Example(s)
– Solution
– Example(s)
– Consequences
– (Follow-up)
72/169
Form
 General
form as for the GoF
also inspired by Coplien’s form
– Not formal
– Room for interpretation
– But…
• UML-like class diagrams
• UML-like sequence diagrams
• Smalltalk / C++ example code
73/169
Outline
 Definition
 Quality
 Form
 Example
 Catalogue
 Practice
 Conclusion
74/169
Example
 Simplified
(1/5)
compiler
– Parse files to build an AST
– Iterate over the AST
• Build DefaultMutableTreeNodes
javax.swing.tree.DefaultMutableTreeNode
for a graphical representation of the AST
• Bind types
• Generate code
• …
75/169
Example
 Simplified
(1/5)
compiler
– Parse files to build an AST
– Iterate over the AST
• Build DefaultMutableTreeNodes
javax.swing.tree.DefaultMutableTreeNode
for a graphical representation of the AST
• Bind types
• Generate code
• …
76/169
Example

(2/5)
AST
CompilationUnit
Main
generateCode()
Class
generateCode()
Field
Method
generateCode()
generateCode()
Statement
generateCode()
77/169
Example
(3/5)
package compiler;
import java.util.Set;
public class Method {
private Set statements;
public void addStatement(final Statement aStatement) {
this.statements.add(aStatement);
}
public void removeStatement(final Statement aStatement) {
this.statements.remove(aStatement);
}
}
package compiler;
package compiler;
public class Field {
/* To be implemented. */
}
public class Statement {
/* To be implemented. */
}
78/169
Example
(4/5)
package compiler;
import java.util.Set;
public class Class {
private String name;
private Set methods;
private Set fields;
public String getName() {
return this.name;
}
public void addMethod(final Method aMethod) {
this.methods.add(aMethod);
}
public void removeMethod(final Method aMethod) {
this.methods.remove(aMethod);
}
public void addField(final Method aField) {
this.fields.add(aField);
}
public void removeField(final Field aField) {
this.fields.remove(aField);
}
}
79/169
Example
(5/5)
package compiler;
import java.util.Iterator;
import java.util.Set;
public class CompilationUnit {
private Set classes;
public void addClass(final Class aClass) {
this.classes.add(aClass);
}
public void removeClass(final Class aClass) {
this.classes.remove(aClass);
}
public Class getClass(final String aName) {
final Iterator iterator = this.classes.iterator();
while (iterator.hasNext()) {
final Class aClass = (Class) iterator.next();
if (aClass.getName().equals(aName)) {
return aClass;
}
}
return null;
}
}
80/169
Naïve Implementation
 How
(1/7)
to generate microcode for
– Microsoft Windows operating system
– Intel Pentium processor
81/169
Naïve Implementation
 How
(1/7)
to generate microcode for
– Microsoft Windows operating system
– Intel Pentium processor
Add a generateCode()
method in each class
82/169
Naïve Implementation
(2/7)
public class Method {
…
public String generateCode() {
String generatedCode = "";
/* Do something at the beginning. */
final Iterator iterator = this.statements.iterator();
while (iterator.hasNext()) {
final Statement aStatement = (Statement) iterator.next();
generatedCode += aStatement.generateCode();
}
/* Do something at the end. */
return generatedCode;
}
}
public class Field {
…
public String generateCode() {
String generatedCode = "";
/* Do something. */
return generatedCode;
}
}
public class Statement {
…
public String generateCode() {
String generatedCode = "";
/* Do something. */
return generatedCode;
}
}
83/169
Naïve Implementation
(3/7)
public class Class {
…
public String generateCode() {
String generatedCode = "";
/* Do something at the beginning. */
final Iterator iteratorOnFields = this.fields.iterator();
while (iteratorOnFields.hasNext()) {
final Field aField = (Field) iteratorOnFields.next();
generatedCode += aField.generateCode();
}
final Iterator iteratorOnMethods = this.methods.iterator();
while (iteratorOnMethods.hasNext()) {
final Method aMethod = (Method) iteratorOnMethods.next();
generatedCode += aMethod.generateCode();
}
/* Do something at the end. */
return generatedCode;
}
}
84/169
Naïve Implementation
(4/7)
public class CompilationUnit {
…
public String generateCode() {
String generatedCode = "";
/* Do something at the beginning. */
final Iterator iterator = this.classes.iterator();
while (iterator.hasNext()) {
final Class aClass = (Class) iterator.next();
generatedCode += aClass.generateCode();
}
/* Do something at the end. */
return generatedCode;
}
}
85/169
Naïve Implementation
m : Main
cu :
CompilationUnit
c : Class
(5/7)
m : Method
s : Statement
generateCode( )
generateCode( )
generateCode( )
generateCode( )
86/169
Naïve Implementation
 Limitations
(6/7)
of the naïve implementation
– What about generating code for
• Linux on PowerPC?
• Linux on Motorola 68060?
• OS/400 on AS/400?
87/169
Naïve Implementation
 Limitations
(6/7)
of the naïve implementation
– What about generating code for
• Linux on PowerPC?
• Linux on Motorola 68060?
• OS/400 on AS/400?
Combinatorial explosion of
generateCodeForXXX()
methods in each class
88/169
Naïve Implementation
(7/7)
 Requirements
– Decouple the data structure
• The AST
– From algorithms on the data structure
• The generateCodeForXXX() method
• And others, including type binding!
89/169
Naïve Implementation
(7/7)
 Requirements
– Decouple the data structure
• The AST
– From algorithms on the data structure
• The generateCodeForXXX() method
• And others, including type binding!
The Visitor design pattern
guides you to do that!
90/169
Visitor
 Name:
(2/13)
Visitor
 Intent:
“Represent an operation to be
performed on the elements of an object
structure. Visitor lets you define a new
operation without changing the classes of
the elements on which it operates.”
91/169
Visitor
(3/13)
 Motivation:
“Consider a compiler that
represents programs as abstract syntax
trees. It will need to perform operations on
abstract syntax trees for "static semantic"
analyses like checking that all variables are
defined. It will also need to generate code.”
92/169
Visitor
(4/13)
 Motivation
(cont’d): “[…] It will be confusing
to have type-checking code mixed with
pretty-printing code or flow analysis code.
[…] It would be better if each new operation
could be added separately, and the node
classes were independent of the operations
that apply to them.”
93/169
Visitor
(5/13)
 Motivation
(cont’d): “We can have both by
packaging related operations from each
class in a separate object, called a visitor,
and passing it to elements of the abstract
syntax tree as it's traversed.”
94/169
Visitor
(6/13)
 Motivation
(cont’d): “When an element
accepts the visitor, it sends a request to the
visitor that encodes the element's class. It
also includes the element as an argument.
The visitor will then execute the operation for
that element—the operation that used to be
in the class of the element.”
95/169
Visitor
 Double
(7/13)
dispatch idiom
– Receive a call
– Send a call back with parameter values
class Client {
void printAllEverywhere(Figure[] figures, Printer[] printers) {
for (int i = 0; i < figures.length; i++) {
final Figure figure = figures[i];
for (int j = 0; j < printers.length; j++) {
Printer printer = printers[j];
figure.printOn(printer);
}
}
}
}
http://c2.com/cgi-bin/wiki?DoubleDispatchExample
http://www.patentstorm.us/patents/6721807/description.html
96/169
Visitor
(8/13)
 Applicability
– An object structure contains many classes of
objects with differing interfaces…
– Many distinct and unrelated operations need to
be performed on objects in an object structure…
– The classes defining the object structure rarely
change, but you often want to define new
operations over the structure…
97/169
Visitor
(9/13)
 Structure
98/169
Visitor

(10/13)
Participants
– Visitor (NodeVisitor)
• Declares a Visit operation for
each class…
– ConcreteVisitor
(TypeCheckingVisitor)
• Implements each Visit…
– Element (Node)
• Defines an Accept operation…
– ConcreteElement
(AssignmentNode)
• Implements Accept …
– ObjectStructure (Program)
• Can enumerate its elements
• May provide a high-level
interface to allow the visitor
to visit its elements
• May either be a composite
(see Composite) or a
collection
99/169
Visitor
(11/13)
 Collaborations
100/169
Visitor
(13/13)
 Consequences:
…
 Implementation: …
 Sample code: …
 Known uses
– ASTs
– Meta-models
–…
 Related
patterns: Composite
101/169
Better Implementation
(1/6)
package compiler.visitor;
import
import
import
import
import
compiler.Class;
compiler.CompilationUnit;
compiler.Field;
compiler.Method;
compiler.Statement;
public interface Visitor {
void open(final Class aClass);
void open(final CompilationUnit aCompilationUnit);
void open(final Method aMethod);
void close(final Class aClass);
void close(final CompilationUnit aCompilationUnit);
void close(final Method aMethod);
void visit(final Field aField);
void visit(final Statement aStatement);
}
102/169
Better Implementation
(2/6)
public class Method {
…
public void accept(final Visitor aVisitor) {
aVisitor.open(this);
final Iterator iterator = this.statements.iterator();
while (iterator.hasNext()) {
final Statement aStatement = (Statement) iterator.next();
aStatement.accept(aVisitor);
}
aVisitor.close(this);
}
}
public class Field {
…
public void accept(final Visitor aVisitor) {
aVisitor.visit(this);
}
}
public class Statement {
…
public void accept(final Visitor aVisitor) {
aVisitor.visit(this);
}
}
103/169
Better Implementation
(3/6)
public class Class {
…
public void accept(final Visitor aVisitor) {
aVisitor.open(this);
final Iterator iteratorOnFields = this.fields.iterator();
while (iteratorOnFields.hasNext()) {
final Field aField = (Field) iteratorOnFields.next();
aField.accept(aVisitor);
}
final Iterator iteratorOnMethods = this.methods.iterator();
while (iteratorOnMethods.hasNext()) {
final Method aMethod = (Method) iteratorOnMethods.next();
aMethod.accept(aVisitor);
}
aVisitor.close(this);
}
}
104/169
Better Implementation
(4/6)
public class CompilationUnit {
…
public void accept(final Visitor aVisitor) {
aVisitor.open(this);
final Iterator iterator = this.classes.iterator();
while (iterator.hasNext()) {
final Class aClass = (Class) iterator.next();
aClass.accept(aVisitor);
}
aVisitor.close(this);
}
}
105/169
(5/6)
m : Mai n
cu :
CompilationUnit
c : Class
m : Method
s : Statem ent
v : IVisitor
accept(IVisitor)
open(Com pilationUnit)
a ccept(IVisitor)
o pen(Cl as s)
accept(IVisitor)
Better implementation
open(Method)
a ccept(IVis itor)
visit(Statement)
clos e(Method)
close(C lass)
clos e(Compil ationUn it)
106/169
Better Implementation
 By
(6/6)
using the visitor design pattern
– Decouple data structure and algorithms
– Put the traversal in only one place, in the AST
– Allow the addition of new algorithms without
changing the data structure
107/169
Better Implementation
 By
(6/6)
using the visitor design pattern
– Decouple data structure and algorithms
– Put the traversal in only one place, in the AST
– Allow the addition of new algorithms without
changing the data structure
Much better, clearer
implementation!
108/169
Conclusion on the Example
 The
Visitor design pattern is useful
anywhere you have
– A data (stable) structure
– Algorithms (infinite) on that data structure
 Design
patterns provided good solution to
recurrent problems!
109/169
Outline
 Definition
 Quality
 Form
 Example
 Catalogue
 Practice
 Conclusion
110/169
Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides ;
Design Patterns: Elements of Reusable Object-Oriented Software ;
Addison-Wesley, 1995
111/169
Catalogue
 Design
patterns
– Development and maintenance
– Design/implementation levels
– Examples in C++ and Smalltalk
 Divided
in three categories
– Behavioural
– Creational
– Structural
112/169
Catalogue
113/169
Catalogue
114/169
Catalogue
 Abstract
Factory (87)
– Provide an interface for creating families of
related or dependent objects without specifying
their concrete classes
 Adapter
(139)
– Convert the interface of a class into another
interface clients expect. Adapter lets classes
work together that couldn't otherwise because of
incompatible interfaces
115/169
Catalogue
 Bridge
(151)
– Decouple an abstraction from its implementation
so that the two can vary independently
 Builder
(97)
– Separate the construction of a complex object
from its representation so that the same
construction process can create different
representations
116/169
Catalogue
 Chain
of Responsibility (223)
– Avoid coupling the sender of a request to its
receiver by giving more than one object a
chance to handle the request. Chain the
receiving objects and pass the request along the
chain until an object handles it
117/169
Catalogue
 Command
(233)
– Encapsulate a request as an object, thereby
letting you parameterize clients with different
requests, queue or log requests, and support
undoable operations
 Composite
(163)
– Compose objects into tree structures to
represent part-whole hierarchies. Composite lets
clients treat individual objects and compositions
of objects uniformly
118/169
Catalogue
 Decorator
(175)
– Attach additional responsibilities to an object
dynamically. Decorators provide a flexible
alternative to subclassing for extending
functionality
 Facade
(185)
– Provide a unified interface to a set of interfaces
in a subsystem. Facade defines a higher-level
interface that makes the subsystem easier to use
119/169
Catalogue
 Factory
Method (107)
– Define an interface for creating an object, but let
subclasses decide which class to instantiate.
Factory Method lets a class defer instantiation to
subclasses
 Flyweight
(195)
– Use sharing to support large numbers of finegrained objects efficiently
120/169
Catalogue
 Interpreter
(243)
– Given a language, define a representation for its
grammar along with an interpreter that uses the
representation to interpret sentences in the
language
 Iterator
(257)
– Provide a way to access the elements of an
aggregate object sequentially without exposing
its underlying representation
121/169
Catalogue
 Mediator
(273)
– Define an object that encapsulates how a set of
objects interacts. Mediator promotes loose
coupling by keeping objects from referring to
each other explicitly, and it lets you vary their
interaction independently
 Memento
(283)
– Without violating encapsulation, capture and
externalize an object's internal state so that the
object can be restored to this state later
122/169
Catalogue
 Observer
(293)
– Define a one-to-many dependency between
objects so that when one object changes state,
all its dependents are notified and updated
automatically
 Prototype
(117)
– Specify the kinds of objects to create using a
prototypical instance, and create new objects by
copying this prototype
123/169
Catalogue
 Proxy
(207)
– Provide a surrogate or placeholder for another
object to control access to it.
 Singleton
(127)
– Ensure a class only has one instance, and
provide a global point of access to it
124/169
Catalogue
 State
(305)
– Allow an object to alter its behaviour when its
internal state changes. The object will appear to
change its class
 Strategy
(315)
– Define a family of algorithms, encapsulate each
one, and make them interchangeable. Strategy
lets the algorithm vary independently from
clients that use it
125/169
Catalogue
 Template
Method (325)
– Define the skeleton of an algorithm in an
operation, deferring some steps to subclasses.
Template Method lets subclasses redefine
certain steps of an algorithm without changing
the algorithm's structure
126/169
Catalogue
 Visitor
(331)
– Represent an operation to be performed on the
elements of an object structure. Visitor lets you
define a new operation without changing the
classes of the elements on which it operates
127/169
Outline
 Definition
 Quality
 Form
 Example
 Catalogue
 Practice
 Conclusion
128/169
Practice
“The strict modeling of the real world leads
to reflect today’s realities but not necessarily
tomorrow’s. The abstractions that emerge
during design are key to making a design
flexible.”
129/169
Practice
“The description of communicating objects
and classes customized to solve general
design problem in a particular context.”
130/169
Practice
“Each design pattern lets some aspect of
system structure vary independently of other
aspects, thereby making a system more
robust to a particular kind of change.”
131/169
The following is only complementary
to reading books and practicing
132/169
Practice
 Scattered
information
– Informal text
A
suggested example rather than a
general rule
Interpreting them all...
133/169
Practice
 When
encountering complex problems?
– Numerous design patterns (is there any
complete list out there?)
– Granularity
•
•
•
•
Requirements, analysis, architecture
Design, implementation (idioms)
Refactoring, testing
…
Knowing them all...
134/169
Practice
 Iterative
induction process
– From an example to an abstraction to an
application to the abstraction to an application…
– Validation process?
Applying them all...
135/169
Practice
 Use
know categories
– Behavioural
– Creational
– Structural
 Use
the Internet
 Read
and discuss others’ code
136/169
Practice
 Use
know categories
– Behavioural
– Creational
– Structural
 Use
the Internet
 Read
and discuss others’ code
137/169
Practice
 Assess
the trade-offs
– Flexibility
– Complexity
138/169
Practice
 Assess
the trade-offs
– Flexibility
– Complexity
139/169
Practice
 Assess
the trade-offs
– Flexibility
– Complexity
 Sometimes
it is necessary to remove the
solution of a DP used in the code
140/169
Practice
 Sometimes
it is necessary to remove the
solution of a DP used in the code
141/169
Practice
“There is a natural relation between patterns
and refactorings. “Patterns are where you
want to be; refactorings are ways to get
there from somewhere else”
—Josuha Kerievsky citing
Martin Fowler, 2004
142/169
143/169
Practice
 Refactoring
to a Visitor
– Previous example of code generation from a
common AST
 Implementing
a variant of the Visitor
– padl.kernel.impl.Constituent.accept(IVisitor)
– padl.kernel.impl.Constituent.accept(IVisitor, String)
– padl.kernel.impl.Constituent.accept(Class, IVisitor,
String, boolean)
 Refactoring
away from the Visitor
– ptidej.statement.creator.classfiles.loc.BCELLOCFinder
144/169
Practice
 Refactoring
to a Visitor
– Previous example of code generation from a
common AST
 Implementing
a variant of the Visitor
– padl.kernel.impl.Constituent.accept(IVisitor)
– padl.kernel.impl.Constituent.accept(IVisitor, String)
– padl.kernel.impl.Constituent.accept(Class, IVisitor,
String, boolean)
 Refactoring
away from the Visitor
– ptidej.statement.creator.classfiles.loc.BCELLOCFinder
145/169
Practice
 Refactoring
to a Visitor
– Previous example of code generation from a
common AST
 Implementing
a variant of the Visitor
– padl.kernel.impl.Constituent.accept(IVisitor)
– padl.kernel.impl.Constituent.accept(IVisitor, String)
– padl.kernel.impl.Constituent.accept(Class, IVisitor,
String, boolean)
 Refactoring
away from the Visitor
– ptidej.statement.creator.classfiles.loc.BCELLOCFinder
146/169
Practice
 Implementing
a variant of the Visitor
– Problem when implementing the solution of the
Visitor design pattern
• Too many duplicated accept(…) methods
• Two cases for visit(…) and open(…)+close(…)
147/169
Practice
 Implementing
a variant of the Visitor
– Problem when implementing the solution of the
Visitor design pattern
• Too many duplicated accept(…) methods
• Two cases for visit(…) and open(…)+close(…)
– Solution
• Use the introspection mechanism of Java
148/169
Practice
 Implementing
a variant of the Visitor
– Problem when implementing the solution of the
Visitor design pattern
• Too many duplicated accept(…) methods
• Two cases for visit(…) and open(…)+close(…)
– Solution
• Use the introspection mechanism of Java
149/169
private boolean accept(
final java.lang.Class currentReceiver,
final IVisitor visitor,
final String methodName,
final boolean shouldRecurse) {
acceptClassName = currentReceiver.getName();
java.lang.Class argument = null;
try {
}
the introspection
mechanism of Java
 Use
Practice
argument = visitor.getClass().getClassLoader().loadClass(acceptClassName);
catch (final ClassNotFoundException e) {
visitor.unknownConstituentHandler(methodName, this);
return false;
}
try {
final Method method = visitor.getClass().getMethod(
methodName,
new java.lang.Class[] { argument });
method.invoke(visitor, new Object[] { this });
return true;
}
catch (final Exception e) {
if (e instanceof NoSuchMethodException) {
visitor.unknownConstituentHandler(methodName + '(‘ + argument.getName() + ')', this);
}
else {
throw new RuntimeException(e);
}
}
return false;
}
150/169
private boolean accept(
final java.lang.Class currentReceiver,
final IVisitor visitor,
final Method
method = visitor.getClass().getMethod(
final String methodName,
final boolean
methodName,
shouldRecurse) {
new java.lang.Class[]
{ argument });
acceptClassName = currentReceiver.getName();
java.lang.Class argument = null;
method.invoke(visitor,
new Object[] { this });
try {
}
the introspection
mechanism of Java
 Use
Practice
argument = visitor.getClass().getClassLoader().loadClass(acceptClassName);
catch (final ClassNotFoundException e) {
visitor.unknownConstituentHandler(methodName, this);
return false;
}
try {
final Method method = visitor.getClass().getMethod(
methodName,
new java.lang.Class[] { argument });
method.invoke(visitor, new Object[] { this });
return true;
}
catch (final Exception e) {
if (e instanceof NoSuchMethodException) {
visitor.unknownConstituentHandler(methodName + '(‘ + argument.getName() + ')', this);
}
else {
throw new RuntimeException(e);
}
}
return false;
}
151/169
private boolean accept(
final java.lang.Class currentReceiver,
final IVisitor visitor,
final String methodName,
final boolean shouldRecurse) {
acceptClassName = currentReceiver.getName();
java.lang.Class argument = null;
try {
}
the introspection
mechanism of Java
 Use
Practice
argument = visitor.getClass().getClassLoader().loadClass(acceptClassName);
catch (final ClassNotFoundException e) {
visitor.unknownConstituentHandler(methodName, this);
return false;
}
try {
final Method method = visitor.getClass().getMethod(
methodName,
new java.lang.Class[] { argument });
method.invoke(visitor, new Object[] { this });
return true;
}
catch (final Exception e) {
if (e instanceof NoSuchMethodException) {
visitor.unknownConstituentHandler(methodName + '(‘ + argument.getName() + ')', this);
}
else {
throw new RuntimeException(e);
}
}
return false;
}
152/169
private boolean accept(
final java.lang.Class currentReceiver,
final IVisitor visitor,
final String methodName,
final boolean shouldRecurse) {
acceptClassName = currentReceiver.getName();
java.lang.Class argument = null;
try {
argument = visitor.getClass().getClassLoader().loadClass(acceptClassName);
the introspection
mechanism of Java
}
catch (final ClassNotFoundException e) {
visitor.unknownConstituentHandler(methodName, this);
return false;
}
try {
final Method method = visitor.getClass().getMethod(
methodName,
acceptClassName = currentReceiver.getName();
new java.lang.Class[] { argument });
java.lang.Class argumentmethod.invoke(visitor,
= null;
Practice
try {
new Object[] { this });
return true;
}
catch (final Exception e) {
argument = visitor.getClass().getClassLoader().loadClass(acceptClassName);
if (e instanceof NoSuchMethodException) {
}
visitor.unknownConstituentHandler(methodName + '(‘ + argument.getName() + ')', this);
}
 Use
catch (final ClassNotFoundException
else {
e) {
throw new RuntimeException(e);
visitor.unknownConstituentHandler(methodName,
this);
}
}
return false;
}c
return false;
}
153/169
private boolean accept(
final java.lang.Class currentReceiver,
final IVisitor visitor,
final String methodName,
final boolean shouldRecurse) {
acceptClassName = currentReceiver.getName();
java.lang.Class argument = null;
try {
}
the introspection
mechanism of Java
 Use
Practice
argument = visitor.getClass().getClassLoader().loadClass(acceptClassName);
catch (final ClassNotFoundException e) {
visitor.unknownConstituentHandler(methodName, this);
return false;
}
try {
final Method method = visitor.getClass().getMethod(
methodName,
new java.lang.Class[] { argument });
method.invoke(visitor, new Object[] { this });
return true;
}
catch (final Exception e) {
if (e instanceof NoSuchMethodException) {
visitor.unknownConstituentHandler(methodName + '(‘ + argument.getName() + ')', this);
}
else {
throw new RuntimeException(e);
}
}
return false;
}
154/169
private boolean
catch (final Exception
e) { accept(
final java.lang.Class currentReceiver,
if (e instanceof NoSuchMethodException)
{
final IVisitor visitor,
final String methodName,
visitor.unknownConstituentHandler(methodName
+ '(‘ + argument.get...;
final boolean shouldRecurse) {
}
acceptClassName = currentReceiver.getName();
else {
java.lang.Class argument = null;
try {
throw new RuntimeException(e);
argument = visitor.getClass().getClassLoader().loadClass(acceptClassName);
}
the introspection
mechanism of Java
Practice
}
 Use
}
catch (final ClassNotFoundException e) {
visitor.unknownConstituentHandler(methodName, this);
return false;
}
try {
final Method method = visitor.getClass().getMethod(
methodName,
new java.lang.Class[] { argument });
method.invoke(visitor, new Object[] { this });
return true;
}
catch (final Exception e) {
if (e instanceof NoSuchMethodException) {
visitor.unknownConstituentHandler(methodName + '(‘ + argument.getName() + ')', this);
}
else {
throw new RuntimeException(e);
}
}
return false;
}
155/169
Practice
 Use
the introspection mechanism of Java
– No more duplicated accept(…) methods
– Handles cases for visit(…) and
open(…)+close(…)
– Plus, allows extension to the meta-model
without changing all existing Visitors
156/169
Practice
 Use
the introspection mechanism of Java
– No more duplicated accept(…) methods
– Handles cases for visit(…) and
open(…)+close(…)
– Plus, allows extension to the meta-model
without changing all existing Visitors
157/169
Practice
 Refactoring
to a Visitor
– Previous example of code generation from a
common AST
 Implementing
a variant of the Visitor
– padl.kernel.impl.Constituent.accept(IVisitor)
– padl.kernel.impl.Constituent.accept(IVisitor, String)
– padl.kernel.impl.Constituent.accept(Class, IVisitor,
String, boolean)
 Refactoring
away from the Visitor
– ptidej.statement.creator.classfiles.loc.BCELLOCFinder
158/169
away from the Visitor
 Refactoring
Practice
final FileInputStream fis = new FileInputStream(path);
final ClassParser parser = new ClassParser(fis, path);
final JavaClass clazz = parser.parse();
clazz.accept(this.instFinder);
fis.close();
public class BCELLOCFinder implements Visitor {
private JavaClass currentClass;
public void visitCode(final Code aCode) {
}
public void visitCodeException(final CodeException aCodeException) {
}
// 18 other empty “visit” methods
public void visitJavaClass(final JavaClass aClass) {
this.currentClass = aClass;
final Method[] methods = aClass.getMethods();
for (int i = 0; i < methods.length; i++) {
this.visitMethod(methods[i]);
}
}
// 4 more empty “visit” methods
public void visitMethod(final Method aMethod) {
Integer count = null;
final String ckey = this.adaptor.adapt(this.currentClass);
final String mkey = this.adaptor.adapt(this.currentClass, aMethod);
final Map methodMap = this.methodMap(ckey);
count = this.getLOC(code);
methodMap.put(mkey, count);
}
// 6 more empty “visit” methods
}
159/169
away from the Visitor
 Refactoring
Practice
final FileInputStream fis = new FileInputStream(path);
final ClassParser parser = new ClassParser(fis, path);
final JavaClass clazz = parser.parse();
clazz.accept(this.instFinder);
fis.close();
public class BCELLOCFinder implements Visitor {
private JavaClass currentClass;
public void visitCode(final Code aCode) {
}
public void visitCodeException(final CodeException aCodeException) {
final FileInputStream
fis = new FileInputStream(path);
}
// 18 other empty “visit” methods
final ClassParser
parser = new ClassParser(fis, path);
public void visitJavaClass(final JavaClass aClass) {
this.currentClass
final JavaClass
clazz == aClass;
parser.parse();
final Method[] methods = aClass.getMethods();
clazz.accept(this.instFinder);
for (int i = 0; i < methods.length;
fis.close(); }
i++) {
this.visitMethod(methods[i]);
}
// 4 more empty “visit” methods
public void visitMethod(final Method aMethod) {
Integer count = null;
final String ckey = this.adaptor.adapt(this.currentClass);
final String mkey = this.adaptor.adapt(this.currentClass, aMethod);
final Map methodMap = this.methodMap(ckey);
count = this.getLOC(code);
methodMap.put(mkey, count);
}
// 6 more empty “visit” methods
}
160/169
away from the Visitor
 Refactoring
Practice
final FileInputStream fis = new FileInputStream(path);
final ClassParser parser = new ClassParser(fis, path);
final JavaClass clazz = parser.parse();
clazz.accept(this.instFinder);
fis.close();
public class BCELLOCFinder implements Visitor {
private JavaClass currentClass;
public void visitCode(final Code aCode) {
}
public void visitCodeException(final CodeException aCodeException) {
}
// 18 other empty “visit” methods
public void visitJavaClass(final JavaClass aClass) {
this.currentClass = aClass;
final Method[] methods = aClass.getMethods();
for (int i = 0; i < methods.length; i++) {
this.visitMethod(methods[i]);
}
}
// 4 more empty “visit” methods
public void visitMethod(final Method aMethod) {
Integer count = null;
final String ckey = this.adaptor.adapt(this.currentClass);
final String mkey = this.adaptor.adapt(this.currentClass, aMethod);
final Map methodMap = this.methodMap(ckey);
count = this.getLOC(code);
methodMap.put(mkey, count);
}
// 6 more empty “visit” methods
}
161/169
away from the Visitor
 Refactoring
Practice
FileInputStream
fis = new FileInputStream(path);
public final
void
visitJavaClass(final
JavaClass aClass) {
final ClassParser parser = new ClassParser(fis, path);
this.currentClass
= aClass;
final JavaClass clazz = parser.parse();
clazz.accept(this.instFinder);
final
Method[] methods = aClass.getMethods();
fis.close();
for (int i = 0; i < methods.length; i++) {
this.visitMethod(methods[i]);
public class BCELLOCFinder implements Visitor {
private JavaClass currentClass;
}
public void visitCode(final Code aCode) {
}
}
public void visitCodeException(final CodeException aCodeException) {
}
// 18 other empty “visit” methods
public void visitJavaClass(final JavaClass aClass) {
this.currentClass = aClass;
final Method[] methods = aClass.getMethods();
for (int i = 0; i < methods.length; i++) {
this.visitMethod(methods[i]);
}
}
// 4 more empty “visit” methods
public void visitMethod(final Method aMethod) {
Integer count = null;
final String ckey = this.adaptor.adapt(this.currentClass);
final String mkey = this.adaptor.adapt(this.currentClass, aMethod);
final Map methodMap = this.methodMap(ckey);
count = this.getLOC(code);
methodMap.put(mkey, count);
}
// 6 more empty “visit” methods
}
162/169
Practice
 Refactoring
away from the Visitor
– 28 empty methods
– Hard-coded call the visitMethod(…)
• See this.visitMethod(methods[i]);
– JavaClasses do not contain other similar
objects, they are not a Composite object
– Unnecessary code, complexity
163/169
Practice
 Refactoring
away from the Visitor
– 28 empty methods
– Hard-coded call the visitMethod(…)
• See this.visitMethod(methods[i]);
– JavaClasses do not contain other similar
objects, they are not a Composite object
– Unnecessary code, complexity
164/169
Outline
 Definition
 Quality
 Form
 Example
 Catalogue
 Practice
 Conclusion
165/169
Conclusion
 Patterns
ease communication
 Patterns
improve regularity
and quality… even without a name…
 Patterns
avoid surprises
i.e., reinventing the wheel differently each time
 Patterns
generate architectures
166/169
Conclusion
 Identify
a recurring design problem
 Identify
a design pattern that potentially
solve the problem
 Assess
the costs and benefits of
implementing the proposed solution
– Quality and quality without a name
167/169
Conclusion
 Identify
a recurring design problem
 Identify
that the solution brings
– Unneeded flexibility
– Unnecessary complexity
 Assess
the costs and benefits of removing
the proposed solution
168/169
Conclusion
 Tools
supporting design patterns
– “GoF” book
• Lists, classifications, relationships [Gamma et al., 1996]
– CASE Tools
• Fragments [Florijn et al., 1997]
• PatternsBox and Ptidej [Albin et al., 2001]
• Refactoring tools…
– Navigation
• Tutor [Motelet, 2000]
169/169