This page contains links to archived versions of the Stanford CS106B (Programming Methodology) webpage in the quarters I've taught it.
This quarter's offering was an ambitious overhaul of the course materials from the Winter 2017 offering. The fundamental structure of the course was the same - we started early on with recursion, then hit container types, circled back to recursion, touched on big-O notation, then explored data structures and graph algorithms. Aside from that, most of the content in the course was new or heavily revised from prior iterations.
The most visible change to the course was the new suite of assignments. I redesigned most of the assignments this quarter with the intent of giving students problems to work on that were intrinsically interesting or which touched on real-world data analysis. In many ways, I think this worked. The new assignment that replaced Priority Queue, Data Sagas, put searching and sorting algorithms to work in exploring data sets, including some data sets pulled from public APIs. My replacement for Trailblazer, Calligraphy (which was co-developed with Ashley Taylor), included simulations of the impact of sea level rise, with data pulled from the NOAA. Other assignments, such as a revised introductory recursion assignment that included several interesting fractal patterns and a replacement for Word Ladders that simulated crystal growth, focused on the idea that simple rules can give rise to complex, emergent behaviors. I also replaced our older, console-based starter files with GUI-driven programs and added some highly polished demo apps to showcase what student code did. I'm particularly proud of my visualizations of the Human Pyramids and Sierpinski Triangle problems, as well as the runtime plotter for Data Sagas.
As is always the case with a rollout of new materials, in many ways these assignments will still need some tuning. The MiniBrowser assignment I co-authored with Ashley Taylor was much more difficult than expected, primarily due to me misjudging the difficulty students would face in translating from diagrams into code. The revised version of the Recursion! assignment didn't resonate with students as much as I'd hoped that it would. These are items that will need some attention in future iterations of the course.
One of the more visible changes I made to the assignments was the inclusion of a series of automated unit testing suites. I think this helped expose bugs to students better than before and made it easier for students to write their own test cases. At the same time, I seem to have underestimated the difficulty of learning to write good tests, and that's something I'm going to need to look at more closely in the future. Do we just ship tons of tests with the starter files and tell students that they don't need to write their own? Or do we include a Guide to Testing that helps students figure out what sorts of test cases to write? That's something I'm going to need to think about more in future iterations.
I did a major overhaul of the lectures this quarter with the goal of motivating concepts more from first principles rather than presenting "here's the finished product." I'm really proud of some of these new motivations, such as using the respiratory tree to motivate binary search trees and looking at historical methods of organizing text information to introduce tries. I also improved the quality of the visuals and animations in some key places, such as detailing how the delete keyword operates on the pointee rather than the pointer.
One set of overhauls to the lectures that really surprised me was the presentation of recursion and recursive backtracking. Based on my notes from the past version of the course, I changed the way I introduced recursive exploration and recursive optimization to distinguish between the style of recursion (enumeration, optimization, backtracking, etc.) and the structure being explored (subsets, combinations, permutations, etc.). My hope was that this would help students get a better sense of how to conceptualize the problems they were working on. Surprisingly, this didn't seem to work very well, and many students were very much caught off-guard on the assignments and exams when the problems didn't exactly match these topics. This is something I'm going to need to spend a lot of time thinking about for the future. At the end of the quarter, students seemed to have a phenomenal grasp on recursion, though the process of getting there was tough. Is this due to an overly ambitious set of targets for students to reach, is this because that transition is just plain difficult, or is this due to that teaching model not working particularly well?
In terms of topic coverage, after giving things a lot of thought, I decided to eliminate the discussion of Dijkstra's algorithm and A* search and to focus more on BFS, DFS, and related algorithms. The motivation here was that our coverage of Dijkstra's algorithm and A* primarily consisted of "here's the algorithms, now go code them up" rather than "here's the algorithms, and let's make sure you really understand how they work." This, I think, was a good call. The new Calligraphy assignment did a great job reinforcing BFS and DFS and on the final exam students absolutely nailed the conceptual questions on these algorithms. I was very surprised to see, however, that students were most excited by Kruskal's algorithm and its applications to data clustering, which I'd included simply because I thought it was a fun topic and we had the space in which to present it. In future offerings of the course, I might decide to make that more of a direct focus. I'm considering replacing MiniBrowser with an assignment about data exploration (possibly using random forests and agglomerative clusterig?), in which case we could integrate Kruskal's algorithm more tightly into the course materials.
This quarter, I also did a major overhaul on the Stanford C++ Libraries, replacing our implementations of the container types with the equivalent STL containers to improve the quality of the debugging information generated. I also added in a number of static_assert checks in places where students might get into trouble (using non-comparable or non-hashable types as keys in containers, for example), which probably will save a lot of students a lot of headache in the future. I also massively cleaned up the build system on Windows, reducing compile and run times by as much as 75%. I now know far more about Qt Creator and qmake than any reasonable person should. :-)
I've left copious notes to myself about how to proceed differently next quarter, and I'm excited to see how the revised version ends up going. There are a few spots where there's still a good amount of work to do - I suspect that A1, A2, and A6 might need some major revisions to get into a good working state - and other spots where things are mostly working just great (A4, A5, and A7). There are a lot of missing materials in the course (a Guide to Debugging, a Guide to Recursion, etc.) that could save huge amounts of student and staff time in the LaIR that I'll need to build out. But given the sorts of feedback I heard from students at the end of the quarter - many of whom had no prior programming experience and were blown away by the breadth of the material and how well it connected to other topics - I get the sense that I'm on to something here. The question for the future is how best to strengthen the components that work and tune and tweak the parts that are in need of help.
It had been almost four years since the last time I taught CS106B when I took over this offering of the course, and I decided to use the opportunity to make a number of changes to the course and the assignments.
In this quarter, I also introduced an updated Assignment 0 with an animated Guide to the Debugger based on the animated guides I'd developed for CS103. I also included an "Honor Code Maze" assignment that required students to work through a series of questions about the Honor Code before starting. The number of Honor Code cases emerging from CS106B this quarter was significantly lower than in the past, and I was very happy with how that turned out.
The biggest changes to the assignments were an overhauled Assignment 3 that pushed more on recursive enumeration and optimization than the past, and a completely new Assignment 4 (Recursion to the Rescue!) that explored recursive backtracking in the context of a number of socially-relevant applications (patient scheduling, disaster preparation, pathogen detection, and US Presidential Elections). These assignments were tough, but based on the experience I think that with some small updates and tweaks the assignment could become a mainstay in my offering of the course.
I also invested a lot of time updating the section handouts to provide significantly more coverage of core topics. I'm extremely happy with how those turned out and am definitely looking forward to using them more in the future!
In a break from what I did in previous offerings, I updated many of the assignments to introduce new technical concepts (structures, stack overflows, memoization, etc.) that didn't fit cleanly into lecture. I was pleasantly surprised with how well this worked and will definitely consider doing this again in the future.
In a more visible set of changes, I also updated the lecture examples, assignment starter files, and section handouts to use more C++11 concepts, such as automatic type inference (hugely useful in recursion), const correctness (which I had mistakenly thought was the norm in CS106B... oops), the nullptr keyword, and uniform-intialization syntax (also hugely useful in recursion).
The last set of major updates were to the lectures. While content-wise they were mostly the same, I spent more time talking about big motivating examples, like using recursion to figure out the best team to send to a developing country or big-O notation to analyze the efficiency of grade-school arithmetic. I also pushed much harder on recursion throughout the quarter, using it to dramatically simplify the presentation of linked lists and binary search trees. I think that I still have some work to do at the beginning of the quarter to get stronger motivating examples for elementary recursion.
And I'm really, really proud of the exams from this quarter. I invested a ton of effort building four versions of the midterm (actual, practice, alternate, and yet another alternate) and a final that I think had genuinely interesting questions on them. It will be dramatically easier to teach this class in the future simply because I can fall back on those questions when I need to.
I feel like there's a lot more work to be done - upgrading the earlier lectures and assignments, rethinking the Huffman and Trailblazer assignments, revisiting how we teach graph theory, etc. But I feel like that's going to be a much, much easier task given that I now have a stable set of materials to work with.
A massive thanks to Anton and the CS106B section leaders for making this quarter so easy to teach. It was a pleasure to work with that team and I would be happy to do so again in the future.
My second offering of CS106B was 50% larger than the previous years' offering, but it was a blast! I refined the syllabus to slim down the breadth of material while increasing the depth, and overall students did quite well. This quarter also saw the introduction of a new first assignment (a modified "Welcome to C++" that included Flesch-Kincaid readability) and new final assignment (Trailblazer).
This was my first run teaching CS106B and it was a lot of fun. Although I had given a few CS106B lectures before as an undergrad, I had never actually taught the entire course. It was exciting getting to develop different algorithmic approaches and data structures in lecture, and I'm looking forward to the next iteration of the course.