Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
How to Teach Webcraft and Programming to Free-Range Students

Notes on natural-(second) language learning and learning programming languages

1. Notes from a course on teaching English pronounciation and grammar


I think some of the lessons here are useful to the situation of someone who already has learned some programming concepts (grammatical structure), but is struggling with a new programming language, especially one that is based in a different paradigm. Or someone who has a handle on procedural programming for instance (the basic mechanics of doing something with the language), but now is being introduced to compositional/design issues.

In other words: someone who can get by in the language, but is not fluent, and may need help in any number of areas, depending on their background.

Course notes

The course notes I'm looking at are for a graduate-level course in designing a "needs-based curriculum" for teaching ESL students. The aim of the course was:

To teach you how to

  • listen to your students

  • analyze their speech

  • distinguish their strengths and weaknesses

  • apply needs-based curriculum principles to design sequences of activities that aim to address their weaknesses and difficulties

The "needs-based" philosophy is defined as

  • Learning is not a process of information transfer
  • We learn best by doing, through reflection, interaction, and hands-on practice
  • We also learn best when instruction is suited to our needs

In this framework, the challenge for the teacher/tutor then is to combine

  1. a curriculum designed around the students' needs/interests ("content objectives"), something they will be intrinsically motivated to use language for, with

  2. an analysis of the particular technical weaknesses of the students' pronounciation/grammar ("language objectives")

your goal is to merge your content and language objectives:

  1. define your content goals;
  2. define your pronunciation goals > review target vocabulary and try to anticipate the difficulties your students might experience and to address them in a systematic manner

I think this is a really useful framework for teaching programming as well, whether the teaching environment is structured around fixed lessons or more open-ended assignments. On the one hand you are attentive to the learner's technical weaknesses; on the other, you want to help the learner find motivation to work on them. Otherwise, without motivation the point may seem academic to the learner ('why do I need to do it this way when I've always done it that way just fine?'); but without pinpointing the technical issues, it's not instructive at all.

The following is the suggested sequence of a lesson/tutoring session.

  • introduce topic/content of the lesson
  • introduce pronunciation goals (explicitly or implicitly)
  • design controlled exercises: listening > production
  • design communicative exercises > proceduralization

Note that the listening/analyzing phase happens not just in an initial evaluation, but in each session. Also, I see some similarities here with the IES recommendation to "interleave example solutions with problem-solving exercises".

Some distinctions

Of course, with natural languages the dimensions of learner proficiency are much more studied and well-defined than in programming languages. There are standardized tests that help determine a speaker's proficiency and weak areas, for instance, and books written about specific pronounciation problems say a Polish speaker will likely have in spoken English.

By comparison, styles of programming are less established as best practices. What in one context is appropriate to use might in another context be completely wrong (overengineered, for example). Unlike in natural-language pronounciation or grammar where a native speaker can nearly always tell you immediately that the usage is wrong in that context, in programming two 'native speakers' often disagree on a particular usage. In part this is because the 'context' is much wider - it expands beyond phonetic/grammatical context and into 'what the code is being used for', how it's being developed, etc. (In this sense it may be more worth comparing teaching programming style to written composition).

But it still may be worth considering whether there are generally useful approaches/exercises/points to make when teaching, say, someone learning a dynamically-typed language coming from a static-typed language; or a functional language coming from an object-oriented one.

Texts used in the course:

Further work to do

  • Read/skim some of the scholarly articles for this class

  • Look for articles on the teaching of written composition that might be useful

  • Look for articles specifically comparing language-learning to learning programming

1. The IES report and Mendicant University's mentoring program

On the Software Carpentry blog, Greg Wilson put down some reflections on how Software Carpentry implements (or doesn't) the recommendations in a 2007 Institute of Education Sciences report Organizing Instruction and Study to Improve Student Learning. He asked us to do the same based on our own experiences teaching and learning programming skills, in order to "explore how our various approaches to teaching programming do and don't fit with what we know about how people actually learn."

My own experience teaching programming is limited and non-systematic, in the sense that I mostly have worked with students one-on-one (or at most 3 at a time), in one-off mentoring sessions and asynchronous code reviews online. In terms of Mendicant University's collective teaching practices, I defer to Gregory Brown's very thorough reflections on this topic. I have a few things to add in relation to my experiences. But first I think it would help to describe how MU's mentoring program works (and how we hope to make it work) in relation to the rest of MU's curriculum.

About MU's one-on-one mentoring program

The mentoring program of MU is a fledgling program that - as Gregory mentions - mainly serves as a review of entrance exam problems (for both students that were accepted and those that weren't), and also a preparation for the expectations of the core course, for accepted students. Even in this limited capacity, it serves an important function, by introducing coding standards and practices that will come up again in different forms during the course, and by identifying potential areas where a specific student may need to work on improving.

It also serves as a bridge between the entrance exam problems, which are deterministic, somewhat 'contrived', and worked on individually; and the course projects which are open-ended, practical, and worked on in collaboration with other students and mentors/teachers. We have found that the course completion rate (% of those who finish the core course) has increased as we have more closely integrated the entrance exam and pre-course mentoring with the core course -- there are other factors as well but this integration has definitely contributed.

Most of the students who apply to MU are intermediate-level Ruby programmers -- a broad spectrum, but still one that assumes that students have many basic skills (or can pick things up quickly if they don't). One of the challenges we have is to expand the mentoring program to include students who do not have as much, or any, programming experience, and also may lack some of the prerequisite skills (e.g. using distributed version control, regular expressions, command-line interfaces, package managers, debuggers, editors, ability to communicate abstract concepts in English, etc). This is one area I hope to learn a lot from others' experiences and from the research.

The IES recommendations

As Gregory mentioned, it's something of a stretch to try to apply the IES recommendations to our situation. Our students are not primary school students, it's not a classroom setting, it's a very limited time period, and we have an 'open' curriculum that's based on student's own interests. It's definitely useful to look at though, especially in thinking about how best to teach beginners. I also think it would be useful to see what research has been done on approaches not covered by this report that might be more applicable to "free-range" and adult learners, and non-classroom settings - such as basing the material on students' own interests, pair-programming, and students reviewing each others' work. I gather some of that research is collected in Greg's book.

I have just a couple things to add to Gregory's reflections, in terms of the one-on-one mentoring. For us to even look at things like spacing learning over time, use pre-questions to introduce a new topic, and quizzes, we would need to have more than one-off sessions as we do now. Some (very few) mentored students come back for a code review after their first mentoring session, on a voluntary basis. I think if we expand the mentoring to beginner students, we would definitely want to plan a number of sessions with more structure and could start to implement some of these ideas.

The other thing that struck me reading some of the details of the IES report, was that interleave worked example solutions with problem-solving exercises was in part based on a study of teaching computer programming (the only one that specifically mentioned programming). This definitely fits with my intuitions about one way we learn programming -- by reading other people's code, and then working a similar problem oneself. At the beginning levels this might mean simply typing in the code verbatim (not copy-pasting, but typing each line); at higher levels working a different problem using concepts of the worked example. I often recommend code reading to my mentoree students, including other students' code for the same problem, even if not "perfect".

2. Who are your learners?

Picking up where Gregory Brown left off in Who should study at Mendicant University?, here are some sketches of students who come through the one-on-one mentoring program of Mendicant University, in an effort to distinguish the kinds of needs and "groups of needs" our students have. They are necessarily sketchier and narrower than Greg's, since these are based on students who don't take the 3-week core course, who we may only interact with once or twice.

As Greg said, we have a very individualized approach and so this list is a bit of stereotyping, but I think it is useful in terms of hypothesizing how common weaknesses in coding practice can be linked to students' existing training backgrounds.

The Proceduralist

This student approaches problems in a brute-force way, typically using basic data structures, and with minimal object-orientation. The code has lots of array and hash manipulation, little consideration of principles such as information hiding and single responsibility, and is hard to read, although it works. He may be relatively new to programming, or have done some one-off scripting in another language but never needed to consider design principles, has mostly worked things out on his own with the help of Google and Stackoverflow. In some cases he is an older student who learned programming through a procedural language, and is coming back to it after many years. He has typically not had the experience of working collaboratively on a code base.

The Shaver

This student's code comes with tests for every method in every class, perhaps even leaving methods public that should be private, in order to test them. The problem may not be completely implemented however, or she may be stuck on the basic algorithm. In some cases, she has come up with an interface/DSL that is impractical to implement, at least as a first draft. Her tests themselves are brittle and will probably have to be thrown away. The basic weakness is she isn't analyzing the problem into manageable chunks, but instead working on peripheral or unnecessary things and avoiding the harder central problem. Ruby is typically this student's first programming language, and she has learned TDD from books, doing code katas, and attending weekend code camps. She is used to learning programming socially.

The Professional

She comes to Ruby from years of working professionally in Java or C++. Her code is technically OK, but verbose and reflective of her "native" language instead of idiomatic Ruby, and this makes it harder to read. She does not use closures, perhaps not even in iteration, resorting instead to for loops. She uses class inheritance where mixins would be a more flexible design. Her class names are abstract, reflecting her training in design patterns, and she tends to reinvent the wheel here rather than use built-in features of the language or standard libraries.

The Golfer

He prefers the most compact expressions possible, even though they make the code harder to read. His code has examples of a half-dozen different obscure techniques. He uses metaprogramming even when there is a much more direct solution. If there are comments in the code at all, they are clever jokes. His background is "a little bit of this, a little bit of that", and his interests are wide, if undefined. Like the proceduralist, he hasn't worked collaboratively very much. He is a current or former CS major.

The sketches above are all amalgams of current mentoring students, who have all submitted correct solutions to the entrance exam problems. They all have more than a basic proficiency in Ruby and programming skills in general. In other words, they are varying degrees of 'intermediate' or 'advanced beginner' -- not quite the skill level of those who are accepted into the Mendicant core course, but not beginners either.

What follows are some profiles of beginning students we would potentially like to mentor, in addition. These are even more sketchier, since not based on actual students, but on guesses about who might be good candidates for such a program. It's not intended to be an exhaustive list, just some preliminary ideas.

The Secretary

This student is perhaps similar to Luis' "Anna". He has mastered Excel functions for his job, and dabbled a little bit in recording his own macros and tweaking the code, but code is generally pretty mysterious to him and he hasn't had a need to learn more. Although he is curious about it, since he has seen others benefit from writing programs to automate some of their work. And he has a ton of semi-repetitive tasks he needs to do every day.

The Designer

This student is a graphic designer by training and has taken a few classes in web design, enough to have a basic understanding of HTML, CSS, Typekit, etc. She has started a wordpress blog, and tries to follow various web design blogs but a lot of it goes over her head. She is starting a new job where she has to interact with web developers and finds it frustrating, since they speak an entirely different language and yet seem entirely ignorant of graphic design principles. She is motivated to learn more about web development so she can better understand the "plumbing", and better communicate with developers.

The Gamer

A young person who loves playing games and socializing on the computer, particularly creative and open-ended games or games that involve an element of game creation within them. They are motivated to learn programming to create something unique to show their friends, and programming is one way of doing that among many. They have some basic understanding of programming concepts through Logo-like educational games and circuit simulators, etc.

The Sysadmin

He knows his way around setting up servers, but has only a vague sense from his university days of what programming is and how it could be useful. He has a new-found interest in learning it because he read somewhere about new scripting techniques/tools that could make his job easier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment