Students do the learning

There’s nothing you can do to create learning in a student’s brain.  The student does the learning.

I think the natural corollary is that learning will probably happen more when students are doing more, and learning will happen less when teachers are doing more.

Given these assumptions, masters of teaching would work to set up environments that would encourage students to follow particular trains of thought.  That sounds way, way harder than just telling the students what you want them to know.

Personal Update: Next Project

Ahoy, long-time readers!  Guess what?  I’m starting a brand-new project!  It’s going to be awesome.

I still have a passion for SBG.  We’ve gotten ActiveGrade all embedded in Haiku and they’re going to continue to do great work with it, but I’m heading a new direction – beefing up ActivePrompt to make it easier to use in your classroom, and useful to you as a teacher in deeper ways.  I think of ActiveGrade + Haiku as a big success and I’m proud of what we accomplished with it.  Thanks for all of your help with ideas, feedback, and your own stories on your own blogs!  Everything I know about SBG I learned from you.

I’m happy to answer any questions, and I’m *really* happy to collect any ideas or successes you have with ActivePrompt.  We’ll be making a bigger announcement in a couple of months, but you can reach me right now at rileylark@gmail.com .  I’m afraid I won’t be checking my ActiveGrade mail any more, so please write to me directly, or leave comments here.

Thanks again,

Riley

Use Promises to Remove Dependencies and Increase Flexibility

Quickly: What’s a Promise?

A Promise is an object that helps you deal with asynchronous code. A lot of async code looks like this:

fetchResourceFromServer(function(resource) {
    processResource(resource, function(successCode) {
        alertUserOfSuccess();
    });
});

Promises DRY that up by encapsulating the “when this is eventually done, do this other thing” concept. Promises have a then method that does the waiting and forwarding so you don’t have to keep writing it yourself.

fetchResourceFromServer()
.then(processResource)
.then(alertUserOfSuccess);

We can see at a glance that this is easier to read, but there are other, more better benefits as well.

An Example Problem

I was challenged to write the bulk standard uploader for Haiku, to which we’re adding all of our SBG functionality from ActiveGrade.  Basically, the problem was:

  1. upload a file
  2. display results after the file was processed by the server.

Both steps could take an arbitrary amount of time, depending on file size, processing power, etc. We need to display feedback to the user at each step.

Naive Solution

This is the kind of problem that is easy to describe but usually pretty annoying to implement. It might look something like this:

startFileUpload();
 
function checkIfFileIsUploaded() { 
    if (fileIsUploaded()) {
        displayProcessingMessage();
        checkIfProcessingIsDone();
    } else {
        setTimeout(checkIfFileIsUploaded, 1000); //check again in a second
    }
}
 
function checkIfProcessingIsDone() {
   if (processingIsDone()) {
       displayDoneMessage();
   } else {
        setTimeout(checkIfProcessingIsDone, 1000); //check again in a second
   }
}
 
checkIfFileIsUploaded();

There are a lot of problems with this code that will stop you from being an awesome developer.

  1. You have to read the definitions of those functions to understand what is happening
  2. If you want to insert a step between the two functions, you have to change BOTH functions, and link your new function to both existing functions. When your planning meeting comes up and someone suggests adding a step in between (“Can we ask them if they want to continue after the file is uploaded?”) you’re going to groan unprofessionally and say, “uh, I GUESS…”
  3. …and many, many more!

A Better Solution with Promises

Here’s how this code looks with promises.

    startFileUpload()
    .then(displayProcessingMessage)
    .then(waitForProcessingToFinish)
    .then(displayDoneMessage);

This addresses all of the problems I mentioned before:

  1. You do not have to read the definitions of those functions to understand the process
  2. If you want to insert a new step, you just add another `then` line.
  3. When you suddenly realize that processingIsDone() should actually be asynchronous, you don’t have to punch anything.
  4. More that we won’t cover here. Summary: simpler error handling, guarantees, easy expression of multiple paths, etc

The point of promises is to give us back functional composition and error bubbling in the async world.

-Posted by Domenic Denicola Oct 14th, 2012

How Does It Work?

The basic functionality comes from abstracting that repeated pattern you could already see in the first code sample.

function waitTilAThingIsDone() {
   if (thingIsDone()) {
       doTheNextThing();
   } else {
       waitALittle();
   }
}

This is a common pattern, and the Promise essentially abstracts it, leaving you to fill in only the actual functionality. Promises can cover many different types of “do this [eventually]” patterns. Consider similar code with callbacks:

