Thursday, March 30, 2006

Teaching Computer Science

Computer science suffers from a problem that's almost unseen in nearly any other major. It is tied closely to technology, the kind of technology that changes in the space of a few years. In many subjects, language, most sciences, mathematics, many social sciences, the lectures that were given twenty years ago are often suitable for today.

That's not the case in computer science. Twenty five years ago, assembly language programming was common. Fortran was widely taught. By the early to mid 1980s, Pascal was gaining a foothold in computer science programs throughout the country. There weer a few oddballs like MIT which taught (and continues to teach) Scheme. By the 1990s, Pascal was being replaced by C++. The late 80s saw industry adoption of C++ and the goodness of object-oriented programming. As usual, universities lagged behind, wanting to know whether this was a trend they should bother with.

By 1995 and the advent of the web, Java was starting to get major play. Computer science departments who had avoided C++ because they couldn't stand its complexity quickly leapt onto Java. Those who stayed with C/C++ were given a push to use Java when the AP exam, the exam used in high schools throughout the country to give college credit to high school students that score well on the exam, moved to Java about a year ago.

Those who had taught Pascal liked it. Pascal was specifically designed to be used in the classroom. It was not seriously used in industry, which was using C, then C++, then Java and C#, and now, Ruby. Those who learned to program in Pascal or in FORTRAN learned to code in a procedural way.

The switch to object oriented programming was not an easy leap for teachers, some of whom continued to think in very procedural ways. Procedural programming, in a nutshell, is like a recipe, do A, then do B, then do C. There are decision steps, such as, if you work more than 8 hours, add overtime and of course, functions, which encapsulates chunks of work.

Programming in Java or C++ does not automatically mean you are doing object oriented programming. Some have coined the term object-based programming, which is programming with objects. Most people argue that true OO programming requires inheritance, or at the very least, use of interfaces.

To give you a sense of what I mean by procedural thinking, I relate a tale. I was once co-teaching a course. The person created a project that had something to do with strings. The specs required a three step process that involved removing spaces, converting to lowercase, and one other step. Each of these three steps were three seperate methods in a class. Students were expected to use these methods one after another.

I know the thought process behind this thinking. In the 80s, and even beyond, teachers taught beginning programmers to break a problem down into smaller pieces. Eventually, the pieces would be so small as to be easily coded. This was stepwise refinement. In general, it's a very good idea for solving a problem, not just a coding problem.

However, having objects with multiple steps publicly simply doesn't make sense. These steps are there to make the task of writing the program easier. Objects should have methods that makes sense to be called. If the implementation requires multiple steps and multiple functions, that's fine, but those methods should be private.

A useful exercise when you're starting to do OO programming is to think about what kinds of operations the class should support, and to think of it independent of the task to be done. Very often, students come up with methods that are specifically aimed for the task, but would be untouched in other contexts. For example, look at Java's String class. Is there an encrypt function? Is there a function that causes it to compile a small bit of Lisp code?

Learning OO programming typically requires you to rethink how you solve the problem. The first step is to think about which objects/classes you think you need, then to think about what operations these classes should support, then to use the objects to solve your problem. Procedural programming decouples data and control. OO programming tries to unify the two. OO programming attempts to provide programmers the ability to create their own abstractions. Procedural programming generally forces you to use the abstractions provided (arrays, pointers, etc).

But this isn't really supposed to be a lecture on how to teach OO programming for those who still think procedurally, but to point out that teaching programming often requires changing one's view of programming, and that's tough.

Let's compare computer science to another field: mathematics. There are advancements that occur in mathematics, too. Mathematicians continue to come up with new techniques for proving things. New developments in those fields are not taught in introductory classes because they require such sophisitication that several years of grad school are often needed before one is ready to use those techniques.

That's not the case with computer science. If the field is changing, the changes can ripple all the way down to introductory level courses. Those changes don't even have to do with things that are traditionally thought of as programming. For example, if you're coding in Java today, you may be using the popular IDE, Eclipse. This is a great, great tool for coding in Java, but it is very complex. A 500 page book might only scratch the surface of all the functionality Eclipse has to offer.

If you're experience with typing code is Wordpad, then you might wonder why you need functionality that you never knew existed.

