Strategies For Making Friends

Preview:

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?