Computer Science Division


Case Studies in the Classroom

Michael J. Clancy Marcia C. Linn
Computer Science Division
EECS Department
School of Education
University of California University of California
Berkeley, CA 94720 Berkeley, CA 94720


Abstract
We and others have created case studies to engate students in the process of designing solutions to complex programming problems. Case studies involve learners in activities of expert programmers such as identifying decisions, justifying choices among alternatives, and evaluating the consequences of these choices. Case studies improve computer programming courses by emphasizing the process rather than the product of problem solving. This paper describes specific uses of case studies in freshman and sophmore-level courses.

This paper was presented at the Twenty-Third SIGCSE Technical Symposium on Computer Science Education, Kansas City, MO, March 5-6, 1992, and published in SIGSCE Bulletin, volume 24, number 1, March 1992, pages 220-224.

Introduction

What is a Case Study?
A cast study describes a programming problem, the process used by an expert to solve the problem, and one or more solutions to the problem. Case studies emphasize the decisions encountered by the programmer and the criteria used to choose among alternatives.

Learners are engaged in the case study through questions that are interspersed in the presentation. Students can "think along" with the experts by making predictions, helping with parts of the solution, or analyzing alternatives. More comprehensive questions ask students to modify the solution, apply the ideas to new problems, detect bugs in related problems, and reflect on their own methods for solving problems.

A sample case study is outlined in Appendix A. It deals with the problem of completing a program to print a calendar for a given year. The problem specifies that two subprograms are to be supplied: a function NumberOfDaysIn, which returns the number of days in a given month in a given year, and a procedure PrintMonth, which prints the calendar "page" for a given month. (The solution to this problem is treated in more detail in Clancy and Linn [4].)

What are the advantages of case studies?
Case studies engage students in a kind of "apprenticeship" with an expert programmer (cs. Collins et. al [5]). Linn and Clancy [11] elaborate on their advantages, which include the following:

Why aren't case studies more commonly used?
The case study approach is atypical in introductory and intermediate programming courses. One reason is the relative scarcity of appropriate material. Published sources of case studies include the "Literate Programming" columns in Communications of the ACM [13], the books by Bentley [1][2], Kernighan and Plauger [6], and Clancy and Linn [4], and excerpts from books such as Ledgard and Tauer [9], Kruse [8], and Reges [12]. Much of this material is intended for experts or teachers, not students.

Many CS 1 and CS 2 courses are packed with details, and instructors may believe they have no room to include case studies. In such courses, however, it is easy for students to lose sight of the big picture, gain only superficial understanding of program design, and fail to appreciate the problem-solving power of a programming language.

Perhaps another reason that case studies aren't used is an impression by instructors that novice programmers are not ready, or inclined, to appreciate the issues discussed in a case study. Personal experience and informal surveys indicate, however, that students learn from case studies both in college introductory courses and in precollege programming classes.

Lastly, instructors may not be aware of the variety of ways to incorporate case studies into their classes? hence this paper. We describe how case studies can enhance laboratory and homework exercises, small group work, examinations, and lectures. We or all colleagues at Berkeley and elsewhere have tested, in introductory and intermediate programming courses, all the techniques we describe. These techniques are useful in more advanced settings as well.

Laboratory and homework assignments
A case study presents opportunities for students to analyze, modify, or extend a large program, or reuse the code to solve a related problem. The accompanying narrative makes the code easier for the student to understand, and thus reduces the complexity and maximizes the benefit of the assigned exercises.

One set of exercises requires students to use a compiled executable version of the code. A version with the sizes of the data structures reduced for experiments is provided. With executable code? a source listing need not be provided? Students can still accumulate a substantial amount of information about a program, by predicting its behavior given sample input, providing input that produces a given bahavior, distinguishing legal from illegal input, and devising good examples to teach new users about the program. They can also probe the limits of the program: How much input can it handle? What are constraints on the input format? How are out-of-bounds or overflow cases handled? Finally, students can evaluate the user interface, and compare it and the program's capabilities to other similar programs they have used.

With online source code, students working together can play "debugging games". One partner (or staff member if students are to work individually) inserts a bug into the program; the other attempts to find it. This requires that students have read the program but do not have the code listing nearby. It encourages students to invent thorough sets of test data, and to think about what aspects of a program's style and organization facilitate testing and debugging.

Typical laboratory or homework assignments using online code include modifying a program to change its user interface, replacing its data structures, and adding or extending features. Such activities can be profitably done in teams as well as individually. They illustrate the importance of code readability, planning, and incremental development, and introduce subtle issues, for instance, that the program should be modified in the style in which it is written.

