Object Design in the First Year: An Oxymoron

Owen Astrachan
Department of Computer Science
Duke University
Durham, NC 27708
ola@cs.duke.edu

Abstract

What is meant by "Object Design"? Certainly we should analyze the problem before discussing viewpoints and solutions. In this paper I'll first discuss different views of design (as opposed to, e.g., programming). Next I'll discuss how we as educators can build a framework in the first year on which to build design skills, but that concentration on design per se can only come if we either accept a weakened definition of design or measure our success with metrics that measure anything successfully. Finally, I will discuss how we have adopted object-oriented techniques in our first two years (and, to a degree, in later courses) by building a framework on which real design skills can be taught.

Introduction: Specification

As a starting point, I'll provide several definitions of Object Design taken from a variety of sources. I'll try to distill the different definitions into two that make sense in the context of the first year (and beyond) in the arena of academic computer science. This amounts to the specification phase of an object-oriented design for object-oriented design in the first year.

Object-Oriented Design

Booch provides the following definition of object-oriented design: (page 39)
Object-oriented design is a method of design encompassing the process of object-oriented decomposition and a notation for depicting both logical and physical as well as static and dynamic models of the system under design.
This begs the question to a degree; we need to unfold the definition at least one level:
The empahasis in programming methods is primarily on the proper and effective use of particular language mechanisms. By contrast, design methods emphasize the proper and effective structuring of a complex system. There are two important parts to [the definition of design above]: object-oriented design (1) leads to an object-oriented decomposition and (2) uses different notations to express different models of the logical (class and object structure) and physical (module and process architecture) design of a system...
While Booch uses object-design to mean system design, Rumbaugh differentiates system design from object design: (page 227)
During object design the designer carries out the strategy chosen during system design and fleshes out the details. There is a shift in emphasis from application domain concepts toward computer concepts. The objects discovered during analysis serve as the skeleton of the design, but the object designer must choose among different ways to implement them with an eye toward minimizing execution time, memory, and other measures of cost. In particular, the operations identified during analysis must be expressed as algorithms, with complex operations decomposed into simpler internal operations. The classes, attributes, and associations from analysis must be implemented as specific data structures. New object classes mut be introduced to store intermediate results during program execution and to avoid the need for recomputation. Optimization of the design should not be carried to excess, as ease of implementation, maintainability, and extensibility are also important concerns.
Wirfs-Brock defines object-oriented design as: (page 28)
the process by which software requirements are turned into a detailed specification of objects. This specification includes a complete description of the respective roles and responsibilities of objects and how they communicate with each other.
Stroustrup has this to say about the scale and purpose of design: (page 366)
The purpose of "design" is to create a clean and relatively simple internal structure, sometimes also called an architecture, for a program -- in other words, to create a framework into which the individual pieces of code can fit and thereby guide the writing of these individual pieces of code.

A design is the end product of the design process (as far as there is an end product of an iterative process). It is the focus of the communication between the designer and the programmer and between programmers. It is important to have a sense of proportion here. If I -- as an individual progrmmer -- design a small program that I'm going to implement tomorrow, the appropriate level of precision adn detail may be some scribbles on the back of an envelope. At the other extreme, the development of a system involving hundreds of designers and programmers may require books of specifications carefully writen using formal or semi-formal notations. Determining a suitable level of detail, precision, and formality for a design is in itself a challenging technical and managerial task.

Finally, Davis defines design as: (page 73)
the set of activities including (1) defining an architecture for the software that satisfies the requirements and (2) specifying an algorithm for each softare component in the architecture. The architecture includes a specification of all the building blocks of the softwre, how they interface with each other, how they are composed of one another, and how copies of components are instantiated ... and destroyed. The final product of design is a design specification.

OO Design: a Synthesis

The books from which the definitions above are taken all define key attributes of an object-oriented language and object-oriented principles that are prerequisites for an object-oriented design. These include, among other things: abstraction, encapsulation, polymorphism, modularity, and hierarchy. Each of these must be taught during the first year as part of the framework on which design will be taught. However, in and of themselves they're not really part of design. The definitions above often point to a result of design: a document, a diagram, a deliverable.

In the context of the first year, it is unrealistic to expect students to produce a design document. In the first place, programs are usually too small to merit a design document and the production of such a document is most likely a deterrent to a working program rather than an aid. In the second place, students will resent producing such a document, mostly because the document doesn't help solve the problem or write the program. It is all well and good to proclaim that "it's good for them", but we want to attract the best and brightest students to our discipline, not turn them off with paper work. As programs get larger, we will have ample time to show students the advantages of producing a design.

This leads to my definition/specification of design in the first year:

  1. Students must learn those parts of a language (be it C++, Smalltalk, Eiffel, Ada, or Java) that are prerequisites to object design. In particular students should understand and see advantages of encapsulation, class hiearchies (including inheritance), and design patterns (see, e.g., Gamma et. al.).

    These language and object features should be studied in the context of larger programs and frameworks whose design has been well-thought out and implemented. Students work as apprentices, building on the work of others: augmenting classes and programs rather than implementing from scratch, adding a class to an existing class hierarchy, and reading and studying good design by example.

  2. Design heuristics (see, e.g., Riel) should be used to highlight why the classes, programs, and frameworks provided are good designs. Exemplars of the heuristics we use in our first year (taken from Riel) are

