Compy Ed: Blogging about Computer Science Education

Saturday, September 30, 2006

Who To Teach To?

Filed under: computer science, education — compyed @ 3:34 pm

As a teacher, you have to decide how challenging a course ought to be.  I recall, once, when a non-faculty teacher was teaching a senior data structures course.  Notice I said senior.  Most universities teach data structures to first or second year students, not fourth year students.  Indeed, if you pick up a data structures book meant for college use, you see data structures such as stack, queues, heaps, binary trees, and perhaps one or two complex balanced tree structures (red-black trees, AVL trees).

This teacher thought he was teaching at this level, so he assigned a binary search tree as a project.  Part of the problem was that he didn’t seem to consult anyone about what level to teach this class.  As traditionally taught, this senior level data structures course covered advanced data structures such as B trees, but also spatial data structures (meant to store coordinates, lines, etc. in 2D and 3D).  There are other complex structures, such as Fibonacci heaps, and even data structures so complex that algortihms researchers generally talk about the data structure, rather than implement it.

There’s some level to go up, if you want to get really complex.

The teacher’s mistake, one of not consulting those who taught the course, was a problem. It’s certainly possible, given the unique nature of this course, that he didn’t know about these other data structures, and either was embarassed over the fact, or, even as a Ph.D. unwilling to learn the nuances of the data structures and implement it.  After all, it’s so much easier to teach something you already know, even if it’s been a while since you’ve seen it, than to teach something you have to learn.

More than likely, if you’re teaching for the first time, you’ve been given a book and a syllabus from the course taught before.  You can look at exams to get a sense of the level of difficulty, then decide how difficult the course should be.

Difficulty can be measured in different ways.  For example, you can make the course “easy”, at least conceptually, but be a hard grader.  You can make the course intellectually challenging, but make the grading easy (or hard).  You can make the programming aspects lengthy, requiring thousands of lines of code, or shorter, but requiring some advanced knowledge.

All of this can be put under the umbrella of “who should you teach to”?  The best students in the class?  The average student?  (Rarely, does a teacher say they will teach so even the worst students will understand).  Perhaps take a two-tiered approach?  That is, teach some things everyone should learn, but a few things only the best should learn?

Some people prefer to teach to the very smart.  It has one huge benefit.  It takes less work.   One could argue that it’s the mark of a good teacher to make a poor student learn.  However, many teachers don’t aspire to be that good.  It takes too much work.  Imagine you’re presenting the best explanation you can possibly think of.  And still someone says “I don’t get it”.   That has to be deflating, as you feel you’ve done your best, and still, it’s not simple enough.

Teaching to the smart has another benefit.  They’re the ones most likely to use that information well.  Even so, it can be hard to teach well, even to smart people.  You can cover a complex topic in some abstruse way.  Sure, the best students will work hard to learn it, but it doesn’t mean you’ve done a good job.

In the US, you can get various kitchen tools, such as can openers, peelers, ice cream scoops, and so forth, by a company named Oxo.  Oxo makes grips that are largish, round, and rubbery.  These tools were originally aimed at those with arthritis who wanted bigger handles.  However, even those who were perfectly fine liked these oversized handles.  Without the non-elderly, non-arthritic majority, Oxo would not have been as successful as they have been.

Similarly, if you teach well even to the average student, it can benefit the best student to.

My suggestion is to teach both to the average and to the best student.  Doing so may be difficult.  Some people have no idea how to teach to a really good student, not being really an expert.  Some have no idea what average means.

Indeed, that’s my last point to make for this entry.  What is average and excellent depends very much where you are.   Teaching to the average at one university may be just fine, yet too advanced for another, and far too simple for another.  You have to learn to adjust your teaching to your audience, which means you need to know your audience.

Thus, I leave you with this thought.  Figure out your audience.  Figure out who you want to teach to.

What is Programming?

Filed under: computer science, education — compyed @ 2:08 pm

Once upon a time, nearly twenty years ago, Pascal was the most commonly taught language in high school and colleges. It replaced older languages like Fortran and more obscure languages.

I haven’t programmed in Pascal in quite a while, so you’ll have to forgive me if my recollection is a bit rusty. Pascal is a procedural language. There was no notion of objects with Pascal. In that sense, it resembled C.

Pascal had a few features that C didn’t have and vice versa. For example, in Pascal, there are two ways to pass a value to a function. Either you pass by value (a copy of the value is made) or you pass by reference (essentially, a pointer to the value is sent). Passing by reference in Pascal is similar to C++.

