Chapter7
Computing Curricula 2001
Computer Science Volume
Chapter 7
Introductory Courses
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.
7.1 Overall philosophy
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.
7.2 Where does programming fit in the introductory curriculum
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:
- Programming is an essential skill that must be mastered by anyone studying computer science. Placing it early in the curriculum ensures that students have the necessary facility with programming when they enroll in intermediate and advanced courses.
- Computer science did not become an academic discipline until after most institutions had already developed a set of introductory programming courses to serve a much wider audience. By the time our predecessors began to develop computer science curricula, the antecedents of our introductory courses had already evolved explicitly as "skills courses" dating from a time in which programming was regarded primarily as a tool. Thus, computer science curricula were often built on top of existing programming courses, which never had the opportunity to evolve into a more broadly based introduction to computer science as a field.
- The programming-first model was implicitly endorsed by the early curriculum reports through the design of their recommended courses. Curriculum '68 [ACM68], for example, begins with a course entitled "Introduction to Computing" in which the overwhelming majority of the topics are programming-related. The centrality of programming in introductory courses was further reinforced by the definitions of CS1 and CS2 in Curriculum '78 [ACM78], which defined these courses as an "Introduction to Programming" sequence.
The programming-first approach, however, has several shortcomings. The most commonly cited objections to this approach are the following:
- Focusing on programming to the exclusion of other topics gives students a limited sense of the discipline, thereby reinforcing the common misperception that "computer science equals programming."
- Theoretical topics that would enhance the students' understanding of the practical material are deferred to later points in the curriculum, when they no longer have the same immediate relevance. This limitation has implications for both majors and nonmajors. Nonmajors who take only introductory courses are deprived of any exposure to the conceptual and intellectual foundations that underlie the revolutionary technological developments driving change throughout society. For majors, the fact that theory is not introduced in the early courses fuels the bias of many students who conclude that theory is irrelevant their educational and professional needs.
- Programming courses often focus on syntax and the particular characteristics of a programming language, leading students to concentrate on these relatively unimportant details rather than the underlying algorithmic skills. This focus on details means that many students fail to comprehend the essential algorithmic model that transcends particular programming languages. Moreover, concentrating on the mechanistic details of programming constructs often leaves students to figure out the essential character of programming through an ad hoc process of trial and error. Such courses thus risk leaving students who are at the very beginning of their academic careers to flounder on their own with respect to the complex activity of programming.
- Introductory programming courses often oversimplify the programming process to make it accessible to beginning students, giving too little weight to design, analysis, and testing relative to the conceptually simpler process of coding. Thus, the superficial impression students take from their mastery of programming skills masks fundamental shortcomings that will limit their ability to adapt to different kinds of problems and problem-solving contexts in the future.
- Programming-intensive courses disadvantage students who have no prior exposure to computers while giving the illusion to those who have previously used computers that they know more than they really do. As a result, students who are new to computing are often overwhelmed, while students who have a prior background often simply continue bad habits.
- Programming-first approaches can lead students to believe that writing a program is the only viable approach to solving problems using a computer. The power and versatility of application programs have increased substantially in recent years, and it is important for students to recognize that such applications can be extremely effective as a problem-solving tool without the need for classical programming. This concern is particularly relevant to nonmajors, whose problem-solving abilities and sense of empowerment can be significantly increased through a knowledge of modern applications.
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 most institutions (at least in the United States), the primary audience of the introductory computer science course consists of students outside of computer science who are seeking to acquire programming skills. Departments that adopt a programming-first strategy can use a single course for computer science majors and nonmajors alike. If an institution adopts an alternative strategy that serves only its majors -- even if it is arguably superior pedagogically -- that institution may then need to offer additional programming courses to satisfy the demand from other departments.
- Programming is a prerequisite for many advanced courses in computer science. Curricular strategies that delay mastery of fundamental programming skills make it harder for students to take as many advanced courses as they would like, since they do not have the necessary background until a later point in their studies.
- Students often like programming more than other aspects of the field. Programming-based courses therefore tend to attract more students to computer science.
- Programming courses offer skills and training that meets many of the needs expressed by students, their near-term employers, and non-CS faculty.
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.
7.3 The length of the introductory sequence
Although the philosophy and structure of introductory courses have varied widely over the years, one aspect of the computer science curriculum has remained surprisingly constant: the length of the introductory sequence. For several decades, the vast majority of institutions have used a two-course sequence to introduce students to computer science. In the computer science education community, these two courses are generally known as CS1 and CS2, following the lead of Curriculum '78 [ACM78]. While the content of these courses has evolved over time in response to changes in technology and pedagogical approach, the length of the sequence has remained the same.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.
7.4 Integrating discrete mathematics into the introductory curriculum
As we discuss in Chapter 9, the CC2001 Task Force believes it is important for computer science students to study discrete mathematics early in their academic program, preferably in the first year. There are at least two workable strategies for accomplishing this goal:- Require computer science students to take courses in discrete mathematics concurrently with the introductory sequence. The course descriptions in Appendix B include two implementations of a discrete mathematics course: a one-term course (CS115) that covers the bulk of the material in the Discrete Structures (DS) area of the body of knowledge in an intensive way, and a two-term sequence (CS105 and CS106) that covers the required material, together with some useful elective topics, at a slower pace that encourages greater thoroughness of coverage.
- Integrate at least part of the material on discrete mathematics directly into the introductory computer science sequence so that students can more easily appreciate how these mathematical tools apply in practical contexts. While it is certainly advantageous to adopt this approach for certain topics, it is important to ensure that students have sufficient exposure to discrete mathematics to provide the necessary mastery of the material. Given the size of the Discrete Structures (DS) area in the body of knowledge, it is impossible to incorporate all the required topics into the introductory sequence without adding an additional course to the introductory sequence. Typical implementations will therefore incorporate some material into the computer science sequence but retain a one-term course in discrete structures to complete the coverage. The three-course implementation of the breadth-first approach (CS101B/102B/103B) adopts this model of integrating the mathematical material directly into the introductory courses.
7.5 Expectations of the introductory curriculum
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:
- Introduces students to a set of fundamental computer science concepts
- Facilitates the development of cognitive models for these concepts
- Encourages students to develop the skills necessary to apply the conceptual knowledge
- Facilitates transfer by students from two-year colleges into four-year programs by establishing clearly defined outcomes and content equivalencies
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
|
Applications Web browsers, word processors, spreadsheets, data bases, e-mail systems Make effective use of standard computing applications
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:
|
7.6 Implementation strategies for introductory computer science
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.
7.6.1 Imperative-first
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:
-
CS101I. Programming Fundamentals
CS102I. The Object-Oriented Paradigm
CS103I. Data Structures and Algorithms
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.
7.6.2 Objects-first
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:
-
CS101O. Introduction to Object-Oriented Programming
CS102O. Objects and Data Abstraction
CS103O. Algorithms and Data Structures
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.
7.6.3 Functional-first
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:
- Using a language outside the professional mainstream reduces the effect of diversity in background, since relatively few students coming into college will already have experience programming in this paradigm.
- The minimalist syntax of functional languages means that courses can focus on more fundamental issues.
- Several important ideas -- most notably recursion, linked data structures, and functions as first-class data objects -- occur naturally in this domain and can be covered much earlier in the curriculum.
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
7.6.4 Breadth-first
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:
- A one-semester course (CS100B) that serves as a prerequisite to a more traditional programming sequence
- A preliminary implementation of a breadth-first introductory sequence (CS101B/102B/103B) that seeks to accomplish in three semesters what has proven to be so difficult in two
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.
7.6.5 Algorithms-first
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:
- For non-majors, it permits some access to the "science" of computer science.
- For computer science majors, it permits them to encounter appropriate aspects of theory from the very beginning of their course of study, minimizing the risk that they will later experience coursework in theory as an irrelevant curricular appendage.
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 first course focuses on algorithms and applications early, and then goes on to offer an introduction to object-oriented programming towards the end. The second course provides intensive coverage of object-oriented programming to ensure that students are up to speed on these techniques.7.6.6 Hardware-first
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
The first course in the sequence covers the computer from the bottom up; the second uses that foundation to build up the programming skills of the students and to give them a solid introduction to object-oriented techniques.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.
![]() |
CC2001 Report
December 15, 2001 |
![]() |



