Presentation is loading. Please wait.

Presentation is loading. Please wait.

Nested Collaborations

Similar presentations


Presentation on theme: "Nested Collaborations"— Presentation transcript:

1 Nested Collaborations

2 Collaboration reuse We want to reuse collaborations at two levels:
Refined collaborations similar to is-a relationship between classes Nested collaborations similar to has-a relationship between classes This idea was already in contracts (Helm, Holland et al.) and in Holland’s thesis.

3 Boolean Collaborations
Collaboration is trivial: only one participant Example is realistic because we want to record the result history. Example indicates that each subcollaboration should be represented by an object. Only in special cases can collaborations be implemented by code insertion only.

4 Recording And Collaboration
collaboration And { participant D { boolean res; public Vector r = new Vector();// result history public boolean andR() { res = input1() and input2(); r.append(new Boolean(res); return res;} expect boolean input1(); expect boolean input2(); } Each time andR() is called, return value will be stored in a vector local to participant D.

5 Recording Or Collaboration
collaboration Or { participant D { boolean res; public Vector r = new Vector();// result history public boolean orR() { res = input1() or input2(); r.append(new Boolean(res); return res;} expect boolean input1(); expect boolean input2(); } Each time orR() is called, return value will be stored in a vector local to participant D.

6 Compose Collaborations
And AndOr Or

7 collaboration AndOr { participant D { expect boolean input1(); expect boolean input2(); expect boolean input3(); public boolean andOrR() {return AndAdapter.D.andR();} public void andOrStatistics() { System.out.println(AndAdapter.D.r(true); System.out.println(AndAdapter.D.r(false); System.out.println(OrAdapter.D.r(true); System.out.println(OrAdapter.D.r(false); } adapter AndAdapter { AndOr.D plays And.D { boolean input1() {return AndOr.D.input1();} boolean input2() {return OrAdapter.D.orR();}}} adapter OrAdapter { AndOr.D plays Or.D { boolean input1() {return AndOr.D.input2();} boolean input2() {return AndOr.D.input3();}}}

8 Conflict with Result Vector?
No: each adapter has its own

9 Hardware-style Components
Can be expressed with nested collaborations Adapters are used to instantiate components It is important to name adapters How should collaborations be implemented? Adapted collaborations should be represented as objects.

10 Methods versus Signals
The model we use uses methods for input. An alternative model would be to use signals on ports.

11 Counting Collaboration
Have CountingAdapter.BusRoute Adapter creates adapter object When count() is invoked, count() on adapter object is invoked? BusRoute.count() calls CountingAdapter.BusRoute.count(). But we might have another adapter. Need to rename count in adapter in that case.

12 Better example Pricing and Summing: add Order participant to participant graph of Pricing. Call it OrderPricing because it computes the cost of an order not just of a line item. Both negotiated and regular price. Mapping for Pricing is identity? Mapping for Summing is Source -> Order, Target -> LineItem.

13 LineItemPricing example
collaboration LineItemPricing { private int qty; private float unitPrice; participant LineItem { //OrderUnit abstract Product getProduct(); // abstract instead of expect abstract Pricer getPricer(); abstract Customer getCustomer(); abstract int getQuantity(); public float price() { qty = getQuantity(); prod = getProduct(); k = getCustomer(); unitPrice = getPricer().unitPrice(prod, k); float price = unitPrice + getProduct().extraCosts(); return price; } Expected Interface Beilspil SAP und Telecom Australia Provided Interface LineItem = Product Pricer Customer <quantity> int. Product = List(ExtraCost). Customer = . Pricer = . ExtraCost = .

14 abstract ExtraCost[] getExtraCosts(); private float extraCosts() {
participant Product { abstract ExtraCost[] getExtraCosts(); private float extraCosts() { float total = 0; while (getExtraCosts().hasElement()) total =+ getExtraCosts().next().getAmount(qty, unitPrice, this); return total; } } participant Pricer { abstract float getBasicPrice(Product prod); abstract float getDiscount(Product prod, Customer k); private float unitPrice(Product prod, Customer k) { float basicPr = getBasicPrice(prod); return basicPr - (getDiscount(prod, k) * basicPr);} participant ExtraCost{ abstract float getAmount(int qty, float unitPrice, Product prod); Beilspil SAP und Telecom Australia

15 LineItemPricing added and modified behavior LineItemPricing pg pg’

16 OrderPricing Source Summing Order Target LineItem LineItemPricing

17 Missing: pg for each collaboration
OrderPricing Source Summing Order Target LineItem LineItemPricing

18 OrderPricing PriceForLineItem SumForPrice Order Source sum price ProductCategory Summing LineItem toSum Target OfficeProduct price LineItem LineItemPricing Product Pricer Customer

19 RPriceForLineItem SumForRPrice NPriceForLineItem SumForNPrice OrderPricing sum rprice Order sum nprice ProductCategory Source Source Summing Summing LineItem toSum toSum Target Target OfficeProduct price price LineItem LineItemPricing LineItem LineItemPricing Product Pricer Customer Product Pricer Customer

20 Summing Collaboration
collaboration Summing { participant Source { expect TraversalGraph getT(); public int sum (){ // traversal/visitor weaving getT().traverse(this, new Visitor(){ int r; public void before(Target host){ r=r+host.toSum(); } public void start() { r = 0;} …) } } participant Target { expect int toSum();} } can we really program with strategies? Here is how. Base: regular Meta variable: bold Keywords: underscore

21 Composed collaboration OrderPricing
// Participant graph: first only for negotiated price, followed by regular // price Order = <productCategories> List(ProductCategory) Customer. ProductCategory = Name List(LineItem). LineItem = OfficeProduct Pricer Customer <quantity> int. OfficeProduct = <extraCosts> List(Tax). Tax = . Customer = . Pricer = . // Customer in Order is transported to Customer in LineItem

22 Adapter SumForPrice adapter SumForPrice { Order is Summing.Source
with { TraversalGraph getT() { ClassGraph classGraph1 = new ClassGraph(); return new TraversalGraph(classGraph1, new Strategy(“from Order to LineItem”));} } LineItem is Summing.Target with int toSum{ NegPriceForOrder.LineItem.price();}

23 Adapter NegPriceForLineItem
LineItem is LineItemPricing.LineItem OfficeProduct is LineItemPricing.Product Customer is LineItemPricing.Pricer with { float getBasicPrice (Product p) { return negotiatedPrice(p);} float getDiscount(Product p, Customer c) { return negotiatedDiscount(p);}} Tax is ExtraCost with { … } }

24 NegOrderPricing Aspect Pattern
collaboration NegOrderPricing { participant Order { public int negPrice (){ SumForPrice.Order.sum();} // participant graph and the adapters SumForPrice and // NegPriceForOrder seen earlier } can we really program with strategies? Here is how. Base: regular Meta variable: bold Keywords: underscore

25 Now add regular price computation
Need a new adapter for summing regular prices: notice need to parameterize adapters Need a new adapter for computing regular price Need to distinguish between two price methods: regPrice and negPrice.

26 Adapter SumRegForPrice
adapter SumForRegPrice { Order is Summing.Source with { TraversalGraph getT() { ClassGraph classGraph1 = new ClassGraph(); return new TraversalGraph(classGraph1, new Strategy(“from Order to LineItem”));} } LineItem is Summing.Target with int toSum{ RegPriceForLineItem.LineItem.price();}

27 Adapter RegPriceForOrder
LineItem is LineItemPricing.LineItem OfficeProduct is LineItemPricing.Product OfficeProduct is LineItemPricing.Pricer with { float getBasicPrice (Product p) { return p.regPrice();} float getDiscount(Product p, Customer c) { return p.regDiscount();}} Tax is ExtraCost with { … } }

28 OrderPricing Aspect Pattern
collaboration OrderPricing { participant Order { public int negPrice (){ SumForPrice.Order.sum();} // participant graph and the adapters SumForPrice and // NegPriceForOrder seen earlier public int regPrice (){ SumForRegPrice.Order.sum();} // participant graph and the adapters SumRegForPrice and // RegPriceForOrder seen earlier } can we really program with strategies? Here is how. Base: regular Meta variable: bold Keywords: underscore

29 Role of Pricer is once played by Kunde and once by Büromaterial
connector NegotiatedPrice { Bestellung is LineItemParty; Kunde is Pricer with { float getBasicPrice (Product p) { return verhandelterPreis (p);} float getDiscount(Product p, Customer c) { return verhandelterDiscount (p);} } Büromaterial is Product with { ExtraCost[] extraCosts () { ... }; } Steuer is Zusatzkosten with { float getAmount (...) { ... }; } connector RegularPrice { Bestellung is LineItemParty; Büromaterial is Pricer with { float getBasicPrice(Product p) { return p.regPreis();} float getDiscount(Product p, Customer c) { return p.regDiscount(c);} }; Büromaterial is Product with { ExtraCost[] extraCosts() { ... }; } Steuer is ExtraCost with { float getAmount (...) { ... }; } } Role of Pricer is once played by Kunde and once by Büromaterial

30 Need for collaboration composition
Need two instances of the summing collaboration. Need to instances of the line item cost collaboration.

31 Collaborations Collaboration
Participant graph: for each participant a provided and required interface Set C of reused collaboration names and the corresponding adapters

32 Tim Sheard Mark meta variables express meta code
show how base code can become meta code

33 Example : Count Aspect Pattern
aspect pattern Counting { participant Source { expect TraversalGraph getT(); public int count (){ // traversal/visitor weaving getT().traverse(this, new Visitor(){ int r; public void before(Target host){ r++; } public void start() { r = 0;} …) } } participant Target {} } can we really program with strategies? Here is how. Base: Meta variable: bold Keywords: underscore

34 Adapter 1 classGraph1 is fixed and therefore the traversal is fixed
adapter CountingForBusRoute1 { BusRoute is Counting.Source with { TraversalGraph getT() { ClassGraph classGraph1 = new ClassGraph(); return new TraversalGraph(classGraph1, new Strategy(“from BusRoute via BusStop to Person”));} } Person is Counting.Target { }

35 Aspect Pattern Partial Evaluation
Because the class graph is fixed for CountingForBusRoute1, it can be frozen and a more efficient specialization can be produced. aspect specialization CountingForBusRoute1 freeze getT() in getT().traverse(…) Visitor constant too!

36 Aspect pattern example
aspect pattern Pricing { private int qty; private float unitPrice; participant LineItemParty { //OrderUnit abstract Product getProduct(); // abstract instead of expect abstract Pricer getPricer(); abstract Customer getCustomer(); abstract int getQuantity(); public float price() { qty = getQuantity(); prod = getProduct(); k = getCustomer(); unitPrice = getPricer().unitPrice(prod, k); float price = unitPrice + getProduct().extraCosts(); return price; } Expected Interface Beilspil SAP und Telecom Australia Provided Interface LineItemParty = Product Pricer Customer <quantity> int. Product = List(ExtraCost). Customer = . ? Pricer = .

37 abstract ExtraCost[] getExtraCosts(); private float extraCosts() {
participant Product { abstract ExtraCost[] getExtraCosts(); private float extraCosts() { float total = 0; while (getExtraCosts().hasElement()) total =+ getExtraCosts().next().getAmount(qty, unitPrice, this); return total; } } participant Pricer { abstract float getBasicPrice(Product prod); abstract float getDiscount(Product prod, Customer k); private float unitPrice(Product prod, Customer k) { float basicPr = getBasicPrice(prod); return basicPr - (getDiscount(prod, k) * basicPr);} participant ExtraCost{ abstract float getAmount(int qty, float unitPrice, Product prod); Beilspil SAP und Telecom Australia

38 Aspect Patterns: Adapters
adapter RegularPrice { Bestellung is LineItemParty; Büromaterial is Pricer with { float getBasicPrice(Product p) { return p.regPreis();} float getDiscount(Product p, Customer c) { return p.regDiscount(c);} }; Büromaterial is Product with { ExtraCost[] extraCosts() { ... }; } Steuer is ExtraCost with { float getAmount (...) { ... }; } } Beilspil SAP und Telecom Australia Price computation Office material vendor Java code

39 Role of Pricer is once played by Kunde and once by Büromaterial
adapter NegotiatedPrice { Bestellung is LineItemParty; Kunde is Pricer with { float getBasicPrice (Product p) { return verhandelterPreis (p);} float getDiscount(Product p, Customer c) { return verhandelterDiscount (p);} } Büromaterial is Product with { ExtraCost[] extraCosts () { ... }; } Steuer is Zusatzkosten with { float getAmount (...) { ... }; } adapter RegularPrice { Bestellung is LineItemParty; Büromaterial is Pricer with { float getBasicPrice(Product p) { return p.regPreis();} float getDiscount(Product p, Customer c) { return p.regDiscount(c);} }; Büromaterial is Product with { ExtraCost[] extraCosts() { ... }; } Steuer is ExtraCost with { float getAmount (...) { ... }; } } Role of Pricer is once played by Kunde and once by Büromaterial

40 adapter SalesPrice { Bestellung is LineItemParty;
Büromaterial is Pricer with { float getBasicPrice(Product p) { return p.salesPrice();} float getDiscount(Product p, Customer c) {return p.salesDiscount(c);} }; Büromaterial is Product with { ExtraCost[] extraCosts() { ... }; } Steuer is ExtraCost with { float getAmount (...) { ... }; } }

41 Example: Feature-oriented Programming
Dependent aspects Order of deployment is relevant

42 DataWithCounter : pairwise interaction Data/Counter
aspect pattern DataWithCounter { private participant Counter { int i=0; void reset(){i=0;}; void inc(){…}; void dec(){…};} participant DataStructure { protected Counter counter; expect void initCounter(); expect void make_empty(); expect void push(Object a); expect void pop(); replace void make_empty(){counter.reset();expected();} replace void push(Object a){counter.inc(); expected(a);} replace void pop() {counter.dec();expected();} }

43 DataWithCounter : pairwise interaction Data/Counter
make_empty push pop make_empty push pop

44 DataWithLock Pattern pairwise interaction Data/Lock
aspect pattern DataWithLock { participant Data { Lock lock; expect void initLock(); expect AnyType method_to_wrap(Object[] args); replace AnyType method_to_wrap(Object[] args) { if (lock.is_unlocked()) { lock.lock(); expected(Object[] args); lock.unlock(); }}} private participant Lock {boolean l = true; void lock(){…}; void unlock(){…}; boolean is_unlocked(){return l}; }

45 DataWithLock Pattern pairwise interaction Data/Lock
method_to_wrap method_to_wrap

46 DataWithCounter StackImpl Counter QueueImpl DataWithLock Lock
in den vorherigen Kapiteln wurde erklärt: 1. in der Informatik darum, Rechnermodelle zu bauen, die Prozessen in der reellen Welt simulieren. 2. Es gibt formale Mitteln, die es erlauben, die Modelle in eine für den Rechner verständlich en Sprache zu schreiben.t. In dieser Vorlesung erden wir das sogenannte objekt-orientierte Programmiermodel als das Mittel für die Beschreibung der Modelle benutzen. Mit anderen Worten, werden wir objekt-orientierte Rechnermodelle der reellen Welt bauen. Wir werden zuerst, die Konstrukte des objekt-orientierten Programmiermodels kennenlernen, d.h. die Bestandteile unsere Toolboxes. Als zweites werden wir kurz QueueImpl DataWithLock Lock

47 First adapter adapter addCounterAndLock {
StackImpl is DataWithCounter.DataStructure with { void initCounter() {counter = new Counter();} void push(Object obj) {push(obj));} // use name map instead Object top() {return top();} ... } StackImpl is DataWithLock.Data method_to_wrap = {pop, push, top, make_empty, initCounter}; }; QueueImpl is DataWithCounter.DataStructure with { ... } is DataWithLock.Data with { ... };

48 DataWithCounterAndLock
DataWithLock DataWithCounterAndLock in den vorherigen Kapiteln wurde erklärt: 1. in der Informatik darum, Rechnermodelle zu bauen, die Prozessen in der reellen Welt simulieren. 2. Es gibt formale Mitteln, die es erlauben, die Modelle in eine für den Rechner verständlich en Sprache zu schreiben.t. In dieser Vorlesung erden wir das sogenannte objekt-orientierte Programmiermodel als das Mittel für die Beschreibung der Modelle benutzen. Mit anderen Worten, werden wir objekt-orientierte Rechnermodelle der reellen Welt bauen. Wir werden zuerst, die Konstrukte des objekt-orientierten Programmiermodels kennenlernen, d.h. die Bestandteile unsere Toolboxes. Als zweites werden wir kurz

49 DataWithCounter : pairwise interaction Data/Counter
make_empty push pop make_empty push pop

50 DataWithLock Pattern pairwise interaction Data/Lock
method_to_wrap method_to_wrap

51 DataWithCounterAndLock pattern composition
make_empty push pop make_empty’ push’ pop’ DataWithCounter DataWithLock make_empty’’ push’’ pop’’ to-wrap Name stays the same, but behavior changes Should composed component have its interface computed? Yes?

52 Method flow diagram Composition of aspect patterns defines method flow
Methods come in and out of patterns Patterns may create new methods and absorb methods Graph: nodes are pattern, edges are methods What about participant graph? Participant name part of method name. Should nodes have ports? Multiple edges in, multiple edges out

53 Create composed aspects prior to deployment
aspect pattern DataWithCounterAndLock uses DataWithCounter, DataWithLock { participant Data { expect void make_empty(); expect void push(Object a); expect void pop(); } adapter DataWithCounterA { Data is DataWithCounter.DataStructure} // identity name map adapter DataWithLockA { Data plays DataWithLock.Data with { method-to-wrap = replaced methods of DataWithCounterA } } // ordering of adapters is relevant

54 Create composed aspects prior to deployment
Do we need this nested adapter syntax? aspect pattern DataWithCounterAndLock { participant Data = DataWithCounter.DataStructure is DataWithLock.Data with { method-to-wrap = {make_empty, pop, push}}; }

55 Create composed aspects prior to deployment
aspect pattern DataWithCounterAndLock { participant Data = DataWithCounter.DataStructure is DataWithLock.Data with { method-to-wrap = {make_empty, pop, top, push}}; } Instantiate DataWithCounter and DataWithLock

56 Second connector: Deploy composed component
connector addCounter&Lock { StackImpl is DataWithCounterAndLock.Data with { void make_empty() {empty();} void initCounter() { counter = new Counter();} void push(Object obj) {push(obj);} ... }; QueueImpl is DataWithCounterAndLock.Data with {...}; }

57 Doug Schmidt Apply collaborations and adapters to express middleware: Namingserver, EventChannel Express basic patterns, compose them to core functionality. Add synchronization, persistence, and later real-time aspects. Compare handwritten code with generated code.


Download ppt "Nested Collaborations"

Similar presentations


Ads by Google