This might fall under the category of “things that should have been obvious”, but teaching programming is vastly different from teaching English.
They are moving towards a goal – to write an interactive quiz, game, or storybook to use for the young learners in our school. I try to explicitly relate each new concept or tool to one of these goals, but I don’t really know a way to explain why you need to know how variables work in order to code a game without boiling it down to “you just do, and you’ll have to trust me for now”. You know – the answer we all hated to get from teachers.
I bring up variables because one piece of research (.pdf) I turned up in my investigation into the (relatively young) field of computer programming pedagogy indicated that the workings of variables were the first of three major intuitive hurdles that potential programmers would need to surmount in order to have any degree of success in the field. Armed with this knowledge, I left plenty of time for my students to get accustomed to assignment and sequencing concepts and designed some problems meant to illustrate how assignment works and doesn’t work.
An interesting thing I noticed was that my students almost universally agreed that after the statement “x=y;” was entered, any subsequent modifications of x would be applied to y, and vice versa. In other words, they viewed the assignment as establishing a relationship between x and y, rather than just making a copy of y and putting it into x. I don’t have enough background in the conceptual roots of programming intuition to draw any kind of conclusion, and anyway it’s a small sample size (about 50 students in five sections), but this jumped out and I wanted to share.
In any case, I asked them to implement a small program to test their theory (just assign values to x and y, perform the assignment, then reassign one of the variables and output the result) and they all went “hunh, that’s not what I thought would happen,” and I explained it and we moved on. I would consider the lesson a success, except that one student asked “why do we have to learn this?” and I didn’t have an answer (see above) even though I wanted to shout, “are you kidding me? this could be the single most important concept in determining your success as a computer scientist!” and so instead I just had mixed feelings – I had successfully guided my students over this first hurdle, but also somehow bored them in the process.
And that’s the tricky part, because there’s a balance to find between the kinds of abstract, conceptual problems that are going to help the students form accurate mental models of what a computer is and what it does, and the kinds of concrete problems that are going to give the students that feeling of “I did this!” and the ability to show off to their community. I could just teach them how to patch code samples together and substitute their own questions to make a quiz or a game, effectively teaching them nothing about programming and essentially mimicking the work they’ve grown accustomed to doing with PowerPoint and Flash, but I have aspirations.
Also, I’ve always been an algorithms guy – interested in the problem for its own sake, rather than for the sake of creating a product – and so I can’t really relate to the students who just want to be able to write their own version of Flappy Bird and have no patience for all this “variables” nonsense.
The real challenge of this class is that I have to design a series of small tasks that, collectively, maintain in students a consistent sense of achievement (they have to feel like they’ve solved some small but meaningful problem on a regular basis – ideally at least once per lesson), a consistent sense of interest (they have to feel that what they are learning is building towards what they want to do, and not either a tangent or some arcane academic trifle oriented towards some vague future reward), and a consistent progression towards the actual ability to program (the tasks have to actually get the students over the conceptual and practical hurdles of programming).
This is even trickier than it sounds.
In any case, I’ve made some observations based on my experience in the classroom, and connected to some of the theory that’s out there, and I’m working towards an understanding of what some good practices or strategies might be. Viz:
- I had a theory that teaching based on Notepad and a browser would confer several benefits, and so far I am pleased with the results. It means that students can work on any computer anywhere (for a Mac they have to learn how to configure TextEdit, but still) without even needing an internet connection. It means that students can immediately produce results that they can easily share with anyone with a computer or publish on a personal webpage. It forces students to learn to manage their own files. It forces students to be careful with syntax because there is no error highlighting, which in turn trains students’ attention to detail. It allows me to move seamlessly from the HTML/CSS unit to the JS unit.
- Starting with HTML/CSS was also good. The HTML/CSS unit builds basic programming skills – and confidence – without forcing students to confront the intuitive hurdles early on. For instance, it sneaks in a kind of assignment: typing ‘src=“screen1.jpg”’ subtly and non-invasively reinforces the idea that the “=” is for assigning a value, not asserting equality. It also lets the students handle user input/output in a way they are familiar with, without the weirdness of byte streams, console input/output, etc. that are a sort of logistical overhead that often confounds a student who is grappling with the conceptual aspects of coding. This is all especially true with HTML5 (I can’t wait to start using the canvas element to painlessly teach graphical output). Basically, you don’t lose any of the rigor of programming by teaching web-only programming, but you do toss aside the stuff that will only become relevant if the student becomes a professional.
- Some of the students have started to pick up on my troubleshooting methodology. I have gained a strong sense of what the common errors are in the class and a rough order of likelihood (syntax is common, as you might expect – but it’s also very common for my students to save multiple copies of a file on the same computer and have one copy open in their editor and a different copy open in their browser, which I didn’t really expect but which helps the students learn to organize their files better than if I just let them use an IDE and eliminates the sense of dislocation I often feel when working with files in an IDE). I now see a small but growing number of students helping their neighbors using the same tactics I use (for instance, going into the Save As dialog to check where the file they are currently editing resides, and correcting obvious syntax errors). I am considering the merits of explicitly teaching a debugging flowchart rather than simply modeling this technique – the modeling seems to be working, but maybe an explicit lesson would work better? (See also: Why Don’t Schools Teach Debugging?)
- My students in particular respond better to problems of the type “take this model and modify it” than to problems of the type “take this information and act on it.” For example, almost all of my students were able to take their “Hello World” programs – a button that, when clicked, pops up an alert window that says “Hello World” – and, with very little help or prompting, modify them into a one-question quiz in which each answer had its own button which popped up its own alert window with either “correct” or “incorrect”. Practically, this is not a particularly difficult problem, but it is complex in the sense that it requires coordination between HTML elements and JS functions and knowledge of things like where attributes, arguments, and statements go. On the other hand, when we did our variables lesson, none of the students were able to arrive at the solution to the question “how can we switch the contents of two variables?” without significant help and prompting, even though the solution requires nothing outside of the problem’s immediate context, and can be solved in three lines using the exact two techniques (variable declaration and assignment) that we had spent that lesson focusing on and practicing. I’m not sure if this had to do with interest level, or level of abstraction, or something else, but it does give me pause about some of the other conceptual exercises I would have otherwise planned in order to introduce later topics.
It might be better to show students simple, working code examples that demonstrate a particular concept and also do something interesting, and have the students work through how and why the example works. I don’t like the idea of depriving students of the thrill you get the first time you figure out “var z = x; x = y; y = z;” on your own (I remember it from when I was their age), but since most students don’t really seem to get that thrill (I was in an elective CS class, whereas this is a mandatory school-wide program) it might just be a better service to the class as a whole to learn from dissecting and modifying examples rather than from trying to stimulate intuitive leaps that some students will never make.
I want to stress I don’t mean just telling students the answers. I mean something more like this – letting the students gain insight through a guided tour of some code, rather than through just happening to be the lucky student whose mind has been trained to produce code-like insights. This is another brick in the foundation of the growing idea I have that learning to code, and coding, can be made more systematic, and less intuitive, and that therefore – like long division – everyone can, and should, be able to learn to do it.
Also, the skill of examining a program for meaning is highly valuable in itself, and also probably under-taught in computer science programs. My CS degree program (which I dropped, in favor of Political Science, after two years) focused on algorithms, data structures, discrete math, etc. – the usual stuff – but I have the impression that in the professional programming world you will end up working on someone else’s code a lot (for instance, if you collaborate on open source projects) and I don’t recall ever taking a class that started with code samples and worked backwards to discover the technique or solution being used, rather than the standard format of starting with a problem and working towards implementing an algorithm/data structure/whatever to solve it.
If this technique can indeed help make learning to program less intimidating/more accessible, and can provide more concrete goals for students to work towards, while also teaching a valuable skill that is often missing from formal education, then I’m all for using it – as long as it’s also counterbalanced with a healthy amount of from-scratch program development. After all, I don’t want to turn out students who can’t write FizzBuzz.
So this is probably my longest post ever, but I’ve been teaching CS for six months now and haven’t said a thing about it, so I’m actually cutting myself off short here. That said, six months isn’t all that long, so if any of you have any experience at this sort of thing and want to throw in your ideas/advice/cautions, I’d love to hear them.
Also, big, giant hat tip to Danielle Sucher for being my conduit to many of the programming articles that I linked to in this post.