Hi Mira: does this look good? strategies S1 = from Foo to Y Foo { // a traversal method called average void average() do S1; } adjustment Count { (@ int total_count; @) init (@ total_count = 0; @) change (@ total_count++; call_super(); @) return (@ total @) } modifies Y adjustment Sum { (@ int total_sum; @) init (@ total_sum = 0; @) (@ total_sum+=value; call_super(); @) return (@ total @) } modifies Y adjustment Average { (@ int avg; @) change (@ System.out.println( total_sum/total_count ); } modifies Y Foo f = new Foo() modify average with {Count,Sum,Average}; f.average(); Alternatively we could say earlier: void average() do S1 with {Count,Sum,Average}; ================= Here the container example: I got lost ... How do we refer to variables in other adjustments? We need to do this together. -- Karl ======================================= Container { int checkCapacity() to Weight; } adjustment Summing { init (@ total = new Integer(0); @) change (@ System.out.println("sum " + total.intValue()); total = new Integer(total.intValue() + host.get_i().intValue()); ^^^^^ delete? @) } modifies Weight adjustment Checking { init (@ violations = new Integer(0); @) change (@ // before System.out.println(" start new container "); @) call_super(); // after Integer initial = iV.get_initial(); int cap = host.get_capacity().get_i().intValue(); int diff = iV.get_current_sum() - initial.intValue(); if (diff > cap) { this.set_violations(new Integer(get_violations().intValue() + 1)); System.out.println(" total weight " + diff + " but limit is = " + cap + " OVER CAPACITY "); }; System.out.println(" end container "); @) // Demeter/Java requires to give the return type after return return int (@ violations.intValue() @) } modifies Container //1 InitialVisitor { // stack handling init (@ stack = new Stack(); @) // init (@ stack = new MyStack(); @) before Container (@ stack.push(sV.get_total()); @) after Container (@ initial = (Integer) stack.pop(); @) int get_current_sum() to SummingVisitor { before SummingVisitor (@ return_val = host.get_total().intValue(); @) } } Main { (@ static public void main(String args[]) throws Exception { Container a = Container.parse(System.in); int result = a.checkCapacity(); int result2 = a.checkCapacity2(); if ((result == 2) && (result == result2)) { System.out.println("SUCCESS"); -- Karl // BEHAVIOR //======================================================================== // A simple Demeter/Java program for checking capacity // constraints for recursive containers. // Three behavioral concerns: Checking, Summing, Initial // abbreviated C S I // Two generic concerns: traversal, behavior modification (visitor) // count transition points, except in formal or actual parameters Container { traversal allWeights( //1 // ordering of visitors is important // initial must be initalized before it is used // after methods are called in reverse order of appearance // it is important that InitialVisitor is after CheckingVisitor // could also use: CheckingVisitor InitialVisitor SummingVisitor ordering CheckingVisitor cV, SummingVisitor sV, InitialVisitor iV ) { to Weight;} (@ // traverse while counting and summing int checkCapacity() { // CheckingVisitor cV = new CheckingVisitor(iV, null); // SummingVisitor sV = new SummingVisitor(); // InitialVisitor iV = new InitialVisitor(null, null, sV); CheckingVisitor cV = new CheckingVisitor(); //1 SummingVisitor sV = new SummingVisitor(); //1 InitialVisitor iV = new InitialVisitor(); //1 cV.set_iV(iV); //2 iV.set_sV(sV); //2 this.allWeights(cV, sV, iV ); //1 return (cV.get_return_val()); //1 } @) // the same in propagation pattern style to show you the connection // to what you learn in the book // the propagation pattern solution has the disadvantage // that it is a tangled arrangement of the visitor code. // It violates the basic principle of separation of concerns. // Below we show the interlacing with comments. // The tangling could be avoided if we could have multiple // before (after, around) methods for the same class. // To avoid such tangling using the Selective Visitor pattern // is one of the key innovations // behind Demeter/Java. int checkCapacity2() //1 // traverse to Weight //1 { // the visitors inlined // first declare local variables of the visitor objects // now they are all at the same level and not nested. (@ // from SummingVisitor Integer total; //1 // from CheckingVisitor Integer violations; //1 // from InitialVisitor Stack stack; // MyStack stack; Integer initial; //1 @) init (@ // from SummingVisitor total = new Integer(0); //1 // from CheckingVisitor violations = new Integer(0); //1 // from InitialVisitor stack = new Stack(); //1 // stack = new MyStack(); //1 @) // from SummingVisitor before Weight (@ System.out.println("sum " + total.intValue()); total = new Integer(total.intValue() + host.get_i().intValue()); @) // from CheckingVisitor //1 before Container (@ System.out.println(" start new container "); //1 bad tangling // from InitialVisitor stack.push(total); @) //1 after Container (@ //1 bad tangling // from InitialVisitor initial = (Integer) stack.pop(); //1 // Integer initial = iV.get_initial(); int cap = host.get_capacity().get_i().intValue(); int diff = total.intValue() - initial.intValue(); //2 S,I bad tangling if (diff > cap) { violations = new Integer(violations.intValue() + 1); // { this.set_violations(new Integer(violations.intValue() + 1)); System.out.println(" total weight " + diff + " but limit is = " + cap + " OVER CAPACITY "); }; System.out.println(" end container "); @) return int (@ violations.intValue() @) } } //1 SummingVisitor { init (@ total = new Integer(0); @) before Weight (@ System.out.println("sum " + total.intValue()); total = new Integer(total.intValue() + host.get_i().intValue()); @) } //1 CheckingVisitor { init (@ violations = new Integer(0); @) before Container (@ System.out.println(" start new container "); @) after Container (@ Integer initial = iV.get_initial(); int cap = host.get_capacity().get_i().intValue(); int diff = iV.get_current_sum() - initial.intValue(); if (diff > cap) { this.set_violations(new Integer(get_violations().intValue() + 1)); System.out.println(" total weight " + diff + " but limit is = " + cap + " OVER CAPACITY "); }; System.out.println(" end container "); @) // Demeter/Java requires to give the return type after return return int (@ violations.intValue() @) } //1 InitialVisitor { // stack handling init (@ stack = new Stack(); @) // init (@ stack = new MyStack(); @) before Container (@ stack.push(sV.get_total()); @) after Container (@ initial = (Integer) stack.pop(); @) int get_current_sum() to SummingVisitor { before SummingVisitor (@ return_val = host.get_total().intValue(); @) } } Main { (@ static public void main(String args[]) throws Exception { Container a = Container.parse(System.in); int result = a.checkCapacity(); int result2 = a.checkCapacity2(); if ((result == 2) && (result == result2)) { System.out.println("SUCCESS"); } else { System.out.println(" FAILURE " + result + "," + result2); } System.out.println("done "); } @) }