APPENDIX A Object-Oriented Programming and Software Engineering Object-oriented programming is an evolutionary development in software engineering. The foundation for many object-oriented languages were established by decades of software engineering experience that motivated the invention of language features such as closed procedures, modules and abstract data types. Also important were the widely recognized value of such software engineering techniques as information hiding, encapsulation, strict enforcement of interfaces, and layering. Object-oriented programming address (at least) the three major software engineering goals shown in this figure: Software Engineering Goals The language features that address these issues are those of objects, classes, inheritance, polymorphism, templates, and design patterns. Reusability is an important issue in software engineering for at least two major reasons. First reusability is one means to cope with the pressures of producing ever larger and more functional systems in an ever decreasing development cycle (time to market). Reusability allows developers to be more efficient because the same code can be developed once and used in many different applications. Second, reliability can be improved by reusing previously developed, and previously tested, components. The development of new code entails the additional costs in time and money of testing, validation, and verification of the new code. Much of these expenses can be avoided by using "off-the-shelf" components. Software reuse is certainly not a goal unique to object-oriented programming. While libraries of procedures proved this approach to be useful, in practice procedures were too primitive a unit to promote extensive reuse. Objects and classes are more sophisticated mechanisms for achieving software reuse because they bind together more completely all the aspects of an entire abstraction. Therefore, the abstraction can more easily be transported across applications. Any of the forms of generalization also contribute to reuse. A class in an inheritance hierarchy can be reused directly when it serves as a generalized base class from which a new class is derived by specialization. Templates can be reused by supplying different parameters for the template arguments. Design patterns allow design experience and success to be reused across designers. Extensibility in software is important because software systems are long-lived and are subject to user's demands for new features and added capability. Object-oriented programming can help to satisfy this need through inheritance. Recall that inheritance is a generalization/specialization hierarchy. Referring to the Window hierarchy discussed earlier, extensibility is possible in two ways. The first way in which a generalization/specialization hierarchy supports extensibility is that any new attributes or behaviour that is added to a more generalized concept (e.g., Window) will automatically become part of the attributes and behaviour of its specializations (e.g., Frame, Item, Button). For example, as shown below, if the Window abstraction is enhanced to include a colour with which the Window would be displayed on the screen, then the attribute "currentColor" and the behavior "setColor" might be added to Window. It would then be possible to manipulate the colour of a Window but all its specializations as well. Adding new Attributes and Behaviour The second way in which a generalization/specialization hierarchy supports extensibility is that the hierarchy itself can be extended. New additions can be made under any existing node. For example, as shown below, the TextWindow might be specialized to a HyperTextWindow by including additional attributes and additional behaviour that distinguishes ordinary words from those words that are hyperlink and can be clicked-on to transfer to another place in the text. Adding new Specialized Classes Flexibility in software systems means, in part, that additions, variations or modification can be made without the need to modify numerous places in the system's code. Historically, many software systems were very brittle in that the addition of a small change could only be accommodated by making modifications in many, and often apparently unrelated, parts of the existing system. This brittle property stood in marked contrast to the prevailing notion that, unlike hardware systems, software system were supposed to be extremely malleable and changes can be made easily. Object-oriented programming contributes to flexibility in two ways. First, the separation of an interface from its implementation allows the user of the interface to remain unaffected by changes in the implementation. Thus, a modification can be made to the implementation (e.g., to improve its efficiency or reliability) without requiring any changes in the code that uses the interface. Second, polymorphism allows variations and additions to be made to the set of classes over which the polymorphism applies. For example, referring to the Window hierarchy, consider adding a new kind of interaction Item, a RadioButton. Since Items can be placed in a Panel, it would seem necessary to modify the Panel to allow a Panel to manipulate the newly created RadioButton. However, the Panel can use polymorphism so that the Panel's algorithms only rely on the more general attributes and behavior of an object (i.e., that it is a kind of Item) and does not need to be aware of the exact "type" (i.e., RadiButton) of the object. Using this approach, the Panel can be designed to operate on Items. Any newly created Item, even one - like the RadioButton - that is created after the Panel is already written, automatically can be manipulated by a Panel without changing the code of the Panel. <> 1. Appendix A contains an article explaining the relationship between software engineering and object orientated programming. Based on this article and information gained from other sources (referenced) describe the characterises of object orientated programming and how it complements procedural programming techniques. Criteria P1.1 2. Appendix B shows the code for a number guessing game using the object (or class) “GuessGame”. Produce documentation which would allow a programmer to use this object in their code, without them having seen the C++ code. Your answer should include: a. Explanation of all the variables defined in the object and whether they are private, protected or public. b. All the functions which are available to manipulate the object variables. c. The purpose of the constructor routine d. Why is a destructor routine inappropriate for this object? Criteria P4.3 3. You are to design a program which uses the GuessGame class. The program is to have 10 rounds. In each round the user is asked to guess the number. After the 10 rounds the program is to print out the user’s best score, worst score and average score. Produce the appropriate program design and resulting C++ code listing. Criteria P3.1, P3.2 Answer for Part 3 #include #include #include #include #include using namespace std; /* Define a "Guess Game" object that keeps track of the state of the game, the score etc over multiple rounds. Adapted from code posted by Warren Okrassa on his nightwares.com mailing list. */ classGuessGame { /* private members are only accessable by an instance of this class */ private: intfavorite; /* public members may be accessed anywhere */ public: int guesses, rounds, score, average; /* The special "constructer" method always has the same name as the class */ GuessGame() { srand(time(NULL)); // only needs to be done once guesses = 0, score = 0, rounds = 0; } /* Compare a number with the "favorite" */ int guess(int number) { ++guesses, ++score; if (number >favorite) return 1; // too high else if (number >num; response = my_guess.guess(num); cout<< "response is " << response << "\n"; while (response != 0) { if (response == 1) cout<< "Too big " <>num; response = my_guess.guess(num); } cout<< "Well done, your guess is right, it took you " < largest) { largest = my_guess.guesses; } } cout<< "Your smallest score is " << smallest <