This is an open-book, open-note, open-library, open-WWW, but closed-any-person-other-than-yourself, examination.
From the time you open the packet, you may spend any four consecutive hours on the examination. I wouldn't expect everyone to spend the full time on the exam, but I do understand that some people work more slowly than others.
There are 150 total points. I wouldn't expect the time spent on each question either to be identical for each person nor to match the point assignment ratios exactly.
The exams are due, in hardcopy form, at the beginning of lecture (12:30PM) next Monday, February 22, 1999.
A few hints (in no specific order):
Legible answers are greatly preferable to illegible ones.
Precise answers are greatly preferable to vague, imprecise ones.
Connecting the questions to topics covered in the lectures and readings is recommended, when possible and reasonable.
For any questions asking for an opinion, the arguments for (or against) a point of view are as important as the opinion itself.
I will be travelling during most of this period, but I will try hard to read email from the road at least once every evening, in case there are questions. Since people will be taking the exam at different times, however, in the name of fairness I will have to be cautious in how I answer any questions. (In an absolute pinch, you can track me down at the Cathedral Hill Hotel in San Francisco, where I will be chairing the ACM SIG Governing Board meeting.)
Basic structure of the exam
There are three parts, each equally weighted in points (but, as mentioned above, not necessarily in time)
Part I: I will distribute a paper and ask you to discuss an approach described in that paper with respect to several topics covered in the lectures and readings.
Part II: A high-level description of a software system is given, and you have to produce a design and a rationale for that design.
Part III: 10 relatively short-answer questions about miscellaneous material.
Topics we covered
Design
Information hiding
Design for change
Use interfaces to capture stable aspects of systems, implementations to capture likely to change aspects of systems
Goal is to localize the cost of making a change, protecting clients from changing when an interface's implementation changes
Clients are to be unaware of the actual implementation, implementations are to be unaware of the clients that are supported
Open implementation
The assumption that implementations should be defined independent of the clients is unreasonable, especially with regards to performance, since different clients have different needs
In the absence of this, clients often do additional work to do an effective job on top of a "poor" client: coding between the lines and hematomas of duplication are the other approach
OI says, for domains that you understand well, build a module with two interfaces: the usual "base" interface, that provides the needed and desired behavior, and an additional "meta" interface, that allows clients to control key aspects of the implementation
Layered design
One often develops a family of systems, in which the commonalities among the systems are more important and valuable than their differences
For some such families of systems, one can take advantage of the notion of layered systems, in which each layer defines an abstract machine
Each layer is define solely in terms of the layer below
The uses relation must be designed carefully to achieve effective layering
A uses B if A's correctness depends on the presence of a correct version of B
Parnas provides some criteria for aiding in the design of the uses relation
The uses relation is related to, but not at all identical to, other relations such as calls, invokes (including implicit invocation), etc.
Frameworks
A reusable design of all or part of a system that is represented by a set of abstract classes and the way their instances interact.
By filling in these abstract classes in a specialized way, one can quickly build an application based on that framework
Design patterns
Idiomatic and structured combinations of objects, each of which is intended to solve a common and well-defined problem in object-oriented programming
Derived from actual experience
Software architecture
Identify classes of overall software system design that have shown the test of time
Carefully characterize the advantages and disadvantages of adopting one of these styles
Provide a basis for reasoning about an entire class of designs, with one goal being to amortize the costs of that reasoning across many uses
Requirements and specification
Informal requirements are inherently problematic; natural language is generally unsatisfying with respect to writing requirements
Meyer identified a set of common problems with requirements, which tend to crop up more frequently in natural language descriptions: noise, remorse, silence, contradiction, overspecification, ambiguity, forward references
Formal specifications provide an alternative, with at least two distinct and potentially important uses
They can provide the basis for showing that an implementation satisfies a specification
They can provide the basis for showing properties about a specification, such as consistency and completeness
Two common formulations of the "does an implementation satisfy a specification" are Hoare triples (predicates) and Dijkstra weakest-preconditions (predicate transformers)
They both, in essence, check whether, given state that satisfies a logical precondition, the execution of a set of given statements is guaranteed to yield a state that satisfies a given logical postcondition.
Loops are the most difficult aspect, as they generally require the manual development of a loop invariant that captures the progress made during successive iterations of a loop.
Many realistic language features, such as side-effects, reference parameters, etc., are difficult to handle in this approach
Z is in many ways similar to these two formulations, but it more directly supports a focus on properties of a specification alone, as opposed to primarily associating specifications with implementations (although it supports that as well)
Z static schemas define legal states of a system; Z dynamic schemas define operations that describe transitions from one state of a system to another
The schemas are defined in a precise mathematical language; they are also intentionally small and intended to be interspersed with (non-checkable) natural language to build the readers' intuition about the specification
Algebraic specifications use heterogeneous algebras to define the semantics of abstract data types (this is in contrast to the use of logic and set theory for Z)
The syntax of a specification defines the sorts (essentially, types) used in the definition, the names of the operations in the specification, and the signature of those operations
A set of axioms then defines the semantics of these operations
State is not explicit in algebraic specifications
Jackson's videotape covered some high-level issues in requirements, specifications, and programs
Requirements are inherently a part of the (real) world
We build machines (programs) to achieve a desired goal in the world
Programs are inherently a part of the machine
Specifications are at the intersection of the requirements and the program
A specification is a requirement (since it's true of the world) and it is a program (since it's true of the machine)
It captures the shared phenomena between the requirements and the program
We more often make mistakes about the association between specification and the requirements than between the program and the specification
There is much more in the videotape that this, but these are some of the very highest level highlights