
As you can see, most students are not coming into the class cold. But 37 is still a large and non-trivial chunk of newbie brains to consider.
Now that grades have been calculated, I can see how grades were distributed across these experience levels. I was disappointed in last year’s results. If you were a new programmer in the fall 2016 offering, you were unlikely to have received a high grade. The cause of that skew is not entirely clear to me, but I had something in the works to help fix it…
In fall 2017, we split our introductory course up into two sections: Introduction to Programming for New Programmers and Introduction to Programming for Experienced Programmers. 90 students self-selected into the class for new programmers, 30 into the class for experienced programmers. The classes were not all that different—they had the same homework and exams, and they followed the same overall plan. What was different were the labs (kind of) and the tone of the conversation during lecture. Showboats and showboating were not welcomed in the class for new programmers.
At the end of the semester, this is how the grades spanned the various experience levels:

I see a couple of takeaways from this graph:
I’m okay with all of these.
Was it the restructuring of the course that helped out new programmers? I don’t know. I don’t have time to conduct that kind of analysis. Or time to figure out how to do it.
]]>Occasionally students identify themselves in their messages. I’ve substituted in pseudonyms. Occasionally students identify me in their messages. I’ve left those references intact.
Not all messages make sense out of context. I assure you that I don’t know what they’re talking about either—and I taught the class.
Still working
Yay, I'm done. Might revisit Shuriken later if I figure out a way to simplify the code.
I'm worried about getFraction, might revisit.
That was rough. Should be good though.
Made isImage less likely to explode: kept original code just in case.
This is for getting help.
Only two left.
Try again
Okay. Two more.
Finally drew the stupid circles
Here we go again
Almost. So close. My line part of plot is a little off.
Getting closer...
Done. Finally.
First five done.
One more down.
Done through repeat.
One more down. Getting there.
Another down. Only two more. :)
Only one left.
Done. Gonna Go do the extra credit now.
Want to have this looked at.
Finished placesCache, still have problems with places.
Asking for help
For Piazza issue.
Done.
Was bored
Sunday Morning coding session!
All done!
All done! FOR REAL THIS TIME, sorry forgot to index the files.
Got er done after looking up 5 different methods on oracle
Started falling down the hill after method 8. They may need rewriting.
we gonna win
head hurts
Come buy my lemonade.
Tickets please!
Ninja stars!
I DID IT
I FINISHED
I'm Done *mmicdrop*
I DID IT YEEEEEEEEEEEEAAAAAAAAH BOIIIIIII
*Dora Voice* You did it!!!
IM DONE
Killed BrailleUtilities.
Defeated WebUtilities.
Killed BrailleUtilies.
Killed the main.
Killed NumberUtilites.
Killed WebUtilities.
Killed main.
Killed WebUtilities.
I've never done something so difficult in my life. Ever.
Committing before a heavy binge session
Meaningful
This is causing grief
Closer...
WE GOTTER OTTER
what even
it workssss
These are lit
yoooo
Happy Friday.
Will it?
not understanding
Closer
Can't get the color to go
ughhhhhhh
yup
less profane
yaaas
mmmm
Transposing is easy irl but not here
Sooo close
Yea
It works :)
We're so close it hurts
I'm going to die soon
IT WORKS
Every Villain is Lemons
if (this goes thru) return happy; else return sad
i have time management problems
if (i break arm && have your kid sign cast) {hw4 = 10 bluegolds}
pushed again just in case
almost there!
even better stuff here!
omg i'm crying this is the best stuff!!
why is this in intro course I love you chris but damn this is hard
In my meeting during lab they said my names weren't the best so I changed them.
Donion rings.
Double Check last minute panic. its working, make sure online code is too
progress
mas progress
mas+ progress
mas++
mas+++ progress
MAS+++ progress
Will obliterate later
You can do it Jerome!
You are doing it Jerome!!!
Good luck Jerome
YOU DID IT JEROME
You started it Jerome!
HI CHRIS!!!!!
Hello again Chris, forgot to push my NumberUtilities
You can do it!
PUSH!!!!
YOU ARE DOING IT JEROME!!! NEVER LOSE HOPE
Great start Jerome
YOU ARE DOING HECKIN GOOD JEROME
I AM DOING IT
10/16 JEROME!!
forgot one Chris. Sorry
I DID IT CHRIS!!!!! PLEASE GIVE ME A HIGH FIVE!!!!
I fixed the compiler error Chris.... Can I still have a high five?
Uploading it so I can work it on it later Chris.
I solved one of my issues Chris!! Now to solve another I created
I am a bit stuck on how to do Colors Chris but I will succeed
I am making progress Chris, had a stressful October but now I can start fresh
I MADE A LOT OF PROGRESS CHRIS BUT I AM STILL FREAKING OUT
I made some progress Chris but I am still struggling
Do you actually read these Chris?
I am stuck again Chris....
I AM SO CLOSE CHRIS!!!!
I DID THE HOMEWORK CHRIS I AM SO HAPPY!! CAN I GET A HIGH FIVE TOMORROW?
Im stuck Chris.....
..... I will come into TA office hours tomorrow for help
CHRIS IS DID HALF OF THE METHODS!!! I FEEL CONFIDENT AGAIN!!!!
I did join Chris. Now I am taking a break while I think about the code
I DID TWO MORE METHODS CHRIS!!
I DID IT CHRIS I AM SO HAPPY!!!!!!!!!!!!!!!!!!!
Got a start Chris
I did more of it Chris
I am asking a question on bitbucket Chris
Did more work Chris, still confused
KRISTEN HELPED TEACH ME TWODEE ARRAYS AND NOW I AM DOING METHODS!!!
Doing a work session for this tomorrow with some CS buddies
I DID MORE OF THE THING
GOT BITMAP UTILITIES DONE CHRIS!!!
I am so close to being done Chris
Pushing it so I can ask for help on Piazza
I am almost there Chris
I DID IT CHRIS AND FIXED MY BITBUCKET
I GOT A START CHRIS
Pushing it to bitbucket just incase you want to see it Chris
I DID MORE OF IT CHRIS. Please notice me......
IM DOING THIS FOR YOU BUDDY!!!!!!!
I DID MORE OF IT CHRIS!!! IM GONNA COMPLETE THIS
Got more done Chris
I DID MORE OF IT CHRIS
So close Chris.
Cant figure it out Chris :(
Still stuck on Donde, Chris.
I MADE PROGRESS CHRIS!!!
I feel like I am so close Chris!!!!!
I AM SO CLOSE CHRIS!!!
I DID IT CHRIS!!!!
eminem beat donald trump
My roommates got a hermit crab and I don't know why. His name is noodle.
"It is finished"-Jesus of Nazareth
TAHITI IS A MAGICAL PLACE!!!
A girl told me what files were, a guy told me that loops weren't allowed, and now I have to figure out calendars. :)
One hour left...
It's midnight :(
Please don't be up yet :(
I just need to change the names now. This assignment was so fun!
Nevermind. Now, on to the fun part!!!!
A whole bunch of late work done. +10 points.
All written up. Now, time for ... THE SPECKCHECER OF DOOOOOM!
Slayed CS 148
Hi Chris. I died with this homework. :)
]]>I called the homework Stella because the first images I made looked space-ish. But in one of my debugging sessions, as I randomly dragged the mouse around the screen, I ended up with an image that looked more like a grandmother:
This was pure accident. I didn’t know that I had made anything until I released the mouse.
It’s difficult to tell, but there are three radial axes here. All wedges contain the exact same pixel content, but the two leftmost wedges are mirrors of each other. It’s easier to see when we superimpose the axes:
]]>Room class to support a text adventure game. Each Room has a description, four Room neighbors, and whatever other state the students need to support their interaction.
One of the students designed an adventure that featured me as the “villain.” Here’s what happens if you try to take me on before getting your work done:
Welcome to the Horror House Use the keyboard to indicate your actions N-Travel North | E-Travel East | S-Travel South | W-Travel West end-Channel your cowardice, and end the game +++++++++++++++++++++++++++++++++++++++++ You have arrived in the landing of a dark and weathered house. There is a crumbling flight of stairs ahead of you, a glass door to your right, a rusted iron door to your left, and a heavy double door behind you. >s You turn around and exit the door onto the patio. A thick fog blocks your path out of the house. Press y to attempt to maneuver through the fog. >y You travel not even five feet before you are knocked onto the ground. From the fog, appears a towering figure. Christophoros Johnsonus, Checker of Specifications has blocked your path! If you believe you are well prepared for the fight, press t to defeat the defender of the house. >t The defender is not pleased. His gaze pierces you with the strength of a thousand suns as he shrieks, 'You have not passed all tests. But you will! Keep at it.' You have failed. Game Over
Here’s what happens if you don’t manage your time well:
You have arrived in the landing of a dark and weathered house. There is a crumbling flight of stairs ahead of you, a glass door to your right, a rusted iron door to your left, and a heavy double door behind you. >n You traverse the stairs to the Upstairs Study. There is a comfortable bed in the corner, beckoning to you. Press p to take a rest, or Press o to search the underside of the bed >p You wake up from your rest feeling refreshed. It is still dark outside, and you are unsure of how much time has passed. >s You have arrived in the landing of a dark and weathered house. There is a crumbling flight of stairs ahead of you, a glass door to your right, a rusted iron door to your left, and a heavy double door behind you. >s You turn around and exit the door onto the patio. A thick fog blocks your path out of the house. Press y to attempt to maneuver through the fog. >y You travel not even five feet before you are knocked onto the ground. From the fog, appears a towering figure. Christophoros Johnsonus, Checker of Specifications has blocked your path! If you believe you are well prepared for the fight, press t to defeat the defender of the house. >t You have slept through the time required. There will be no Amnesty Period provided. You have failed. Game Over
And here is what happens when you get all your work done in time:
You have arrived in the landing of a dark and weathered house. There is a crumbling flight of stairs ahead of you, a glass door to your right, a rusted iron door to your left, and a heavy double door behind you. >w You pull the door open just enough to squeeze through. It is darker than the blackest night. There is a chipped lightswitch to your right. Press i to illuminate the area. >i You flip the switch and it reveals the room to be a crypt. You see a shadow dart out of the corner of your eye. It is a man. Press u to confront the man. >u The man speaks in a garbled language. You cannot understand him, but he motions for you to put out your hands. He places into them a scroll. The scroll contains a hodgepodge of characters and braces. Perhaps a 'code' of sorts Scroll added to inventory >e You have arrived in the landing of a dark and weathered house. There is a crumbling flight of stairs ahead of you, a glass door to your right, a rusted iron door to your left, and a heavy double door behind you. >n You traverse the stairs to the Upstairs Study. There is a comfortable bed in the corner, beckoning to you. Press p to take a rest, or Press o to search the underside of the bed >o While searching under the bed, you find an elixir and consume it. Willpower added to inventory >s You have arrived in the landing of a dark and weathered house. There is a crumbling flight of stairs ahead of you, a glass door to your right, a rusted iron door to your left, and a heavy double door behind you. >e The sacrifice is ready to be made. A force beyond your own mind compells you to push the items from your inventory to the bucket. With a great flash, the items are consumed by the bucket, and you are left empty handed. Items 'scroll' and 'willpower' removed from inventory. >w You have arrived in the landing of a dark and weathered house. There is a crumbling flight of stairs ahead of you, a glass door to your right, a rusted iron door to your left, and a heavy double door behind you. >s You turn around and exit the door onto the patio. A thick fog blocks your path out of the house. Press y to attempt to maneuver through the fog. >y You travel not even five feet before you are knocked onto the ground. From the fog, appears a towering figure. Christophoros Johnsonus, Checker of Specifications has blocked your path! If you believe you are well prepared for the fight, press t to defeat the defender of the house. >t The defender bellows with the strength of a thousand winds '4 out of 4 tests pass. High five. You have passed all tests.' You have now left the Horror House. Thank you for playing!
The quotes that Michael includes are taken directly from the SpecCheckers—the unit tests—that I distribute to students. Thanks, Michael, for honoring them and me in this way!
]]>She immediately disappeared with no further words. That’s not much a joke, I thought, but then I uncrumpled the paper:
]]>if (isTall == true) {
...
}
Dr. Wallingford showed me with his red pen that == true is completely unnecessary. This is quite clear when you consider the truth table:
isTall
|
isTall == true
|
| 0 | 0 |
| 1 | 1 |
The second column is no different than the first.
Not only is == true unnecessary, it also makes the code unpronounceable. When we are first learning to program, it’s helpful if we stick close to natural language, especially when you find yourself writing != false.
These days I am the teacher. I never ever write == true in my examples, nor does our textbook. But my students write == true all the time, and I want them to stop. I’ve been reading Young Children Reinvent Arithmetic by Constance Kamii, who studied under Piaget, and this sentence from the first chapter caught my eye:
… to understand human knowledge [Piaget] believed that it was necessary to study its development rather than only the end product.
When I read that sentence, I am challenged. Instead of just wanting to rid my students’ code of == true, I find myself wanting to understand what’s going on in their brains that they (and I) would even write that.
My hypothesis is that we tend to introduce logic with numbers and the relational operators: >, >=, <, <=, ==, and !=. We fixate on the binary structure of these expressions and can’t depart from it when boolean operands are introduced. I can think of a few things we might try in order to investigate this further:
if isOrdered(x, y, z) ... elsif list.isEmpty ...
This eliminates the binary structure altogether. If students do not initially see the binary structure when they’re cutting their logical teeth, would they not write list.isEmpty == true even after the relational operators are introduced?
boolean isBiggerX = x > y if isBiggerX ...
This practice would get students used to seeing single tokens in the condition. It would retain the binary structure in assignment expressions, but I would expect a lot of self-correction there from students when they write == true on the right-hand side. For one, the type of the variable is made explicit. You might realize that you already have a boolean. For two, coming up with a name for the variable takes on the value of isTall == true is awkward. The name isTall comes to mind, but you’ve already got that:
boolean isTall = isTall == true
Perhaps you’d realize that another variable is unnecessary?
For the time being, I do not understand what’s going on my students’ heads. However, the unit tests I distribute to them scan for == true in their code. If they want credit, contains better be false.
Ironically, my own classes are getting large enough that my forum dynamics are not that different from the MOOCs. So, this semester I’m going to create some small discussion communities in one of my classes. These students will discuss articles not with the entire class, but only within their group of five peers.
To facilitate this, I plan on using Slack. I’ll create a channel for each group. Students will get their participation within their channel marked in the gradebook, which leads us to the real content of this post: how can I make marking this participation easier?
Because I suffer from developerism, the answer is to write a script to query all the messages in a certain time period and automatically give the contributors their credit. While the script is busy doing the grunt work, I am freed up to actually read the content of the messages.
Talking to Slack in a script requires OAuth2 authentication. I despise this stuff. So I’m documenting it in this post. Let’s walk through a Ruby script that does the OAuth2 dance and issues a simple request for the channels in a Slack instance.
First we need some constants. The CLIENT_ID and CLIENT_SECRET we get from adding a new app representing our script to our Slack instance. The REDIRECT_URI is a URL for a fake page that Slack will jump to after the script has been authorized.
CLIENT_ID = '...'
CLIENT_SECRET = '...'
PORT = 4000
REDIRECT_URI = "http://localhost:#{PORT}/oauth"
Next we use the oauth2 gem to create an authorization client:
oauthor = OAuth2::Client.new(CLIENT_ID, CLIENT_SECRET, {
site: 'https://slack.com/',
authorize_url: '/oauth/authorize',
token_url: '/api/oauth.access',
redirect_uri: REDIRECT_URI
})
The oauthor object can give us a link that will allow the runner of the script to authorize herself. Unfortunately, this needs to happen in a web browser. So, we just prompt the user to visit the link there:
puts "Visit this URL in your web browser:"
puts oauthor.auth_code.authorize_url(scope: 'channels:read')
If you plan on doing more than list channel information, the scope parameter will need to be altered. See Slack’s documentation.
Once the user hits the Authorize button, the page will redirect to the REDIRECT_URI. One of the GET parameters sent to that page is an authorization code. This page doesn’t have to actually exist, but we do need that code. We could let the browser try and fail to access it, copy the parameter out of the URL, and paste it into a prompt in our script. I found several scripts that do that. I’d rather just start up a server that handles the request and slurps down the code automatically:
authorizeCode = nil
thread = Thread.new do
TCPServer.open(PORT) do |server|
client = server.accept
# Read the browser's GET request. We assume the request is legitimate.
while authorizeCode.nil?
line = client.gets
if line =~ /code=([^&\s]+)/
authorizeCode = $1
end
end
# Send the okay back to the browser.
client.print "HTTP/1.1 200\r\n"
client.print "Content-Type: text/html\r\n"
client.print "\r\n"
client.print "You are authorized. Feel free to close this window. Or leave it open."
client.close
end
end
thread.join
The thread stays alive only long enough to grab the authorization code. We block the script until the server has what we need.
We can now get the access token that will need to accompany every message we send to Slack:
accessToken = oauthor.auth_code.get_token(authorizeCode)
And here we put it to good use by requesting a list of the channels:
response = oauthor.request(:get, '/api/channels.list', {
params: {
token: accessToken.token
}
})
The oauth2 API tells me that I should have been able to write the GET request more simply:
response = accessToken.get('/api/channels.list')
But apparently Slack doesn’t conform to a standard and needs the parameter named differently.
Finally, we can extract the channels, which are nested inside a JSON structure:
body = JSON.parse(response.body)
p body['channels'].map { |channel| channel['name'] }
That’s it! The next step for me is to actually retrieve all the messages and give the authors credit, but that hardly concerns you.
The full script is below. I’ve added automatic caching of the access token so that secondary runs don’t need to re-authorize.
#!/usr/bin/env ruby
require 'oauth2'
require 'socket'
CLIENT_ID = '...'
CLIENT_SECRET = '...'
PORT = 4000
REDIRECT_URI = "http://localhost:#{PORT}/oauth"
oauthor = OAuth2::Client.new(CLIENT_ID, CLIENT_SECRET, {
site: 'https://slack.com/',
authorize_url: '/oauth/authorize',
token_url: '/api/oauth.access',
redirect_uri: REDIRECT_URI
})
if File.exist? '.otoken'
accessToken = File.read '.otoken'
accessToken = OAuth2::AccessToken.new(oauthor, accessToken)
else
puts "Visit this URL in your web browser:"
puts oauthor.auth_code.authorize_url(scope: 'channels:read')
# Start up a server to grab the authorization code that will get sent back.
authorizeCode = nil
thread = Thread.new do
TCPServer.open(PORT) do |server|
client = server.accept
# Read the browser's GET request. We assume the request is legitimate.
while authorizeCode.nil?
line = client.gets
if line =~ /code=([^&\s]+)/
authorizeCode = $1
end
end
# Send the okay back to the browser.
client.print "HTTP/1.1 200\r\n"
client.print "Content-Type: text/html\r\n"
client.print "\r\n"
client.print "You are authorized. Feel free to close this window. Or leave it open."
client.close
end
end
thread.join
# The authorization code is our ticket to an access token that must accompany
# each API call.
accessToken = oauthor.auth_code.get_token(authorizeCode)
# Access tokens don't expire, so let's save this to avoid unnecessary future
# authorizations.
puts "Saving token to .otoken for future use. Don't add this to your VCS."
File.open('.otoken', 'wb') do |f|
f.write accessToken.token
end
end
response = oauthor.request(:get, '/api/channels.list', {
params: {
token: accessToken.token
}
})
answer = JSON.parse(response.body)
p answer['channels'].map { |channel| channel['name'] }
The day started with Writer’s Workshop. The entire class gathered at the central platform in the room, and they browsed the website of a local fun park. Mr. Kurt asked them to closely examine the descriptions of the attractions. Some attractions were obviously written to cautious parents, others to kids. Some included height and weight requirements. The students then found a workstation, designed their own attraction, and wrote about it. I visited with one young man about Orbs-a-Turn, a ride that had more axes of rotation than I thought possible. Another young man had a blank piece of paper. I asked what ideas he had. None, he said. I asked him if he liked water. He said yes. I asked him if he liked lights. He said yes. I asked him if he liked bugs. He said kind of. I suggested he put them all together into some sort of thrill ride. I don’t know what he ended up doing.
Next Mr. Kurt gathered just the 4th graders to the platform. He asked them all to find a picture of their favorite animals on Google Images and share it via AirPlay to the projector. They discussed how the animals organized into communities. He then weaved a fictitious story around the kids that kept me enthralled to its end. They started off as a small group trying to survive. But then one of them discovered a tasty fruit growing far away. Given the distance, one individual is put in charge of harvesting the fruit full-time. But soon the village is overrun by the stone pits that have been spat out everywhere. Another individual is commissioned to build clay spittoons to hold the discarded pits, and another is commissioned to empty the jars regularly in the dump outside the village. But one day, some hunters discover that the fruits are growing in the dump. Soon enough, agriculture has developed. By the end, the students have learned about how a society grows up into a civilization. What I liked about this lesson was that Mr. Kurt made every child a participant in it without being dependent on their participation. He gave each a role and personality that drew them in, even though he did most of the talking.
The 5th graders came to the platform next to learn about six types of interactions between tectonic plates. Mr. Kurt had assigned that they each build or bake a model of the Earth’s layers. But there was some confusion about the due date. Some had brought in baked goods, but not the ones who thought they had until Friday. Mr. Kurt solicited ideas about how they should handle the mixup. Strangely, the students voted to freeze the cakes that had been brought in already and save them until Friday. They even had the option of eating the cakes both today and on Friday. I was sad, because one girl had brought cream cheese and chocolate cupcakes that looked wonderful. But my sadness was short-lived. Mr. Kurt overruled the decision to wait after the girl said that she needed to get her container back home.
The whole class had specials next. I was invited to go with to music, but I didn’t want to drop in unannounced on the music teacher. Instead, I joined a different class. They were headed to gym, the teacher of which knew I was visiting. The warm up activity was to visit all the letters of sportsmanship painted around the perimeter and do ten exercises at each. Mr. Bart then brought the class together, inviting the 5th graders to reflect on the track event from last week. I had to sit between two boys who couldn’t stop talking with and touching each other. All headed outside to play Capture the Football. I joined the yellow team, and I think we probably got trounced. But I didn’t hold back. I ripped flags off of young people with abandon and avoided getting my own flags pulled. My adult legs get all the credit. But I wasn’t adult enough to organize my team. We had no strategy and no defense.
Sweaty and worn out, I headed to the teacher’s lounge for lunch. One of the teachers had brought two drumsticks lathered in barbecue sauce for lunch. But she had no plate. I lent her a lid to one of my Pyrex dishes. I learned that one of the teachers had just run the same half-marathon that I had run. Another, the teacher of my 8-year-old son, had run the full marathon in less than four hours. I had already respected her, but this took her up a couple of notches.
Back in the classroom, Mr. Kurt read to us from Peak, a young adult novel about climbing Mount Everest. The lights stay low for the rest of the day, and the classroom is far more peaceful than I could have imagined. The class then broke up into reading groups, and I was asked to go around the room and visit with students about their work. Isaac showed me a catching game he was working on in Tynker. The player tilted the iPad to slide a player around and catch falling objects. The tilt movement was working fine, but he needed a counter to track the player’s score. It was excruciating to watch him switch back and forth between the Tynker app and the PDF worksheet that structured the activity. Right then and there, I vowed to always integrate walkthrus into the app itself. Besides the clumsy interface, he ran into several issues. First, he confused the idea of script ownership. He had a when touches? alien event defined on the alien actor. He realized on his own that the event needed to be on the player. Next he had a set count to 0 instruction inside the event handler. This was immediately followed by a count = count + 1. Needless to say, the score never grew past 1. I talked to him about one-time execution vs. the many-time execution of his collision event handler. He wasn’t getting it. I tried to make an analogy: “Suppose you were saving up for a Nintendo Switch. What if every time you got your allowance, your parents first emptied out your piggy bank?” He said he didn’t want a Switch and didn’t get an allowance. But he did end moving the set count to 0 block into the on start event.
A girl showed me her program, which she said wasn’t working correctly. Two coral sprites were supposed to disappear when the player died, having collided with a crab. They had these event handlers:
when "im ded" received hide
But the coral weren’t disappearing when im ded was broadcast. I helped her discover that a stop other scripts instruction was probably the culprit. It was killing the coral’s event handlers. The girl immediately suggested adding a 2-second delay before stop other scripts, which would give the coral event handlers enough time to do their thing.
All told, I am amazed at how much coding experience these students are getting. I think the landscape of introductory computer science is going to be very different in 10 years. The students are spending a lot of time on their iPads, and I think pencil and paper skills will suffer.
In the final hour of the day, students decomposed numbers into balancing mobile-like structures. For instance, the number at the root might be 48. 24 of that number would be distributed out to the left and 24 to the right. But the left might have three square children distributing the weight (8 and 8 and 8), while the right had two circles (12 and 12). I think math is being taught in a lot of fun ways these days. I’m jealous.
The day was really quite fun. But there are two negatives. First, Mr. Kurt is not returning next year. He told me that he isn’t able to fully utilize his Montessori training at the upper elementary level. There’s been a lot of focus on engineering and math, and his passions lie elsewhere. Second, and quite devastating to me who’s trying to build tools for teaching computer science, I think that educational technology and curricula play a very minor role in young people’s learning. Nothing beats a quality relationship with a caring adult.
]]>cd /home/USERNAME
Students will report back that the directory /home/USERNAME did not exist, and they were therefore not able to do their homework.
Do not describe an image file format to students like this:
P1 WIDTH HEIGHT ...
Students will output literally the text “WIDTH” and “HEIGHT” and not understand why their images will not open.
Do not depict an example user interaction with a program like this:
What's your guess? 17 Too high. What's your guess? 8 Too low. What's your guess? 13 You got it!
They will hardcode exactly four print statements and eliminate user input entirely.
If not placeholders, then what can you use to describe a pattern? Nothing. You are out of luck. Young people only speak concrete. You can’t preempt this misunderstanding. Let it happen, and then give them a very concrete 0.
Sadly, older people—who have the prefrontal cortex to know better—are not helping when they pull stunts like these:

