SPD Course Review


Here is my review of the Systematic Program Design course. I will start by giving a background about myself, then discuss why I’m taking this course and why I believe it’s important, then an overview of the course structure and what the course is about. Then, I will discuss the course’s programming paradigm, recursion, the space invaders project, and the TA solver. Finally, I will discuss my thoughts on the course overall.

A little bit about my background: I have been programming since 2014. I studied Computer Science at a university (non top CS school) from 2015 - 2019, and worked in the industry for 3.5 years. My work was mainly web development.

Why this course? Even though I’m not a beginner, I decided to humble myself and take the course anyway to see what I could learn from it, and share my learnings. Also, this course is a part of the Open Source Society University’s Computer Science curriculum. I am going through this curriculum to strengthen my fundamentals, as I discuss in my blog post here.

Fundamentals are important in any discipline. And since this course teaches some of the fundamentals of program design, I figured it would be important for me to learn. SPD comes from a reputable university, and is based on a book written by reputable authors.

It’s an important course for beginner’s to take because it teaches a process for solving programming problems. Many intro computer science or programming courses don’t teach this. They usually take a “tinker until it works” approach, which is not very helpful for harder problems. It’s great that they’re teaching such a process early in the curriculum as an intro course, because the concepts will be used for later courses and beyond. I think it fulfills a need in computer science education. That is, the need of learning a problem solving process.

Beginner students can often get stuck staring at a problem, not knowing where to even start. SPD solves that problem by giving students a recipe to follow when approaching any programming problem. I think it’s good, but not perfect though, as I will discuss below. Still, all credit to the instructor and authors of How to Design Programs book, it’s a great process to follow that’s better than no process at all.

This course matters because it gives you good mental tools/models that will influence your thinking in a positive way moving forward. You will adopt good general habits such as properly defining the problem, coming up with good examples, test-driven development, the idea of templates, etc. You’ll have these ideas to think about when coming across any programming problem, and they will increase your chances of solving a problem. More of my thoughts overall towards the end of this article. But first, let’s go over a little background of the course and its structure.

Systematic Program Design is a course taught by Gregor Kiczales, a computer science professor at the University of British Colombia. He is best known for developing the concept of Aspect-Oriented Programming. However, this concept is not relevant to the course. Feel free to do some research if you want, but you don’t need to understand it in order to take this course.

The course is based on the book How to Design Programs, 2nd edition. No need to read the book if you are taking this class. But I do recommend checking out the preface here, which talks about what you’ll learn from the book, and gives an overview. There is some debate as to whether How to Design Programs or SICP (Structure and Interpretation of Computer Programs) is better as an introductory course.

After doing some research and reading this paper comparing the two (though it’s written by the authors of How to Design Programs, so it may be biased), it seems to me that How to Design Programs might be better as an introductory course. That’s not to say that SICP is useless. In fact, I do plan on reading SICP sometime, maybe after completing the Core Programming section of OSSU. It’s a part of the teachyourselfcs curriculum. But I digress. Now, about the Systematic Program Design course structure.

The instructor starts by telling us a bit about what the course covers, how it is organized, and gives us some suggestions for how to learn this material most effectively.

First, he talks about what makes it hard to write programs. When we’re asked to write a program, we’re typically given a poorly formed problem. That is, we’re asked to write a program to solve some task, but the task’s description is somewhat vague, or it might be incomplete, or sometimes it’s just inconsistent. So the first challenge is figuring out exactly what we want our program to do. And the systematic design method that we will be learning in this course will help us figure that out.

The second thing that makes programming hard is that oftentimes the program is too big for us to solve in one go. In fact, the way our brains work is we can only focus on one small part of the program at once. So we have to find some way to manage that complexity.

What the systematic program design method does is break the program down into well chosen smaller pieces. With the problem broken down into smaller pieces, we then need to write one part of the program for each piece of the problem. Because the pieces were well chosen, and because of other properties of the design method, what you’ll see is that the pieces end up fitting together well and being well tested.

The resulting program is then easy to read and modify. And that’s important because any program that’s actually useful ends up needing to be modified — maybe to add some new functionality or to fix a hidden problem.

