Update the course to reflect industry standards

As Lecture Head TA, I was responsible for the content and syllabus of the course. While Java is still a very common language in industry, the ideological standards about OOP have changed drastically. As I had some experience in industry via internships, I wanted to update course pedagogy accordingly.

Reflecting Industry Standards

CS15 is an object-oriented programming class, and as such, spends a large portion of the semester talking about design patterns. Three key concepts are introduced fairly early on in the semester- interfaces, inheritance, and polymorphism. These concepts are some of the key principles of OOP and are used heavily in the rest of the course. When I was a student in the course, inheritance was emphasized over interfaces, and polymorphism was taught within the lens of inheritance. As a result, in my future classes and internships, I tended to design projects with inheritance as the main pattern. My TAs and internship mentors would often question why I chose to design my programs in such a way, and I never felt like I had a proper justification.

When I first took on the responsibilities of Lecture HTA, a former TA of Andy van Dam’s suggested to rewrite the course to emphasize interfaces over inheritance. I agreed with him- the majority of my experience had shown me that inheritance was no longer the preferred pattern and in fact, interfaces were far more flexible. As such, I spent my spring and summer rewriting this section of course content. I met frequently with Andy over the summer to refine these lectures. Originally, the lecture order was inheritance, interfaces, and then polymorphism. I decided to reframe the lectures into “interfaces and polymorphism” and “inheritance and polymorphism”. A third lecture, “Design Patterns” was added later on in the semester once students had some experience using these concepts. The design patterns lecture discussed tradeoffs between using inheritance and interfaces.

Developing the Lectures

Interfaces, inheritance, and polymorphism are incredibly abstract concepts and difficult to think about as a beginning programmer. The old lectures introduced these topics and then connected it to the existing knowledge of the students. When I started revamping these lectures in the summer, I wanted to make sure we did the opposite. My 3 new lectures followed the same pattern- introducing a problem, coming up with a solution based on what the students have already learned, and discussing the pros and cons of this solution. The new concepts are then introduced as ways to address the cons of the original solution.

“Introduce, Explain, and Use” vs. “Problem and Solution”

Throughout my development of these lectures, Andy and I discussed how best to introduce these complex concepts. He felt that the “problem/solution” approach was too abstract and it took too long to get to the point- students would be bored and confused and would “check out” before they learned the new concepts. Andy much preferred a simpler introductory example that led into a description of the concept and how it could be used.

In my original draft of the interfaces lecture, it took me 15 slides to introduce interfaces. These slides can be seen below.

In my original draft of the interfaces lecture, it took me 15 slides to introduce interfaces. These slides can be seen below.

With Andy’s suggested approach, it took 6 slides to introduce interfaces. These slides can be seen below.

With Andy’s suggested approach, it took 6 slides to introduce interfaces. These slides can be seen below.

Above, an original draft of the interface and polymorphism lecture. There is a long lead up to actually introducing interfaces.

Below, a subsequent draft of the same lecture that introduces interfaces much earlier.

Andy and I made countless edits to the early versions of these new lectures, but we were still doubtful if this would be the best way to teach our new pedagogy. Inheritance is clearly easier to learn because it is familiar and there are clear real world examples (like taxonomy in biology). However, in the past, this led to students relying solely on the inheritance pattern, and not using “the other tools in their toolbox” (i.e. interfaces, composition, etc). Our main motivation in teaching interfaces first was to combat this. But, interfaces are more abstract and we were concerned that introducing two difficult concepts in one lecture (interfaces and polymorphism) might be too much for students to take in. We discussed keeping the lecture order the same (inheritance, interfaces, polymorphism) but altering them so inheritance is not so heavily emphasized and emphasizing interfaces more broadly in other aspects of the course.

Ultimately, after the input of my fellow co-Head TAs and HTAs from past years, we decided to keep the new lecture order and the original “problem/solution” format. By introducing the problem and engaging the students in a discussion of a solution, we felt confident that they would understand the motivation behind using interfaces. Moreover, it helped teach the students how to think critically about the design of their programs and what key attributes make up “a good program”.

Comments from the co-HTAs while debating lecture order

“Also in favor of the new order. I think that all three topics are foreign enough that changing the order will not make a huge difference in how people understand these topics. I do think that it will emphasize that interfaces are equally strong (or stronger) tools in an OOP language, as opposed to a second choice. I think that the slides are very strong and the direct comparison of cars showcases the different use cases for interfaces and inheritance but also teaches the topics such that interfaces can come first and be taught well even though students will not be able to relate interfaces to more concrete inheritance.”

“I’m also very much in favor of the new lecture sequence, as I think it will give students a better intuition for when to use interfaces, rather than just having them as an afterthought. I also think it more tightly fits with the industry standards, and puts the course in a better position for a larger change to TASafeHouse next year to fit with this pedagogy.”

Comments from former HTAs about the “problem/solution” flow

“I like this idea. This is a good idea. For me, this is very good motivation. You're trying to do something, and you run into a problem, and then we tell you how to solve it. That's better than saying here's a tool, let's figure out how to use it. Whenever I'm learning new things, I always have an actual task I want to get done. Then I look for what does it. If I learn about a design pattern, it's because I've kept messing things up in a particular way and need a solution. I never used, cared about, or understood builders until I needed one.”

“I think that we should start with a concrete necessity in code instead of "well they both do X, so just throw it up into an X-Doer-Interface." Using a more concrete motivation might add the necessary context to the word "contract" that others were asking for!”

Results

Ultimately, the lectures went off well and students tended to lean more towards interfaces while working on subsequent assignments. One of the best success markers came a full 7 months after these lectures were taught. In the spring, students are invited to apply to TA this course. One of the questions in the TA interview is to explain polymorphism, and in previous years, almost all interviewees use examples of inheritance. In the spring after the new lectures were taught, 140 past students of the class applied to TA and the overwhelmingly majority chose examples of interfaces.

The final lectures can be found below, and are still being taught today (with minor changes), as evidenced by the course website.

Interfaces and Polymorphism | Inheritance and Polymorphism | Design Patterns