Upload
sanjay-jha
View
720
Download
0
Embed Size (px)
Citation preview
Adaptive Programming (AP):Strategies for making friends
Karl Lieberherr
Northeastern University, Boston
Demeter Research Group
faculty: Lorenz, Mezini, Patt-Shamir, Palsberg, Wand
Overview• What is AP? Where does it come from?
• Law of Demeter (talk only to your friends) and how to follow it adaptively.
• Traversal strategies and how they create friends
• Compiling adaptive programs
• Evolutionary use of AP with current lang.
• Connections to polytypic programming
Connection to Components
• Mira Mezini’s talk on APPC
• An evolutionary use of AP: AP as a solution to component composition problems
• AP ideas useful to working with components with and without tool support: this is practical stuff
What is AP? Some two-line phrases
• Structure-shy or schema-shy programming
• Programming with “regular expressions” over graphs
• Programming with traversal strategies
• Succinct traversal-visitor-style programming
• Programming in terms of graph constraints on data types, not data types themselves
12/04/23 AOOP / Demeter 5
What is AP? Special case of AOP
ordinary programstructure-shyfunctionality
structure
navigation
adaptive program
Classdictionary/graph
Traversalstrategies
Visitors
…
What is AP?
• Aspect-Oriented Programming (AOP) where the components/connectors/aspects are written in terms of graphs and traversal strategies
Why traversal strategies?
• Law of Demeter
• A style rule for building systems
• See also upcoming book by Krzysztof Czarnecki / Ulrich Eisenegger on Generative Programming
12/04/23 AOOP / Demeter 8
Why Traversal Strategies?
• Law of Demeter: a method should talk only to its friends: arguments and part objects (computed or stored) and newly created objects
• Dilemma:•Small method problem of OO (if followed) or•Unmaintainable code (if not followed)
•Traversal strategies are the solution to this dilemma
Law of Demeter Principle
• Each unit should only use a limited set of other units: only units “closely” related to the current unit.
• “Each unit should only talk to its friends.” “Don’t talk to strangers.”
• Main Motivation: Control information overload. We can only keep a limited set of items in short-term memory.
Law of DemeterFRIENDS
Application to OO
• Unit = method– closely related =
• methods of class of this/self and other argument classes
• methods of immediate part classes (classes that are return types of methods of class of this/self)
• In the following we talk about this application of the Law of Demeter Principle to OO
The Law of Demeter (cont.)Violation of the Law
class A {public: void m(); P p(); B b; };
class B {public: C c; };
class C {public: void foo(); };
class P {public: Q q(); };
class Q {public: void bar(); };
void A::m() {
this.b.c.foo(); this.p().q().bar();}
Violations: Dataflow Diagram
AB C
1:b 2:c
P Q
3:p()
4:q()
foo()
bar()
m
Rumbaugh and the Law of Demeter
Quote: Avoid traversing multiple links or methods. A method should have limited knowledge of an object model. A method must be able to traverse links to obtain its neighbors and must be able to call operations on them, but it should not traverse a second link from the neighbor to a third class.
Agreement that LoD Good Idea
• How to follow LoD: good solutions exist but they are not widely known. Two approaches to following LoD:– OO approach: many programmers do this– Adaptive approaches
• Traversal support
• APPC
• Demeter/Java
• Demeter/C++
Adaptive Following of LoD
void A::m() {
(C)
Traversal.long_get(this,”A->C”).foo();
(Q)
Traversal.long_get(this,”A->Q”).bar();}
void A::m() {
this.b.c.foo(); this.p().q().bar();} // violation
OO Following of LoD
AB C
1:b c
P Q3:p() q()
foo()
bar()
m
2:foo2()
4:bar2()
foo2
bar2
What if your friends are far away?
• You pay them to travel to you or you send an agent to them to collect the information you need.– Approximate Directions (AP solution): You
give them or your agent directions about what kind of information to collect but you don’t care about accidental details of the travel.
– Detailed Directions: You give them or your agent detailed travel directions.
Adaptive Following LoDFRIENDS
S
A
b
C
X
a: S -> Ab: S -> B c: S -> X -> C
a
c
What is a traversal strategy
• A graph (defines a “regular expression” for data navigation)
• An edge (A,B) in the graph means: A any* B
• any means: any edge or node
12/04/23 AOOP / Demeter 21
Collaborating Classes
BusRoute BusStopList
BusStopBusList
Bus PersonList
Person
passengers
buses
busStops
waiting
0..*
0..*
0..*
find all persons waiting at any bus stop on a bus route
OO solution:one methodfor each redclass
12/04/23 AOOP / Demeter 22
Traversal Strategy
BusRoute BusStopList
BusStopBusList
Bus PersonList
Person
passengers
buses
busStops
waiting
0..*
0..*
0..*
first try: from BusRoute to Person
find all persons waiting at any bus stop on a bus route
12/04/23 AOOP / Demeter 23
Traversal Strategy
BusRoute BusStopList
BusStopBusList
Bus PersonList
Person
passengers
buses
busStops
waiting
0..*
0..*
0..*
from BusRoute through BusStop to Person
find all persons waiting at any bus stop on a bus route
12/04/23 AOOP / Demeter 24
Robustness of Strategy
BusRoute BusStopList
BusStopBusList
Bus PersonList
Person
passengers
busesbusStops
waiting
0..*
0..*
0..*
from BusRoute through BusStop to Person
VillageList
Village
villages
0..*
find all persons waiting at any bus stop on a bus route
12/04/23 AOOP / Demeter 25
Even better: interface class graph
BusRoute BusStop
Bus Personpassengers
buses
busStops
waiting
0..*
0..*
0..*
find all persons waiting at any bus stop on a bus route
0..*
from BusRoute through BusStop to Person
12/04/23 AOOP / Demeter 26
Map interface class graph to application class graph
BusRoute BusStopList
BusStopBusList
Bus PersonList
Person
passengers
busesbusStops
waiting
0..*
0..*
0..*
from BusRoute through BusStop to Person
VillageList
Village
villages
0..*
edge -> path
12/04/23 AOOP / Demeter 27
Map interface class graph to application class graph
BusRoute BusStopList
BusStop
busStops 0..*
from BusRoute through BusStop to Person
VillageList
Village
villages
0..*
edge -> path
BusRoute BusStopbusStops
0..*edge
path
12/04/23 AOP/Demeter 28
Adaptive Programming
Strategy
Graphs
Object Graphs
define family of
Class Graphs
are use-case basedabstractions of
12/04/23 AOP/Demeter 29
Adaptive Programming
Strategy
Graphs
Object Graphs
define traversals of
12/04/23 AOP/Demeter 30
Adaptive Programming
Strategy Graphs
Visitors
guide andinform
12/04/23 AOP/Demeter 31
Strategy Graphs
Nodes: positive information: Mark corner
stones in class diagram: Overall topology
of collaborating classes.
from BusRoute
through BusStop
to Person
BusRoute BusStop Person
Traversal strategies create friends
• Class Traversal is an intermediate class between classes that need to communicate
Traversal.long_get(Object o, Strategy s)
Some nodes are not friends for accidental reasons
• Non-friend classes exist for other reasons
• Many non-friend classes are filtered out by traversal strategies
• Ideal class graph: all are friends, even “far” away classes
Adaptive Following LoD: Key idea
• Introduce an ideal class graph
• Write current behavior in terms of ideal class graph
• Map ideal class graph flexibly into concrete class graph using traversal strategies
A = s A
B BC C
D DE E
F=t F
G
S
S is a strategy for G
Important is concept of compatibility
• A graph G is compatible with a graph S, if S is a connected subgraph of the transitive closure of G. (G: concrete graph, S: abstract graph).
• Different forms of compatibility: refinement, strong refinement
A A
B BC C
D DE E
F F
G1
G2
G1 compatible G2
Compatible: connectivity of G2 is in G1
A A
B BC C
D DE E
F F
G1
G2
G1 strong refinement G2
refinement: connectivity of G2
is in “pure” form in G1 and G1 contains nonew connections in terms ofnodes of G2
A A
B BC C
D DE E
F F
G1
G2
G1 refinement G2
refinement: connectivity of G2
is in “pure” form in G1
Allows extra connectivity.
C1
C2 C3
C4
C5
P1
P2
P3
C1
C3
C2
C4
APPL1APPLn
Design Goal: Adaptiveness
C1
C2 C3
C4C5
P1
P2
P3
APPL1
APPL1
C2 C3
C4C5
C1
Design Goal: Adaptiveness
Compiling Adaptive Programs
• Palsberg/Xiao/Lieberherr: TOPLAS ‘95
• Palsberg/Patt-Shamir/Lieberherr: Science of Computer Programming 1997
• Lieberherr/Patt-Shamir: Strategy graphs, 1997 NU TR
• Lieberherr/Patt-Shamir: Dagstuhl ‘98 Workshop on Generic Programming (LNCS)
Short-cutstrategy:{A -> B B -> C}
A
B
C
X
0..1
x
x
b
c
A B C
strategy graph with name map
c
Incorrect traversal code:class A {void t(){x.t();}}class X {void t(){if (b!==null)b.t();c.t();}}class B {void t(){x.t();}}class C {void t(){}}
Correct traversal code:class A {void t(){x.t();}}class X {void t(){if (b!==null)b.t2();} void t2(){if (b!==null)b.t2();c.t2();}}class B {void t2(){x.t2();}}class C {void t2(){}}
1 1 3
Short-cutstrategy:{A -> B B -> C}
A
X
x
B
C
X
0..1
x
b
c
start set
finish set
b
A( <x> X( <b> B( <x> X( <c> C())) <c> C()))
Object graphTraversal graph
Modulo some details: Traversal graph = Cross-product of NFAs
Short-cutstrategy:{A -> B B -> C}
A
X
x
B
C
X
0..1
x
b
c
start set
finish set
b
A( <x> X( <b> B( <x> X( <c> C())) <c> C()))
Object graphTraversal graph
Used for token set and currently active object
Short-cutstrategy:{A -> B B -> C}
A
X
x
B
C
X
0..1
x
b
c
start set
finish set
b
A( <x> X( <b> B( <x> X( <c> C())) <c> C()))
Object graphTraversal graph
Used for token set and currently active object
Short-cutstrategy:{A -> B B -> C}
A
X
x
B
C
X
0..1
x
b
c
start set
finish set
b
A( <x> X( <b> B( <x> X( <c> C())) <c> C()))
Object graphTraversal graph
Used for token set and currently active object
Short-cutstrategy:{A -> B B -> C}
A
X
x
B
C
X
0..1
x
b
c
start set
finish set
b
A( <x> X( <b> B( <x> X( <c> C())) <c> C()))
Object graphTraversal graph
Used for token set and currently active object
Short-cutstrategy:{A -> B B -> C}
A
X
x
B
C
X
0..1
x
b
c
start set
finish set
b
A( <x> X( <b> B( <x> X( <c> C())) <c> C()))
Object graphTraversal graph
Used for token set and currently active object
Short-cutstrategy:{A -> B B -> C}
A
X
x
B
C
X
0..1
x
b
c
start set
finish set
b
A( <x> X( <b> B( <x> X( <c> C())) <c> C()))
Object graphTraversal graph
Used for token set and currently active object
After going back to X
Modulo some details: SIMULATION OF AN NFA
Main Theorem (correctness)
• Let SS be a strategy, let G be a class graph, let N be a name map, and let B be a constraint map. Let TG be the traversal graph generated by the Traversal Graph Algorithm, and let Ts and Tf be the start and finish sets, respectively.
Main Theorem (cont.)
• Let O be an object tree and let o be an object in O. Let H be the sequence of nodes visited when o.Traverse is called with argument Ts , guided by TG. Then traversing
O from o guided by PathSet[SS,G,N,B] produces H.
Complexity of algorithm
• Traversal Graph Alg.: All steps run in time linear in the size of their input and output. Size of traversal graph: O(|S|2 |G| d0) where d0 is the maximal number of edges outgoing from a node in the class graph.
• Traverse: How many tokens? Size of argument T is bounded by the number of edges in strategy graph.
Traversal Support for Java: class Traversal
• static Object long_get(Object o, Strategy s);
• static Iteration long_collect(Object o, Strategy s);
• static Object traverse(Object o, Strategy s, Visitor v[]);
Traversal Support for Java
• static X long_get(Object o, Strategy s);– starting at object o, traverse down following s
and return target object of s– s must have a single target and s must specify
unique path
Traversal Support for Java
• static Iteration long_collect(Object o, Strategy s);– starting at object o traverse following s and
return the collection of target objects of s.
Traversal Support for Java
• static Object traverse(Object o, Strategy s, Visitor v[]);– starting at object o traverse down following s
and execute the visitors in v. Return the object returned by first visitor.
Traversal Support: visitorsclass SampleVisitor extends Visitor{ // local variables public SampleVisitor(); // initialize public void before(Visited host)...; public void after (Visited host)...; public void before_z(X source, Y dest)...; public void after_z (X source, Y dest)...; Object get_return_val()...; public void start()...; public void finish()...;}
Traversal Support: visitors
abstract class Visitor { // GENERATED CODE public Visitor() {super();} public void start() {} public void finish() {} public void before(Visited host){}; public void after (Visited host){}; public void before_p(Q source, H dest){}; public void after_p (Q source, H dest){}; …}
Polytypic and Adaptive Programming
• Polytypic programming is programming in the meta-model of self-describing systems
• Adaptive programming is useful for polytypic programming as well as for application-centered polytypic programming
Polytypic and Adaptive Programming
Style Data typefamily
Traversal Appl.specific
polytypic yes universal no
adaptive yes selective yes
Polytypic and Adaptive Programming
Style Graphs Programstyle
Algorithms
polytypic infinite functional ?
adaptive finite imperative automatatheoretic
Related Work
• AOP at Xerox PARC
• Subject-oriented Programming
• Polytypic Programming
• Generative Programming
12/04/23 AOP/Demeter 64
Conclusions/On-line information
• AP works well– no tool support: navigation/visitor separation is
useful: HP printer installation project– with tool support: Demeter/C++, Demeter/Java:
several industrial projects
• The best way to follow the LoD
• www.ccs.neu.edu/research/demeter
The end
Future work
• Does AP work on infinite graphs?
• Inductive graphs in polytypic programming
• Non regular data types: correspond to the ones where grammar defines non-context sensitive language?
Nested polymorphic datatypes and traversals
• Nested datatype but rational tree
• ZigZag(A,B) : Nil|NonNil(A,ZigZag(B,A)).
• NonNil(C,D) = <first> C <rest> D.
• Nil = .
• MyZigZag = ZigZag(X,Y). X=“x”.Y=“y”.
• Sentence: x y x y ...
Polymorphic datatypes and traversals
• Non-nested datatype with rational tree
• Zig(A,B) : Nil|NonNil(A,Zag(A,B)).
• Zag(A,B) : Nil|NonNil(B,Zig(A,B)).
• NonNil(C,D) = <first> C <rest> D. Nil = .
• MyZig = Zig(X,Y). X=“x”.Y=“y”.
• Sentence: x y x y …
• Zig(A,B) = ZigZag(A,B)
Polymorphic datatypes and traversals
• TypeConstructor Bool
• ValueConstructors False, True
• data Bool = False | True
• TypeConstructors = AbstractClasses
• There is a need for type constructors / value constructors in Haskell because of parameterization: need nice constructor names
Polymorphic datatypes and traversals
• Rose(A) = Branch(A, List(Rose(A)).
• Rose(A) = <a> A <l> List(Rose(A).
• If we don’t use Branch, we don’t have a constructor name if definition is algebraic, i.e., there is no finite expansion.
• Interface inheritance using “nested” polymorphic types: subtype polymorphism is a special case of nested parametric polymorphism
Polymorphic datatypes and traversals
• Non-nested datatype with rational tree:
• Rose(A) = Branch(A, List(Rose(A)).
• List(S) : Nil|NonNil(S,List(S)).
• NonNil(C,D) = <first> C <rest> D. Nil = .
• Branch(C,D) = “(”<first> C <rest> D “)”.
• MyRose = Rose(X). X=“x”.
• Sentence: (x (x) (x) (x (x)))
Perfect trees
Perfect(T) : Zero(T) |
Succ(Perfect(Pair(T,T))).
Zero(T) = <t> T.
Pair(S,T)= <f> S <s> T. Succ(A) = A
succ(succ(zero(((1,2),(3,4))))
Perfect trees
• Perfect t = Zero | Succ(Perfect(t,t))
• succ(succ(zero(((1,2),(3,4))))
• Zero :: t -> Perfect t
• Succ :: Perfect(t,t) -> Perfect t
Usage of nested polymorphic datatypes
• Nested means: recursive call different.
• Phil Wadler: GJ works with them.They are only used by people with large brains.
• Complex data structures: 2-3 trees, Perfect trees, etc.
Usage of “nested” polymorphic datatypes
• Nested means: like a nested function call.
• Simulate inheritance
• See also paper by Remy (Ask Eric Meijer)
Parameterized traversal strategies
T1(A) = from Rose(A) to A
T2(A,B) = from Rose(A) via B to A
Sources(N) = from Graph(N,*) through *,source,* to N
Sources2(G,T) = from G through *,source,* to T.
call: Sources2(Graph(Integer,X),X)
DJ: put traversal strategies in separate file
Navigation aspect file: Strategy s = new Strategy(…);
Graph example
Graph(NL,EL) =
<edges> List(Edge(NL,EL))
<nodes> List(Node(NL)).
Edge(N,L) =
<source> Node(N) <label> L
<target> Node(N).
Node(N) = <n> N.
Program Analysis via Graph Reachability
• Talk by Thomas Reps at Dagstuhl March 1998: Program Comprehension and SE.
• CFL reachability is central problem– graph, edges labeled from alphabet– grammar defining L– a path from s to t counts as valid connection if
the word formed by labels is in L– O(n3)
Concrete syntax is more abstract than abstract syntax
• ICG as grammar. Represent ICG objects by constructor expressions. CCG defines same language as CCG. Have new CCG2 also same language. Create CCG2 objects automatically: pretty print CCG objects and parse them as CCG2 objects
• Advantage: ICG objects not as sentences; not dependent on concrete syntax. Is this a good way to define the map? Adding syntax to ICG and matching syntax to CCG so that parsing creates correponding objects. How get accessors? Get_x() -> get_a()->get_b()-> … For long_get: unique: can derive from one sample object. For long_collect: use maximal sample object.
• language equivalence: not just same language but objects must correspond
Concrete syntax versus traversal strategies
• Expressing map with traversal strategies versus expressing it with concrete syntax
Traversal StrategiesConcrete Syntax
• Default translation is often sufficient
Distinguish between paths
A = B C. B = D. C = D.
from A via B to D
A = [“b” B[ [C]. B = D. C = D.
Want only mapping between class graphs:
A = B C. B = D. C = D.
Mapping between class graphs
A = B. B = D.
Want only mapping between class graphs:
A = B1 C1. B1 = B2. B2 = D. C1 = C2. C2 = D.
No syntax needed to translate.
If multiple paths in CCG: B1 = [D]. Added
B1 = [“d”D]. For edge
B1 = “b2” B2. Object represented by b2. A=“b2”B. Is this general?
Pattern Language for AP 84
Parsers weave sentences into objects
Problem in OO programs: Constructor calls for compoundobjects are brittle with respect to structure changes.
Solution: Replace constructor calls by calls to a parser. Annotateclass diagram to make it a grammar.
Benefit: reduce size of code to define objects, object descriptions are more robust
Correspondence: Sentence defines a family of objects. Adaptive program defines family of object-oriented programs. In both cases,family member is selected by (annotated) class diagram.
Structure-shy Object
Pattern Language for AP 85
Run-time weaving: Description
Sentence* 3 + 4 5
GrammarCompound ...Simple ...Number ...Multiply ...Add ...etc.
C
M
*
N
3
C
A
+
N N
4 5
Object in linear form (Constructor calls)
C M * N 3 C A + N 4 N 5
Object as tree
Grammar defined by annotating UML class diagram
SENTENCE IS MORE ROBUST THAN OBJECT
Structure-shy Object
Connection: Program Analysis via Graph Reachability
• graph, edges labeled from alphabet: class graph
• grammar defining cfl L: traversal graph!
• a path from s to t counts as valid connection if the word formed by labels is in L
• traversal graph: regular language?