Methods for Using Spaced Repetition for Programming
Spaced repetition has a reputation for being useless for code. That's mostly because the tools can't run code. Here's how to make it work, and where it still falls short.
How many times have you looked up the syntax for sorting a list by a custom key? Or how to write a LEFT JOIN, or which way round the arguments to reduce go? You've understood each of these things more than once. You just haven't kept them.
That's the problem spaced repetition is supposed to solve. You review something just before you'd forget it, and each review pushes the next one further out. It works remarkably well for languages and medicine. For programming, it has a worse reputation, and I think that's mostly the tools' fault.
The gap
The biggest weakness of most spaced repetition systems, when it comes to programming knowledge, is that they have no way of actually running the code behind the concept you're trying to review. You end up switching to another context to complete a card. And frequently, the thing you want to review makes you write a lot more code than you really need to exercise the core concept you want to remember.
So people fall back to cards like "What does Array.prototype.splice return?" That tests whether you can recall a fact, and it's easy to flip the card, read the answer and think "yeah, I knew that." It doesn't test whether you can use splice correctly the next time you need it.
This has led to the mistaken claim that spaced repetition isn't useful for programming because it only applies to pure information recall. To make it useful, you have to close the gap between recognizing an important concept and turning it into a skill-based challenge you can attempt conveniently, without switching context.
What a good programming card looks like
Say you keep forgetting how to sort by more than one key in Python. A recall card would ask "How do you sort by two keys?" A practice card makes you do it:
Given a list of
(name, score)pairs, return the names ordered by score, highest first. Break ties alphabetically.
The card comes with tests. Each one is just the input and the expected output:
[
{ "in": [[["ana", 3], ["bo", 5], ["cy", 3]]], "out": ["bo", "ana", "cy"] },
{ "in": [[["zed", 1], ["amy", 1]]], "out": ["amy", "zed"] },
{ "in": [[]], "out": [] }
]And when the card comes up for review, you write the answer from scratch:
def rank(pairs):
return [name for name, _ in sorted(pairs, key=lambda p: (-p[1], p[0]))]It takes a minute or two. You can't fake it: either the tests pass or they don't. And the thing you're practicing is exactly the thing you forgot, a tuple key with a negated number to flip one direction, with nothing else in the way.
That example points to a few methods that I think matter most:
- Shrink the problem to the concept. Strip away everything that isn't the thing you want to remember. If a card needs a class hierarchy and a config file before you get to the interesting part, it's too big. You'll dread it, and then you'll skip it.
- Make yourself produce the code, not recognize it. Reading a solution and nodding along feels like knowing it. Writing it against tests is the only honest check.
- Let the tests carry the spec. The prompt can stay short when the tests define what "correct" means. Put your effort into the edge cases, especially the one that caught you the first time.
- Write the card when you hit the problem. The moment you look something up for the second time is the moment to make a card. You know exactly what you got wrong, and that's the test case to include.
- Keep plain flashcards for plain facts. Not everything needs to be code. What
HAVINGdoes thatWHEREdoesn't is a fact. Writing the query that needs it is a skill. Use the cheaper card when it's enough.
I wrote more about the practical side in How to write cards you'll still want to see in six months.
How SRS Badger approaches it
SRS Badger lets you create or import your own sets of programming cards, arranged by the topics of whatever you're studying, whether that's something you learned in the past or something you're working through now. Unlike the popular online platforms for practicing programming problems, it has spaced repetition built in, and it lets you write your own problems as you study from a textbook, or as you come across things you know you want to remember while going about your work.
The code runs right next to the prompt, so a review never means opening an editor, setting up a project or switching windows. That's the whole point. The friction of switching context is what kills the habit.
Where it doesn't work (yet)
The area I haven't figured out how to systematically study and review is software architecture. It would be pretty difficult to write review questions that accurately test refactoring skills in a way that can be easily checked. Those who are skeptical of using spaced repetition for coding have a point here: refactoring and structuring good systems can only be learned by dealing with larger amounts of code. If I tried to turn those skills into problems that fit here, they would quickly become unwieldy.
The same goes for debugging intuition, knowing a large codebase, and judgment about trade-offs. Those come from doing real work, and I don't think a review card can stand in for that.
Where it does
Syntax, the idiosyncrasies of a programming language, standard library functions and algorithmic concepts are different. They can all be reviewed and systematically mastered with a prompt that requires writing real code to pass test cases. The idea scales from something as simple as remembering the syntax of a for loop all the way up to reviewing a challenging algorithmic problem or design pattern.
These are also the things that make the bigger work go smoothly. When you're not stopping every ten minutes to look up how to group a dictionary or write a window function, you have more attention left for the design questions that cards can't help with.
Why bother remembering anything?
It's fair to ask why any of this matters when you can look everything up, or ask an AI to write it for you.
One essential value of knowing things, rather than looking everything up as we need it, is that our minds use what we know to generate ideas. You can't reach for a tool you've forgotten exists, and you can't search for a solution you don't know to look for. Our minds can be starving for knowledge despite having the world's information at our fingertips. Knowledge decays unless it's used regularly, and spaced repetition fixes that.
Try it
SRS Badger runs code in eight languages, including SQL. You can start with an example course or write your first card from something you looked up this week. We're also working on more extensive courses, starting with SQL concepts, introductory Python programming, and data structures.