-------------------------------------------------------------------------- Software Design and Development Winter 1995 COM1205 Karl Lieberherr Feb. 25, 1995 --------------------------------------------------------------------------- Midterm --------------------------------------------------------------------------- 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: =========== 1-18: 3 points per UNKNOWN; 19-32: 6 points per UNKNOWN 32 UNKNOWNS Consider the following class dictionary, object graph, corresponding sentence, propagation patterns and corresponding trace information and Tcl/Tk script. Find the UNKNOWNS. Class dictionary: -------------------------------------------------------------------------- Example = MyList MyList DemString. MyList : Empty | NonEmpty. Empty = "e" . NonEmpty = Element MyList. Element = DemNumber. Object graph: -------------------------------------------------------------------------- Example ( < l1 > : UNKNOWN1 ( < first > : UNKNOWN2 ( < v > : DemNumber "1" ) < rest > : UNKNOWN3 ( < first > : Element ( < v > : UNKNOWN4 "2" ) < UNKNOWN5 > : NonEmpty ( < UNKNOWN6 > : Element ( < v > : UNKNOWN7 "UNKNOWN8" ) < rest > : NonEmpty ( < first > : Element ( < v > : UNKNOWN9 "UNKNOWN10" ) < rest > : UNKNOWN11 ( ) ) ) ) ) < l2 > : NonEmpty ( < first > : Element ( < v > : UNKNOWN12 "UNKNOWN13" ) < rest > : NonEmpty ( < first > : Element ( < v > : DemNumber "33" ) < rest > : NonEmpty ( < first > : Element ( < v > : DemNumber "44" ) < rest > : Empty ( ) ) ) ) < string > : DemString "ABC" ) corresponding sentence: -------------------------------------------------------------------------- // some comment UNKNOWN14 UNKNOWN15 3 4 UNKNOWN16 22 UNKNOWN17 44 UNKNOWN18 // string "ABC" propagation patterns -------------------------------------------------------------------------- *operation* DemNumber* rst() *init* (@ new DemNumber(0) @) *traverse* *from* {MyList, NonEmpty} *to* Element *wrapper* Element *prefix* (@ return_val -> set_val(*return_val + 1); @) *operation* MyList* xyz(MyList* second) *wrapper* MyList (@ @) *wrapper* Empty *suffix* (@ return_val = second; @) *wrapper* NonEmpty *prefix* (@ return_val = new NonEmpty(this -> get_first(), this -> get_rest() -> xyz(second)); @) Tcl/Tk script in main.tcl -------------------------------------------------------------------------- set l1 [$iExample get_l1:] # give the object corresponding to l1 as a sentence in UNKNOWN19 set l2 [$iExample get_l2:] # give the object corresponding to l2 as a sentence in UNKNOWN20 activate $l1 NonEmpty activate $l2 NonEmpty $l1 g_equal: $l2 # the last line will return UNKNOWN21 $l1 g_equal: $l1 # the last line will return UNKNOWN22 set rst1 [[$l1 rst:] get_val:] # give in UNKNOWN23 the value of rst1 set rst2 [[$l2 rst:] get_val:] # give in UNKNOWN24 the value of rst2 message .m1 -relief raised -justify center -text "first list $rst1" message .m2 -relief raised -justify center -text "second list $rst2" pack .m1 -side left # draw in UNKNOWN25 what is drawn in the window pack .m2 -side left # draw in UNKNOWN26 what is drawn in the window set uvw [$l2 xyz: $l1] # give the object corresponding to uvw as a sentence in UNKNOWN27 set lc [[$uvw rst:] get_val:] # give in UNKNOWN28 the value of lc message .m3 -relief raised -justify center -text "list $lc" pack .m3 -side left # draw in UNKNOWN29 what is drawn in the window trace information -------------------------------------------------------------------------- Which of the above commands produces the following trace? Give the command in UNKNOWN30. >> DemNumber* NonEmpty::rst(), >> void NonEmpty::rst_(DemNumber* & return_val), >> void Element::rst_(DemNumber* & return_val), << void Element::rst_(DemNumber* & return_val), >> void NonEmpty::rst_(DemNumber* & return_val), >> void Element::rst_(DemNumber* & return_val), << void Element::rst_(DemNumber* & return_val), >> void NonEmpty::rst_(DemNumber* & return_val), >> void Element::rst_(DemNumber* & return_val), << void Element::rst_(DemNumber* & return_val), >> void NonEmpty::rst_(DemNumber* & return_val), >> void Element::rst_(DemNumber* & return_val), << void Element::rst_(DemNumber* & return_val), >> void MyList::rst_(DemNumber* & return_val), >> at Empty , *** PREMATURELY TERMINATED *** , << at Empty , *** PREMATURELY TERMINATED *** , << void MyList::rst_(DemNumber* & return_val), << void NonEmpty::rst_(DemNumber* & return_val), << void NonEmpty::rst_(DemNumber* & return_val), << void NonEmpty::rst_(DemNumber* & return_val), << void NonEmpty::rst_(DemNumber* & return_val), << DemNumber* NonEmpty::rst(), What is a better name for member function rst? give the answer in UNKNOWN31. What is a better name for member function xyz? give the answer in UNKNOWN32. Question 2: =========== 5 points per UNKNOWN. 8 UNKNOWNs Sentences and class dictionaries Find the UNKNOWNs in the following class dictionary: A = UNKNOWN1 B C. B = List(B1) List(B2). B1 = "UNKNOWN2". B2 = "UNKNOWN3" D. D : E | F. E = "UNKNOWN4". F = UNKNOWN5. List(S) ~ "UNKNOWN6" {S} "UNKNOWN7". C : G | H. G = "UNKNOWN8". H = A. so that the following sentence // sentence ( x x x ) ( y e y y e) () () u gets parsed correctly. Make your UNKNOWNs of minimal size. Do not introduce extra classes. Note: UNKNOWN? = NOTHING is also a legitimate answer. Question 3: =========== 5 points per UNKNOWN 11 UNKNOWNs Law of Demeter and propagation patterns Consider the following class dictionary which is a simplification of the cd from the previous question. A = B C. B = B1 B2. B1 = . B2 = D. D : E | F. E = . F = . List(S) ~ {S} . C : G | H. G = . H = A. Consider the following propagation patterns written for the above class dictionary. *operation* void g() *wrapper* D (@ cout << this; @) 1: *operation* void f1() 2: *wrapper* A 3: (@ this -> get_b() 4: -> get_ds() 5: -> get_d() 6: -> g(); @) On which line is the first violation of the Law of Demeter? Give the line number in UNKNOWN1. Rewrite the above function f1 as an equivalent function f2 which is written in terms of propagation patterns. *operation* void f2() *traverse* *UNKNOWN2* UNKNOWN3 *UNKNOWN4* -> *,UNKNOWN5,* *to* UNKNOWN6 *wrapper* UNKNOWN7 (@ this -> g(); @) The above propagation pattern generates C++ code which satisfies the Law of Demeter. Find the UNKNOWNs in the C++ code below. void A::f2( ) { this->UNKNOWN8; } void B::f2( ) { this->UNKNOWN9; } void B2::f2( ) { this->UNKNOWN10; } void D::f2( ) { this -> UNKNOWN11; }