C exposes pointers everywhere. You can take the address of practically anything in C. In Pascal, you can only use “new” (or whatever the equivalent was in Pascal) to create dynamically allocated structures. You couldn’t take the address of anything.

Pascal allowed for functions nested inside other functions. If function Inside was nested inside of function Outside, then Inside has access to Outside’s parameters. Only Outside could make calls to the nested functions. They were not accessible by functions outside of Outside.

Pascal makes a distinction between a procedure and a function. In C, a procedure would be called a void function, i.e., a function that does not return a value. A function returns a value.

In C, for a function to return a value, you use the return statement, and return the value back with it. In Pascal, there’s a special variable named after the function, having the return type of the function. You assign this special variable to the return value. Unlike C, where the code of the function is complete once the return statement is run, Pascal runs the code until the end of the function block, even if you have already assigned the function variable.

To illustrate, suppose you have a function foo. This function is supposed to return an integer value. At some point, you’d be expected to assign the variable foo inside the function to an integer. In principle, you could assign it several times. Whatever value the variable has when the function block is complete, that’s the return value of the function.

Pascal was designed by Niklaus Wirth to be a teaching language, not meant to be used in the “real world”.  Perhaps its chief deficiency is the lack of separate compilation (though later versions may have fixed that).  This meant everything had to be in one file.  I suppose it may have had a limited library (thus stabilizing the language).

In fact, the key feature of a teaching language is one that doesn’t change because industry demands this feature or that.

But let me not delve too deeply into Pascal.  What I want to get at is what we think programming is.

When I was teaching programming, we spent a good deal of time talking about control flow, arrays, variables, functions, and pointers (we taught C).  Notice one topic I didn’t cover deeply, and the one that might be of greatest controversy is algorithms.

Why didn’t we cover (much) algorithms?  I was teaching at a public university in a major that was non-selective.  Anyone could be a computer science major.  And, unlike engineers, these majors require far less math to graduate.  We required two semesters of calculus (or was it three?), a semester of stats, and a semester of linear algebra.  Even so, all you need is a grade of C to pass, and that isn’t a particularly high standard (to be fair, there are excellent programmers that are awful at math).

Algorithms require some mathematical maturity to properly understand them.   Many Ph.Ds have been so good at math for so long that they can sometimes scarcely believe that some folks are bad at it, or that those that are bad at it would even contemplate majoring in computer science.   Yet, many students can become good programmers without math (I personally believe you can’t be great without some knowledge of math, however).

Some intro teachers focus on problem solving and algorithms rather than features of the language, believing that this transcends specific details of programming languages.  In other words, you simply have to think algorithmically, not in any particular language (though resembling Pascal, perhaps).  The niggling details of this language or that is merely a distraction, preventing you from solving a problem.

This is why many a professor has stopped programming for real.   Those details are a pain.  And why bother commiting them to memory.  The proof for the undecidability of the halting problem is so much more elegant than the mundane overloading of the term static in C/C++, which can mean “having file scope”, “having static storage”, “being a class variable”, depending on where this keyword is applied, or remembering that a compare operator doesn’t always return -1, 0, 1 (instead returning negative, zero, and positive).  After all, there are no syntax errors in proofs.  You can write in stylized Math English, and have a great deal of latitude in the proof.

Still, these represent the two competing (possibly among many) ideas in teaching programming.  In the one camp, which is the majority, teachers say syntax is irrelevant.  The details of the syntax can be looked up, so look them up when needed.  On the other, syntax is very important, because how many people are really going to look things up (not many, in my experience), but then syntax is often the first thing students forget.

Let’s compare this to English writing.  Many a English teacher are grammar sticklers.  There is a right way to write.  There is a wrong way.  Bad grammar is seen as an offense to man and God.   However, more recently, some have advocated getting students to get their ideas across coherently, regardless of grammar.  Getting students to write is more important than the niggling details of the language.

There is something to be said about this approach.  Grammar is difficult to master.  I recall a professor, who wanted to become chair of the EE department, who complained about foreign students and their lack of good English.  He felt foreign students needed to be good at English (even as many native speakers are bad at it).  I would guess that he had no good idea how to teach good English, nor how hard it is to master.  I’d have more respect (but only barely), if he’d attempt to learn the grammar of another language (preferably Asian), and see just how challenging it is.  Naturally, this person assumed that someone else (the student) would take care of this problem.  If they had truly cared for foreign students to get good at grammar, they might have either hired someone to help out, or simply make acceptance into the program based on grammar.

The point is that English teachers used to stress the importance of grammar, but computer programming teachers somehow dislike this aspect of programming.  And I think, as onerous as syntax is, it insulates students from real world programming.

The question of this essay is to ask what is programming, because once we have a semblance of answer to this question, we can then ask, how do we best teach programming?  How do newcomers to programming fail to understand the ideas of programming?  How is one beginner different from another?

In hindsight, when I was teaching programming, I stressed syntax.  Occasionally, I discussed problem solving, but honestly, not that much.   That was a mistake.  I needed to strike a balance between the two.   Indeed, even if a student never learns how to program “properly”, learning to solve problems in an algorithmic way is still of value.

Thursday, September 28, 2006

Installation Anyone?

Filed under: Uncategorized — compyed @ 5:31 pm

I was talking to a friend recently.  As a teacher, he had to install some software needed by his class.  A MIPS interpreter.  The submit server that he had written.   Perhaps a few other things.  He had to fight the Linux installation.   There was a lack of real tech support staff to get him through this mess.  Lucky for him, he had been through installation hell like this many times before.  It didn’t make it much easier, but he knew, with time, he could persevere.

How common is this task?

For a class of computer science/programming teachers, the tasks he had to do may have been beyond belief.  I know of professors who would simply yell at the tech staff.  Professors don’t need to fill their brains with useless arcana of Linux.  Get the d**n thing to work.

But what my friend went through is starting to become typical.  Computer science types need to know how real systems work (and more often than that, how they don’t work).

What’s my point?

How much should we insulate students from this kind of mess?  Computer science teachers like to present a pristine programming world where every worry is confined to a clean language that is unchanging and sensible.  For example, the student doesn’t worry about installing a compiler.  They don’t worry about the operating system.  They just think about loops and functions and objects.

I recall, as a kid, watching a science television show, called 3-2-1 Contact.  It was on PBS.  Its goal was to teach young viewers a love of science.  Of course, it lacked one key ingredient.  Math.  Yup.  The thing that most scientists must know well is math, and yet, these shows basically show the glamor of science, without any of the difficulties.

Of course, students that lack talent in math are weeded out pretty quickly, and so it’s not as if we waste students’ time by giving a candy coated vision of science.

We do try to present this vision of programming however.  I’ve read that the Computer Science AP folks, who write college placement exams for high school students across the United States, want to make a core Java, that is insulated from the changes in Java, so students won’t be scared away by a language that is still evolving.

I don’t know exactly what I feel about this.  On the one hand, I think it’s a shame that the computing industry evolves as quickly as it does, and that it takes an incredible amount of work to make things simple, whereas it takes almost no work to make things complex, and that most software developers have to deal with complexity.

At universities it’s common to have specialization.  Professors learn advanced math and some advanced programming, but ignore the evolution of Linux, clinging to the permanence of the knowledge they have, while deriding the fleeting fad of the real world.  If a computer doesn’t work, the sys admin takes care of it.  Specialization.

Maybe the software industry will become extremely specialized, with people isolating other people from differing levels of expertise.

For example, it takes a certain skill set to simply write code, but takes another to optimize.  Most programmers would say optimization is simply the next level up, that a good coder eventually needs to know how to optimize, otherwise they aren’t so good.  (By optimization, I mean make the code run faster, or make the code use less memory as it runs).

Would this skill ever be specialized enough that someone would come in and do that work?  Certainly, there are people specialized in, say, internationalization, and focus on getting applications to work in different character sets, while insulating others from having to know anything about this.

I know this is an old topic, but I believe we tend to focus on intro courses where we inspire students to the world of programming, but the same people that do that are often loathe to discuss the messy stuff, partly (perhaps mostly) because they don’t know how to teach the messy stuff.

I can’t say I know how to teach it either.  It’s the messy stuff that drives students away (heck, even debugging drives students away).   Programming takes a good deal of patience.

Sunday, September 17, 2006

Has CS1 and CS2 become obsolete?

Filed under: computer science, education — compyed @ 12:26 am

CS1 and CS2 are the traditional names given to the first and second courses of programming.  Even if that’s not the name your university or college use, it’s a shorthand name.

