Visitor: Just Do It Didier Verna Introduction Revisiting the Visitor: the “Just Do It” Pattern C++ L ISP Step 1: plain L ISP Step 2: brute force Step 3: first class Didier Verna Step 4: mapping Step 5: generic map State didier@lrde.epita.fr Step 6: objects http://www.lrde.epita.fr/˜didier Step 7: closures step 8: visit schemes Conclusion ACCU 2009 – Friday, April 24th 1/25
Introduction Visitor: Just Do It Necessary literature Didier Verna The G O F Book: Design Patterns, Elements of Introduction Reusable Object-Oriented Software. Gamma, Helm, C++ Johnson, Vlissides. L ISP Step 1: plain L ISP The P OSA Book: Pattern-Oriented Software Step 2: brute force Step 3: first class Architecture. Buschmann, Meunier, Rohnert, Step 4: mapping Step 5: generic map Sommerlad, Stal. State Step 6: objects Step 7: closures What is a software design pattern ? step 8: visit schemes ◮ Context (P OSA ) Conclusion ◮ Problem ◮ Solution ◮ Consequences (G O F) 2/25
A constatation Visitor: Just Do It Peter Norvig (Object World, 1996) Didier Verna About the G O F book: Introduction 16 of 23 patterns are either invisible or simpler C++ [...] in Dylan or Lisp L ISP Step 1: plain L ISP Step 2: brute force Step 3: first class Peter Norvig is right , so Step 4: mapping Step 5: generic map ◮ is the G O F book (70%) wrong ? State ◮ are patterns (70%) useless ? Step 6: objects Step 7: closures step 8: visit schemes Conclusion 3/25
Some clues from the G O F book itself Visitor: Just Do It Although design patterns describe Didier Verna object-oriented designs, they are based on Introduction practical solutions that have been implemented in C++ mainstream object-oriented programming L ISP languages [. . . ] Step 1: plain L ISP Step 2: brute force Step 3: first class Step 4: mapping Step 5: generic map Similarly, some of our patterns are supported State Step 6: objects directly by the less common object-oriented Step 7: closures step 8: visit schemes languages. Conclusion ◮ That’s what people usually miss 4/25
Patterns descriptions / organizations Visitor: G O F: Creational, Structural, Behavioral Just Do It ◮ usage-oriented Didier Verna P OSA : Architectural, Design, Idioms Introduction ◮ abstraction-oriented C++ L ISP Step 1: plain L ISP Idioms according to P OSA Step 2: brute force Step 3: first class An idiom is a low-level pattern specific to a Step 4: mapping Step 5: generic map programming language. An idiom describes how to State implement particular aspects of components or the Step 6: objects Step 7: closures relationships between them using the features of step 8: visit schemes Conclusion the given language. [. . . ] They address aspects of both design and implementation. ◮ G O F’s design patterns are closer to P OSA ’s idioms 5/25
The risk: blind pattern application Visitor: Just Do It P OSA ’s advice: Didier Verna [. . . ] sometimes, an idiom that is useful for one Introduction programming language does not make sense into C++ another. L ISP Step 1: plain L ISP Step 2: brute force Step 3: first class G O F’s Visitor example: Step 4: mapping Step 5: generic map Use the Visitor pattern when [. . . ] many distinct State and unrelated operations need to be performed on Step 6: objects Step 7: closures step 8: visit schemes objects in an object structure, and you want to Conclusion avoid “polluting” their classes with these operations. ◮ But who said operations belong to classes ? 6/25
Table of contents Visitor: Just Do It Visiting in C++ 1 Didier Verna Introduction Visiting in L ISP 2 C++ Step 1: plain L ISP L ISP Step 2: brute force visiting Step 1: plain L ISP Step 2: brute force Step 3: first class generic functions Step 3: first class Step 4: mapping Step 4: mapping Step 5: generic map State Step 5: generic mapping Step 6: objects Step 7: closures step 8: visit schemes Visiting with state 3 Conclusion Step 6: objects Step 7: lexical closures Step 8: dynamic visitation schemes 7/25
Visiting in C++ Visitor: Just Do It Problems: Didier Verna Original hierarchy R/O Introduction Abstract the visiting process away C++ L ISP Step 1: plain L ISP Solution: Step 2: brute force Step 3: first class 1 Equip original hierarchy for visits Step 4: mapping Step 5: generic map ◮ A Visitable abstract class State ◮ An accept method in each visitable component Step 6: objects Step 7: closures 2 Write independent visitors step 8: visit schemes Conclusion ◮ A Visitor abstract class ◮ A visit method for each visitable component 9/25
Step 1: plain L ISP Visitor: Just Do It Classes Didier Verna ( defclass class ( superclass1 superclass2 . . . ) Introduction ( ( s l o t : i n i t f o r m <form> : i n i t a r g : s l o t : accessor s l o t ) . . . ) C++ options . . . ) L ISP ( make − instance ’ class : s l o t <value > . . . ) Step 1: plain L ISP Step 2: brute force Step 3: first class Step 4: mapping Generic functions, methods Step 5: generic map State ( defgeneric func ( arg1 arg2 . . . ) Step 6: objects ( : method ( ( arg1 class1 ) arg2 . . . ) Step 7: closures body ) step 8: visit schemes options . . . ) Conclusion ( defmethod func ( ( arg1 class1 ) arg2 . . . ) body ) ◮ Methods are outside the classes (ordinary function calls) ◮ Multiple dispatch (multi-methods) 11/25
Summary of step 1 Visitor: 1 Original hierarchy untouched Just Do It ◮ Generic function model (outside the classes) Didier Verna 2 Abstract the visiting process away Introduction ◮ Still needs to be done C++ L ISP Step 1: plain L ISP Step 2: brute force Step 3: first class Step 4: mapping Step 5: generic map State Step 6: objects Step 7: closures step 8: visit schemes Conclusion 12/25
Step 2: brute force visiting Visitor: Abstract the visiting process away Just Do It ◮ OK: the accept generic function Didier Verna Introduction But what’s wrong with this picture ? C++ L ISP obj visitor Step 1: plain L ISP Step 2: brute force Step 3: first class Step 4: mapping Step 5: generic map State visit accept Step 6: objects Step 7: closures step 8: visit schemes obj visitor obj visitor Conclusion obj visitor ... ... ◮ One indirection too many 13/25
Step 3: first class (generic) functions Visitor: Just Do It Notion of first class / order Didier Verna (Christopher Strachey, 1916–1975) storage (in variables) Introduction C++ aggregation (in structures) L ISP argument (to functions) Step 1: plain L ISP Step 2: brute force Step 3: first class return value (from functions) Step 4: mapping Step 5: generic map anonymous manipulation State Step 6: objects dynamic creation Step 7: closures step 8: visit schemes . . . Conclusion ◮ Generic functions are first class objects in L ISP 14/25
The better picture Visitor: Just Do It obj Didier Verna Introduction C++ L ISP visitor accept Step 1: plain L ISP Step 2: brute force obj Step 3: first class obj Step 4: mapping Step 5: generic map obj State ... Step 6: objects Step 7: closures step 8: visit schemes Conclusion Retrieving function objects in L ISP ( function func ) ; ; => #<FUNCTION FUNC> # ’ func ; ; => #<FUNCTION FUNC> 15/25
Step 4: mapping Visitor: Prominent concept in functional programming Just Do It ◮ Along with folding (reduction), filtering etc. Didier Verna Thanks to first class functions Introduction ◮ Argument passing C++ L ISP Step 1: plain L ISP Typical mapping example Step 2: brute force Step 3: first class Step 4: mapping ( mapcar # ’ string − upcase ’ ( "foo" "bar" "baz" ) ) Step 5: generic map ; ; => ( "FOO" "BAR" "BAZ" ) State Step 6: objects ◮ “visiting” is a form of structural mapping Step 7: closures step 8: visit schemes Conclusion 16/25
Step 5: generic mapping Visitor: Having to specialize mapobject is boring Just Do It ◮ Mapping over lists, vectors, arrays, even class slots Didier Verna should be written only once Introduction C++ The C LOS Meta-Object Protocol ( MOP ) L ISP Step 1: plain L ISP C LOS itself is object-oriented Step 2: brute force Step 3: first class ◮ The C LOS MOP : a de facto implementation standard Step 4: mapping Step 5: generic map ◮ The C LOS components (classes etc. ) are State (meta-)objects of some (meta-)classes Step 6: objects Step 7: closures step 8: visit schemes ◮ We have reflexive (introspective) access to class slots Conclusion 17/25
Step 6: objects Visitor: Just Do It How about a component counter visitor ? Didier Verna C++: left as an exercise. . . Introduction L ISP : how does that fit with first class functions ? C++ ◮ Global state (yuck !) L ISP ◮ Behavior + state = objects ! Step 1: plain L ISP Step 2: brute force Step 3: first class So we’re back to visitor objects ? Step 4: mapping Step 5: generic map State ◮ There has got to be a better way. . . Step 6: objects Step 7: closures step 8: visit schemes Conclusion 19/25
Recommend
More recommend