Other online exercises include using the code in a larger application, or solving a similar problem. The advantages of rewriting reusable code are apparent in both activities.

Students can also be encouraged to create their own case studies. This activity reveals student thinking and helps instructors make sense of students' understanding of the material. Instructors can also incorporate the student solutions into subsequent course activities.

One other activity, that of solving the problem before seeing the solution and accompanying discussion, would seem to be good preparation for a case study. Students might be expected to be more sensitive to the decisions described in the narrative. Linn and Clancy [10] noted, however, that this approach was not always productive. Some students, having written one program to solve the problem, weren't interested in alternative.

Example exercises involving the "Calendar" case study
The solution programs in teh "Calendar" case study read a year from from the user, then print the calendar for that year. Students might be asked to perform experiments with executable versions of these programs, to determine how the programs handle years before the Gregorian reform of 1582, and whether erratic behavior results from negative or exceptionally large year values.

There are many places in the program to insert bugs, such as off-by-one initializations and off-by-one or reversed comparisons.

Possible modifications of the programs include highlighting of holidays or other significant days, and printing weekend days in a special format. Code from the calendar programs can be reused in a variety of applications involving date computations, and in programs to produce different kinds of calendars. Examples of the latter are the Jewish, Muslim, Mayan, Chinese, and French Revolutionary calendars, and a fantasy calendar without Mondays.

Small-group discussion
Discussion is most effective when students can contribute diverse perspectives and expertise. Naturally-occurring differences in problem-solving style among group members provide good grist for discussion and brainstorming. For instance, what aspects of the style and organization of the program make it easy or hard to understand, and why? What parts of the program match code that group members have seen before? Which of the design or development decisions would group members have made differently, and why?

One way to ensure that students have different types of expertise is to ask subgroups to study different case studies and then present the ideas to the rest of the class.

Discussion can also take advantage of previous online exercises. What were various ways of approaching these exercises? What aspects of the style and organization of the program made it easy or hard to modify? How does one set of test results provide better evidence for the correctness of the program than another? How did a partnership divide the problem, and how were the skills of the partners put to effective use?

Finally, discussion can provide opportunities for students to reflect on their own behaviors. The discussion leader might ask the group to compare their abilities to detect errors in output, to locate errors in code once they’ve been detected, and to find the simplest ways to fix the errors. Discussion might also encourage students to recognize and admit their programming weaknesses, such as propensities to "rush to the computer" or to test too much code at once.

Assessment
Learning to program well requires the acquisition of a number of subtle skills. The course objectives of ACM’s CS 2 [7], for instance, included the following:

How can these skills be assessed? In the typical programming course, the end product of a programming assignment is graded rather than the supposedly "disciplined approach to design, coding, and testing" that created it. An exam is constrained by limits on the time available to take it and the time available to grade it. Exam questions tend to focus on isolated facts rather than on complex problems.

Case studies allow assessment of analysis, design, and development in the context of a challenging problem. Here are some example question patterns. They must, of course, be asked in the context of a particular case study.

Analysis

Design and Development

Such questions, based on the context provided by the case study, are much less open-ended and much easier to grade than entire programs. They also require much less reading during an examination, since case studies can be reviewed in advance, than do questions in which a context must be set up from scratch. They therefore allow good programmers with reading deficiencies a better opportunity to display their knowledge.

The narrative description of design and development decisions is an important component for assessment. Linn and Clancy [10] found that students who received expert commentary did significantly better on their tests than students who received documented code without commentary.

Examples of assessment using the "Calendar" case study
The programs described in the "Calendar" case study, though each no more than two pages of code, provide surprising opportunities for questions about analysis, design, and development. Here are some examples.

Analysis

Design and Development

Lectures
One might guess that lecturing about a case study would be difficult; the narrative description contains much of what a lecturer might wish to say about the problem solution. How, then, can a lecturer provide an interesting, enthusiastic presentation for students?

One good approach is to give suggestions about how to read the narrative and program: how to find the important parts, how to take notes on the program, what experiments to try, and what collection of input data should be built to test the program. The lecturer can also point out what programming patterns and good habits are illustrated in the case study, and relate them to students’ previous experiences in the class. In addition, the lecturer might enrich the problem solution by supplying missing information and structure for the students, and by adapting the material to their experience and background. Hints for the homework are an obvious source of material. Much of the published case study material discusses the design but not the development stage; the lecturer might present a model sequence for testing and debugging the program.

