289f5ac1fbaf3646ed2b6db5d64d5ead.ppt
- Количество слайдов: 50
Modular OOP with Units and Mixins Paper by Finder/Flatt Presentation by Dan Licata
Scheme in Fixnum Minutes > 4 4 >(define x 4) > x 4
Scheme in Fixnum Minutes >(+ 4 4) 8 > (+ (+ 4 4)) 20
Scheme in Fixnum Minutes > 5 5
Scheme in Fixnum Minutes > (define add 2 (lambda (x y) (+ x y))) > (add 2 4 5) 9 > add 2 <#procedure. . . >
Scheme in Fixnum Minutes (define add 2 (lambda (x y) (+ x y)) > (add 2 4 5) 9 (define mk-add (lambda (x) (lambda(y) (+ x y))))
Scheme in Fixnum Minutes > (mk-add 4) #<procedure> > (define add 4 (mk-add 4)) > (add 4 5) 1 (define mk-add (lambda (x) (lambda(y) (+ x y))))
Reading a Paper 1. What problem are they solving? 2. How do they solve it? 3. Why should I care?
Reading a Paper 1. What problem are they solving? 2. How do they solve it? 3. Why should I care?
Extensibility! Same story as last time: ©Functional programming => easy to add a new operation ©OOP => easy to add a new datatype variant What would the ideal be?
Extensibility Shape Clients
Add a New Variant Shape Clients Existing clients should not need to be modified!
Add a New Variant Shape Clients New Clients
Add a New Operation Shape Clients New Clients
Presumptions in the Picture © Add a new operation by subclassing © If the change gets used behind the original interface, unmodified clients should see it In traditional OOP, do they?
Define Original Datatype (define Shape (interface () draw) (define Rectangle (class* null (Shape) (width height) (public [draw (lambda (window x y) …))]))
Define Original Datatype (define Circle (class* null (Shape) (radius) (public [draw (lambda (window x y). . . ))]))
Define Original Datatype (define display-shape (lambda (shape) (let ([window. . . ]) (send shape draw window 0 0))))
Create A Client (display-shape (make-object Rectangle 50 100))
Add a New Variant (define Union (class* null (Shape) (left right) (public [draw (lambda (window x y). . . ))]))
Add a Client that Uses It (display-shape (make-object Union (make-object Rectangle 10 30) (make-object Circle 20)))
Add a New Operation (define BB-Shape (interface (shape) bounding-box) (define BB-Rectangle (class* Rectangle (BB-Shape) (w h) (public [bounding-box (lambda () (make-object BB 0 0 w h))]). . . ))
Add a New Operation (define display-shape (lambda (shape) (let ([bb (send shape bounding-box)] (let ([window. . . ] [x. . . ] [y. . . ]) (send shape draw window x y)))))
Do the Old Clients Use It? (display-shape (make-object Rectangle 50 100)) (display-shape (make-object Union (make-object Rectangle 10 30) (make-object Circle 20)))
Do the Old Clients Use It? (display-shape (make-object Rectangle 50 100)) (display-shape (make-object Union (make-object Rectangle 10 30) (make-object Circle 20)))
Potential Solution © Always program using Abstract Factory © Downsides: ©Requires forethought ©Contorts the code How can we add language support?
Reading a Paper 1. What problem are they solving? 2. How do they solve it? 3. Why should I care?
Fortune-Cookie Wisdom Every problem in CS can be solved by adding a layer of indirection. ©Layers: ©Mixins ©Units
Mixin Class that is parameterized by its superclass (define BB-Rect (class* Rectangle. . . )) (define BB-Rect (lambda (Rect) (class* Rect. . . )))
Unit Module that is ©Separately compilable ©Black-box reusable (has an interface) ©Multiply instantiable ©Dynamically linkable
Define Original Datatype (define Basic-Shapes (unit (import) (export Shape Rectangle Circle) (define Shape (interface. . . )) (define Rectangle (class*. . . )) (define Circle (class*. . . ))))
Define Original Datatype (define GUI (unit (import Shape) (export display-shape) (define display-shape. . . )))
Create a Client (define Picture (unit (import Shape Rectangle Circle display-shape) (export) (display-shape (make-object Rectangle 50 100))))
Link Them All Together (define Basic-Program (compound-unit (import) (link [S (Basic-Shapes)] [G (GUI (S Shape))] [P (Picture (S Rectangle) (S Circle) (G display-shape))]) (export)))
And Run It (invoke-unit Basic-Program)
Add a New Variant (define Union-Shape (unit (import Shape) (export Union) (define Union (class*. . . ))))
Package It Up with the Others (define Basic+Union-Shapes (compound-unit (import) (link [S (Basic-Shapes)] [US (Union-Shape (S Shape))]) (export (S Shape) (S Rectangle) (S Circle) (US Union))))
Add a Client that Uses It (define Union-Picture (unit (import Rectangle Circle Union display-shape) (export) (display-shape (make-object Union (make-object Rectangle 10 30) (make-object Circle 20))))
Link Them All Together (define Union-Program (compound-unit (import) (link [S (Basic+Union-Shapes)] [G (GUI (S Shape))] [P (Picture (S Rectangle) (S Circle) (G display-shape))] [UP (Union-Picture (S Rectangle) (S Circle) (S Union) (G display-shape))]) (export))) Picture is unchanged!
Add a New Operation (define BB-Shapes (unit (import Shape Rectangle Implicit mixin! Circle Union) (export BB-Shape BB-Rectangle BB-Circle BB-Union) (define BB-Shape (interface. . . )) (define BB-Rectangle (class* Rectangle. . . )) (define BB-Circle (class* Circle. . . ) (define BB-Union (class* Union. . . ) (define BB. . . )))
Package It Up with the Others (define Basic+Union+BB-Shapes (compound-unit (import) (link [S (Basic+Union-Shapes)] [BS (BB-Shapes (S Shape) (S Rectangle) (S Circle) (S Union))]) (export (S Shape) (BS BB-Shape) (BS BB) (BS (BB-Rectangle)). . . ))) Rename to preserve substitutability!
Use the New Functionality (define BB-GUI (unit (import BB-Shape BB) (export display-shape) (define display-shape. . . )))
Link Them All Together Picture and Union. Picture are unchanged! (define BB-Program (compound-unit (import) (link [S (Basic+Union+BB-Shapes)] [BG (BB-GUI (S BB-Shape) (S BB))] [P (Picture (S Rectangle) (S Circle) (BG display-shape))] [UP (Union-Picture (S Rectangle) (S Circle) (S Union) (BG display-shape))]) (export)))
Reading a Paper 1. What problem are they solving? 2. How do they solve it? 3. Why should I care?
Solves Extensibility Problem © You can add both new variants and new operations without modifying existing clients © Unmodified clients may use the new operation © Or, they may not
Synergy Between Modules and Classes © Modules are good for: ©Separate development ©Linking © Classes are good for: ©Extensible datatypes ©Selective reuse © Language should have both!
Separate Definitions and Linking © Module: externally link dependencies © Classs: externally specify superclass In both, allow substitution of subtypes!
In A Statically-Typed Setting © Would this work for Java? © Would this work for ML-with-objects?
Bigger Picture © Do you buy it? © How could it be improved?
289f5ac1fbaf3646ed2b6db5d64d5ead.ppt