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)?