Chapter 3

CS Teaching Approaches

Chapter 3

Computer Science Teaching Approaches

Subsections of CS Teaching Approaches

Introduction

Now that you understand more about what computer science is, and how we learn it, we can turn our attention to pedagogy and tools for effectively teaching computer science. Remember, our goal is to help students develop cognitive structures that help them read and write programs and solve problems with computational thinking. Ultimately, there is a lot for students to learn in order to engage with computer science effectively. We therefore need to carefully scaffold our teaching efforts to help minimize the cognitive load our students encounter as they develop the mental structures they need to reason about both programming and computational thinking. We need to keep the students in the zone (the zone of proximal development)!

This chapter will discuss tools and teaching techniques to help manage this cognitive load.

CS Unplugged

Learning computer science can be hard - you’re trying to learn the skills of computational thinking and a new language at the same time. Consider what it would be like learning algebra for the first time in Spanish at the same time you were learning Spanish, and you’ll get the idea of the challenge.

Of course, there are important differences:

  1. With a language like Spanish, a skilled speaker will be able to interpret your meaning even if you don’t quite follow the grammatical rules of the language. A computer will not - you must follow the rules exactly!
  2. A programming language contains a much smaller vocabulary and fewer grammatical rules than a human one like Spanish, so there is ultimately less to learn.
  3. Programming languages typically use English words, so you don’t have to learn a whole new set of words and meanings… except the way a programming language uses those words doesn’t always line up with our expectations based on the English language - this makes for some significant gotchas.

CS Unplugged curriculum is an attempt to sidestep the programming language challenge entirely, and focus on teaching computational thinking with no computers at all. Instead, it teaches the concepts through games, puzzles, and lots of physical real-world action.

Based on our readings from chapter 2, you probably realize that we need to incorporate use of an actual computer and programming language to help our students develop an accurate internal notional machine to guide problem-solving efforts to utilize a computer. And indeed, research into CS Unplugged suggests that by itself, it does not help students become better programmers. This is actually part of a broader issue of knowledge transfer - humans are not great at taking what they learn in one domain and applying it in another, without guidance on how the two connect.

But combining CS Unplugged activities with the other strategies laid out in this chapter can be a recipe for success. When you do so, be sure to explicitly call out the connections between the various activities to help your students see how it all connects.

Block-based Programming

In learning a programming language, few tools have been as powerful for reducing cognitive load on students learning computer science as block-based programming. In a block-based programming environment, instead of typing program code, you drag and connect graphical blocks representing program code. This means students don’t have to remember and reproduce the exact spelling of program syntax, and blocks can only ‘snap’ together in grammatically correct ways. This eliminates the possibility of making two of the most common families of errors novice programmers face - syntax and grammar errors - and allows them to focus on learning how to solve problems with programs.

The Scratch programming environment The Scratch programming environment

While any programming language could be presented in block-based form, a number of pedagogical programming languages (programming languages specifically developed to be easy to learn) have been developed using this approach. These include MIT’s Scratch (pictured above), Berkley’s Snap!, and Google’s Blockly.

Scratch is especially used in elementary and middle school education. It is completely browser-based, and can run on any computing platform (PC, Mac, iPads, Android tablets). It is a multimedia programming environment, where programs can control sprites on a virtual stage. If students create an account, their work is also saved to the cloud, so they can edit their programs both at home and school. Scratch also has plugins for programming many popular robotics and electronics kits. Finally, numerous curriculum resources exist to support teachers interested in using it: Scratch’s Educator Guides, ScratchEd’s Creative Computing Curriculum, Google’s CS First Curriculum, and my own Scratch K-12 Curriculum Materials.

Snap! is similar to Scratch in many ways - it also browser-based and can run on any platform, and provides a multimedia programming environment. It also sports many plugins for robots and electronics. However, its colors are more muted and its blocks are smaller, helping it feel more “professional”. And while Scratch’s core focus has always been approachability, Snap! focuses more on providing additional functionality found in other programming languages (like the recently added map and combine functions). This makes it more powerful, but at a cost of additional complexity. As such, it is less a beginner programming environment than an opportunity for students who have mastered Scratch to explore more complex programming approaches. The Snap! Manual. describes these ideas in detail. Berkley offers a companion curriculum, Beauty and Joy of Computing.

Google’s Blockly is not a stand-alone programming environment, rather it is a tool for creating such environments (in fact, Scratch uses Blockly for its blocks). Blockly is also the basis on which the Code.org programming environments are built, as well as MIT’s App Inventor, which allows you to create Android and iPhone apps using a block-based programming approach.

Parsons Problems

Parsons problems are another commonly used tool for reducing the cognitive load of learning to program. A Parsons Problem gives the student all the lines of code needed to complete a task, and asks them to arrange them in order. While this can be done on paper (by marking an order), they are commonly delivered using a drag-and-drop interactive interface that also allows the student to verify they have completed the task correctly:

Parsons Problem Example Parsons Problem Example

Parsons problems can be used with any programming language, including text-based ones like the Python example above. But they offer some of the same benefits of block-based programming: the student doesn’t need to remember the exact syntax constructions - just recognize them and be able to order them correctly.