The whole trip from a poorly-formed problem to a well-structure solution — that’s systematic program design — and what we learn in this course. That’s what separates really good programmers from people who just type and hope for the best.

The way the course is organized is that each module is broken into a series of lecture videos. In most of those lectures, the instructor takes a design problem, and works through it to completion following the design method. It’s sort of like a walkthrough.

I really like this approach because when practicing on our own, we want to have a good example for how to practice, so that the practice becomes deliberate. There are quiz questions along the way to test your knowledge and help make the concepts stick.

The instructor gives a tip which is to type along the whole way with him, solving the design problems step by step as he’s doing it, using your computer. He gives the analogy of playing a sport or a musical instrument or a video game. He says that “You didn’t get good at that by watching somebody else do it. You got good at that by doing it yourself. And programming is the same sort of thing. If you really want to learn this material, you have to do it yourself, to practice it, and really internalize it.”

I agree for the most part except that I think we do get good by watching somebody else do it too. By watching an expert do something, we are able to learn how to practice the right way. So I would tweak what he said a bit by saying “You didn’t get good at that just by watching somebody else do it. Watching an expert example is useful. But you got good at that by also doing it yourself, using the expert example as a guide.” I think that’s a more accurate interpretation of the reality.

The instructor goes on to claim that the techniques used in this course can be used with any other programming language you may learn in the future. They use BSL (Beginning Student Language) to teach these techniques. The instructor claims that the reason they chose BSL is that it’s simple to learn, so we’ll have more time to focus on the design method, and that it has the core functionality of essentially all other programming languages but in a simple, lean package that makes it easy to learn.

I think that’s fair, and I’m eager to see how I can apply this information beyond the course. Concepts from this course might get used in later courses such as class-based program design (they also use cons, rest, etc.) and Programming Languages parts A/B/C (mutual recursion, parentheses-based programming, functional programming, etc.), so taking this course will prepare you for future courses in the curriculum. I do plan on going through those courses and writing reviews of them as well.

To many, it might seem like learning BSL is a waste of time. But remember, it’s not the programming language that’s the focus here. It’s the systematic program design method that’s most important. The steps of this method can be applied to any programming language or problem. As we get to the actual method below, I will discuss my thoughts on how it can be used beyond this course in other programming environments.

However, do note that I just recently finished this course and haven’t worked on enough harder problems outside this course where I apply this method just yet. As I move forward and perhaps use some if not all of these steps, then I might come back and update this article with explicit edits.

In theory, it makes sense. Teach a framework for solving programming problems that is language agnostic. And I do see its benefits. It’s like training wheels. Then, you internalize it and don’t have to think about it much anymore.

Interesting thing is that recently this course offered at the actual university is now using Python as their main language to teach systematic program design instead of BSL:

As of Fall 2025, Northeastern’s College of Computer Science will replace this curriculum with a set of new courses, starting with Python in the first year.

I don’t know exactly why they are moving to Python. Maybe they figured out a way to teach the systematic program design method using Python. Maybe they decided that it would be better for students to have a more relevant language to use instead. Maybe they decided that they wanted to kill two birds with one stone — that is, teach the systematic design method and use a relevant language at the same time.

Still, that doesn’t mean you won’t learn anything by using the learning language for this course. Trust the process, and keep in mind that although the language won’t be super relevant beyond this course, the main ideas will be, as I discuss below. But first, a little note about the programming paradigm/style.

The course is taught using a functional programming paradigm. Now, you don’t need to know the specifics about the different paradigms of programming out there in order to do well in this course. But I do think it’s a good thing to be aware of. Check out this page about programming paradigms to learn more. I recommend doing some research about programming paradigms to get some exposure to the ideas at least.

I’ve come across many functional programming concepts throughout my career. My main languages are Python and JavaScript, both of which have support for functional programming concepts (most, if not all other languages have functional programming support too). Concepts like closures, filter/map, and lambdas, which are covered in this course, were familiar to me, since I’ve come across them in my career using Python and JavaScript. The instructor talks a little bit about functional programming at the end of the course, in the extra videos playlist. I think you’ll learn more about functional programming in the Programming Languages part A/B/C courses. Now, let’s discuss recursion.

