I’m writing this on a plane back from Toronto, where I spent a few days teaching librarians to code as part of the Mozilla Foundation’s Software Carpentry program (which was basically the funnest thing ever, and Mozillans are smart and nice, and Toronto makes a spectacular case for itself, and Canadian librarians are 100% high-grade awesome).
Teaching this clarified for me some of the difficulties I had with my online Python course (where by “clarified” I meant “I sat bolt upright at 3am wondering why I hadn’t realized this before and had to spend the next hour writing it all down and trying to figure out how to get back to sleep”). So let me try to put that into words — but first I need to back up and explain an important paradigm I have for understanding the programming learning curve.
I believe, from personal experience and talking to people at different places on the programming learning curve, that the kinds of problems you are engaged with fundamentally change with every order of magnitude of the size of program you write. (Yes, lines-of-code is a bad metric, but it’s a good ballpark, so let’s roll with it.) They’re all important, complex, meaningful problems (though it can be hard to remember that you ever needed to solve them when you get too many orders of magnitude past them). They go roughly thus:
- 0 → 1 line. “What the heck is this?!” What is a programming language; if applicable, how does it differ from other related things you may be familiar with, like markup languages or Excel formulae; what do “function” and “control flow” mean and why do you care.
- 1 → 10 lines. “How can I do something useful with a programming language?” And by “something”, I mean one atomic task, but one that runs from beginning to end with correct syntax and employs those fundamental conceptual building blocks.
- 10 → 100 lines. “How do I break a task down into subtasks?” Modularity, reuse, DRYness, planning.
I’m not going to articulate the next few orders of magnitude, both because they are not relevant to beginner or intermediate programmers, and because I’m climbing the 1K → 10K transition myself, so I’m not able to articulate it well. But they have to do with elegance, abstraction, performance, scalability, collaboration, best practices, code as craft.
The 3am realization is that many, many “introduction” to programming materials start at the 1 → 10 transition. But learners start at the 0 → 1 transition — and a 10-line program has the approachability of Everest at that point.
This is why the CodingBat exercises that Boston Python Workshop developed are such a big deal. From this side of the 0 → 1 transition they look meaningless — they’re functions, with the def function_name()
part already written, that require you to write, in many cases, one line of code to accomplish the goal. One. Line. And they’re not meaningless at all. They’re where students discover what they did and didn’t understand from readings and lectures and messing around with the shell. They’re where students discover that they may have vocabulary and syntax, but they don’t yet have a conceptual model of what a function is. And in practicing writing one-line functions, they develop that conceptual model. It’s absolutely critical.
And this is going to be the next big thing I struggle with in teaching this better. Because the fact is, you want to be teaching examples that are grounded in real-world tasks. They’re motivational; they’re more comprehensible than abstract examples; they make it easier for students to connect course material to their actual work, meaning they’re more likely to be able to keep using it, to climb more of the learning curve on their own — to get to a place they can actually use this stuff, which is not a place you can get people in a day or two.
But I don’t know how to do a real-world task as a one-line function. I know how to write a ten-line function that does something real-world-useful, and how to walk students through discussing it and modifying it. And that is great for the students who have already climbed the 0 → 1 learning curve. But it’s baffling for the ones who haven’t.
I think I can do this, with thoughtfully chosen examples. I think I can come up with one-line things that can be wound into ten-line things, so students leave a course with a working program that does a thing they can imagine using (or, at least, a working program that’s a close enough cousin to something useful that it suggests where to go next and gives them a head start in getting there). But this is going to be hard. This is totally, “I apologize for the length of this letter; I did not have time to make it shorter” territory. Simplicity is brutal. And one-day intensives, or four-week onlines, do not have time for unnecessary things.
At any rate. I came out of the last two days with this to mull over, plus a stack of books and articles of research on code pedagogy, plus a bunch of good memories and tasty food experiences and new people to follow on Twitter and face-to-face encounters with people previously followed, so it’s just made of win. But I welcome your thoughts.
Great article and interesting problem posed. If the useful one-line program holds the key to entry level learning, why not start with a powerful language that does one-liners well with lots of simple and useful examples? Awk.
See http://www.catonmat.net/blog/awk-one-liners-explained-part-one/
LikeLike
I LOVE THIS. Thank you for writing it!
LikeLike
Christopher – hmm, I imagine that the ecology of useful things the learner can do *in that language* to accomplish their end goals, and of learning materials and teachers and so on, would also be a pretty strong factor here. Otherwise perhaps we’d all be speaking Ithkuil… 🙂
LikeLike
Awesome!!! I also helped with swcarpentry + librarians last year and took eerily similar notes. I did a brief write-up at http://pgbovine.net/teaching-librarians-programming.htm but didn’t go into details on the topics that you covered in this post.
Look up the STEM education literature on “worked examples”, “scaffolding”, and “cognitive load”. This dissertation is a wonderful starting point — start with the related work chapters:
http://lib.tkk.fi/Diss/2012/isbn9789526046266/
The upshot is that you don’t need to worry about real-world applicability when going from 0->1 lines. That’s too much to ask for. In fact, I’d argue that you don’t need to worry about real-world applicability even for 1->10 lines. Just focus on the fundamentals first … without a solid foundation in the “1+1” of programming, it’s impossible to develop higher-order computational thinking skills. Best wishes!
LikeLike
Yay, you stopped by! I’ve been reading your stuff on software carpentry (and silent technical privilege) lately. I’m glad to have the research pointer to look at – I’ll add it to the pile.
LikeLike
One thing I have used when people are just taking their first steps is an exercise where the code is given to them, and they need to rearrange it in to the right order — see “Speed Calculator” at
http://cscircles.cemc.uwaterloo.ca/1-variables/
Maybe this is greater than 0, but less than 1 lines of code?
I’m teaching Java these days. It is completely crazy with its 5 lines of mumbo jumbo to just get anything started. But we often will give students a template, with selected blanks for them to fill in. So there are good ways to get students to focus on one line of syntax at a time, even if you can’t think of a lot of good 1-line programs (I, for one, really cannot! And to compress a multi-line program into one line is probably not a good thing to try to do for beginners — readability rules).
Thanks for sharing your experience teaching this group, and good luck!
LikeLike
One oneline function that I use is an identity function. Just returns the thing passed in.
Sounds silly, but here’s my case:
calling a function that collects data from a database, and converts (or doesn’t convert) it to standard measurements from metric.
Add to this funtion by checking that the thing passed in is a number.
After building an identity function, build the conversion function.
Another little function would be checking the validity of a datapoint – but you have to check that it’s a number and then check that it’s in a valid range – so more than one line.
Hope those are useful in your 0->10 lines!
LikeLike
This is one reason I love languages that let you skip the “def” line and just write one-line programs you can run directly 😉
You teach functions *after* they cross the 0->1 line hump.
LikeLike
I do think it’s helpful to have single lines of code that execute and perform some recognizably useful thing. (For my audience, Python’s string.replace() is a good example; other audiences may vary.)
I’m not sure whether skipping the def line is relevant – obviously you have to write that in Python – but jumping the conceptual hurdle about what functions are is going to happen regardless of what your syntax is, and I don’t know whether obscuring that would help. (I truly don’t! I do think that reducing the amount of magic boilerplate students have to have around is helpful, and def probably looks like magical boilerplate to beginners. On the other hand, it *is* a key concept and maybe signposting where it’s happening is useful. I’ve found that asking students to write one-line functions (even if I provide the ‘def’ scaffolding for them) is a huge conceptual hurdle, and I imagine that’s the case regardless of what the scaffolding looks like.)
LikeLike