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, my overall thoughts on the course, then some background of the course and what it’s about. Then, I will discuss the course’s programming paradigm, recursion, the space invaders project, and the TA solver (no spoilers). Finally, I will discuss my thoughts on SPD's process in comparison with my own processes learned outside of this course. By the end of this review, you will gain some insights about the course and about my thoughts as an experienced software developer who has completed the course.
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 thoughts and learnings. Also, this course is a part of the Open Source Society University’s Computer Science curriculum (OSSU). 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 beginners 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 having 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. You will also 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.
All credit to the instructor and authors of the How to Design Programs book. It’s a great process to follow that’s better than no process at all. Even if you're experienced, I think this course will still be useful. You can apply the ideas to other programming languages or environments.
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 or the nature of the problem, however, is what I might be using.
Since I just finished this course, I’ll need some more time before I can fully express the usefulness of it in my career. It’s usually a non-linear process — you don’t know when it’s going to happen. But thinking through my past experience, I can see how using this approach could help me get the ball rolling on hard problems.
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 (or courses based on HTDP such as SPD) might be better as an introductory. 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.
This course is structured with a series of lecture videos for each module along with quizzes in between to help make the knowledge stick. There are also practice problems and a problem bank to exercise what you’ve learned. Many of the lectures are like a walkthrough. You watch the instructor code up programs using the design methods. It serves as a good example to follow and use when you’re doing the practice problems on your own.
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. This is great for deliberate practice.
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.
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 too and writing reviews of them.
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.
Interesting thing though is that recently this course offered at the actual university is now using Pyret as their main language to teach systematic program design instead of BSL:
For the first 8–9 weeks, CS 2000 will be taught in Pyret, a teaching language built by CS educators who understand the successes and limitations of Racket teaching languages. In addition to first-class support for tables and data science, better support for testing, and a more modern environment with better errors, Pyret facilitates a smooth transition to Python for the last 4–5 weeks, once students have learned foundational computer and data science concepts.
Still, that doesn’t mean you won’t learn anything by using the BSL learning language for this course. Trust the process. Although the language won’t be super relevant beyond this course, remember that the main ideas taught using the language will be.
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. And 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 first half of the course was not too difficult. The second half was a lot harder and the learning curve was steeper.
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, using the systematic design methods. 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 and the right ideas in mind.
Before I took this course, I followed a different systematic process for solving programming problems. Or rather, I built up and internalized 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, courses from my degree programs learning from other good programmers, reading books, reading blog posts, Reddit and Quora, through trial and error, etc.
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, or whenever the algorithm isn't clear in my head, using pen and paper to write the algorithm and test it step by step can still be helpful.
Although I already had a working process for writing code, I did not find SPD to be useless or a waste of time. I appreciated seeing things from another perspective. I had a question in mind — would this make me a better programmer? I consider myself an okay 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 think that increasing programming knowledge can lead to becoming a better programmer though, so 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 can’t say this systematic approach is the perfect thing for every problem just yet. Yes, it can definitely get the ball rolling and increase your chances of solving harder problems. 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 many 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 supplementing 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.
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 (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.
SPD's method is powerful on its own though. The specific method was new to me, even though it had overlap with other ideas I've came across when it comes to writing/designing functions and solving problems. I am looking forward to taking the learnings from this course and applying it to future programs that I work with.
So yes, I do recommend this course for beginners and experienced folks. If you're a beginner, definitely go through the course. If you're experienced, you might be able to get away with reading my module-by-module notes below. Check them out if you want, and you can decide for yourself.
Summary of key points for each module:
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.
Whether you are a beginner or an experienced programmer, you can learn new things from this course. It’s definitely a significant time investment, but I believe in the long run it will be worth it. I hope this review gave you some useful insights and I wish you the best on your learning journey.
Additional readings: Here are some articles written by one of the authors of this course and the book How to Design Programs that I think you might find interesting:
- Developing Developers - author's perspective on developing developers
- Thoughts - Q&A with one of the creators of the course