Good Design/Bad Design

Nowhere in this specification do I expect students to produce good object-oriented designs. I expect students to appreciate good design, to use good design, and to understand some heuristics. I also expect students to produce bad designs, in fact I hope they do so. This is, in part, because producing good object designs is a very difficult task. It is also because this is how students will understand good design. A quote attributed to Fred Brooks puts this well:
Good design comes from experience, and experience comes from bad design.

I hope to inculcate an aesthetic sense of design during the first year. Since I do not claim to be able to measure whether students are good designers in the first year, I am sure to be successful. I can measure student performance on assignments and judge how well student code and classes fit with designs, code, and classes provided as part of each assignment. In my view, time spent on learning CASE tools, notation, methodologies, and so on is time taken from topics in computer science that must be taught as necessary background in computer science. Perhaps Winograd is right in asking for software design to be a separate profession. However, as university educators we must fit our plan into an overall design that precludes concentration on design at the expense, for example, of proof by induction. So, my plan for design is to foster a sense of what's right and good hoping students flounder enough to appreciate good design and how well-designed components can make a programming task enjoyable.


Implementing the Design

Now that I've provided an incomplete specification for design, I will discuss some of how we implement this design in our first year courses at Duke.

We use C++ in our courses. In our first course we expect students to become comfortable with three design patterns from Gamma et. al.: iterators, observers, and adapters. We don't use the terminology from Gamma, but use classes that are based on these paterns. For example, classes for reading words from a file, simulating a random walk, implementing templated lists, and traversing directory hierarchies all employ member functions that implement internal iterators. This is the most important pattern we use. We also use the observer pattern to produce different views of data, e.g,. a random-walk object can be viewed graphically, by recording a history of the walk, or be producing a histogram. The adapter pattern (somewhat of a stretch) is used to encapsulate strings and vectors to provide a safe, uniform interface. All these classes are integral to the book by Astrachan that we use the course.

In our second course, we build on the experiences of our first course with larger and more complex programs based on the same patterns and heuristics from the first course. We use external iterators, for hash tables, lists, and maps. The observer pattern is used extensively in a discrete-event simulation framework we have developed (and will use for the first time this year) for the control and simulation of multiple elevators. We use inheritance for the first time in our second course (although we are looking for examples for use in the first course; the observer pattern may provide this example).

We view both courses as providing the framework on which object design is finally studied and performed by students. Our third (sometime fourth) course Software Design and Implementation uses both C++ and Java (previous offerings used Python instead of Java). Students must design and implement several large programs requiring extensive class hierarchies. Here many patterns from Gamma et. al. are used. Students are accustomed to thinking about patterns and design from the groundwork set in the first courses. Here, where large programs are designed from scratch for the first time, students can appreciate the need for a good design, and for a good design document. Part of this is because projects are large enough that a real team effort is required.

References

  1. Owen Astrachan , Trevor Selby, and Joshua Unger. An Object-Oriented, Apprenticeship Approach to Data Structures using Simulation. Proceedings of Frontiers in Education (FIE), 1996.

  2. Owen L. Astrachan. A Computer Science Tapestry: Exploring Computer Science and Programming with C++. McGraw-Hill, 1997.

  3. Grady Booch. Object Oriented Analysis and Design with Applications. Addison-Wesley, 2 edition, 1994.

  4. Davis, Alan. 201 Principles of Software Development, McGraw-Hill, 1995.

  5. Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. Design Patterns: Elements of Reusable Software , Addison-Wesley, 1995.

  6. Rick Mercer. Computing Fundamentals with C++, Franklin Beedle & Associates, 1994.

  7. Bertrand Meyer. Object-Oriented Software Construction, Prentice-Hall, 1988.

  8. Arthur J. Riel. Object-Oriented Design Heuristics , Addison-Wesley, 1996.

  9. James Rumbaugh, Michael Blaha, William Premerlani, Frederick Eddy, and William Lorensen. Object-Oriented Modeling and Design , Prentice-Hall, 1991.

  10. Bjarne Stroustrup. The C++ Programming Language, Second Edition, Addison-Wesley, 1993.

  11. Taligent. Taligent's Guide to Designing Programs: Well-mannered object-oriented design in C++ , Addison-Wesley, 1994.

  12. Terry Winograd (editor). Bringing Design to Software, Addison-Wesley, 1996.

  13. Rebecca Wirfs-Brock, , Brian Wilkerson, and Lauren Wiener. Designing Object-Oriented Software, Prentice-Hall, 1990.

Biography

Owen L. Astrachan is Associate Professor of the Practice of Computer Science at Duke University and the department's Director of Undergraduate Studies. Professor Astrachan has written many technical and pedagogical articles, is the author of "A Computer Science Tapestry: Exploring Computer Science and Programming with C++" (published by McGraw-Hill), and is the Principal Investigator in two NSF-sponsored educational programs: "The Applied Apprenticeship Approach: An Object-Oriented/Object-Based Framework for CS2" and "CURIOUS: Center for Undergraduate Education and Research: Integration through Performance and Visualization". Professor Astrachan is finally beginning to understand object-design after working on it for three years.