ddbf296bf30e52c97032ea69ee5a01ba.ppt
- Количество слайдов: 42
Selective Open Recursion Modular Reasoning about Components and Inheritance Jonathan Aldrich Carnegie Mellon University Kevin Donnelly Boston University
Outline The Fragile Base Class Problem n Selective Open Recursion n Implementation & Analysis n Discussion n
Inheritance and Information Hiding n Parnas’ advice: n Modularize a system to hide information that may change
Inheritance and Information Hiding n Parnas’ advice: n n Modularize a system to hide information that may change Research question n How to hide information in component-based systems with inheritance?
A Challenge: Open Recursion n Objects can make self-calls to their own methods
A Challenge: Open Recursion n n Objects can make self-calls to their own methods Open Recursion n Self-calls are dynamically dispatched n n I. e. , target of call is “open” and can be overridden Beneficial in “template method” design patterns
Open Recursion class Window { void draw() { // draw background this. draw. Foreground(); } void draw. Foreground() { … } } class My. Window { void draw() { super. draw(); } void draw. Foreground() { super. draw. Foreground(); . . . } Window draw. Fore
Open Recursion Window class Window { void draw() { // draw background this. draw. Foreground(); } void draw. Foreground() { … } } class My. Window { void draw() { super. draw(); } void draw. Foreground() { super. draw. Foreground(); . . . } draw. Fore Window My. Window draw. Fore
Hook Methods n Hook methods n n n Called by this when some event occurs Intended as extension point for subclasses Open recursion is necessary
Hook Methods n Hook methods n n Called by this when some event occurs Intended as extension point for subclasses Open recursion is necessary Other methods n n n Perform some task May be overridden, but has no “event” semantics Open recursion unnecessary n n At best, minor convenience Has potential to cause the Fragile Base Class Problem
The Fragile Base Class Problem class Counting. Set extends Set { private int count; void add(Object elem) { super. add(elem); count++; } void add. All(Collection c){ super. add. All(c); count+=c. size(); } int size() { return count; } // other functions } Set Counting. Set add. All add
The Fragile Base Class Problem class Counting. Set extends Set { private int count; void add(Object elem) { super. add(elem); count++; } void add. All(Collection c){ super. add. All(c); count+=c. size(); } int size() { return count; } // other functions } Set Counting. Set add. All add Implicit assumption: Set. add. All does not call Set. add If this assumption is violated (or changed), Counting. Set breaks
The Fragile Base Class Problem n Definition (for this instance of FBC) n A class may depend on the calling patterns of a superclass, and break if these are changed
Two Solutions to the FBC n Document open recursion [Kiczales & Lamping, Steyaert et al. , Ruby & Leavens] n n Exposes information, rather than hiding it Prohibits natural changes to superclass Use forwarding to avoid open recursion [Bloch, Szyperski] Gives up benefits of open recursion Can we get the benefits of open recursion without the reasoning costs?
Two Solutions to the FBC n Document open recursion [Kiczales & Lamping, Steyaert et al. , Ruby & Leavens] n n n Exposes information, rather than hiding it Prohibits natural changes to superclass Use forwarding to avoid open recursion [Bloch, Szyperski] n Gives up benefits of open recursion Can we get the benefits of open recursion without the reasoning costs?
Two Solutions to the FBC n Document open recursion [Kiczales & Lamping, Steyaert et al. , Ruby & Leavens] n n n Exposes information, rather than hiding it Prohibits natural changes to superclass Use forwarding to avoid open recursion [Bloch, Szyperski] n n Gives up benefits of open recursion Can we get the benefits of open recursion without the reasoning costs?
Outline The Fragile Base Class Problem n Selective Open Recursion n Implementation & Analysis n Discussion n
Selective Open Recursion Use open recursion only where necessary n Hook methods n Use open modifier on method n n Expresses “hook method” intent All calls to open methods dispatched dynamically n Just as in Java today
Selective Open Recursion Use open recursion only where necessary n Hook methods n Use open modifier on method n n All calls to open methods dispatched dynamically n n Expresses “hook method” intent Just as in Java today Other methods n Calls to non-open methods on this dispatched statically n n n The only change vs. Java Hides internal calling patterns from subclasses Other calls dispatched dynamically n open ≠ virtual
Selective Open Recursion Examples class Set { void add(Object o) { // adds an element } void add. All(Collection c){ foreach (Object o in c) this. add(o); } } add is not open, so subclass cannot intercept and depend on the call. Set can change without affecting subclasses.
Selective Open Recursion Examples class Set { void add(Object o) { // adds an element } void add. All(Collection c){ foreach (Object o in c) this. add(o); } } add is not open, so subclass cannot intercept and depend on the call. Set can change without affecting subclasses. class Set { // invoked for each add op. open void add(Object o) { // adds an element } void add. All(Collection c){ foreach (Object o in c) this. add(o); } } add is open, indicating the developer’s intent to expose this method as a semantic event to subclasses. Any changes to class Set must preserve these semantics.
Design Principles n Non-open as default n Only use open recursion when explicitly intended
Design Principles n Non-open as default n n Only use open recursion when explicitly intended Annotate the method, not the call n Design intent is attached to operation
Do you have to change the language? n Coding guidelines n n Never call a public method on this Hook methods should be protected Non-hook, protected methods should be final Not our idea n n Suggested by Ruby & Leavens Used extensively in JDK libraries
Do you have to change the language? n Coding guidelines n n Not our idea n n n Never call a public method on this Hook methods should be protected Non-hook, protected methods should be final Suggested by Ruby & Leavens Used extensively in JDK libraries However— n n This solution relies on programmer discipline Language integration provides automated checking
Outline The Fragile Base Class Problem n Selective Open Recursion n Implementation & Analysis n Future work and Conclusion n
Implementation in Java n Extension to Barat compiler n n Rewrite calls to non-open methods on this n n Bokowski & Spiegel Call a final method with the implementation for the current class Available at http: //www. archjava. org/
Open Recursion Inference n Analysis to compute open annotations n Method m in class C must be open if: n n n Method m’ in class C’ <= C calls this. m Class C’’ <= C’ overrides m Class C’’ inherits or super-calls C’. m’
Open Recursion Inference n Analysis to compute open annotations n Method m in class C must be open if: n n Method m’ in class C’ <= C calls this. m Class C’’ <= C’ overrides m Class C’’ inherits or super-calls C’. m’ Results may be imperfect n Assumes whole program is available n n Misses open methods that are not overridden May mark methods open that should be refactored to be non-open
Experiments n Ran open recursion inference n java. * packages in JDK 1. 4. 2 n Except java. nio, java. sql (see paper)
Experiments n Ran open recursion inference n java. * packages in JDK 1. 4. 2 n n Except java. nio, java. sql (see paper) Hypotheses n n Open recursion is rarely needed Selective open recursion enables more optimization
Frequency of Open Recursion n n 9897 methods in our portion of stdlib 246 (2. 5%) of methods were inferred open
Frequency of Open Recursion n n 9897 methods in our portion of stdlib 246 (2. 5%) of methods were inferred open n Maybe the stdlib doesn’t use inheritance n n 1394 of these methods are overridden Only 18% of these are open Open recursion is rarely needed Thus making it selective may enable substantial information hiding
Frequency of Open Recursion n n 9897 methods in our portion of stdlib 246 (2. 5%) of methods were inferred open n Maybe the stdlib doesn’t use inheritance n n n 1394 of these methods are overridden Only 18% of these are open Open recursion is rarely needed n Thus making it selective may enable substantial information hiding
Optimization Potential 22339 calls in our portion of stdlib n 6852 self-calls n n 716 to open methods n n Must be dynamically dispatched 6136 to non-open methods n n Can be inlined in our proposal (27% of total calls) Inlining in Java would require private, final, or whole-program analysis
Outline The Fragile Base Class Problem n Selective Open Recursion n Implementation & Analysis n Future Work and Conclusion n
Future Work: Application to Formal Reasoning n Formalizing as Featherweight Java + module system
Future Work: Application to Formal Reasoning n n Formalizing as Featherweight Java + module system Goal: bisimulation-based proof technique for showing contextual equivalence of modules in the presence of inheritance
Future Work: Application to Formal Reasoning n n n Formalizing as Featherweight Java + module system Goal: bisimulation-based proof technique for showing contextual equivalence of modules in the presence of inheritance Use selective open recursion and other techniques to provide more information hiding n i. e. prove more programs equivalent
Conclusion n Open Recursion complicates reasoning n n rarely used in practice Selective open recursion n n retains benefits of open recursion where needed avoids fragile base class problem can be efficiently inferred may allow more optimization and reasoning
Open Recursion class Set { void add(Object elem) { // adds an element } void add. All(Collection c) { foreach (Object o in c) this. add(o) }. . . class Counting. Set extends Set { private int count; void add(Object elem) { super. add(elem); count++; } void add. All(Collection c){ super. add. All(c); count+=c. size(); } int size() { return count; } // other functions Calls to this are dispatched to subclass Thus subclass can tell exactly when each method is called }
ddbf296bf30e52c97032ea69ee5a01ba.ppt