Software Engineering Qualifier Exam

Fall 2003

Directions:  Answer any six of the eight following questions.  For all answers provide citations of relevant literature sufficient to identify the source.

1. (a) Compare and contrast the relative advantages of (i) requirements specifications in natural language (e.g. English or Thai), (ii) requirements specifications in a formal notation (e.g. Z), and (iii) requirements scenarios (e.g. using UML notations). In your answer, concentrate on the trade-offs among the three approaches for validating the customers' or other stakeholders' "real" needs.

(b) How are the distinctions you made between use cases and the two types of specification the same as the analogous distinctions between program analysis and testing and how are they different? What makes a requirements specification or a set of use cases "good enough"?

2. Implicit invocation (II) is an architectural style in which two components take part.  One component invokes the other without explicitly naming it.  Consider implementations of II.  You may assume the environment is sequential (that is that only a single process is involved).

(a) Give a precise description of the issues that need to be considered in designing a solution?  Try to come up with an orthogonal set. For each issue, describe the choices available and the tradeoffs involved.  Provide at least three different examples of situations in which II is applicable and describe the choices appropriate for those situations.

(b) Choose an implementation approach from the design space presented in (a). Using the formalism of your choice, provide a formal description of that choice.

(c) Describe how your answers would change if two parallel processes are involved; that is, if one process would like to request the services of another implicitly.

3. Brooks has called conceptual integrity the single most important issue in software design.  In an open source environment, multiple developers may wish to extend a given asset in a variety of ways.  The danger is that the process of including all the changes might result in a loss of conceptual integrity.

How could you measure conceptual integrity?  If you had to decide whether a change should be included in a system, how would you determine whether or not it was a natural extension or a wart.  Is it possible to provide automated support for this process?  If so, how?  If not, why not?

4. Testing at the integration level is becoming increasingly important because of the widespread use of components.  The ideal situation would be for developers of components to test their components and for application developers to test their applications without retesting the components they use.

(a) Suppose that the component developer guarantees that it has provided coverage of component C according to some adequacy criterion---such as branch-coverage--- before release.  If the application developer creates a test suite T that provides branch coverage of the application A, can he/she be guaranteed that T will also provide branch coverage of C?  Justify your answer.

(b) Perry and Kaiser describe the problems with adequacy for object-oriented programs in their paper "Adequate Testing and Object-Oriented Programming.  They discuss the problems for general object-oriented programming languages, and the problems may not exist for all object-oriented languages.  Select three of the issues they raise, and discuss whether they apply to Java programs.  

 (c) Suppose that the application developer that integrates component C into A needs to be sure that both the intraprocedural def-use pairs in C and the interprocedural def-use pairs between A and C are exercised by the test suite T that the application developer creates for A.  One way that the application developer can do this is to instrument C and measure the coverage.  However, suppose that A has no access to C's code.  Describe two techniques that could be used to measure the required coverage of C without instrumenting C.

5. Program slicing has been proposed as being useful for debugging and fault-localization purposes.

(a) Describe two approaches for computing static slices---one based on graph reach ability and one based on data-flow.  For each approach, (1) describe the analyses performed before the slice is computed and (2) the method used to compute the slice. (For this question, assume that procedures are being sliced---i.e. intraprocedural slicing.)

(b) When performing interprocedural slicing, what is the main problem that must be addressed?  How do the two approaches for static slicing mentioned in (a) address the problem?

(c) Describe one approach for computing dynamic slices.

(d) Discuss two ways that slicing---either static or dynamic---can be used for debugging/fault-localization.

6. (a) Comment on the C code below for implementing the library function "strdup" (duplicate a string). Do you see any particularly good or bad programming practices exhibited in this code?

   char *strdup(char *str) {
     char *strNew;

     ASSERT(str != NULL);

     strNew = (char *) malloc (strlen(str)+1);
     ASSERT(strNew != NULL);
     strcpy(strNew, str);

     return (strNew);
   }
 
(b) Consider code of the form:

     ASSERT(pointer);
     return pointer->x;

Upon viewing this code, a programmer comments, "the ASSERT is redundant. If the pointer is NULL, the dereference will fail anyway". Do you agree or not? Is there any good argument for using an ASSERT like that?

7.  Class invariants plus pre-conditions and post-conditions on operations are one mechanism that can be used for specifying the behavior of classes defined in a program written in an object-oriented language.
(a) What makes an assertion I a correct class invariant for a class C?
(b) Does an invariant make the job of implementing a class easier or harder?
(c) When is a class correct?
(d) How can having a formal semantic definition of a programming language aid in the development of correct classes and systems?
(e) How can there be errors in a system composed entirely of correct classes (according to the criteria you described in (c))?

8.  Many programming languages provide some kind of exception handling capability.
(a) What software engineering goals can be supported through disciplined use of exceptions?

(b) Suppose that the requirements of a software system include robustness in the face of certain kinds of errors that might be represented by user-defined exceptions.  In what phases of the development process must this use of exceptions be considered?  What will be required in each phase?

(c) Choose a particular language and describe how its features could be used to meet the requirement described in (b).  How much would dependence on these particular features impact any other phases you described in answering (b)?