Monday, January 27, 2014

New curriculum on object literals

Anyone who knows JavaScript is well acquainted with object literals, the language's approach to a hash or dictionary like storage mechanism. They're a fantastic way to store data, especially when combined with arrays, and once a JS programmer discovers them, it's hard to go back to using multi-dimensional arrays or excessive variables. That's why we now have a full tutorial on object literals - creating them, modifying them, and making arrays of them.

In the challenges, students use object literals to describe a recipe, make a painting program, and review their favorite movies.

In the final project, students use what they've learnt about objects to create a virtual bookshelf of their favorite books - storing colors and ratings in the books, and using loops to tile them across multiple shelves.

Thursday, January 23, 2014

Loops Curriculum Complete!

We now have a full tutorial covering the basics of loops. We start off with while loops, showing how they can be a great way to repeat code in interesting ways, then we introduce for loops as a shortcut syntax for common looping scenarios. We finish off with nested for loops, a technique that students find quite useful when making drawings, animations, and games (think of all the grids!).

In the challenges, students practice loop syntax to make a ruler, a landscape, and lined paper.

In the final project, students use everything they've learn about loops to turn a simple house into a way more impressive house - with grass, trees, tiling, windows, and more. We've seen some great ones already!

Check out the full loops curriculum here!

Programming Avatars

An extremely common request amongst students was for the addition of programming-themed avatars! All students can change their personal avatar in their profile. Until now the only avatars available were generic in nature, not relating to any curriculum.

Inside the Computer Science curriculum we have a few recurring characters that the students have fallen in love with: Winston (introduced by Jessica Liu), Hopper (introduced in the first coding challenge), and Oh Noes, the Error Buddy (who pops up on every error).

All of these characters have been turned into avatars for Computer Science students to enjoy! However, there's a catch: students must first complete a number of different tasks within the CS curriculum in order to unlock the avatars. The full list of the required accomplishments can be found here:

Unlocking avatars is something new to Khan Academy, before now you had to receive a number of energy points in order to unlock an avatar. Having this new incentive-driven model is exciting for both the students and the teachers. We're curious to see if this has a positive impact on students exploring the site and curriculum!

The Many Ways to Write a For Loop

For our loops curriculum, we start off with introducing while loops, because of their more intuitive form. We then introduce for loops in a talk-through where we describe them as a shortcut syntax for common while loop scenarios, and like with all of our curriculum, we present the students with a coding challenge after to get them actually using for loops.

In this Lined Paper challenge, we start off with a while loop and ask them to convert it to a for loop. The beginning code is:

var i = 0;
while (i < 20) {
    var lineY = 20 + (i * 20);
    line(0, lineY, 400, lineY);
    i++;
}
And the hint code is:
for (_; _; _) {
    var lineY = 20 + (i * 20);
    line(0, lineY, 400, lineY);
}

For the solution, we're looking for them to rearrange the components of the while loop into a for loop, which you can likely do easily if you're reading this.

For all of our challenges, we start them off with a fairly strict StructuredJS-based grader - just looking for the most obvious solutions that we come up with when developing the challenge. But then we release the challenges into the wild, monitor the feedback that comes in through the "Help" link, and adjust the graders. Sometimes that means adding more successful match patterns for students that came up with valid alternate syntax; many times that means adding more messages to help students understand what's wrong with their syntax.

It's always fascinating to see the many ways that new and experienced programmers come up with to write what is effectively the same program, especially in JavaScript because it is a language with multiple overlapping syntaxes - so I thought I'd share some of the for loops variations here.


Ways to get it wrong

Some learners don't quite understand the order of expressions in the for statement:

for (var i < 0; i < 0; i++) {
}
// Warns "The first expression in your for() should be an initialization of your counter variable, *not* a conditional check."

A few learners put their initial variable definition outside of the for loop - which works, but defeats 1/3 of the point of the for syntax, which is what we're trying to teach:

var i = 0; 
for (i; i < 20; i++) {
}
// Warns "It looks like you're initializing your counter variable before you create the for loop. As best practice, you should be doing that as the first expression in the for()."

A few learners came up with creative new syntaxes for adding one to i, which we added regex-based messages for (since the code can't be analyzed as valid JS):

i+++   // Warns "The increment operator is only 2 plus signs after the variable name, not three."
i ++ 1 // Warns "It looks like you were trying to use the += operator but wrote ++ instead."

Of course, learners also struggle with the logic of the for statement, finding all sorts of ways to produce an infinite loop, which we unfortunately can't give helpful messages for yet, due to the way our error messages are produced:

for (var i = 0; i > 360; i++) {
}
for (var i = 0; i < 20; i++) {
  var i = 0;
}

Ways to get it right

Perhaps more interesting is the way that people got it right that I did not anticipate, due to my own deep-seated conventions.

Typically we use i++ in our talk-throughs, but many programmers prefer += 1. Some argue it's more intuitive, some like how easy it is to change the value, and others, like Douglas Crockford, discourage using the increment/decrement operators and bake that into linting tools. So, we now accept all of these for the increment expression:

i += 1 
i++
++i

Note that ++ and += are not functionally equivalent in terms of type casting, as pointed out by Nikolas Co.

var s = "hi";
var t = "hi";
s++; // NaN
t += 1; // hi1

And of course, a post-increment operator works slightly differently than a pre-increment operator. But, in the case of this for loop, where we have already checked that the value is a number, the difference between these operators doesn't matter.

If you're curious, here is what the constraints look like for making sure that their expression is one of the accepted ones, analyzing the AST node that we parsed with Esprima:

var isPlusPlus = function(ast, varName) {
    return ast.type === "UpdateExpression" &&
        ast.operator === "++" &&
        ast.argument.name === varName;
};
var isPlusEqual = function(ast, varName) {
    return ast.type === "AssignmentExpression" &&
        ast.operator === "+=" &&
        ast.left.name === varName &&
        ast.right.value === 1;
};

It is fascinating to teach programming and come up with these challenge graders, because it reminds me of the many ways that new programmers can be confused about a syntax and challenges my ideas about what the right way is to program something.

Friday, January 3, 2014

A Million Hours of Code

On Dec. 8th, we kicked off our Hour of Code campaign with Code.org, with the goal of teaching more students to code. Since then, over 1 million students have come to Khan Academy to try out our Hour of Code. Those students completed more than 500,000 coding challenges, and over 80,000 took on the final project, creating a holiday greeting card:

On Twitter, we read tweets from classrooms of all ages trying out our Hour of Code, including deaf students. Of the many we bookmarked, here’s a favorite:

In our email inboxes, we received great stories from teachers using it with their students:

"Thanks soooo much for this; it’s changed my whole direction for the rest of my teaching career. That sounds dramatic, but it is true!!"
Sherri Long
"Thank you for the AMAZING hour of code lesson! I had so much fun helping and watching my students learn through this outstanding experience. I have to admit that I was nervous about trying it, since I know nothing about coding, but Khan Academy has never let me down before, so I jumped in with both feet. All of my students from grades 6-12 participated in the Hour of Code and there was no negative feedback. Let me repeat that... NO NEGATIVE FEEDBACK! Everyone loved it. One of my students can't stop talking about how great she feels now that she knows what she wants to do for a living."
Mrs. Tracy Cassidy

It was a busy time for us, responding to the deluge of questions from new, eager programmers, but it was also an amazing time because we got to see more students learning to program than ever before — both on our platform and in the world. According to Code.org estimates, 1 in 5 US students tried out one of the many Hour of Code tutorials, students from 170 countries learned to code, and more girls participated in CS in one week than in the last 70 years. Amazing!

We hope this is just the tip of the iceberg for many of those students, and that one day, one of them will look back on their career and realize that it all started for them with just that one hour!

Thursday, January 2, 2014

New Year, New Documentation

We're starting off the New Year with another overhaul of our documentation, and we're pretty excited about it. Here's a round-up of the major improvements that we've made based on the feedback from our fantastic community of learners and teachers:

We documented everything. We previously linked to the ProcessingJS reference for the less commonly used functions, but that is a confusing reference for Khan Academy programmers due to their use of Java syntax and references to renderers that we don't support. We went through the entire ProcessingJS reference to find everything that we do support but hadn't documented yet, and added them to our docs. That meant adding a few new sections entirely (like Transforms and Time & Date) and adding a "See also" to existing sections. If we're missing something still, please let us know. Our goal is that you should be able to learn about everything we support from ProcessingJS from our own documentation.

We added visuals. We get many questions from new programmers about how to draw particular shapes. To help them figure that out faster, we've added screenshots to the "Shapes" section and the new "Complex Shapes" section. Now they can look at a glance to see what shape looks the most like what they have in their head, without having to know already what a "bezier" curve is.

We introduced a consistent format. Now, for everything we document, we follow the same structure: a description followed by a table of parameters and parameter descriptions. This is based on the ProcessingJS reference, but is also based on documentation that learners will find when using many programming languages and libraries. We hope that the more consistent format will help them learn how to use our documentation better, and also to use others' documentation.

We improved the linkability. We made the links on the documentation look more like links, and we also added in-page anchors with a "Quick jump" at the top of the page.

We made it translatable. Previously, we documented functions and parameters inside the comments of the demo programs, but since we don't yet have a translation mechanism for comments, that meant that our documentation had to be in English for everyone. Now, we've moved the descriptions into a field in our database, which will send it off to CrowdIn for translation, which means we could have a Spanish-language documentation! (If you can help with that, read this post.)

We differentiate ProcessingJS from JS. We get a lot of confusion from students about which parts of what they're learning is from JavaScript and which parts are from ProcessingJS. To try and reduce that confusion, we added headers in the docs for "ProcessingJS" and JavaScript.

Check out the new and improved documentation, and let us know what you think… and encourage your students to use it, of course!

Thursday, December 12, 2013

Newbie Syntax Blindness

For the very first step of the very first challenge that learners do in our programming curriculum, they are given one instruction: type a piece of code exactly as it's displayed.

The displayed code is pretty simple, a single command:

rect(80, 70, 60, 240);

...well, it's simple to those of us who know programming. But for somebody who's never programmed before, it's not necessarily that simple. It's a mix of letters and symbols combined in a way that's completely new to them, and even when the goal is just to copy the line exactly, it's easy to get confused. A newbie does not realize what's important about the syntax of a programming language - they don't realize that capitalization matters, they don't know that a misplaced comma can be a fatal error, they don't distinguish between different types of brackets. That's probably because they're coming from human languages, where much of that doesn't matter, and they haven't re-trained their brain to realize what matters in a programming language.

To give you a concrete idea of what I'm talking about, here are specific examples of syntax errors that new programmers make with that single line of code:

(10, 70, 60, 240)           // Not starting with function name
rect{80, 70, 60, 240};      // Using {} instead of ()
rect[80, 70, 60, 240];      // Using [] instead of ()
rect( 80 , 70 , 60 , 240 ), // Using comma instead of semi-colon
rect(140, 170,120, 140, )   // Extra comma
rect()70,60,240);           // Extra close paren
rect;(140, 170, 260, 484);  // Mis-placed semi-colon

Now, we send all user code through JSHint, so they will see an error message pop up when they make a mistake like this. But for many users making these sort of errors, that error message wasn't enough to help them figure out the error, and they clicked our "Help" button to report their confusion. For each of these mistakes, I put them in the editor myself, saw the error that popped up from JSHint, and thought to myself, "Is that what *I* would tell a learner if I saw them make that mistake in person?" For many of them, the answer was no. I would give them a much more specific, helpful message.

That's not because JSHint is bad - it's fantastic - but because I know exactly what their end goal is, I can offer a more informed message than JSHint. JSHint has to offer messages for all possible JS that someone could write, and can't assume it knows anything about their intentions. There are many ambiguous errors that one can make in JS, and the JSHint messages have to equal the ambiguity of those errors.

We can't be emailing every learner that encounters one of these syntax errors with our hand-curated custom messages, as we now have thousands of students going through these challenges every day — that just wouldn't scale! So we've added another set of messages that override JSHint syntax messages, are specific to a challenge, and are served based on matching a RegEx of the code. These messages provide more meaningful, newbie-friendly syntax help, and will hopefully help learners get over the beginner syntax hump.

Here's a before/after of our messages:

Their code Old message New message
(10, 70, 60, 240)
I thought you were going to type an assignment or function call but you typed an expression instead. Make sure you specify the command name, rect, before the parenthesis.
rect{80, 70, 60, 240};
I thought you were going to type an assignment or function call but you typed an expression instead. Make sure you use parenthesis around the numbers, *not* curly brackets.
rect[80, 70, 60, 240];
I thought you were going to type ] to match [ from line 2 but you typed , Make sure you use parenthesis around the numbers, *not* square brackets.
rect( 80 , 70 , 60 , 240 ),
Unexpected early end of program. Make sure you end your statement with a *semi-colon*, not a comma.
rect(140, 170,120, 140, )
I think you either have an extra comma or a missing argument? You have an extra comma after your last parameter.
rect()70,60,240);
It looks like you have an extra ) There's an extra parenthesis before the first parameter of the rect() command.
rect;(140, 170, 260, 484);
I thought you were going to type an assignment or function call but you typed an expression instead. You have an unnecessary semi-colon after the command name.

We won't be able to hand-curate every syntax error they encounter, but we hope that helping them through the first challenge will give them the confidence to approach and interpret the more ambiguous errors they'll encounter late in their programming life.

A big take-away for us, as teachers: never assume anything is obvious. Just because it's obvious to us what the difference is between the written code and the displayed code, does in no way mean it will be obvious to new programmers.