It was once thought that two semesters were all that’s required to master the basics of programming.  CS1 would cover the basics of the language: if statements, loops, functions, structures.  CS2 would cover basic data structures: linked lists, stacks, queues, binary search trees.

Although this was a perfectly good way to teach programming when the language was Pascal, it’s increasingly obvious that it’s not enough for any object-oriented programming language.  Indeed, I’d argue that we need four semesters of programming, rather than two.  Object oriented programming is that tough.
This is just another indication of CS faculty not properly paying attention to what they’re teaching.  Of course, there was a pragmatic reason to keep to two semesters instead of four.  That’s two additional courses that don’t need staffing.  And believe me, staffing is a big issue.

There’s many an academic professor who don’t want to teach introductory courses.  Too many students sign up for programming that don’t really have a head for programming, and the teachers often lack the patience when students don’t understand basic concepts like array indexing.  When professors want students to use continuations and lambda expressions, the thought that simple loops can confound a student is scary.

So imagine the horror if they had to teach not just one, not just two, but four courses.

Of course, you’re now waiting with bated breath, wondering what four courses I think are important to teach.   It’s not terribly surprising.  First course is OO programming one.  This covers basics objects, loops, functions, etc.  Basically, object-based programming.  Not so much inheritance.  Second course is OO programming two.  This would include inheritance.  It would also discuss some basic design patterns.  Course three would be data structures, and some basic software engineering.  Course four would be design and software engineering.

When I taught at Maryland, we had three courses.  First course was C.  Second course was C++.  Third course was C++.  Even with three courses, the drop/fail rate was pretty high.  Since then, they’ve changed the curriculum to two courses in Java, and a third course in C.  The C course was set up to teach systems level programming (low-level programming).  My four courses admittedly misses that.

I found it interesting that Maryland would teach three semesters of introductory programming taking fifteen weeks per semester (or 45 weeks total), while the University of Washington, on a quarter system, would take two quarters (or about 20 weeks total) to cover traditional CS 1 and CS 2.  Maryland spent more than twice as long to cover intro programming.

How did UW manage to avoid awful programmers in their system?  Simple.  They have a selective major that removes more than half the eligible computer science majors.  When you’re willing to teach 200, but only want 70-80 majors, those who survive the cut are likely to be good, no matter what you did in the first courses.  It would be seriously scary if 140 students were allowed through, as it is in Maryland.

Imagine if every major did that.  Many students would simply not graduate.  Of course, computer science professors (and companies recruiting top students/programmers) love this because it means you don’t have people struggling with the basics of the language when you want to address math or some higher level concepts in operating systems.

Ultimately, where we’re failing students is our ability to give appropriate feedback, and large universities are worse than small ones.  English departments, for example, value feedback so much that they force small sizes when they teach.  At one point, I had to teach a course where each grader had to grade nearly 100 students.  Clearly, they had no time to look at their projects to see if it was any good.  They had to check the basics, and move on.  Our resources were that limited, and the department did not see it as a travesty.  English professors and graduate students would have been up in arms.   We were not.

We need to adopt a model that’s closer to what the English department (and similar majors) do when it comes to teaching coding.  It’s amazing that good coders develop, even in a system that doesn’t necessarily evaluate good vs. bad coding.

One reason I decided to be a software developer was to see coding in a real environment, and see how development was done (at least, someplace).  It’s been an eye-opener, especially during code reviews, and it’s something that computer science departments need to adopt.

Do We Need a New Pascal?

Filed under: computer science, education — compyed @ 12:09 am

I just read a short article about “Why Johnny Can’t Code” which, in a nutshell, asks what an appropriate language for beginners is. Once upon a time, it was Pascal. Lots of people liked Pascal, and many still do. They don’t like the monstrosity of C++ or Java or C#. They’ve concluded the object-oriented programming is too tough to teach.

Now, I have a bias. Since I taught at the college level, I think of computer science education at that level. Given the title of my blog, however, I should really consider programming at high school and even earlier. How do we teach programmers to kids? Many kids learn to program using a language called Logo. Logo was pretty much a cursor, which you gave commands to, and it drew lines. It was visual, which gave plenty of feedback to the programmer. It didn’t do anything particularly useful, but the ideas behind logo (looping, conditions) are valuable to programmers.

These days, people want programming languages that allow users to do something interactive with the user, preferably of a graphical nature. This could be a GUI, but more likely is a game, or some interactive world.

Why do teachers want a new Pascal? Even at the college level? What’s wrong with C++ or Java?

