This article discusses strategies for teaching 100% novice programmers--the very first program and next steps after it. Target audience is grade and high school.
For new programmers, particularly kids, Python is the default choice for good reason: it's perfect for simple interactive apps:
answer = input("What's your name? ")
print(answer, "is a beautiful name!")Then move on to ifs:
answer = input("Which Pokemon is awakened by the flute? ").strip().lower()
if answer == "snorlax":
print("correct, Snowlax is awakened by the flute!")
else:
print("incorrect.", answer, "is not awakened by the flute")Python's easy-to-use random module lets novices extend this further.
But after the Q&A stage, Python becomes suboptimal for students who want to build GUI apps. Turtle graphics are a good next step for simple drawings, but is restrictive and confusing once students move on to games. Pygame is the next step after turtle, but (mostly) locks students into a local dev environment, when most everything else they do on the computer is on the web.
HTML/JS/CSS is the logical solution to getting students quickly coding without having to install anything, and working in a friendly, GUI-first browser environment. But interactive Q&A apps are tough to do out of the box:
- Node
readlineis horrible for beginners - Browser
prompt/alert/document.writeis a poor user experience and very restrictive - Browser HTML forms, inputs, onclick/onsubmit are more complex than
input()/print()and not readily accessible for novices.
A number of possible approaches follow. I don't necessarily recommend them, I wanted to present a fairly exhaustive list so the tradeoffs and problem space are apparent. Some seemingly undesirable approaches may make sense in certain situations.
One solution is to skip JS initially and start with Python. Then transition into HTML/JS instead of Python turtle, or once the student starts hitting Python turtle limitations.
The downside is friction when switching languages/environments and spending more time ramping up all over again instead of making forward progress in one language. But if students only take Python a few weeks in, then switch to JS and DOM manipulation or making web applications, students will likely not become too attached to Python and can transition with minimal thrashing and frustration.
readline-sync from npm provides a friendly synchronous UX, with some cool options.
Downsides:
- involves an npm install and import, harder to use on web IDEs than Python out of the box
- still slightly worse syntax than
input()/print() - Node probably doesn't have great next steps for students (turtle, pygame) anyway, so you're installing Node only to switch to the browser.
In this approach, we provide a lightweight library that provides input() and print(), as well as optionally other tools useful for beginners. These lightweight abstractions let students beign with HTML/JS with a decent approximation to Python's command-line interactivity, but without installation, npm or heavy UI libraries.
<form onsubmit="answer()">
Enter your name: <input>
<input type="submit">
</form>
<script>
function answer() {
console.log(this);
}
</script>This is still sub-optimal syntactically relative to Python, there are potential issues forgetting await, and it's a non-standard dependency, albeit a lightweight one. Might cause students to think these functions are standard and get confused if they're not present should they try to code a different application on their own (you'd need to explain what a "library" is).
This approach is useful for quizzes or choose your own adventure games. Or simply make a standard static webpage.
Downside: requires multiple files, no JS need be involved, so it somewhat kicks the can. This approach does provide a nice way to intro HTML without JS, to avoid overhwelming students with both HTML and JS at once.
<details>
<summary>What did the buddhist say to the hot dog vendor?</summary>
Make me one with everything
</details>
<details>
<summary>What is the capital of France?</summary>Paris
</details>This makes a quiz app in a single page, but the interactivity isn't satisfying (user just thinks of their answer) and there's no score. Too boring and static, but perhaps nested dropdowns could be interesting.
Alpine Q&A code
<script src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<div x-data="{
step: 1,
name: '',
color: '',
food: ''
}">
<div x-show="step === 1">
<p>What is your name?</p>
<input x-model="name" @keydown.enter="step = 2">
<button @click="step = 2">Next</button>
</div>
<div x-show="step === 2">
<p>Favorite color?</p>
<input x-model="color" @keydown.enter="step = 3">
<button @click="step = 3">Next</button>
</div>
<div x-show="step === 3">
<p>Favorite food?</p>
<input x-model="food" @keydown.enter="step = 4">
<button @click="step = 4">Finish</button>
</div>
<div x-show="step === 4">
<p x-text="`${name} likes ${color} and ${food}`"></p>
</div>
</div>Although this is fairly elegant, the syntax is still iffy, the library is too nonstandard and not worth building further on, and there's a learning curve for the instructor. Vue, petite-vue and AngularJS have reasonably equivalent translations but all of the same problems.
- TODO--stub
- TODO--stub.
- game: press the key to match the letter on screen.
- shake screen when typing keys (matter.js--whole ui jumps when you type)
TODO--stub. The idea here is to focus heavily on <img> tags and mouse interactions.
HTML/JS with non-typing-related handlers is viable.
button clicker
<style>
button {
transition: all 1s ease-in-out;
position: absolute;
}
</style>
score: <span id="out">0</span>
<button tabindex="-1">click me</button>
<script>
button = document.querySelector("button");
score = 0;
button.onclick = () => {
score++;
out.setHTML(score);
};
setInterval(() => {
button.style.top = Math.random() * innerHeight;
button.style.left = Math.random() * innerWidth;
}, 500);
</script>Downsides: tricky concepts like callbacks, harder for students to understand than simple if/input/print.
For students inclined to games and graphics, you can skip Q&A entirely and go right into graphics from the very start, either with plain canvas or P5.js:
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.3/p5.js"></script>
<script>
function setup() {
createCanvas(400, 400);
}
function draw() {
circle(mouseX, mouseY, 80);
}
</script>Lua and love2d are great, but no real advantages over Python/Pygame.