startFileUpload();
listenForFileUploadCompleteEvent(function() {
    displayProcessingMessage();
    listenForProcessingCompleteEvent(function() {
        displayDoneMessage();
    });
});

This callback code has most of the same problems the original setTimeout code did. It’s tightly coupled and inflexible, uncomposable, and hard to read.

Imagine trying to change it by inserting a UI confirmation and displaying an error if anything goes wrong:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
startFileUpload();
listenForFileUploadCompleteEvent(function(status) {
    if (status === 'success') {
        askUserIfTheyWantToContinue(function(response) {
            if (response === 'yes, continue') {
                displayProcessingMessage();
                listenForProcessingCompleteEvent(function(status) {
                    if (status === 'success') {
                        displayDoneMessage();
                    } else {
                        displayErrorMessage();
                    }
                }
            } else {
                displayDoneMessage();
            }
        });
    } else {
        displayErrorMessage();
    }
});

Ugh!

Promises work by abstracting away that branching, waiting logic. In the early examples it seemed like a trivial abstraction – it’s even a little hard to see exactly what logic is being removed from the individual functions themselves. On a larger scale, the benefits become very obvious.

1
2
3
4
5
6
7
8
9
10
11
startFileUpload()
.then(askUserIfTheyWantToContinue) //promise version
.then(function(responseFromUser){ //receives the result of the previous promise as an argument
    if (responseFromUser === 'yes, continue') {
        return displayProcessingMessage().then(waitForProcessingToFinish);
    } else {
        return true; //just forward immediately to the next effect
    }
}) 
.then(displayDoneMessage)
.fail(displayErrorMessage); //this will be called if ANY part of the chain fails

You can imagine much more complicated paths with more complicated branches being expressed this same way. It’s easy to re-use segments of the path that might appear in different places, as opposed to the original callback-based snippet which had to displayDoneMessage() manually at the end of every branch!

Ok, HOW DOES IT WORK? (with jQuery)

To encapsulate your code as a promise with the then interface, you can use jQuery’s Deferred object or any promise library. Q is a famous one that inspired Angular’s $q, etc.

Original, unpromising code:

function checkIfFileIsUploaded() { 
    listenForFileUploadCompleteEvent(function() {
        displayProcessingMessage();
        checkIfProcessingIsDone();
    });
}

If this was your old code, you might have smelled the multi-concern stink of an extra dependency: you not only had to figure out if the file was uploaded, you ALSO had to know what the next step was.

Promises with jQuery’s Deferred object:

function checkIfFileIsUploaded() {
    var deferred = $.Deferred();  //helps you construct a promise
 
    listenForFileUploadCompleteEvent(function() {
        deferred.resolve();  //this "resolves" the promise you've made, and triggers the `then` actions used outside
    });
 
    return deferred.promise(); //this object has the `then` property that can be called from outside this function.  
    // We don't return the whole deferred object because we don't want the user of this function to be able to call resolve() on it themselves
}

Basically, the unpromising code handled state itself. It kicked off an operation and said, “when you’re done, do these other things.” The outer function returned null immediately, so the caller of checkIfFileIsUploaded didn’t get anything to indicate success or failure.

The promising code was different. It also kicked off an operation, but it said, “when you’re done, tell this deferred object,” and then it returned a promise. The caller of checkIfFileIsUploaded got the promise and could add to the success / error behaviors itself.

Conclusion

In the last section I showed two different ways to implement checkIfFileIsUploaded. The complexity of that function was just about the same with and without promises, but with promises it needed less knowledge about the next step. By returning the promise it gave the CALLER control over the next step.

So, without much extra complexity, we can implement our functions with promises! Then we can get at the amazing simplicity of `then` and the other jQuery.Deferred properties, and the code that uses our implementations will be much simpler and much more flexible.

Small ActivePrompt update

Thanks to Andy Schmitz and rjswanso, ActivePrompt got a little upgrade tonight: student responses will stay on the teacher’s screen even after the student disconnects.  Andy added a button to the teacher’s view that will clear all the responses.  In tandem these two new behaviors add a few possible ways to use ActivePrompt in class – thanks!

ActivePrompt Plus

I’ve got a new sketch for you to look at.  Unlike ActivePrompt, it’s not available on a server for you to try out.  It’s a bit more complex.  But, like ActivePrompt, the source code is on github.  I’ll add instructions for starting the server soon!

This is not a thing you can use, unfortunately, but if you have any notes I’d like to hear them.

Thanks!

Awesome vs. Accessible

In a product planning meeting recently, I said that given the choice between [A: something that's easy to set up but not that awesome] and [B: something that's hard to set up but pretty awesome], I’d choose the latter, B.

Mostly, I prefer awesome things and don’t see much point in making something that’s not that awesome, so this position makes sense to me.

But let’s think about the experience of someone who doesn’t yet know anything about our design!

In the first case, in which we’ve made a good feature that’s easy to use but doesn’t do anything really ground-breakingingly awesome, our new users arrive and think, “ok, I see what this does, fine.”  In the second case, in which we’ve made an awesome feature that’s hard to use, many of our new users will arrive and think, “I don’t know what I’m looking at.”  If we’re lucky, they’re students in our class and they cannot choose to leave.  Online, they mostly leave.

Later, in the first case, when we do extend the functionality to be really awesome, those initial users will think, “wow, ok, now this is going somewhere!”  In the second case, when we enhance the UI so it’s really easy to set up, most of those new users are… nowhere to be seen.  It was too hard to get started.  What’s worse, the users that did stay don’t need the enhancements you just released – they already worked their way through the difficult setup.

These two options are extreme, but I think we often come upon decisions between spending another week on the design and spending another week on the functionality.  Or instead of a week, a day, or an afternoon.

I prefer awesome things, but part of teaching is understanding that other people have not yet prepared their mental contexts for the awesome things I understand.  Making something accessible, or spending time on helping others build up their understanding, is a big difference between making something for myself and making something for other people.

In my calculus classes I insisted on teaching students programming first, so that they could really express themselves.  There’s value in that idea, but now I wonder how much of that was for them and how much was for me.

Opinionated software: teaching is about illuminating consequences

There’s pretty much nothing more annoying than a computer telling you you’re wrong when you’re not.

Users are always making decisions about how to use software. I think it’s too dangerous to try to make your software evaluate those decision, because sometimes the evaluation will be wrong. It’s better when software makes it clear that a decision is being made, and what the effects of the choices will be.

If you have an opinion, like “not much time should be spent discussing trivial details,” then it’s easy to make your software say things like “click here to submit your message. Make sure it’s important that everyone read this – otherwise you’re wasting people’s time.”  You could do something snarky like label the submit button “click here to waste everyone’s time.”

Instead, try just exposing the metric that makes you think discussions can waste time.  A message to twenty people that would take the average person 5 minutes to read costs 100 minutes of reading time.  What if the submit button were next to a note that said “it will cost 100 minutes to send this message?”

We were extremely opinionated with ActiveGrade.  We simply didn’t make features to support teachers doing traditional grading. This meant that teachers who already got standards-based grading loved ActiveGrade, but every other teacher was summarily rejected.  In our integration with Haiku I think we’re doing a better job of giving options to traditional graders who are looking to upgrade to SBG, without giving up on our ideal that students should take more out of school than a grade.

 

[Self-conscious guide for teachers used to posts about high school]

It’s funny, I had these thoughts about software but never thought of them so explicitly for students. Replace “computer” with “teacher” and “user” with “student,” and we have an interesting idea about what classroom teaching can be like.   How much better is it for a teacher to make choices clear… and then let students choose?

Dan Meyer has a lot of interesting theories about education, and one that stands out to me is that student engagement is practically a prerequisite.  How often do students decide what they want to do in your class?

Huh: I think I consciously made 10 or 20 decisions per year when I was in school.

New Point!

Ahoy, faithful readers!

I started this blog as a reflection on my teaching practice. It ended up connecting me with you, a helpful group of people willing to give me feedback on my theories.  The title I picked was just the title of the lesson I gave that day, but it was an apt one for what this blog has done for me.

For the last couple of years I have been making a piece of software to help teachers. I still think about education pretty much all the time, but more and more it’s abstracting away from my thoughts as a high-school math teacher.  These days I learn more about business and software design than I do about teaching, and the problem is that I’ve been limiting my writing to things I think you’ll be interested in.  I still find myself at a point of inflection, but it’s a really new point, very different from the namesake point, and I keep worrying that you’ll be bored if I write about the fascinations of networking, salesmanship, software design.

But I’ve become confident that these things ARE related to being a teacher! Furthermore, I’ve missed the personal development that regular blogging got me. So, loyal reader, this message is a warning and apology: my craft is shifting, and so will my blog.  Thank you for encouraging me and critiquing me thus far!  I hope you will stay, and keep reading, because I happen to know that for at least one teacher software and business are a very natural progression from teaching.  I think you might find that connections to the classroom can be found throughout my experiments in software and business, and I hope you will still comment.

 

Thank you for all of your help. I hope you’ve gotten value out of this blog, and I hope you can get some more!