This chapter looks at the introductory phase of the undergraduate curriculum, when students receive their first college-level exposure to computer science. Section 7.1 outlines our overall philosophy concerning the introductory curriculum. Sections 7.2, 7.3, and 7.4 then look at three topics that are central to the design of introductory courses: the role of programming, the length of the introductory sequence, and strategies for integrating discrete mathematics. Section 7.5 goes on to enumerate the set of concepts, knowledge, and skills that we believe should be part of an ideal introductory sequence. Finally, section 7.6 enumerates a set of six introductory strategies that have proven successful in practice. This section also provides critiques of each approach as an aid to help faculty make informed decisions about which of the alternatives best address the needs of their students, their department, their institution, and their community.
Throughout the history of computer science education, the structure of the introductory computer science course has been the subject of intense debate. Many strategies have been proposed over the years, most of which have strong proponents and equally strong detractors. Like the problem of selecting an implementation language, recommending a strategy for the introductory year of a computer science curriculum all too often takes on the character of a religious war that generates far more heat than light.
In the interest of promoting peace among the warring factions, the CC2001 Task Force has chosen not to recommend any single approach. The truth is that no ideal strategy has yet been found, and that every approach has strengths and weaknesses. Given the current state of the art in this area, we are convinced that no one-size-fits-all approach will succeed at all institutions. Because introductory programs differ so dramatically in their goals, structure, resources, and intended audience, we need a range of strategies that have been validated by practice. Moreover, we must encourage institutions and individual faculty members to continue experimentation in this area. Given a field that changes as rapidly as computer science, pedagogical innovation is necessary for continued success.
One of the most hotly debated questions in computer science education is the role of programming in the introductory curriculum. Throughout the history of the discipline, most introductory computer science courses have focused primarily on the development of programming skills. The adoption of a programming-first introduction arises from a number of practical and historical factors, including the following:
The programming-first approach, however, has several shortcomings. The most commonly cited objections to this approach are the following:
Despite these shortcomings, however, the programming-first model has proven to be extraordinarily durable. Even though the Computing Curricula 1991 report argued strongly for a broader introduction to the discipline, the majority of institutions continue to focus on programming in their introductory sequence. It is important to recognize that the programming-first model has some strengths that have led to its longevity. Of these, the most important are the following:
In section 7.6, we offer three implementations of a programming-first model and three that adopt an alternative paradigm. The programming-first implementations are an imperative-first approach that uses the traditional imperative paradigm, an objects-first approach that emphasizes early use of objects and object-oriented design, and a functional-first approach that introduces algorithmic concepts in a language with a simple functional syntax, such as Scheme. In each case, we have sought to identify curricular models that minimize the weaknesses of the programming-first approach by focusing on algorithmic and problem-solving concepts rather than the vagaries of language syntax. The three alternative models are a breadth-first approach that begins with a general overview of the discipline, an algorithms-first strategy that focuses on algorithms over syntax, and a hardware-first model that begins with circuits and then builds up through increasingly sophisticated layers in the abstract machine hierarchy.
We believe the time is right to question this two-course assumption. The number and complexity of topics that entering students must understand have increased substantially, just as the problems we ask them to solve and the tools they must use have become more sophisticated. An increasing number of institutions are finding that a two-course sequence is no longer sufficient to cover the fundamental concepts of programming, particularly when those same courses seek to offer a broader vision of the field. Expanding the introductory sequence to three courses makes it far easier to cover the growing body of knowledge in a way that gives students adequate time to assimilate the material.
The CC2001 Task Force strongly endorses the concept of moving to a three-course introductory sequence and believes that this option will prove optimal for a relatively wide range of institutions. At the same time, the three-course approach will not be right for everyone. The fact that the traditional two-course approach fits into a single year of study at semester-based institutions often makes it easier to fit the introductory material into the whole of the curriculum without interfering with the scheduling of sophomore-level courses. Similarly, the task of assigning credit for courses taken at other institutions, including advanced placement programs in secondary schools, becomes more complicated if one institution follows a two-semester calendar while the other covers the introductory material in three.
To support both two- and three-course introductions, the CC2001 Task Force has developed both options for three of the introductory tracks -- imperative-first, objects-first, and breadth-first -- for which the three-course model seems to have the greatest advantages. Similar extensions could be developed for the other three approaches, but are not included in this report. For each of the tracks, the two- and three-course variants are distinguished using the course numbering system. The three-course sequences for each track use the numbers 101, 102, and 103; the two-course sequences use 111 and 112.
Despite the ongoing debates over pedagogical approaches, there are many values that virtually all advocates of computer science education share. In this section, we outline what we believe constitutes a general consensus about a minimal set of goals for an introductory curriculum. Each individual strategy articulated in section 7.6 seeks to accomplish much more than what we describe here, but each will cover a common set of topics that can serve as a base for intermediate course structures.
In today's world, computers are ubiquitous. Because of the importance of computer systems and the wide applicability of computer-based skills, introductory computer science experience should certainly expose students to the design, construction, and application of computer systems and offer them training in skills that have demonstrated utility. At the same time, introductory computer science courses must also introduce students to some of the central intellectual aspects of the discipline. When we view computer science as a discipline, it is important to look beyond its popular conception as a tool to consider its conceptual foundations. Upon what principles does it stand? What new concepts does it bring to the realm of knowledge? What kinds of questions do computer scientists ask? What modes of thought and mental disciplines do they bring to bear on problems?
We believe it is possible to develop an introductory computer science experience that accomplishes each of the following goals:
To this end, Figure 7-1 presents a set of concepts, knowledge, and skills that we believe should be a part of each introductory curriculum. While the order of presentation and level of emphasis will vary among individual computer science programs, we expect that all introductory programs will seek to meet these goals. Figure 7-2 expresses similar guidelines in terms of units and topics from the body of knowledge introduced in Chapter 5.
Figure 7-1. Concepts covered in the introductory curriculum
Algorithmic thinking
Programming fundamentals
Computing environments
|
Figure 7-2. Units covered by all six of the introductory tracks
Units for which all topics must be covered:
Units for which only a subset of the topics must be covered:
|
This section describes six implementations of the introductory curriculum that the CC2001 Task Force feels have achieved a level of success that allows them to serve as models of best practices. Determining whether an approach has been successful, however, is more difficult than it might appear. Albert Shanker, the former president of the American Federation of Teachers, wrote that "educational experiments are doomed to succeed," in part because the energy their creators bring to the experiment creates an excitement that encourages success. Given enough enthusiasm, almost any pedagogical approach will succeed as long as its proponents remain committed to that vision. The real test is whether the initial success can be sustained when the approach is adopted by others.
In choosing our set of models for the first year, we have insisted that each strategy be endorsed by people other than the creator who have used the approach successfully. By doing so, we hope to limit our attention to those strategies that already have a track record of successful adoption. The six models identified in the sections that follow have each met the criterion of having a successful track record when taught by faculty other than the original designer. At the same time, it is important to note that only the underlying approaches have been subjected to this level of validation and not the specific course designs included in Appendix B. In particular, we did not find existing models for the three-semester implementations we have proposed under the imperative-first, objects-first, and breadth-first approaches. The approaches themselves have proven successful in the more traditional two-semester packaging, and we believe that there is good reason to believe that the three-semester implementations will achieve similar levels of success.
The imperative-first approach is the most traditional of the models we have included in this report. As noted in section 7.3, we have proposed two implementations of the imperative-first model, one that covers the material in three semesters and one that completes the presentation in two, as follows:
CS111I. Introduction to Programming
CS112I. Data Abstraction
It is important to note that first course in either sequence -- CS101I or CS111I -- may well use an object-oriented language for its programming examples and exercises. What distinguishes this approach from the objects-first model is the emphasis and ordering of the early topics. Even if it is taught using an object-oriented language, the first course focuses on the imperative aspects of that language: expressions, control structures, procedures and functions, and other central elements of the traditional procedural model. The techniques of object-oriented design are deferred to the follow-on course.
The imperative-first strategy is subject to the disadvantages -- as well as the advantages -- of any programming-first implementation, as outlined in section 7.2. In addition, adopting the imperative-first strategy means that students will get less exposure to the techniques of object-oriented programming than they would if the curriculum followed the objects-first model. Given the centrality of object-oriented programming in the curriculum requirements and the difficulty students have learning to program in an object-oriented style, the fact that the introduction of this material is delayed to the second course is clearly a weakness in this approach. At the same time, students do need exposure to the traditional imperative style of programming, which remains in widespread use and which is an integral part of any object-oriented languages. Opinion in the community is divided as to which model should be presented first. Some argue that students who have learned the imperative model first have more trouble adopting an object-oriented approach. Others counter that students who have grown used to working in an object-oriented language will chafe at the idea of learning to work without those features that makes object-oriented programming so powerful.
In any event, institutions adopting the imperative-first model will need to include additional coverage of object-oriented design principles at the intermediate level.
The objects-first model also focuses on programming, but emphasizes the principles of object-oriented programming and design from the very beginning. As with the imperative model, we propose both a two- and three-semester implementation in this report, as follows:
CS111O. Object-Oriented Programming
CS112O. Object-Oriented Design and Methodology
The principal advantage in the objects-first strategy is the early exposure to object-oriented programming, which has become increasingly important in both academia and industry. The December 2000 announcement by the College Board that they plan to introduce a more object-oriented approach in the Advanced Placement curriculum underscores the importance of this approach [AP2000]. At the same time, the objects-first model does not specifically address many of the disadvantages common to programming-first approaches, as described in section 7.2. In fact, the problems of the programming-first approach can be exacerbated in the objects-first model because many of the languages used for object-oriented programming in industry -- particularly C++, but to a certain extent Java as well -- are significantly more complex than classical languages. Unless instructors take special care to introduce the material in a way that limits this complexity, such details can easily overwhelm introductory students.
The functional-first style was pioneered at MIT in the 1980s [Abelson85] and is characterized by using a simple functional language, such as Scheme, in the first course. Compared to the other programming-first implementations, this approach has the following advantages:
There are, however, some dangers in this approach. The first is that students may react skeptically to learning a language that they see as outside of the mainstream. For students who are already committed to computer science, it is possible to overcome this objection by exploiting the expressive power of these languages and showing how much students can accomplish using these tools. For students who are taking an introductory computer science course to test the waters before jumping in, and particularly for students who see the course as a way to learn some practical programming skills, functional languages are a much harder sell. The second danger is that this approach typically requires students to think much more abstractly at an early stage than is true with more traditional programming languages. While forcing students to think in this way is certainly valuable and needs to be part of the curriculum at some point, placing it so early can discourage some students with less experience in that style of thought.
To cover the material that is essential in the first year, an introductory course that follows the functional-first strategy must be followed by an intensive course that covers object-oriented programming and design. The sample courses that implement this strategy are
For many years, there has been concern in the computer science education community that the traditional "programming-oriented" introduction to computer science gives students a limited view of the discipline. Computer science, after all, is an ever-expanding field that includes many activities beyond programming. Courses that emphasize only this one aspect fail to let students experience the many other areas and styles of thought that are part of computer science as a whole.
To provide that more holistic view of the discipline, many computer science educators have argued for a "breadth-first" approach in which the first course considers a much broader range of topics. This approach was recommended strongly in both Computing Curricula 1991 and the earlier "Computing as a Discipline" report, which envisioned a curriculum in which "the first courses in computer science would not only introduce programming, algorithms, and data structures, but introduce material from all the other subdisciplines as well," making sure that "mathematics and other theory would be well integrated into the lectures at appropriate points" [Denning89].
Developing a successful breadth-first implementation, however, has proven to be difficult. In our surveys, the most common implementation of the breadth-first idea was to create an introductory "breadth-first" course that introduces the field to majors and nonmajors alike. Such a course gives students exposure to a range of interesting and important topics rather than plunging them immediately into the details of one specific area. Students who are interested in learning more about the field can then begin a "regular" one-year introductory sequence. Thus, most existing models involve the addition of a single breadth-first introductory course as the entry point into the discipline for all students. Students who complete such a course can then move on to any of the other introductory sequences with a much stronger perspective on the field.
The advantage of offering the breadth-first model as a lead-in to a more conventional programming sequence is that doing so gives students an immediate appreciation for the breadth of computer science, allowing them to more easily decide whether this is a field they do or do not wish to study in depth. The primary disadvantage of this approach, however, is that it adds one course to the size of the major and delays by a term the completion of the introductory sequence.
In our discussions, the CC2001 Task Force saw no reason why it would not be possible to create a successful breadth-first sequence, particularly if one abandons the view that the introductory sequence must be two semesters long. The basic idea is to take the material in the first-year courses -- the introductory programming sequence and the discrete mathematics courses -- and reassemble them in a way that provides early exposure to the breadth of the field. Unfortunately, we have not been able to identify any such models that meet our acceptance criterion of successful implementation by faculty other than the originator. We therefore have presented two separate implementations of a breadth-first approach:
Another approach to providing breadth in the curriculum is to offer a survey of the field after the completion of the introductory programming sequence. This "breadth-second" approach means that students begin with a programming-based introduction to make sure they have the necessary implementation skills but then have an early chance to appreciate the range of topics that are all part of computer science. While we feel that such an approach is worth pursuing as an experiment, we have not yet found models that meet our criterion for acceptance.
In this approach, the basic concepts of computer science are introduced using pseudocode instead of an executable language. By introducing students to basic algorithmic concepts and constructs apart from any particular executable language, this approach minimizes the preoccupation with syntactic detail that demands for successful program execution typically engender among students. Instead, it requires that students reason about and explain the algorithms they construct, tracing them by hand and mind. It permits students to work with a range of data and control structures without having to contend with the various peculiarities that popular programming languages inevitably introduce. Moreover, because students are freed from the need to execute their programs, this approach permits students to experience the range of such constructs more rapidly. Once students have a solid grasp of the algorithmic foundations and the range of data and control structures used in the pseudocode, they can then move on to a more conventional language, either partway through the first course or, at the latest, the beginning of the second course. Because students have experienced a wider range of both data and control structures early, their later progress through conventional programming work can occur more rapidly and class time can be more explicitly focused on issues of effective programming practices and systematic debugging skills.
By eliminating some of the time spent on syntax and the details of a particular programming environment, an introductory course that follows the algorithms-first approach can include additional theoretical topics, such as estimations of efficiency and the rudiments of computability. Doing so appears to be useful in two respects:
At the same time, the algorithms-first approach has several critical weaknesses. For one thing, students at the introductory level want to experience the power and satisfaction that comes from making computers actually do something. Courses focused only on constructing algorithms in pseudocode frustrate this motivation and desire. It is therefore useful to combine the algorithms-first approach with laboratory-based exposure to modern application software that provides students with applied computing experience. This strategy helps students develop a practical skill set that may be of greater relevance to nonmajors than conventional programming. By synchronizing the laboratory-and-project agenda in software applications with the lecture-and-homework coverage of algorithms, students experience the relevance of, for example, data structures in the context of database work, control structures in the context of spreadsheet development, and high-level design in the context of web page creation.
Relying on pseudocode, however, also has the effect of freeing students from the need to demonstrate that their algorithms work in the context of a functioning implementation. While the process of getting a program to compile and execute correctly is sometimes frustrating, it is also a critical skill that students must master early in their education. The process of debugging in the pseudocode environment is quite different from the process of debugging an executable program. The former is characterized by desk-checking and reasoning about the algorithm; the latter is usually more of function of interpreting symptoms and learning to do the detective work associated with finding programming errors. Both skills are important, and it is difficult to assess how the algorithms-first approach affects the students' facility with the debugging process.
The final concern about the algorithms-first approach is that it requires substantial grading effort. While it is certainly inappropriate to assess introductory programming assignments solely on successful execution in a set of test cases, being able to make such tests helps graders identify algorithmic errors much more easily. Evaluating pseudocode for correctness is a much harder challenge that typically requires extensive use of course assistants.
In this report, the algorithms-first approach is illustrated by the following courses:
The hardware-first approach teaches the basics of computer science beginning at the machine level and building up toward more abstract concepts. The basic philosophy behind this strategy is for students to learn about computing in a step-by-step fashion that requires as little mystification as possible. The syllabus begins with switching circuits, uses those to make simple registers and arithmetic units, and then embeds those in a simple von Neumann machine. Only after establishing the hardware foundation, does the course go on to consider programming in a higher-level language.
The courses that comprise this model are
Such an approach works well for students who prefer to understand the process of computation in all of its reductionist detail. It is less effective at encouraging students to see the holistic concepts beyond the mechanics of implementation. The hardware-first approach is also somewhat at odds with the growing centrality of software and the tendency of increasingly sophisticated virtual machines to separate the programming process from the underlying hardware. At the same time, we believe that such a course might be particularly viable in a computing engineering program, where early exposure to hardware issues is essential.
|
December 15, 2001 |
|