Many programming teachers learned an imperative programming language like C or Pascal. It’s taken quite a few years for teachers to learn how to think in object oriented terms.

I’ll relate a story. I was teaching with someone who was bright (at least, enough to get a Ph.D.), but clearly her background was imperative programming. How so? She developed a project, where she wanted the students to break this complex task into three separate subtasks. Each of those subtasks were public methods. They had to be called in sequence. Call subtask A, then subtask B, then subtask C.

It was a good idea to break down the tasks into subtasks. It’s one of the oldest teaching ideas in programming: stepwise refinement (seems like we’ve always given fancy names to simple ideas). But it’s an awful idea in object oriented programming. In general, any class that requires you to sequence method calls is problematic. It forces an order that’s hard to check for in the program. For example, even the common programming idiom of opening and closing a file is a pain.

Ideally, you want the constructor to open a file, and the destructor to close it. But you may not want to open the file right away. Simple. Create two classes. One class, when it calls open() will return a second object. That object, when it gets destructed, will close the file.

But my point that a relatively bright person still thought imperatively, not in object-oriented terms, even though she was familiar with C++ syntax.

It’s been argued that it’s too hard to teach in a “objects first” approach. What is objects first? Many people teach C++ by teaching C first. Learn how to program imperatively, then learn how to program using good OO principles. The reasoning behind this was obvious, yet flawed. C++ came from C, thus object oriented programming comes from imperative programming. As big an authority as Bjarne Stroustrup argues that you can learn C++ directly.

Having said that, it’s tough to say whether Bjarne is right. After all, Bjarne’s a bright fellow, and we’re talking about teaching programming to the masses. It may even be that you can’t teach programming to the masses. It’s like teaching math to the masses. It may be that programming is at least as hard to learn as algebra, and many an American, despite taking algebra, are barely competent, years later, to do algebra.

I don’t know if teaching objects first would work or not. Many do try, and have the benefit that those who don’t get it can seek other majors. I’d like to try it myself at some point, just to see what would happen.

The reason there are objects-first advocates is Java. Java makes it very painful to write in a C-like style. While Java has a main() method, this is the primary remnant of C/C++. To write in a C-like style, you’d have to teach static methods and static variables early on.

Then, once you do that, you’d have to tell students not to use static methods and static variables, because no sane Java programmer codes in this style. Rather than teach this style, then have to convince students this is nuts, you have to teach objects early on. Even advocates of objects later still have to deal with objects really early on, as there’s objects everywhere (Strings are objects, for heaven’s sake).

One reason for teaching Java or C++ in college is that it builds a skill that’s directly usable in the real world. Well, almost. Java is evolving. They just came out with Java 1.5, with generics as the primary new feature. The nice thing about Pascal? It’s fixed. No one was adding new features, because there was no need. It was a teaching language. Sure, it lacked separate compilation, and certainly wasn’t OO, but no one was going to fix the language in major ways.

Even now, many a Java educator wants to teach a controlled version of Java, that limits what students need to know, and they would like to fix this version of Java so that students, and more importantly, teachers, don’t have to keep up with the latest changes in Java.

And that’s what this blog entry is finally all about. Why are teachers reluctant to teach real languages? Because real languages evolve, and many teachers aren’t thrilled that their knowledge of a programming language is going to go obsolete if they do nothing more. Which other disciplines does this affect? Math? Nope. English? Only very slowly. Many fields, once you learn it, that’s it. There’s no strong need to learn more, though you certainly can, and students benefit from it.

Programming? There are universities that won’t switch over to Java because the professors don’t want to learn the language. They spent time learning C++, and the languages don’t seem that different, so why bother?

A teaching language is clean; it avoids lots of details you may not care about to explain, that real languages have to deal with. When you have to learn minutae of the languages that seem to have no other purpose other than to confound you, you wonder why it should be taught in the first place.

But unfortunately, as nice as that is for teaching purposes, it avoids reality, and the reality is that real languages are not always so clean. Most teachers are content to say “They have to start somewhere, and I’d rather start them on a nice clean language”. Which means to say they don’t ever want to teach a language that’s grungy. We must do it for the children. The children!

But of course, the reasons are partly to insulate the teacher, who doesn’t want to teach these details, and partly because programming is simply hard. A programming teacher, at least, those who aren’t bitterly cynical, believes everyone can program. As they teach, they see some students struggle. Some struggly mightily. They begin to say “It’s not important to learn syntax! Look it up! The conditional operator is a nasty feature. Let’s not cover it!”.

