Department of Computer Science
University of Northern Iowa
Cedar Falls, Iowa 50614-0507
We would like to teach design early in the computer science curriculum, but evaluating design for the purposes of giving feedback and grades is hard to do. Much of the difficulty lies in a lack of vocabulary for describing and comparing designs. A pattern language of design and programming provides such a vocabulary--and more. By using a pattern language as one of the basic elements of our instruction, we provide students with a vocabulary for doing and comparing designs, and we provide the necessary foundation for evaluating design.
Over the last several years, a number of computer science (CS) educators have come to believe that we can and should teach object-oriented (OO) techniques early in the CS curriculum, even in the first year. Further, some of these educators have begun to consider how to teach OO design in the first year. These folks teach students OO design techniques such as CRC cards and assign projects that require students to submit design documents in some form.
How do we evaluate student designs, for the purposes of providing feedback, monitoring student progress, and assessing performance?
We want to help students learn how to design and implement good programs. This is the goal of most first-year computer sciences, or at least an important goal among several.
We would like to communicate to students the characteristics of a good design, in language concrete enough that they can consider these characteristics while doing design. Students learn best what they do most often, and we would like for them to learn how to create good designs and how to critique designs.
We want to give our students feedback that helps them do design better. Without feedback, students can only learn by seeing good examples and inferring the principles of good design from the examples. But we usually do not have enough examples available. Even when we do, we do not have enough time to expose students to all of them. And, even if we have enough examples and enough time, we have little control over the generalizations that students form.
We would also like to be able to assign a grade to student designs. Students like for their hard work to be reflected in their course grade, and we would like course grades to reflect student understanding of the elements of the course that we deem most important.
Instructors and students alike perceive the evaluation of design to be a subjective task. This perception follows directly from the absence of concrete standards and criteria.
Subjective evaluations may not make explicit to students the standards of evaluation or the techniques encouraged by the instructor. What the students do manage to learn from implicit standards and techniques tends to be hit-and-miss across the student population.
Instructors themselves may not know explicitly the standards that they use to evaluate a design or the "best practices" that they wish to encourage.
Evaluating design presumes that we have a vocabulary for discussing design in the first place. Without vocabulary, instructors and students struggle to negotiate common terms on the basis of their design experiences, which are often at differing levels of expertise and understanding.
Use a pattern language that documents best practices in good OO design at a level accessible to the student. The patterns in the language constitute a vocabulary for describing designs, and the language provides a simple methodology for generating good designs. And, most important from the perspective of evaluating design, the contexts of the patterns provide an explicit standard against which to evaluate designs.
In providing these benefits, the pattern language's chief attribute is its explicitness. It defines names for patterns and connects them to their technique. Of course, we could do the same without a pattern language. But the pattern language documents explicit connections among patterns, linking one pattern to other patterns that help to achieve it. The result is that design activity can be less trial-and-error and more directed by the characteristics of the problem. The explicit context and resulting context for each pattern document when to consider a pattern and what patterns to consider next--both essential to objective evaluation of a design. Such evaluation can be used to suggest improvements to a design and to evaluate the quality of a solution. As such the pattern language can be used both constructively and normatively.
This pattern transforms the problem of evaluating designs into a problem of identifying which patterns are most appropriate to a given problem. It moves the task of evaluation from an essentially-infinite problem space (which of the possible designs is best?) to a finite problem space (which subset of the finite vocabulary should the student use?).
I teach a course, Programming Languages and Paradigms, in which we devote half of a semester to the topic of functional programming. Students learn to program in Scheme as a way to experience a different way to think about programs and languages. One of the concepts that always causes them trouble is recursion, which they have studied briefly in an imperative context in CS1 or CS2.
When I first began to teach this course, I soon realized that I had difficulty in getting students to use recursion effectively, especially the techniques that make programs more readable, easier to modify, and more efficient. Students would "hack away" at a problem until they had created a working, recursive solution, at which point they would heave a sigh of relief and submit their code.
On a more practical front, I felt unjustified in grading such solutions harshly. Students would either use no advanced techniques to refactor their code, and claim that a working solution was "good enough", or they would try to apply any and all techniques to every problem, even when the techniques were not appropriate. In the former situation, I had a difficult time convincing students that my target solution was a better solution. In the latter, I had a difficult time explaining to students why they should not have used a particular technique. Both problems came down to understanding the context in which each technique applied.
I began to write a small pattern language to document the qualities of good recursive programs (in the functional style). These patterns captured some of the context in which each technique applied, and the resulting context of each pattern indicated which other patterns might be used next in the programming process. The result was a pattern language named Roundabout .
Roundabout provides all three of the benefits of using a pattern language. First, it defines a vocabulary for talking about recursive programs. My students and I can now talk about interface procedures and mutual recursion as elements of the design space for recursive code. Second, the pattern language gives the students some guidance about when and how to use each pattern. When they are implementing the structural recursion pattern, the pattern's resulting context tells them:
If one of your cases operates on another inductively-defined data element, you may need to use Mutual Recursion(3).
When they are implementing the mutual recursion pattern, the pattern's resulting context tells them:
If use of the helper procedure results in undesirable consequences, try using a Local Procedure(6) or Program Derivation(7) to eliminate it.
These explicit links among the patterns help the students see when a pattern is useful.
Third, Roundabout gives me a more objective mechanism for giving students feedback about their code and, ultimately, for grading their code. When I examine their code, I can apply the context of the pattern in question to show that the pattern is appropriate in the current situation. Even better, we can follow through Roundabout from the entry pattern to the "leaf" patterns, whose resulting contexts do not recommend any new patterns, as a way to diagnose the student's design and thought process.
The use of a pattern language resolves the primary forces that underlie the problem of evaluating design. The pattern language provides a vocabulary for talking about design, gives students guidance in creating good designs, and allows the instructor to give feedback and grade designs in a relatively unsubjective way. By eliminating most, if not all, of the subjectivity in evaluating designs, instructors will be more inclined to include design in their courses, and students will be more inclined to take design activities seriously.
This solution introduces two sub-problems that must be addressed.
The Loop Patterns paper grew out of work done at ChiliPLoP'98, which included a three-day workshop on elementary patterns. Other participants, including Joe Bergin and Ed Epp, are writing elementary OO patterns as well.
The Elementary Patterns home page contains pointers much of the work being done in this direction and to some of the people who are doing it.
In the worst case, an instructor can mandate the pattern language as the design standard against which student designs will be evaluated. Even just this step at least makes the evaluation process more objective than subjective.
This solution to the problem of evaluating design derives a number of benefits as side effects to the task of writing the pattern languages that characterize good designs and programs. The direct benefit of writing the pattern languages lies in documenting what we mean by "good design".
The idea of using a pattern language as a means for evaluating artifacts is not new. Christopher Alexander, the architect who first wrote of pattern languages, writes about the process of diagnosis in his book The Oregon Experiment . Communities and urban planners must allocate scarce resources when deciding what parts of a community should be improved or replaced next. In The Oregon Experiment Alexander describes how the same pattern language used by the community to create healthy structures (say, those in his own A Pattern Language ) can be used as part of a process for evaluating existing structures to determine which modification and enhancement projects should be pursued in the face of inadequate money to fund them all.
As described above, I have applied this idea in the context of functional programming. My example shows how we can use a pattern language to help students learn to create good programs, not designs. But the underlying principles of Roundabout are design principles; we simply carry the designs directly through to code. I could just as easily ask students to create designs for their proposed solutions first and evaluate the designs using the same pattern language.
Software engineers at Lucent Technologies use Coplien's organizational pattern language  as a part of diagnosing software organizations. They gather sociometric data and try to identify the presence of the patterns in the organization. As a result of their empirical studies, they have found that organizations which miss the most important process patterns tend not to be as productive as organizations that embody them. Harrison and Coplien  describe such an analysis and identify some of the critical patterns.
In the world of object-oriented design, patterns appearing in Design Patterns  and Pattern-Oriented Software Architecture  document a de facto OO design vocabulary and design standard.
[ Are there others? ]
I thank Ken Auer, Jim Coplien, and Arthur Kevin McGrath for commenting on an earlier draft of this paper. I thank Kevin especially for pointing out the problem-space transformation idea that I mention at the end of the Solution section.