1 / 56

Nested Collaborations

Nested Collaborations. 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

brent-lara
Télécharger la présentation

Nested Collaborations

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

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 collaboration AndOr instances And And AndInstance Or Or OrInstance

  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. with Pengcheng 1 collaboration AndOr { participant D { expect boolean input1(); expect boolean input2(); expect boolean input3(); public boolean andOrR() {return AndInstance.D.andR();} public void andOrStatistics() { System.out.println(AndInstance.D.r(true); System.out.println(AndInstance.D.r(false); System.out.println(OrInstance.D.r(true); System.out.println(OrInstance.D.r(false); } adapter for And creating AndInstance { AndOr.D plays And.D { boolean input1() {return AndOr.D.input1();} boolean input2() {return OrInstance.D.orR();}}} adapter for Or creating OrInstance { AndOr.D plays Or.D { boolean input1() {return AndOr.D.input2();} boolean input2() {return AndOr.D.input3();}}} }

  9. with Pengcheng 2 collaboration AndOr { participant D { expect boolean input1(); expect boolean input2(); expect boolean input3(); public boolean andOrR() { Or.D d = new Or.D(); boolean res1 = d.orR(); return (new And.D.andR(); } public void andOrStatistics() { System.out.println(AndInstance.D.r(true); System.out.println(AndInstance.D.r(false); System.out.println(OrInstance.D.r(true); System.out.println(OrInstance.D.r(false); } adapter creating AndInstance { AndOr.D plays And.D { boolean input1() {return AndOr.D.input1();} boolean input2() {return OrInstance.D.orR();}}} adapter creating OrInstance { AndOr.D plays Or.D { boolean input1() {return AndOr.D.input2();} boolean input2() {return AndOr.D.input3();}}} }

  10. Conflict with Result Vector? • No: each adapter has its own

  11. 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.

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

  13. 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.

  14. 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.

  15. 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 Provided Interface LineItem = Product Pricer Customer <quantity> int. Product = List(ExtraCost). Customer = . Pricer = . ExtraCost = .

  16. 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); } }

  17. OfficeProduct. basicPrice Fig 1a: OrderPricing PriceForLineItem SumForPrice Order Tax Source sum Order. price ProductCategory Summing LineItem toSum Target OfficeProduct price LineItem LineItemPricing Product Pricer Customer ExtraCost

  18. 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

  19. Summing Collaboration • collaborationSumming { • participantSource { • 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;} …) } } • participantTarget { • expect int toSum();} • } Base: regular Meta variable: bold Keywords: underscore

  20. 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

  21. Adapter SumForPrice adapterSumForPrice { OrderisSumming.Source with { TraversalGraph getT() { ClassGraph classGraph1 = new ClassGraph(); returnnew TraversalGraph(classGraph1, new Strategy(“from Order to LineItem”));} } LineItemisSumming.Targetwith int toSum{ NegPriceForOrder.LineItem.price();} }

  22. Adapter NegPriceForLineItem adapter NegPriceForLineItem { LineItem is LineItemPricing.LineItem OfficeProduct is LineItemPricing.Product Customer is LineItemPricing.Pricer with { floatgetBasicPrice (Product p) { returnnegotiatedPrice(p);} floatgetDiscount(Product p, Customer c) { returnnegotiatedDiscount(p);}} Tax is ExtraCost with { … } }

  23. NegOrderPricing Aspect Pattern • collaborationNegOrderPricing { • participantOrder { • public int negPrice (){ SumForPrice.Order.sum();} • // participant graph and the adapters SumForPrice and • // NegPriceForOrder seen earlier • } Base: regular Meta variable: bold Keywords: underscore

  24. 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.

  25. Adapter SumRegForPrice adapterSumForRegPrice { OrderisSumming.Source with { TraversalGraph getT() { ClassGraph classGraph1 = new ClassGraph(); returnnew TraversalGraph(classGraph1, new Strategy(“from Order to LineItem”));} } LineItemisSumming.Targetwith int toSum{ RegPriceForLineItem.LineItem.price();} }

  26. Adapter RegPriceForOrder adapter RegPriceForOrder { LineItem is LineItemPricing.LineItem OfficeProduct is LineItemPricing.Product OfficeProduct is LineItemPricing.Pricer with { floatgetBasicPrice (Product p) { returnp.regPrice();} floatgetDiscount(Product p, Customer c) { returnp.regDiscount();}} Tax is ExtraCost with { … } }

  27. OrderPricing Aspect Pattern • collaborationOrderPricing { • participantOrder { • 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 • } Base: regular Meta variable: bold Keywords: underscore

  28. connectorNegotiatedPrice { BestellungisLineItemParty; KundeisPricerwith { floatgetBasicPrice (Product p) { returnverhandelterPreis (p);} floatgetDiscount(Product p, Customer c) { returnverhandelterDiscount(p);} } Büromaterial isProductwith { ExtraCost[]extraCosts () {...}; } SteuerisZusatzkostenwith { floatgetAmount (...) { ... }; } } connectorRegularPrice { BestellungisLineItemParty; BüromaterialisPricerwith { floatgetBasicPrice(Product p) { returnp.regPreis();} floatgetDiscount(Product p, Customer c){ returnp.regDiscount(c);} }; BüromaterialisProductwith { ExtraCost[]extraCosts() {...}; } SteuerisExtraCostwith { floatgetAmount (...) { ... }; } } Role of Pricer is once played by Kunde and once by Büromaterial

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

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

  31. Tim Sheard • Mark meta variables • express meta code • show how base code can become meta code

  32. Example : Count Aspect Pattern • aspectpattern Counting { • participantSource { • 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;} …) } } • participantTarget {} • } Base: Meta variable: bold Keywords: underscore

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

  34. 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!

  35. 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 Provided Interface LineItemParty = Product Pricer Customer <quantity> int. Product = List(ExtraCost). Customer = . ? Pricer = .

  36. 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); } }

  37. Aspect Patterns: Adapters adapterRegularPrice { Bestellung isLineItemParty; BüromaterialisPricerwith{ floatgetBasicPrice(Product p) { returnp.regPreis();} floatgetDiscount(Product p, Customer c){ returnp.regDiscount(c);} }; BüromaterialisProductwith { ExtraCost[]extraCosts() {...}; } SteuerisExtraCostwith { floatgetAmount (...) { ... }; } } Price computation Office material vendor Java code

  38. adapterNegotiatedPrice { BestellungisLineItemParty; KundeisPricerwith { floatgetBasicPrice (Product p) { returnverhandelterPreis (p);} floatgetDiscount(Product p, Customer c) { returnverhandelterDiscount(p);} } Büromaterial isProductwith { ExtraCost[]extraCosts () {...}; } SteuerisZusatzkostenwith { floatgetAmount (...) { ... }; } } adapterRegularPrice { BestellungisLineItemParty; BüromaterialisPricerwith { floatgetBasicPrice(Product p) { returnp.regPreis();} floatgetDiscount(Product p, Customer c){ returnp.regDiscount(c);} }; BüromaterialisProductwith { ExtraCost[]extraCosts() {...}; } SteuerisExtraCostwith { floatgetAmount (...) { ... }; } } Role of Pricer is once played by Kunde and once by Büromaterial

  39. adapterSalesPrice { Bestellungis LineItemParty; BüromaterialisPricerwith { floatgetBasicPrice(Product p) { return p.salesPrice();} floatgetDiscount(Product p, Customer c){return p.salesDiscount(c);} }; Büromaterial isProductwith { ExtraCost[]extraCosts() { ... }; } SteuerisExtraCostwith { floatgetAmount (...) { ... }; } }

  40. Example: Feature-oriented Programming • Dependent aspects • Order of deployment is relevant

  41. 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();} } }

  42. DataWithCounter :pairwise interaction Data/Counter DataWithCounter make_empty push pop make_empty push pop

  43. DataWithLock Patternpairwise 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}; }

  44. DataWithLock Patternpairwise interaction Data/Lock DataWithLock method_to_wrap method_to_wrap

  45. DataWithCounter StackImpl Counter QueueImpl Lock DataWithLock

  46. 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 with { method_to_wrap = {pop, push, top, make_empty, initCounter}; }; QueueImpl is DataWithCounter.DataStructure with { ... } is DataWithLock.Data with { ... }; }

  47. DataWithCounter DataWithLock DataWithCounterAndLock

  48. DataWithCounter :pairwise interaction Data/Counter DataWithCounter make_empty push pop make_empty push pop

  49. DataWithLock Patternpairwise interaction Data/Lock DataWithLock method_to_wrap method_to_wrap

  50. DataWithCounterAndLockpattern 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?

More Related