-------------------------------------------------------------------------- Adaptive Object-Oriented Software Development Fall 1996 COM 3360 --------------------------------------------------------------------------- Final QUESTION 1: 1 UNKNOWN, 30 points 30 QUESTION 2: 40 points 40 QUESTION 3: 20 UNKNOWNs, 1 point each. 20 QUESTION 4: 15 UNKNOWNs, 5 points each 75 QUESTION 5: 7 UNKNOWNs, 5 points each. 35 200 points total --------------------------------------------------------------------------- Open book and open notes. To make the grading easier, please put your values for the unknowns on the enclosed answer sheet. THE GAME OF REDUNDANCY AND UNKNOWNS ----------------------------------- Most of the questions in this exam ask you to determine unknowns of the form UNKNOWN1, UNKNOWN2, ... This makes it easier for you to answer the questions, since you get extra context information. Yet you need to master the behavioral objectives of the course to answer the questions. Guessing an answer is not a successful strategy and therefore a "game of redundancy" test is more interesting than a multiple choice test. The questions have the following pattern: I show you several artifacts which are related by the theory of object-oriented design and programming. Because of the dependencies between the artifacts, some of the information is redundant and can be recovered from the context by applying the objectives covered in the course. The information which you should discover is marked UNKNOWNx. If an unknown is not uniquely determined, mark the answer with *CHOICE*. An unknown may be anything, e.g., a number, an identifier, a character, two identifiers with a blank between them, a string etc. If an unknown is the empty string, give NOTHING as answer, e.g., UNKNOWN = NOTHING. Example: 5 + UNKNOWN1 = 8 UNKNOWN1 = 3 --------------- UNKNOWN2 * UNKNOWN3 = 20 UNKNOWN2 = 4 *CHOICE* UNKNOWN3 = 5 *CHOICE* At the beginning of a question we give the number of points per unknown. Question 1: ================================================================ THEME: Abstracting out commonalities between object-oriented programs. 1 UNKNOWN, 30 points In the following you are given two class dictionaries CD1 and CD2 and corresponding traversal code T1 and T2. The traversal code T1 is for CD1 and the traversal code T2 is for CD2. The claim is that the traversal code comes from _one_ traversal function which is expressed with a traversal directive. Find a _smallest_ such directive. Find the UNKNOWN in the following: A{ traversal t(V v){ UNKNOWN1 } // in /proj/asl/lieber/java/java-envs/jk-common CD1: ======================================== A = K Q. K = L. L = B. Q = B. B = . V = . Main = . T1 ========================================= class A { // omitted public void t_traverse ( V v ) { q.t_traverse(v); } } class Q { // omitted public void t_traverse ( V v ) { b.t_traverse(v); } } class B { // omitted public void t_traverse ( V v ) { v.before(this); } } // in /proj/asl/lieber/java/java-envs/jk-common2 CD2: ========================================== A = K. K : R | S *common* P "sep" Q. P = B. Q = B. R = "r". S = "s". B = ["c" C]. C = L. L = A. V = . Main = . T2: =========================================== class A { // omitted public void t_traverse ( V v ) { k.t_traverse(v); } } abstract class K { // omitted public void t_traverse ( V v ) { p.t_traverse(v); q.t_traverse(v); } } class P { // omitted public void t_traverse ( V v ) { b.t_traverse(v); } } class Q { // omitted public void t_traverse ( V v ) { b.t_traverse(v); } } class R extends K { // omitted public void t_traverse ( V v ) { super.t_traverse (v); } } class S extends K { // omitted public void t_traverse ( V v ) { super.t_traverse (v); } } class B { // omitted public void t_traverse ( V v ) { v.before(this); } } Question 2: ================================================================ 40 points Theme: Style rules for object-oriented programming. Variation of the Law of Demeter for Adaptive Programming Consider the following Law of Demeter for visitors: In a visitor method M (a before or after method) attached to visitor class V, only use methods of class V, of the host class and of classes which are instantiated in M. (Specifically, it is disallowed to use methods of the classes of immediate parts of host and this.) Answer the following questions (use blue booklet, 10 points each): 1. Is this version of the Law of Demeter too restrictive? Assume M contains the code fragment: host.get_x().f(); How could you rewrite the code so that it follows the Law of Demeter for visitors? 2. Assume M contains the code fragment: this.get_x().f(); How could you rewrite the code so that it follows the Law of Demeter for visitors? 3. Allow also to use methods of the classes of the immediate parts of V. This means that this.get_x().f() is now allowed in a visitor method M. Is this a better version of the Law of Demeter for visitors? Discuss the pros and cons. 4. Consider the adaptive program in Question 5. List all violations of the first version of the Law of Demeter for visitors given above. Question 3: ================================================================ 20 UNKNOWNs, 1 point each. Theme: Parsing. Structure-shy objects. // /proj/asl/lieber/java/java-envs/e/jk-detection2/cpp Consider the following class dictionary, object and corresponding sentence. Find the UNKNOWNs. Class dictionary: Start = List(A). List(S) ~ S {UNKNOWN1 S}. A = ["b" B] ["c" C]. B : D *common* X. C = ["d" D] ["e" E]. D : F *common* Y. E = ["f" F]. F : U *common* Z. U = . X = . Y = . Z = . Main = . V = C_RestrCountVisitor E_RestrCountVisitor. C_RestrCountVisitor = Integer C_DetectionVisitor. E_RestrCountVisitor = Integer E_DetectionVisitor. C_DetectionVisitor = C. E_DetectionVisitor = E. Object: : Start ( < a_list > : A_List { : A ( < UNKNOWN2 > : UNKNOWN3 ) , : A ( < UNKNOWN4 > : UNKNOWN5 < UNKNOWN6 > : UNKNOWN7 ( ) ) , : A ( < UNKNOWN8 > : UNKNOWN9 < UNKNOWN10 > : UNKNOWN11 ( < UNKNOWN12 > : UNKNOWN13 ) ) , : A ( < UNKNOWN14 > : UNKNOWN15 < UNKNOWN16 > : C ( < d > : UNKNOWN17 < UNKNOWN18 > : UNKNOWN19 ( < UNKNOWN20 > : U ( < z > : Z ( ) < y > : Y ( ) < x > : X ( ) ) ) ) ) } ) Sentence: b , b c , b c d , b c d e f Question 4: ================================================================ 15 UNKNOWNs, 5 points each Theme: Program understanding for programs written in traversal-visitor style. Redesign using parameterized classes. Consider the following class dictionary program.cd (it is the same as in question 3!) and behavior file program.beh. The behavior file has the task of printing two numbers for a given Start-object: the number of all Z-objects contained in a C-object and the number of all Z-objects contained in a E-object. Both numbers are computed in one traversal. For example, on input c e f, c d the output is: java Main < program.input 2 Z-objects with C-objects 1 Z-objects with E-objects done: =========================== Find the UNKNOWNs below: Class dictionary program.cd =========================== Start = List(A). List(S) ~ S {"," S}. A = ["b" B] ["c" C]. B : D *common* X. C = ["d" D] ["e" E]. D : F *common* Y. E = ["f" F]. F : U *common* Z. U = . X = . Y = . Z = . Main = . // visitor part V = C_RestrCountVisitor E_RestrCountVisitor. C_RestrCountVisitor = Integer C_DetectionVisitor. E_RestrCountVisitor = Integer E_DetectionVisitor. C_DetectionVisitor = C. E_DetectionVisitor = E. Behavior file program.beh ========================= Start{ traversal t( UNKNOWN1 cd, UNKNOWN2 ed, UNKNOWN3 cr, UNKNOWN4 er, V v){ to Z;} (@ void f() { C_DetectionVisitor cd = new C_DetectionVisitor(); E_DetectionVisitor ed = new E_DetectionVisitor(); C_RestrCountVisitor cr = new C_RestrCountVisitor(UNKNOWN5 ); E_RestrCountVisitor er = new E_RestrCountVisitor(UNKNOWN6 ); V v = new V(UNKNOWN7); this.t(cd,ed,cr,er,v); } @) } V{ UNKNOWN8 Start (@ System.out.println(rc.get_c().intValue() + " Z-objects with C-objects"); System.out.println(re.get_c().intValue() + " Z-objects with E-objects"); @) } C_DetectionVisitor { before UNKNOWN9 after UNKNOWN10 } E_DetectionVisitor { before UNKNOWN11 after UNKNOWN12 } C_RestrCountVisitor { before Z (@ UNKNOWN13 @) } E_RestrCountVisitor { before Z (@ UNKNOWN14 @) } Main { (@ static public void main(String args[]) throws Exception { Start a = Start.parse(System.in); a.f(); System.out.println("done: "); } @) } =========== Part 2 of this question. The class dictionary in program.cd can be better expressed using parameterized classes. Rewrite the visitor part of the class dictionary: V = C_RestrCountVisitor E_RestrCountVisitor. C_RestrCountVisitor = Integer C_DetectionVisitor. E_RestrCountVisitor = Integer E_DetectionVisitor. C_DetectionVisitor = C. E_DetectionVisitor = E. using parameterized classes. Put your answer in UNKNOWN15. Question 5: ================================================================ 7 UNKNOWNs, 5 points each. Theme: Class graph inference for adaptive programs. Testing adaptive programs. Consider the following behavior file program.beh. Find a _minimal_ class dictionary program.cd so that program.beh and program.cd together define a Java program which compiles. Find the UNKNOWNs below: Program { (@ /** Prints all construction class names in a given class graph. A program to show second order visitors. Requires a visitor to traverse a visitor. Also counts the total number of construction classes. */ public static void main(String args[]) throws Exception { Program p = parse(System.in); p.print_and_count_cons_classes(); } @) (@ public void print_and_count_cons_classes() { ClassNameTranspVisitor cntv = new ClassNameTranspVisitor(); PrintConsClassesVisitor pcv = new PrintConsClassesVisitor(cntv); CountingVisitor cv = new CountingVisitor( new Integer(0)); this.toAllConstructionClasses(pcv,cntv,cv); } @) traversal toAllConstructionClasses( PrintConsClassesVisitor pcv, ClassNameTranspVisitor cntv, CountingVisitor cv ) { to ConstructionClass; } } CountingVisitor { before ConstructionClass (@ this.set_total(new Integer(total.intValue() + 1)); @) after Program (@ System.out.println(this.get_total().intValue() + " = number of construction classes"); @) } ClassNameTranspVisitor { before ClassDef (@ this.set_pcn(host.get_classname()); @)} ClassNameRetVisitor { before ClassName (@ this.set_cn(host); @)} PrintConsClassesVisitor { traversal toClassName( ClassNameRetVisitor cnrv) { bypassing -> *,parameters,* to ClassName;} (@ /** Retrieve the class name from the visitor. Requires a traversal from the visitor class which itself needs a visitor. */ public ClassName dig_out() { ClassNameRetVisitor cnrv = new ClassNameRetVisitor(); this.toClassName(cnrv); return cnrv.get_cn(); } @) before ConstructionClass (@ System.out.println("construction class " + this.dig_out().get_name()) ; @) } // program.cd -- reduced class dictionary for Demeter/Java Program = UNKNOWN1. ClassDef = UNKNOWN2. ConstructionClass = UNKNOWN3 . // Terminal buffer classes. ClassName = Ident. // Visitors. CountingVisitor = UNKNOWN4. ClassNameRetVisitor = UNKNOWN5. ClassNameTranspVisitor = UNKNOWN6. PrintConsClassesVisitor = UNKNOWN7. --------------- HAPPY HOLIDAYS