Recursion. There’s lots of it in this course. Instead of using for loops to iterate over a list like in Python, you use recursion to iterate over a list. There are a few practical applications, such as iterating over a file system, or iterating over what’s called an arbitrary-arity tree (a tree-like data structure that we might not know the size of at runtime). One of the main uses of recursion is when you need nested loops but the depth of nesting won't be known until run time. However, in the real world, if you’re doing web or mobile development, you might not come across it much, because you’ll mostly be using for or while loops to iterate on some data. But it depends on the nature of the program and what data you’re working with, of course.

In general though, I haven’t come across recursion much in the web engineering space. But it’s better to know it and not need it than to need it and not know it. Either way, you’ll need it for the OSSU curriculum. So, if you plan on completing the curriculum, you’ll need to get comfortable with recursion.

The course had two main projects. The first one at the half-way mark was to implement a simple Space Invaders game. The second one was at the end of the course which was to implement a course scheduling algorithm.

For space invaders, they gave us a helpful starter file. I started by doing a domain analysis using pen and paper. I wrote out all the scenarios, such as changing direction when an invader reaches edge of screen, missile to invader collision, tank switching directions, spawning invaders, and game over when invader reaches the bottom. I wrote down which big bang functions I would be needing. Then I got to work. There were many helper functions and overall it was fun to implement. The concept of function composition was used here too. The project was a great way to exercise the learnings from the course so far.

For TA Solver, in the starter file, there’s actually another problem before the TA Solver. It was straightforward if you did the practice problems and problem bank problems of that week. Now, the TA Solver seemed daunting at first. But I used the 5 step function design recipe to get the ball rolling. With step 3, I identified the multiple templates this problem looked like it would use. I built out the solution in iterations. Helper functions came up, and I wrote them along with their signature and purposes. I spent a lot of time up front thinking about the solution, how it would work, what the code would need to do, etc. Then I started coding. It actually didn’t take me long to solve this once I had the right templates.

Overall, I liked the course. I learned about important concepts such as how to approach a programming problem from scratch, how to design functions, how to design data, when to use helper functions, thinking of code as having structure rather than just characters on a screen, how data definitions can influence the structure of the program; and for me, review of some concepts I have come across before such as writing the signature and purpose, test driven development, recursion, binary search trees, local variables, closures, refactoring, and backtracking search.

These concepts added to or refined my mental toolkit. I was able to practice enough in the course to internalize these ideas to a certain degree. Moving forward, I might be using the how to design functions and how to design data design recipes, but not use the language-specific details such as the exact templates used. The idea that you can use a template based on the input data, however, is what I might be using.

Since I just finished this course, I’ll need some more time before I can tell the usefulness of it in my career. But thinking through my past experience, I can see how using this systematic approach could help me get the ball rolling on hard problems.

Before I took this course, I followed a different systematic process for solving programming problems. Or rather, I built up a mental toolkit of processes and models for solving programming problems, some of which have overlap with SPD’s method. These processes and models came up from other sources such as online courses, learning from other good programmers, reading books, reading blog posts, Reddit and Quora, through trial and error, etc.

Over time, you end up internalizing many useful/good practices. This course is meant to help you internalize this specific method. So when working on any other programming problem (beyond this course), you are trained how to think about it step by step, which can be useful for harder problems.

Back in 2016-2017, I learned a systematic approach for writing algorithms from a series of courses on Coursera called Java Programming and Software Engineering Fundamentals Specialization from Duke University. I used these tools on some of the Intro to CS and Programming using Python course problem sets. I mostly internalized it, so I am able to do some of the steps in my head rather than on paper. But for harder problems, using paper to write the algorithms and test it step by step is still helpful.