And, as software engineering principles are used more widely, IDEs, like Eclipse, have support for CVS, unit testing, and build support. These are topics that were unheard of even ten years ago, despite the fact that version control has been around for a while. Teachers of programming would argue that version control isn't about programming. Indeed, few books on introductory programming even touch the topic. Are there lectures on how to manage branches? How to handle merges? What a conflict is? How diff works? These are not only complex, but rather tedious. And yet, what working programmer doesn't use some kind of version control every single day?

Teachers will ultimately say to you "we can only teach so much". It's a point that's very valid, but the funny thing is, many of those teachers don't have any idea where it should be taught, and frankly, wonder why it has to be taught at all.

And this raises a particularly interesting thought. Can we teach programming without resorting to technological advances? Fundamentally, we can think of a program in terms of basic constructs: conditional statements, loops, functions, objects. Other languages have other constructs (closures, continuations, etc) that are useful. Many of the challenges of writing modern software is managing a large number of people's code. This is why version control was so important. It's not a perfect solution by any means. To some, it is still some magic ritual they wish would simply go away.

Now, consider that teacher who taught in C, with one single file, no makefile at all, and it compiled to one nice executable. How did that morph into Ant files, Jar files, an IDE that requires hundreds of pages to explain, version control, unit tests, project structuring, not to mention things that are actually code related, such as architecture design.

Furthermore, fewer and fewer people write software from "scratch". Let's say you want to run a website. There are now half a dozen books or more that tell you how to set up Apache (a web server), PHP (server side coding), and MySQL (database). Most people aren't programming from scratch anymore, because it's far too daunting to do so. If you need real database capabilities, you want to get one, not code it yourself. (On the flip side, some people use databases for all sorts of data storage, when a text file can do the job with less overhead and fuss).

I remember hearing a professor recount a story of another professor complaining about teaching data structures. He wondered why he had to learn object-oriented programming just to teach data structures. He had been teaching it for twenty years, before OO programming, and the data structures hadn't changed. You drew circles to represent nodes and arrows to represent pointers. The actual syntax was something they didn't want to deal with.

Now, keep that thought in mind. I'm about to take a tiny detour, before returning to this idea.

A few weeks ago, I was attending one of the ETECH talks, on the last day, a Thursday. For most of the conference, we were on the second floor. For whatever reason, O'Reilly didn't have enough clout to stay there the entire time. On Thursday, we were moved up to the third floor, which was a bit more cramped, but did have a nice view of the water.

One of the talks was titled Learning 2.0, which is one of those awful titles that's almost good because you remember it. It's a riff on Web 2.0, which, in a nutshell, is the evolution of the browser and webpage from something that links one page to another (hypertexting) to rich client (i.e., desktop-like) applications, so your webpages seem more like interacting with Word and Excel, not clicking on links to new pages.

The name Web 2.0 has been derided some. Giving it a version number just seems silly. (Are we to follow that with Web 3.1 and Web XP). It makes it sound like a product or a technology, when it's certainly not a product, and isn't quite a technology either (though certain technologies, mainly Ajax, are giving web pages richer interaction).

Given that you know that, the phrase Learning 2.0 would seem to have something to do with Web 2.0, but only in the vague sense that as the web is evolving, perhaps learning is too.

The presenters are wondering why O'Reilly (who they represent) haven't made much inroads into universities. To remedy the problem, they've started talking to teachers, and apparently, those that they spoke to want the ability to create their own textbooks.

Now, let's step back and think back to our college days.

Sure, there was that one professor who had written his (or her) own book, and of course, made that book required. How many students recall teachers who teach out of their own books fondly? Most don't. Most aren't Michael Sipser, who wrote a book on theory of computation, and seems to be a dynamic lecturer, if comments in the Amazon web page of his book are to be believed.

These teachers were the exception. In computer science, think of how many teachers developed their own material at all? I had a professor once, who taught a grad course by borrowing the complete lecture notes from someone else. I knew another prof. who did just the same for an undergrad course. To be fair, those notes were pretty good, but it can be challenging reading someone else's Powerpoint. I knew another guy who asked me (since we were covering the material) what to teach later that day.