Eventually, this teaches all sorts of bad habits to programmers. The lesson programming apprentices should learn is that experts learn the nooks and crannies of the language, the parts that may seem obscure. For example, continuations are a big feature of Scheme. To avoid teaching it is to avoid teaching a critical part of Scheme (well, maybe not “critical”). Great programmers learn the obscure features of a language, even it’s not widely familiar.
Having said that, I’ve been coding in C++ again, with STL, and find that I must think about const a lot, and how to use iterators, and all sorts of mess that I don’t have to deal with in Java, because I understand Java’s classes much better, and it makes a lot more sense to me. That may simply be familiarity, but the time I waste trying to think about const makes me that much less productive, despite my acknowledgement that const is an important issue which all C++ programmers need to know. (Again, my colleague found const correctness a pain to deal with and wanted to abolish it).

There are even more radical ideas (radical to me, anyway). There are universities that want to ditch strongly typed languages in favor of weakly typed languages like Python and Ruby. These languages often have powerful string methods and regular expression support. Powerful code can be written in a few lines.

I do see some advantage in this. I think I’d write a lot more useful tiny programs if I were more well-versed in Python or Ruby. I find writing some programs in Java or C++ really painful that would only take a few lines in these languages. But honestly, they should have some strongly typed subset of these languages so that there can be some error checking at compile time. Please. (Groovy, a scripting language, built on top of Java, and compiles to Java classes, seems like something that might fit the bill).

So I can see both sides of the issue.  On the one hand, all the plethora of features makes it difficult to learn a real-world language.  It’s hard on the teacher.  It’s hard on the student.  On the other hand, it’s also polite fiction.  If students are expected to learn real-world programming, they need to worry about all of this perceived nastiness.  Teachers want students to learn less (i.e., stick to the basics), while the real-world wants them to learn more.

It may be, in the distant future, the teachers will be right, but I doubt it.  Here’s one example. Internationalization.  Java had to switch to Unicode to deal with international character sets.  How many teachers really want to explain, to American students versed in English, anything about internationalization?  None, I’d imagine.  It’s hard enough to teach programming (loops, functions, inheritance) without having to even mention internationalization.  Yet, it’s a topic of concern for many developers.

Software development is getting more mature, but in the process, it’s making the teaching of computer science more challenging.  I can’t say I honestly know the answer about what language to teach first, only to say that the reasons teachers push students in that direction may be at odds with the real world.

Tuesday, September 12, 2006

Tim Meyer Rants

Filed under: computer science, education — compyed @ 11:49 pm

Tim Meyer had a rant today.  Who is Tim Meyer might you ask?  I have no idea.  He appears to be a professor or something at a place called Buena Vista University, which despite its sunny name, appears to be in Iowa (not to say Iowa doesn’t have sun).

In it, he complains about the lack of enthusiasm from his students, as if they don’t care about their own education.  He ponders why this is the case.  He figures that students simply don’t like school.  They go through the motions, and then they graduate.  Simple.

Let’s see what he says in his rant:

At this point in the class, I had spent the previous 38 minutes doing introductions, and explaining every last detail of the syllabus. At this point, approximately 50% of the class started to pack up their material in preparation for an early departure.

Now, let’s sit from the student’s vantage point and think about what just happened.  Is what happened any different from any other opening day lecture?  Going over the syllabus.  Encouraging folks to study.  I mean he says he goes through every last detail of the syllabus.

What exactly are the students learning at this point?  Rules that they won’t pay attention to until it actually matters.  Are they learning anything about economics?

That first day went to waste.   At times, I think you should hand out the syllabus, and not even discuss it.  Get to that first topic.  Tell students why this class is so important to them.

Go up to the students.  Interact.  Pose a challenging problem for them to think about.  Not everyone who takes a class wants to take a class.  You have to think of yourself like a movie that’s coming out.  How do you get the attention of people who don’t want to be parted with a ten dollar admission ticket (for my foreign readers: that’s a chunk of change, i.e., that’s a lot of money)?

I know.  You’ll say “I’m an educator, not an entertainer.  I shouldn’t have to work this hard to get the students to learn.”  But you do.  Just like every movie works hard to get you to show up.  If you simply expect your material to be compelling just because, it’s not good enough.  You’re a salesperson, and they’ve got to be interested in what you’re selling.