Another source of lecture material is extension of the ideas in the case study. A lecturer might discuss how segments of the program could be used for other problem solutions, or discuss problems that can be solved in ways illustrated in the case study. A lecturer might also talk about more general applications of case study activities. An example might be a technique like mutation testing, in which the goal is to build a test suite that catches standard types of errors intentionally introduced into the program (see Budd [3]).

Finally, the lecturer can personalize the presentation with his or her opinions about controversial aspects of the design or development. Discussion of the lecturer's personal experience with similar problems or approaches can fascinate a class.

Summary
As textbooks for CS 1 and CS 2 get thicker and thicker, are your students memorizing more and understanding less? Case studies allow students, guided by an expert, to explore and experiment with design, analysis, and modification of programs they might not be able to create on their own. Students can solve what seem like "real" problems by altering expert solutions. Instructors can assign homework, lab activities, and discussion topics related to real problems, and easily prepare examinations that both educate students and provide significant information about student progress.

References

     [1] Bentley, J., More Programming Pearls, Addison-Wesley, 1988. 

     [2] Bentley, J., Programming Pearls, Addison-Wesley, 1986. 

     [3] Budd, T.A. "Mutation Analysis: Ideas, Examples, Problems, and
         Prospects", in Computer Program Testing (B. Chandrasekaran and
         S. Radicchi, editors), Elsevier North-Holland, 1981. 

     [4] Clancy, M.J. and Linn, M.C., Designing Pascal Solutions: A
         Case Study Approach (working title), W.H. Freeman and Company, 
         1992.

     [5] Collins, A., Brown, J.S., and Newman, S.E., "Cognitive
         Apprenticeship: Teaching the Craft of Reading, Writing, and
         Mathematics", in Cognition and Instruction: Issues and
         Agendas (L.B. Resnick, editor), Lawrence Erlbaum, 1989.

     [6] Kernighan, B. and Plauger, P.J., Software Tools in Pascal,
         Addison-Wesley, 1981. 

     [7] Koffman, E.B., Stemple, D., and Wardle, C.E., "Recommended
         Curriculum for CS 2, 1984", Communications of the ACM, 
         August 1985, volume 28, number 8. 

     [8] Kruse, R.L., Data Structures and Program Design (second
         edition), Prentice-Hall, 1987. 

     [9] Ledgard, H. and Tauer, J., Pascal with Excellence:
         Programming Proverbs, Hayden, 1986. 

     [10] Linn, M.C. and Clancy, M.J. "Can Experts’ Explanations
          Help Students Develop Program Design Skills?", International 
          Journal of Man-Machine Studies, to appear. 

     [11] Linn, M.C. and Clancy, M.J., "The Case for Case Studies of
          Programming Problems", Communications of the ACM, to appear. 

     [12] Reges, S., Building Pascal Programs, Little-Brown, 1987. 

     [13] Van Wyk, C.J. (moderator), "Literate Programming" columns,
          Communications of the ACM (July 1987, volume 30, number 7; 
          December 1987, volume 30, number 12; December 1988, volume 31, 
          number 12;  June 1989, volume 32, number 6; and 
          September 1989, volume 32, number 9).


Appendix A

Outline of decisions encountered
in the "Calendar" case study

Decision Reason
read the first program from back to front rather than from front to back
start with the design of NumberOfDaysIn rather then PrintMonth
Use a case statement rather than an if... then... elsein PrintMonth

code the case for February as
NumberOfDaysIn :=28 + LeapDay(year) rather than as an if statement or a call to a function FebDays code LeapDay as positive tests rather than negative tests
test NumberOfDaysIn and LeapDay in isolation.

test with years 1986, 1988, 1900. and 2000
decompose PrintMonth into routines that print the heading and print the dates.
code PrintHeading as a case statement rather than an if... then... else
print the dates day-by-day or week-by-week?

choose test data appropriately (left to the reader)

compare day-by-day vs. week-by-week decompositions

program structure for this program is likely to be more important than data structure
NumberOfDaysIn will be easier, and likely to be needed by PrintMonth
a case statement shows more clearly that essentially the same thing is being done for each case
to show more clearly the exceptional nature of a leap year while retaining consistency with the other cases
they're easier to understand

to gain confidence in its correctness before we have to use it somewhere else
to test all cases of leap years
to match the structure of the output

case is more concise, and better conveys the equivalence of the cases
(both alternatives are considered; decisions for each version appear separately)
to detect problems within a month, problems between months, and problems with the year
day-by-day decomposition leads to less code and probably is more natural; week-by-week decomposition allows easier enhancement of output to match real-life calendars

September 1999
clancy@cs.berkeley.edu