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(dogname) {}} class Kennel { Dog* dog; string name; } if (&kennel != this) { thisdog = new Dog(kennel.dog); thisname = 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(dogname) {}} class Kennel { Dog* dog; string name; } if (&kennel != this) { thisdog = new Dog(kennel.dog); thisname = 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(dogname) {}} class Kennel { Dog* dog; string name; } if (&kennel != this) { thisdog = new Dog(kennel.dog); thisname = 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(dogname) {}} class Kennel { Dog* dog; string name; } if (&kennel != this) { thisdog = new Dog(kennel.dog); thisname = 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(dogname) {}} class Kennel { Dog* dog; string name; } if (&kennel != this) { thisdog = new Dog(kennel.dog); thisname = 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(dogname) {}} class Kennel { Dog* dog; string name; } if (&kennel != this) { thisdog = new Dog(kennel.dog); thisname = 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(dogname) {}} class Kennel { Dog* dog; string name; } if (&kennel != this) { thisdog = new Dog(kennel.dog); thisname = 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(dogname) {}} class Kennel { Dog* dog; string name; } if (&kennel != this) { thisdog = new Dog(kennel.dog); thisname = 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
© Copyright 2024