In my last installment in my blogging about teaching miniseries, I'm going to talk about how I approach teaching the upper-level electives. These are courses that are typically taken by our more advanced students: sometimes sophomores, but more typically juniors and seniors, since they are the ones that are most likely to have navigated all of the prerequisite hoops.
In a sense, teaching the upper-level courses is easier than teaching any of the other courses in our curriculum. The topic is very well-defined. The students are somewhat advanced, typically have good programming skills (the "coding maturity" I referred to earlier), and are capable of thinking more deeply about computer science as a field. Usually, if you're teaching an upper-level elective then it's at least marginally related to your field of research, and thus you're fairly comfortable with it. But these same features also can make teaching these courses tricky. How deep, for instance, can/should you go? How much material can/should you cover about a field? How do you reconcile what's important to you--and what you're comfortable teaching--with what the "real world" expects students to know about the field? And how much programming should you expect in an upper-level course, versus covering more theoretical problems? In short, how do you best mix theory with practice in the classroom?
Personally, I tend to teach the electives that have higher numbers of prerequisites, so I have high expectations for my students. I expect them to put more time into their work, and I expect them to have to delve deeper to find answers to the problems I assign. I expect them to be able to make connections to other fields, to apply concepts to completely new areas, and to wrestle with less well-defined problems. Lately, I've been making my expectations more clear up front, so that the students know what to expect going into the class. This minimizes the frustration quite a bit--or at least if the students are frustrated by a particularly hard assignment or exercise, they are more willing to accept the frustration as part of the learning process. (This is one of the key lessons I learned in my first few years here, and one that's served me very well.)
So how do I address the theory/practice issue? The short answer is that I try to work in both. Since the students are more sophisticated programmers, I can assign larger and more complex assignments. I may, for instance, have the students read a real-life design document or specifications document and implement the system that's outlined in there. The neat thing about an assignment like this is that the students have to integrate everything they've learned so far in the CS curriculum. They have to apply good design principles. They have to consider the relevant theory when making design decisions: if some feature can be implemented several ways, what does the theory indicate as the best way to implement it under these circumstances? And they have to deal with things like the fact that these types of documents rarely spell out all of the details, and so design tradeoffs need to be made. In the classroom, I try to split my time equally among theory and practice. We'll discuss theoretical reasons why a particular concept does or doesn't work, and then come up with real-world examples of that phenomenon.
In summary, I find teaching upper-level classes fun and challenging. While I may not spend as much time prepping (learning) the material, I spend more time and energy coming up with relevant assignments and examples, thinking about how my class will fit the students' needs after graduation, and making sure that they continue to develop into deep thinkers and skilled programmers.
technorati tag: teaching-carnival