Teaching Programming To A Highly Motivated Beginner
In the past year, many CS professors and education pundits have written about how MOOCs are scaling up CS education to hundreds of thousands of students. I'm going to take a different approach here and tell the story of how I spent nine months teaching computer programming to one student.
Between July 2011 and March 2012, I taught basic programming to Brian Goler, a veteran San Francisco Bay Area entrepreneur with an extensive background in marketing, sales, and product development. Brian started out with no prior programming experience, but within a few months, he was able to build SwearBuy, a free web application where people can share reviews of products that they love. More importantly, Brian gained the ability to seek out and learn more advanced technical material on his own. My biggest contribution was guiding him over the hurdles that usually demoralize beginners.
Brian learned about me from my personal website because it contains a few articles about computer science education. Here is an excerpt from the first email he sent to me in July 2011:
We haven't met, but I'm reaching out to see if you might have some advice for me.
I found your website while searching online for a tutor who might be able to help me learn more about computer programming. Specifically, I'm looking for someone who would be able to meet with me 1-2 times/week for short, 1-hour tutoring sessions while I work my way through the early phases of a CS curriculum.
I'm starting with MIT's OCW 6.00 course. While OCW and other online resources are great, I think I could advance more quickly and improve my understanding of concepts if there were someone I could turn to with questions and who could review my work and give me feedback.
Given your history at MIT and Stanford, I thought you might know someone who may be interested and a good fit? Or, places I should be looking? Of course, I'd pay for their time.
Since I wasn't too busy at the time, I offered to tutor Brian myself. We had our first one-hour session at his home and the second session at a nearby coffee shop. I then traveled to some academic conferences, so we did our third tutoring session over the Skype online video phone service. We used the screen sharing feature of Skype so that I could see the contents of his computer screen as we chatted. This format worked so well that we decided to do all subsequent sessions over Skype. I tutored Brian only twice in person, but we did over 50 hours of Skype video calls (spanning ~40 sessions).
At first, we were both surprised by how well the online-only Skype format worked for our sessions. It was even better than us meeting in person at a loud coffee shop and huddling around a small laptop screen. Using Skype's screen sharing features, I could view Brian's computer screen from the comfort of my own apartment and interact with him in real time. If I needed to make sketches, then I shared my computer screen with him and drew using a digital pen tablet. (Salman Khan started making his now-world-famous educational videos by tutoring his cousins in a similar way.)
Brian's goal was to learn basic programming skills for personal enrichment; he wasn't trying to get a job as a professional programmer or a computer science researcher. Before we met, Brian had already spent a few weeks teaching himself the Python programming language by following the curriculum of Introduction to Computer Science and Programming (OCW 6.00) from MIT OpenCourseWare. We spent our first few tutoring sessions going over basic programming concepts, grounded in the course lectures and homework.
However, I quickly realized that just learning from academic course materials would not keep Brian sufficiently engaged, especially since he graduated from college almost twenty years ago. He did not seem too keen on limiting himself to learning only computer science terminology and doing math-related puzzle problem sets intended for undergraduates.
Therefore, I decided to teach Brian to become a pragmatic amateur programmer rather than an erudite computer science scholar. I encouraged him to try to think of a piece of software that he would love to build for himself and his friends. My role would be to mentor him while he built his software project. It was such a simple idea, but it worked remarkably well.
Brian came up with a few ideas and ultimately committed to the concept that would eventually turn into SwearBuy. Over the next nine months, he devoted up to dozens of hours per week to building SwearBuy, often working late into the night. We scheduled 1 to 2 Skype tutoring sessions each week, each lasting 1 to 2 hours. I spent most of my time during those calls answering Brian's questions, helping him find and debug software bugs, and sometimes pair programming to write new code together with him. I rarely lectured for more than a few minutes at a time. Besides being highly engaging for him, this Q&A-based format was convenient for me as well since I rarely had to spend time preparing before our sessions.
Project-based learning was immensely effective since Brian cared deeply about his own fledgling creation. His learning was guided by necessity, not by some preset cookie-cutter academic curriculum. Since he was so passionate about SwearBuy, he would come up with lots of ideas for new features. He would inevitably need to learn new programming techniques to implement those desired features. Thus, my role was to:
- assess the feasibility of what he wanted to implement and, if necessary, guide him toward implementing a simpler version of his idea,
- select the subset of programming tools, idioms, and tricks that would best serve his learning needs,
- find him the proper resources (e.g., sample code, blog posts, online tutorials, or even books) so that he could teach himself,
- and answer his questions when he struggled to understand or apply what he had taught himself.
There are dozens or sometimes hundreds of ways to accomplish the same task in computer programming; this multitude of choices can be paralyzing for beginners. Since the space of possibilities is so vast, they simply have no idea where to start. My main job was to narrow down the space of possibilities into a manageable set of concepts to learn at each stage of Brian's project, let him struggle with learning on his own, and then answer his questions when he gets stuck.
Brian's project was a great basis for all of our Skype conversations, since I could teach new concepts within the context of what he wanted to accomplish in his project at any given time. No amount of contrived textbook examples can make up for a real-world application in which a student is personally invested.
Brian usually did 10-15 hours of programming on his own before each 1-2 hour Skype call with me, so he always had plenty of urgent questions and newly-written code that he wanted me to help him debug or improve. If I had just given him lectures without any context, he would not have internalized the lessons as thoroughly. He would have probably nodded his head and been like, "uh huh, ok that makes sense ... cool. what's next?" Instead, because he was usually struggling with concrete, code-related problems before our tutoring sessions -- often to the point of frustration and discouragement -- he would respond more like, "OHHH, WOW! Now I totally get it!", whenever I guided him over some problem that seemed insurmountable to him at the time. His joy and relief were always unmistakable. I don't think there is any better way to internalize knowledge than first spending hours upon hours growing emotionally distraught over such struggles and only then being helped by a mentor.
To make Brian's experience less painful, I took care of I.T. infrastructure setup and other "grunge work" that did not directly contribute to his learning. I wanted him to struggle hard on the actual programming and building of SwearBuy, not to waste his time on banal unrelated issues such as setting up a web server or version control system. (Of course, if his goal were to learn to become a system administrator, then I would have let him struggle with those tasks.)
There are lots of trendy books, online courses, and live seminars that claim to teach you programming (or other skills) in 7 days or 3 weeks or whatever. It's obvious that you cannot master a new skill in a few weeks, but I don't think anyone actually believes they can. The real danger with these sorts of "get skilled quick" schemes is that they don't emphasize sustainability. These courses are like fad diets that might get you to lose 10 pounds right away, but you are not going to keep the weight off unless you develop sustainably good habits. Similarly, there is no way to get skilled at programming unless you keep struggling over many years; but in order to stay motivated to keep struggling, you must be doing something you are passionate about. Struggling isn't fun, so without the proper motivation, it's all too easy to give up prematurely.
I knew that I had succeeded as soon as Brian realized he no longer needed me as his tutor. Even though he acknowledged that it would still take years of struggle to become a skilled programmer, he began to see how he could potentially get there from his current skill level. He had learned enough over the past nine months to sustainably continue learning on his own. I am proud that I gave him enough know-how and wisdom to continue on his own rather than serving him yet another "get skilled quick" fad diet scheme.
After our tutoring sessions ended, Brian reflected that although he cherished this "learning by doing" philosophy, he still believes that there is great value to balancing project-based work with traditional computer science course-based instruction. When building SwearBuy, he often applied ad-hoc solutions "just to get things working" using lots of Google searching, technical blog reading, and copying-and-pasting code from StackOverflow threads. As a consequence, he felt like he too often settled into suboptimal solutions or used concepts that he didn't deeply understand. Some of Brian's biggest forward mental leaps came when he took a step back away from the day-to-day project grind, learned new concepts in a course or from a book, and then thought about how to apply them to SwearBuy.
Since we finished our final tutoring session in March 2012, I didn't hear from Brian for six months. He recently sent me an email mentioning that he just wrote a Python script to help him model personal stock investments: "I'm very proud of this script because it was the first thing I've done that was both practical and purely for personal use. I was evaluating a stock investment and wanted to simulate a bunch of scenarios. I started to model the scenarios in a spreadsheet before I realized that a spreadsheet wouldn't work, but python was perfect."
I loved this email because it showed how programming enabled him to accomplish a task that would have been tedious or difficult to do otherwise. I hope that everyone who learns programming has their own "crossing the precipice" moment when they start programming for themselves rather than just for school or work assignments.
The cliche I'm going to rehash is that motivation is everything. Brian was highly motivated by his own project, so he practically taught himself. All I had to do was to steadily guide him along an efficient path so that his struggles were mostly directed toward useful learning.
How well do my experiences generalize to teaching the vast majority of students who are far less self-motivated than Brian? And how well does this technique scale up beyond one-on-one tutoring? I have no idea. All I know is that if you can get students genuinely motivated, remove unnecessary barriers to learning, and give them nudges at the right times, then they will practically teach themselves.
Great post Phillip! Couldn't agree more with the project-based and struggle learning approach. This is the exact recipe we use at The Starter League in Chicago. The students who are in our program are highly-motivated and want to solve a personal problem. For beginners, those ingredients are crucial to getting a great start in programming.
Awesome! I couldn't agree more with Brian. I have been working through MIT OCW and CodeYear from Codecademy, and it would be very helpful to have a mentor to bounce questions off of from time to time.
This was an interesting article and I like that it advocates a project-based learning approach. I think Alan Kay and Seymour Papert and many others have advocated this approach and you can learn a lot in a shorter amount of time when you're doing things like that.
However, sometimes a break is needed and you need to analyze and study and learn something in isolation. Instead of learning how to use the database for specific purposes in the context of the project, he should have also taken a few weeks to learn how to use the database for other types of projects through contrived examples. Increasing the depth of knowledge is essential for the long-term. In the short-term, especially with web-based projects which require multiple languages, it's understandable to have a broad overview.
@Philip, Your article feels like a running commentary on my life as we speak! The 3 paragraphs under "Project-Based Learning" especially describe my situation almost exactly (barring the extra decade of work experience Brian has, compared with me). As it happens, I too have reached out to someone for help, just like Brian reached out to you, and will shortly commence my own self-learning program with him. So thank you very much for sharing this. It's great validation and encouragement for other people like Brian and I.
Thank-you. An interesting and actually motivational article in itself.
This was a lovely article, I may not fit into the exact same shoes as Brian, but I do endeavor to produce code for my own stock simulation scenarios as well as budget my weekly spendings as of now.
This article just reinforced my belief in learning by doing rather than looking for free open source solutions available online. The road to eternal pleasure it seems is paved with a lot of time spent crouching in the front of a computer.
Any suggestions on where to start with the analysis and design part of a project?
I am a self-taught programmer, and I agree with the project-based learning approach. One outcome of that is, after a few years of struggle trying to build various things (Stack Overflow, Google, and the folks at the local user group have been my primary tutors), I *now* find that I have sufficient understanding that I seek out some of the more academic stuff. Had I started from that perspective, I may not have found things so interesting, and moved on.
Also, I have often (either by choice, or by not knowing better) undertook to do as you did with Brian - "roll my own" instead of using an existing framework solutions. The learning experience there has been vital. Once you build your own ORM or code generation tool, you really understand what is happening under the covers with the underlying technology the framework abstracts away.
While to me, frameworks and libraries provide the ultimate in code reuse, if you want to really understand a database, and how ORMs work, build one. Want to understand what goes into compiling a language (albiet, at a very basic level)? Build a code generator.
While creating any of these things from scratch in a high-level language cannot be considered mastery, it is hard not to take away important concepts from the process. More importantly, doing so can often help one formulate the right questions in search of deeper understanding.
When learning, I find explaining to others what I have just learnt is an invaluable technique for both sanity-checking and reinforcement. I use my wife or even my cat as a sounding-post in the early stages. As I progress, I find a suitable forum, such as tek-tips.com, and look for the questions which, I hope, I can answer. If my answer is incorrect or can be improved upon, someone more advanced than me will quickly correct me, increasing the depth and breadth of my knowledge. As I progress, I answer harder and harder questions while still keepnig an eye on the easier stuff in case I can contribute. As a side-effect, I often find my myself being introduced to new modules, concepts and techniques which I might not have encountered in any other way. Over many years, I have found this sort of "teaching" to be a very fast, effective and gratifying form of learning. I also find the idea philosophically satisfying: a cumminty of peaople helping each other for mutal advantage.
" I don't think there is any better way to internalize knowledge than first spending hours upon hours growing emotionally distraught over such struggles and only then being helped by a mentor."
I would say a slightly better way to internalize knowledge is by spending hours upon hours getting emotionally distraught, then figuring them out somehow. You'll never forget the answer to a but that cost you 3 days of stress LOL.