How many professors do you recall who, despite being brilliant, spent almost no time preparing for class? I recall a prof. who would work through a proof, and would get stuck, and think and think and think. I'm a Ph.D. in theoretical computer science. I don't need to prep for class. And yet sitting and watching someone mess up a proof is highly distracting. Even if a person recovers, the student typically doesn't.

I've seen a prof. who takes a projector, and blows up a technical paper on the wall to display, pointing to a few key sentences, and delivers a lecture that way, typically because he just read the paper earlier, found it fascinating, and lacked the time to write it up properly.

And, there are those who haven't programmed in any real way in twenty years. I always admired a theory professor I knew for reading up on C++, Java, OpenGL, and so forth, so that he was up-to-date. He didn't have to do any of that. He mostly taught theoretical courses (although, he did cover graphics, but he didn't have to do that either). His colleagues in theory thought it was a waste of time to fill up their heads with syntax they weren't going to use or remember.

There was something purer about just thinking about math. The notation stays consistent. The proofs written yesterday are good today, good tomorrow, and good in twenty years.

To be fair, some of those things are changing. People who are graduating today with Ph.D's often are far more well-versed with programming than those of the last "generation" who were really only computer science professors in name. In practice, they're applied mathematicians.

They view syntax as fad. They view version control and unit tests as fads. Things that distract from real problem solving.

Attendees at ETECH are at the other end of the spectrum. They are all about fads. They are all about buzzwords, and they feel no guilt, no compuction, no remorse about this. This is where the cool things are happening. This is the realm of the alpha geeks. They want the concept cars of tomorrow, today. They don't mind filling their heads with the latest trends. Mashups, tagging, social networking, the attention economy. That's where things are at today. Design patterns? That's a decade old. J2EE? Man, we're Ruby On Rails.

So, that's where we are. On the one hand, professors who decide it's easier to present someone else's lecture notes, or who go without prepping, trying to teach what's on the cutting, no bleeding edge. And O'Reilly's solution for this is to have teachers come up with their own books?

Oh Really? (I couldn't resist)

If O'Reilly really (I couldn't resist again) wants to help out with computer science teaching, they should use their position in the technical world to filter out the most important pieces of information and pass that onto teachers. Now, to do that, they'll have to interact with teachers more.

While I was at ETECH, I thought it might be cool to teach programming to APIs by doing mashups. This would have several benefits. First, it's a lot cooler than writing some banking application that computes compound interest. Second, it gets people to do something that's "real". Third, it's exactly the kind of social geek behavior that web services is promoting.

But present this idea to a teacher, and they're likely to tell you "But why should I do that? They don't need to do that to understand programming?". On the one hand, that's absolutely true. You can teach people to program with the same kinds of toy programs people used twenty years ago. The fundamental aspects of programming are roughly the same as they've always been.

On the other hand, it takes students away from the kind of "revolution" that is happening on the Internet, the kind that people living in their ivory towers often miss because they're caught up with research, the folks who missed the OO bandwagon, and the folks who certainly don't care about Ajax or its subcomponents Javascript and XML. How do you tell them that the things that are so important to alpha-geeks should be important to them?

One thought I had was a one-stop web shop. I have a friend who's Ph.D. thesis is about doing analysis on programming habits of introductory students. The key is to commit the student's code every time they save or run their code. This information can be used to track the evolution of a program. It uses an Eclipse plug-in to do the work, and requires CVS to be setup somewhere, and therefore, requires an Internet connection.

But once all of that is in place, students can submit their projects (in Java), and the system will run unit tests and provide feedback.

Here's the idea. A school or university subscribes to this service for some fee. Included with the service are columns that explain the latest ongoings in the world of programming. The key here is to figure out a minimal set, and order them properly. It shouldn't devolve into Dr. Dobbs with a dizzying array of technical topics which the person teaching won't care about. However, it should justify why certain things should be taught.

Furthermore, the site should have some projects people can try out using the new technologies. All the hard work is done by such a site. They figure out what new technologies seem important enough to learn. They provide articles explaining how it works. They provide projects that students can try out. They provide the mechanism by which students can submit their projects, and have it automatically graded.

Now, perhaps, even this notion of teaching programming in this way will disappear, but for now, it's a nice evolution to the way we teach programming now.

No comments: