$30 off During Our Annual Pro Sale. View Details »

Teaching Programming Online (CodeMotion)

Pamela Fox
November 22, 2014

Teaching Programming Online (CodeMotion)

A talk delivered at CodeMotion about teaching programming online on Khan Academy.

Pamela Fox

November 22, 2014
Tweet

More Decks by Pamela Fox

Other Decks in Technology

Transcript

  1. Teaching Programming Online
    pamela fox
    @pamelafox

    View Slide

  2. My Background
    Computer Science Linguistics 3d Animation
    + +
    Developer Relations
    2002
    !
    !
    !
    2007
    2007
    !
    !
    !
    2011
    2012
    !
    2013
    Frontend Engineer

    View Slide

  3. August 2013 - ??????

    View Slide

  4. What is Khan Academy?

    View Slide

  5. K-12 Subject Tutorials

    View Slide

  6. Exercises & Videos

    View Slide

  7. Personalized Learning

    View Slide

  8. Teacher-facing Analytics

    View Slide

  9. Todo traducido

    View Slide

  10. The Tech Stack
    Backend
    Frontend
    Backbone FB React
    jQuery Handlebars LESS

    View Slide

  11. Heavy on Open Source
    Using Contributing
    https://github.com/Khan
    Blogging
    http://bjk5.com/
    http://mattfaus.com/

    View Slide

  12. View Slide

  13. What should we teach, exactly?

    View Slide

  14. So many options
    Languages
    Uses
    Java Python
    C++
    Haskell
    JavaScript
    Ruby
    Scheme
    Games
    Animation
    Hardware
    Robotics
    Data Science
    Simulation
    Mobile
    Websites
    Lua

    View Slide

  15. Our goals
    No Installation Needed
    Shareable
    Fun for Anyone
    Gateway Drug

    View Slide

  16. So many options
    Languages
    Uses
    Java Python
    C++
    Haskell
    JavaScript
    Ruby
    Scheme
    Games
    Animation
    Hardware
    Robotics
    Data Science
    Simulation
    Mobile
    Websites
    Lua

    View Slide

  17. How do students program?

    View Slide

  18. ACE editor
    JSHint ! BabyHint ! Loop Checker
    ProcessingJS

    View Slide

  19. ACE Editor
    number scrubber color picker

    View Slide

  20. ProcessingJS
    http://processingjs.org/reference

    View Slide

  21. JSHint
    var myName = “spaghetti
    if (i == 0) {!
    !
    }
    var i = 2;!
    if (i == 0) {!
    !
    }
    errors
    warnings
    best
    practices

    View Slide

  22. BabyHint
    elipse(10, 10, 20, 30);
    spelling
    wrong
    arguments
    ellipse(1, 1, 20, 30, 5);

    View Slide

  23. Infinite Loop Checker
    var i = 0;!
    while(i < 10) {!
    ellipse(i, i, 30, 30);!
    }
    Web Worker

    View Slide

  24. Now, how do we teach?

    View Slide

  25. Usual way to teach: Videos
    https://www.khanacademy.org/science/computer-science/v/python-lists

    View Slide

  26. Our approach: “talk-throughs”
    Uses same environment they program in
    Making passive instruction interactive!
    https://www.khanacademy.org/cs/programming/drawing-basics/p/intro-to-drawing

    View Slide

  27. Playing talk-throughs
    SoundManager2.js
    commands = [!
    {"key": "\n", "time": 14124},!
    {"key": "\n", "time": 14260},!
    {"key": "r", "time": 14676}, !
    {"key": "e", "time": 14764},!
    {"key": "c", "time": 15036},!
    {"key": "t", "time": 15548},...]!
    or
    var player = soundManager.createSound({ !
    url: revision.getMp3Url(),!
    whileplaying: function() {!
    updateTimeLeft(Record.currentTime());!
    Record.trigger("playUpdate");!
    }!
    });

    View Slide

  28. Creating talk-throughs
    canvas controls
    recording controls

    View Slide

  29. Recording audio
    var multirecorder = new MultiRecorder();!
    multirecorder.startRecording();
    https://github.com/Khan/MultiRecorderJS/blob/master/multirecorder.js
    rightBuffer.push(stream[0]);!
    leftBuffer.push(stream[1]);
    getUserMedia()
    new Worker()
    multirecorder.stopRecording();
    getInterleaved();
    encodeWAV();

    View Slide

  30. How we improve talk-throughs
    Analytics

    View Slide

  31. How we improve talk-throughs
    BEFORE
    AFTER

    View Slide

  32. How can we assess learning?

    View Slide

  33. Usual way to assess: Exercises
    Repeated multiple times with variants

    View Slide

  34. Our approach: coding challenges
    Structured yet flexible.
    More than one way to code the solution.

    View Slide

  35. ...and they’re fun!

    View Slide

  36. How do we “grade” challenges?
    staticTest StructuredJS Esprima

    View Slide

  37. Esprima
    http://esprima.org/demo/parse.html#
    var theNumber = 50;!
    !
    if (theNumber > 0) {!
    !
    }!
    AST
    JavaScript

    View Slide

  38. StructuredJS
    http://khan.github.io/structuredjs/index.html
    var $numVar = $numVal;!
    !
    if ($numVar > 0) {!
    rect($x, $y, $w, $h);!
    }!
    var theNumber = 10;!
    !
    fill(255, 255, 255);!
    if (theNumber > 0) {!
    rect(10, 10, 30, 40);!
    } !
    if (theNumber < 0) {!
    rect(10, 50, 30, 40);!
    }
    structure: user code:
    it’s a match!

    View Slide

  39. staticTest
    staticTest(“Add the ifs!”, function() {!
    var descrip = “Now add an if to check if the number is positive.”;!
    !
    var pattern = function() {!
    var $numVar = $numVal;!
    !
    if ($numVar > 0) {!
    rect($x, $y, $w, $h);!
    }!
    };!
    !
    result = match(pattern);!
    !
    if (passes(result)) {!
    var goodX = structure(pattern, inRange(“$x”, 10, 20));!
    if (!matches(goodX)) {!
    result = fail(“Hm, does your rect start on the side?”);!
    }!
    }!
    assertMatch(result, descrip, displayP);!
    });!

    View Slide

  40. ...Not quite that simple, though!
    Most challenge tests are hundreds of lines long.
    Most steps have 10-20 helpful messages.
    https://www.khanacademy.org/cs/challenge-exploding-sun/2050946856

    View Slide

  41. How we improve challenges
    Challenges Attempted: 244,168
    !
    Challenges Completed: 162,858
    !
    Challenge Completion Rate: 67%
    Overall Analytics

    View Slide

  42. How we improve challenges
    Manual Feedback

    View Slide

  43. Giving more opportunity for practice: Projects

    View Slide

  44. Peer evaluations for projects

    View Slide

  45. How can we create a community?

    View Slide

  46. Questions & Answers

    View Slide

  47. Wilson Voting Algorithm, GAE’d
    def wilson_confidence(upvotes_name, downvotes_name, score):!
    """Lower bound of Wilson score 90% confidence interval.!
    !
    This is the algorithm Reddit uses to sort comments.!
    You should not use this if downvotes are disallowed - it is only useful in!
    the presence of both upvotes and downvotes because its ranking is based on!
    an estimate of the ratio of upvotes to downvotes.!
    !
    See http://www.evanmiller.org/how-not-to-sort-by-average-rating.html!
    """!
    upvotes = getattr(score, upvotes_name)!
    downvotes = getattr(score, downvotes_name)!
    if upvotes == 0:!
    return -downvotes!
    elif upvotes == downvotes:!
    return 0!
    n = upvotes + downvotes!
    z = 1.64485 # 90% confidence z-score!
    phat = float(upvotes) / n # p-hat!
    return ((phat + z * z / (2 * n) - z *!
    math.sqrt((phat * (1 - phat) + z * z / (4 * n)) / n))!
    / (1 + z * z / n))!
    class TimeIndependentScoreProperty(ndb.ComputedProperty):!
    !
    def __init__(self, upvotes_name="upvotes", downvotes_name="downvotes",!
    **kwargs):!
    super(TimeIndependentScoreProperty, self).__init__(!
    functools.partial(wilson_confidence, upvotes_name, downvotes_name),!
    **kwargs)!
    !

    View Slide

  48. Spin-offs!

    View Slide

  49. The Hot Programs

    View Slide

  50. Reddit Voting Algorithm, GAE’d
    def time_dependent(decay_seconds, upvotes_name, downvotes_name, created_name, score):!
    """Ranking based on both age and quality.!
    !
    This is the algorithm Reddit uses to sort stories. We want there to be!
    churn, a constant stream of new programs hitting the hot page,!
    so this algorithm takes into account both the score of the scratchpad and the age.!
    See http://amix.dk/blog/post/19588!
    """!
    s = getattr(score, upvotes_name) - getattr(score, downvotes_name)!
    !
    # Weight votes logarithmically - initial votes are worth a ton!
    order = math.log(max(abs(s), 1), 10)!
    !
    sign = 1 if s > 0 else -1 if s < 0 else 0!
    !
    # Seconds since this algorithm's start date !
    date = getattr(score, created_name) or datetime.datetime.now()!
    seconds = epoch_seconds(date) - 1349108492!
    !
    return round(order + sign * seconds / decay_seconds, 7)
    class TimeDependentScoreProperty(ndb.ComputedProperty):!
    !
    def __init__(self, decay_seconds, upvotes_name="upvotes",!
    downvotes_name="downvotes", created_name="created", **kwargs):!
    super(TimeDependentScoreProperty, self).__init__(functools.partial(!
    time_dependent, decay_seconds, upvotes_name, downvotes_name,!
    created_name), **kwargs)!

    View Slide

  51. Similarity Diffing
    diff = difflib.SequenceMatcher(!
    # Ignore differences in spacing!
    isjunk=lambda x: x in " \t\n",!
    a=origin_revision.code.strip(),!
    b=self.revision.code.strip(),!
    autojunk=True)!
    !
    # Compute the ratio difference between the two revisions!
    # If the code is really large then we just do a quick ratio!
    # instead to try and speed up the comparison!
    if (len(origin_revision.code) > max_ratio_size or!
    len(self.revision.code) > max_ratio_size):!
    similarity = diff.quick_ratio()!
    else:!
    similarity = diff.ratio()
    Uh oh, Re-posts!

    View Slide

  52. Teaching Programming Online
    Learn Practice Create Share Help

    View Slide

  53. Want to help?
    github.com/khan/live-editor

    View Slide