For example, this is how I open up a lecture for a computer architecture class.

You’ve spent the last few semesters learning how to program in a high level language called Java.   And many of you who choose to become software developers, which is quite a lot of you, though I’m sure a few of you will abandon this to find other areas of work you find more interesting, like real estate or teaching Spanish.  I’m not kidding.  After the hundreds of hours you’ve spend learning how to program, and the thousands more you’ll continue to spend trying to make yourself better and better as programmers, some of you will call it quits.  This is not what you want to do the rest of your life.

But for the rest of you, you need to get beyond the fantasy land that is Java.  Yes, Java is a perfectly good language, good enough that Microsoft basically copied it and tried to improve on it with C#.  These languages hide a lot from you.  And that’s normally a good thing.  But if you’re going to be good programmers, no great programmers, you’ve got to know something about computer architecture.  That’s right.  Hardware.

Oh, I know what you’re thinking.  Hardware is for electrical engineers.  I’m never going to have to deal with any of that.  But you’re wrong.  One day someone will want you to write programs that run faster, and knowing something about caches may save you.  When you see stack overflow, you have some idea what that means.

But we’re going to do better than that in this course.  How many of you think about what happens when you hit that compile button in your IDE?  How many of you wonder what that high powered CPU is doing?

It’s running machine code.  When all gets said and done, a CPU runs machine code.  1’s and 0’s.  Lots of them.  Real fast.

And while you think this hunk of silicon is beyond comprehension, and only those who pray to the altar of silicon gods can ever fathom the mysteries of how a computer works, you’re wrong.

Absolutely wrong.

For in this class, we’re going to build a computer.  We’re going to build it from logic gates, a clock, and wires.  And this computer is going to process machine code.

But this isn’t the kind of computer construction many of you may think of.  How many of you have built a computer?  Raise your hands.  What you did was tinker toys.  You bought a motherboard?  And a fan, and a power supply?  And then hooked it together.  Put in some memory, installed Windows or Linux?

Those computers, to be fair, are far more complex than the kind of computer we’ll build.  And the computer we’ll build is a paper computer, meaning I’m not going to have real hardware, but you will imagine that it could be built, if we had the right materials.  And when we finally get it done, you’ll figure out that that magic that makes the computer run your programs is not magic after all, and in this understanding you will gain knowledge and wisdom about programs  and how they really work that you never would have had you not taken this course.

How many of you are ready to take the first step of this journey?  How many of you are ready to cast the Java yoke off your shoulders and roam free into the world of hardware, the world of computers?

Let’s begin.

Now, how many students do you think are paying attention to that, as opposed to covering the minutae of the syllabus?

I have other ideas on how you can get students to try to form study groups and such, but it’s more than simply lip-service.

As teachers, we have something to sell, and that’s education.  When you learn that you are in the business of selling, then you’ll find that students may be willing to buy.

Experience Counts

Filed under: computer science, education — compyed @ 12:32 pm

Suppose you’re teaching a course that you know little about.  I wanted to say “nothing”, but most people with a decent background know a little about most topics, even if it’s not sufficient to do anything about.

However, even with knowledge of the subject area, there’s going to be times when you’re covering something advanced or you have bright students, and you’re not going to be able to answer the questions they ask, because you’ve never given it that much thought either.  As long as you’re willing to look silly initially, and then try hard to find the answer, you’ll end up doing a much better job later on.

And that can be tough.  Most people don’t have that much humility.  I recall listening to someone say that C++ was compiled to C before being compiled down to machine code.  While that was true once upon a time (you’d write your C++ compiler in C, then cross compile the source to C, and then compile both with a C compiler), I don’t think it’s true now (and hasn’t been true for a decade).   Even facts you thought you knew about Java based on knowledge of compilers may no longer be true (vectors, for example, can now be optimized not to do locking, if the compiler can detect that locks aren’t needed, thus removing the overhead of locks).

If you have time, and know of a colleague that’s taught the subject well, sit in their class.  Find out what they do.  You can take ideas you like, and avoid pedagogical practices you don’t.  I find that sitting in a class on a subject I know well is great, because I can focus on the teaching, and see what examples are being picked and why (it tended to make the person lecturing nervous, because they would wonder what my motivation for being there was).

Teaching often teaches you why the subject matters, and if you can’t figure it out, you should be looking for reasons.  Your lack of enthusiasm can translate to lack of enthusiasm for the students, and while some of the best teachers (I say this hesitantingly) may not be enthusiastic, most are.

I’ve made the tacit assumption that you’re an expert on the topic you teach, but really, there’s always much more to learn.  When I taught C++, I spent time learning about STL.  I wasn’t an expert by the end, but STL was hardly mentioned by anyone else.  For a subject as fluid and dynamic as computer science, you should always be finding the latest trends, the newest topics, and trying to figure it out.  The more you visit and revisit a topic, the better you get at the topic, attacking it from different angles.  I can’t tell you how many times I’ve thought about two’s complement, and still there’s stuff for me to learn there.

Teaching is a lifelong endeavor.  You get better over time, even if the first few times may be embarassingly bad.  You just have to care enough to try.

Monday, September 11, 2006

More Than Just Programming

Filed under: computer science, education — compyed @ 11:24 am

I’ve just received my first comment by a fellow from Portugal, so one other person out there is reading this.  Ah, the amazing power of search when it comes to blog.

I wanted to quickly blog on something that’s been on my mind, which is that programming is more than just programming.

Let me list out some distinct skills that “good” programmers have:

  • Basic control flow/syntax of a language (loops, functions, classes, etc).
  • OO skills (inheritance, templates, design patterns)
  • Algorithmic skills (quicksort, binary search, depth first search)
  • Tasteful design (write “general” code)
  • Testing
  • Debugging
  • Learning new tools (debuggers, profilers)
  • Learning IDEs

Several of these topics are not regularly covered in programming courses.  In particular, little time is spent discussing the debugger and about the debugging process.  More generally, not much time is spent on learning new tools.

Why?

As fast as programming languages change, they are relatively steady.  If you learned Java 1.1 from 1998 or so, then you’re still more or less good for programming now.  Maybe you have to pick up generics, but you don’t have to, if you don’t want.

However, Eclipse and others are pumping out updates on IDEs every year or so. It can be extremely difficult to write an up-to-date book on IDEs.  Plus, you never know when one of those IDEs will be shut down.  I knew someone who wrote a book on Visual Age, which was IBM’s Java IDE.  He made a little money on it, but they eventually shut the project down, and so no more money on that book.

If you write a programming book with an IDE in mind, you cut down your audience too.  If you code in emacs using gcc, then that book on Visual Studio may not be that useful to you.

And with IDEs as complex as they are, it can require its own book (and often does) to cover even the basics, which detracts from the main effort of teaching a programming language!

But what I want to talk about is the desire of students to learn tools on their own.  Many students who come to programming like to work in a shell.  I don’t mean like Korn shell or Bourne shell.  I mean, they like to work in something familiar.  Here’s a test to show this kind of thinking.  You tell a student, who’s been editing in emacs, that there’s a cool IDE called Eclipse, and it has a ton of cool features.

What’s the reaction?  Does the student say “That is so cool.  I’ll download it and try it later today” or is it “That’s fine.  I’m happy with what I’m using now.  I don’t have time to learn something new”.  It’s this second attitude (and I’m somewhat in that camp myself) that is bad for programmers working in the real world.  As uncomfortable or unnatural as this is, they have to learn to play with new stuff all the time, even if it initially wastes a lot of time.

You know those Linux fans?  They tell you to abandon PCs or Macs in favor of Linux?  But then they spend 2-3 days trying to install Linux in exactly the configuration they want.  That’s the kind of attitude programmers need, sadly.

I say sadly because it is a waste of time.  There are so many tools out in the real world that haven’t been updated in a long time, mostly because the functionality is so minimal.  Real world software and consumer electronics has a gazillion features, and many are a bit too complex to use, so there is motivation to tinker with the features to make it easier to use, while adding even more features.

And yet this skill of learning new technology is not taught.  It’s such a nebulous skill, after all.  You tell a class, download this new profiler, and tell me what results you get.  How many say “but you need to teach this to us first”, i.e., predigest the act, make sure any errors that occur you deal with, so we don’t have to.

Many non-programmers are techno-phobes.  They hate this uncertainty.  They don’t want to tinker until it works.  The first sign of something wrong, and they want to panic, and quit.  Or they ask a guru to do the work for them because they don’t want to be the one spending two days figuring stuff out.

How do you teach this desire to tinker with new technology?  Other than programming itself, it’s one of the most valuable skill a programmer can develop (or anyone interested in technology).

Blog at WordPress.com.