Thus, Parsons problems are commonly used to practice syntax as students are learning it. Additionally, they are commonly used in assessments. You can fine-tune the challenge of a Parsons problem by “fixing” some of the solution lines in place (so they aren’t draggable, and by adding detractors (lines that don’t actually belong in the program).

Code Tracing

Moving beyond tools for reducing cognitive load on our students, let’s turn our attention to specific activities we can employ in our teaching. Perhaps one of the most important, and commonly overlooked, is reading code. Think for a moment about how writing a program is like writing a story or essay. You wouldn’t ask a student to write a story until after they have read many examples of stories, would you? Likewise, when we introduce essay writing, we first have students read many good examples of essays. The same should be true of programming - students learn to write good programs in part from reading good programs.

But how do we read a program? There is a specific strategy we employ known as code tracing, and it refers to evaluating what happens in a program on a line-by-line basis. You start at the entry point of the program - the first line that is executed (often the first line for many programming languages, though for C/C++, Java, and C# it will be the first line in the main method).

Then, for each line, you determine what that line is doing. If it carries out a calculation, you carry out the calculation. If it declares a variable, you draw a box on a piece of scratch paper to represent the variable. If it assigns a value to that variable, you write the value in the box. If you reach a branching point (i.e. an if statement), you determine which branch to follow based on its test condition. And if you enter a loop, you repeat the lines of code in the loop until its test condition is no longer true.

Below are some example videos walking through code tracing with Scratch and Java:

The Developmental Epistemology of Programming we discussed in the prior chapter claims that when students are able to trace code with greater than 50% accuracy, they have moved into the preoperational stage, which marks initial readiness to start programming. Remember, that stage is specific to each code construct, so as you introduce new operations (like loops) you will need to repeat code tracing with examples of the new syntax.

It is also important to note that as students develop cognitive structures to reason about programs, they will need to perform line-by-line code traces less and less. Eventually, they will be able to recognize the purpose of multiple lines of code at a glance, i.e. when presented with this code:

bool sorted = true;
for(int i = 0; i < numbers.length -1; i++)
{
  if(numbers[i] > numbers[i+1]) 
  {
    sorted = false;
    break;
  }
}

They will recognize that it is testing the array numbers to determine if it is sorted in ascending order. This ability to recognize the purpose from a pattern of code corresponds with the Formal Operational stage.

Live Coding

An approach that has been used to teach computer science for many years is Live Coding (also known as Demonstration Coding or Apprenticeship Coding). In this strategy, the teacher models the activities of solving a problem and writing the corresponding program in front of the class.

An important aspect of this approach is explaining your thought process as you approach, think about, solve, the problem and write the program solution. By exposing your thought process out loud, you are guiding your students to think about their own processes.

It is a good idea to work through the problem and solution you want to demonstrate several times before you present it to students - but be sure to keep notes on your thought process during your first attempts so you can present it accurately. You don’t want to present students with a perfect step-by-step process; doing so will give them an unrealistic expectation of what programming should be. Showing them how you encounter and debug errors will help them understand that it is a normal part of the programming process. But you also don’t want so many that it derails the momentum of the lesson.

Live coding can be used with any part of working in CS, and combined with many of the pedagogical approaches we will discuss shortly.

Finally, some teachers have students “follow along” - write the same program the teacher is demonstrating. This can be helpful for getting students more practice programming and keep students’ attention focused on the lesson. But it also adds additional cognitive load, and may result in students missing some of the benefits of your modeling as they focus on getting their program to match yours. Also, you may find that students want you to move at different speeds - some want to go fast, while others will need you to slow down to get everything written. For large classes, this can become a major challenge. A good alternative for follow-along live coding is pre-recording a programming session and providing it as a video for your students to use. This allows them to proceed at their own pace, and also go back to review parts they missed.

Pair Programming

Peer programming is a technique where two students work together to create a program solution. One student takes on the role of the driver, and writes the actual program code, while the second is the navigator, who provides guidance on what code needs to be written. In effect we are reducing the cognitive load in that each student only needs to tackle a subset of the challenges in writing software. The navigator is primarily employing the skills of computational thinking, while the driver is primarily engaging in programming.

This approach also means two pairs of eyes (and the minds behind them) are seeing the code as it is written, which can help increase the chances that simple mistakes (like typos, using the wrong variable name, etc.) will be caught early. It also encourages the two programmers to discuss strategy and plan rather than jumping into programming blindly. For many of these reasons, pair programming is also used in professional practice.

Coaching

As students gain knowledge and skills in programming, we want to provide less structured scaffolding and allow them to develop more independent problem-solving skills. However, it is still common for a student to encounter an issue that is beyond their ability to solve even after they have developed significant skills (in fact, expert programmers still often find themselves confronted with a challenge they aren’t sure how to tackle). If students are left to struggle too long, frustration sets in, and learning is derailed.

Thus, as we move towards more independent programming, we want to shift to the role of a coach or mentor, and watch for those high levels of frustration and step in to provide guidance. It is important not to step in too early - as we can unwittingly relieve the cognitive dissonance the students need to be encountering to learn. But it is also important not to let them struggle too long with a problem beyond their current understanding.

Also, when coaching, be very careful not to ‘solve’ the issue for your students. Keep your hands off their keyboard and mouse! Ask them leading questions to help them find the answer themselves, and have them add it to their programs themselves.

Peer coaching - allowing students to help each other - can also be a powerful tool. In peer coaching, more experienced students coach less-experienced ones (Note this is different from peer programming, in which the students are at a similar level of proficiency). However, peer coaching should be closely monitored, as bad interactions can discourage learners and dampen interest in computer science entirely.

Summary

In this chapter we explored tools and techniques for teaching computer science and limiting cognitive load. These include approaches that simplify the use of programming from eliminating it altogether (CS Unplugged) to providing a drag-and-drop interface to remove the need to type syntax correctly (block-based programming and Parsons problems).

We also discussed the importance of reading code for comprehension, which helps to develop the student’s internalized notional machine for the programming language they are learning. Likewise, live coding - modeling our development practice for our students can help them develop the skills necessary to write their own programs. Finally, peer programming and coaching can help support students as they continue to develop their own proficiency.