Although I already had a decent process for writing code, I did not find SPD to be useless or a waste of time. I appreciated seeing things from another perspective. It also served as good review for some of the topics I had come across before. Plus, I had a question in mind — would this make me a better programmer? I consider myself a decent programmer. I’m no genius, and there are many people out there better than me. But there’s always something I can learn, even from beginner courses such as this one. I don’t know yet if learning this makes me a better programmer. I’d like to say yes, but I won’t know yet until I create more working, efficient, complex programs using the information from this course.

I have some ideas about how I could utilize this information in the future. I can’t say this systematic approach is the end-all be-all for any programming problem though. I think it can get the ball rolling and increase your chances of solving a harder problem. But I can also see how someone could potentially struggle. Step 4 — code the body — can be ambiguous with respect to the exact steps of the body when applied to a different language. But to give credit to SPD’s method, step 2 does make you come up with examples.

If you work out those examples by hand, then you can use that knowledge to implement step 4. The course does mention to do the examples first, to make the following steps easier. In the examples from the video walkthroughs, the instructor does elaborate or expand out the steps in the tests, which helps to code the function body. But if you don’t watch the videos and rely on just the steps without taking the course, then you might not adopt those example-specific details.

For this course, the examples are simple enough to where, after doing steps 1-3, it’s not a big jump to make to code the function body for most of the problems. You might get stuck here and there and have to look at the solution, and that’s fine, but only if you are truly stuck. Anyway, not a super big jump to make for step 4. Expanding the examples into more specific steps will help with step 4 too.

For outside this course, coding the function body may not be straightforward, and you might not be able to expand out the steps like in the style of Dr. Racket. However, if you carry the idea of “expanding” the example steps, then coming up with the specific steps from there, in theory, should be enough to solve for step 4.

It’s a little different for programs with longer steps in sequence, like the ones from Intro to CS using Python course, where you can’t expand the test case steps like in Dr. Racket. That’s why it can be confusing at first to apply SPD’s method to other programming languages, where the execution style is different. In Dr Racket, the code steps execute in a nested fashion. In Python, the code steps happen in top-down sequential order (although nesting can occur). But if you keep the main ideas in mind instead of the language specific details, I think you’ll be able to translate it to other languages effectively.

For algorithms such as the problem set 1 part a from Intro to CS using Python from this OSSU curriculum, I think replacing step 4 with the 7 step problem solving technique that I learned from the Coursera specialization mentioned above can help a little more to come up with a working algorithm, because its steps for coming up with an algorithm are more explicit.

We can supplement step 4 from SPD by using the 7-step method if needed. This is an instance where I see that SPD can be combined with another systematic process from a different source. This is why it can be useful to get a breadth of knowledge. You can see where one thing would work in combination with another. Or perhaps you can see how one method works over another method in some instances. You have more mental problem-solving tools to work with.

I’m not saying that SPD’s method is useless or inferior. It’s definitely a strong method. Just a nuance I noticed about it in comparison with my own processes.

For SPD’s method, if you adopt/internalize the idea of expanding out the examples into it’s specific steps, then you might not need to adopt the 7 step approach, and so SPD’s method would be sufficient in theory. So maybe I’m wrong. Maybe SPD’s method is perfect for beyond the course and you don’t need an extra process. Still, I think the 7 step approach is a good mental problem-solving tool to have.

Outside of this course, I haven’t had enough practice with SPD’s method to determine the true winner. However, we shouldn’t think of these as competing methods but rather tools that can both be handy whenever we need them. For now, I’ll be looking to combine both. The 7 Step Method doesn’t design functions, it’s specifically for writing out an algorithm, so the code body. I can use SPD’s method for the function specific details and the templating idea. Both have a test and debug step.

Those are all my thoughts for this review. Thanks for reading. I hope you found it somewhat insightful.

If you want a summary of key points for each module of SPD, along with a deeper discussion, I wrote a separate article for the first half of SPD here, and the second half from the articles I wrote here (week 6b - week 11). I wrote the key points of each module, along with my thoughts/analysis about them. It can serve as a succinct summary of the course’s main ideas. It might be useful to some people and I think it might be useful for myself to look back at. I mostly have it as a journal for my learning experiences.

Additional readings: Here are some articles written by one of the authors of How to Design Programs that I think you might find interesting: