Archive for September 9, 2019
Where a Notional Machine Doesn’t Help: JavaScript and the DOM
At the Dagstuhl Seminar on Notional Machines and Programming Language Semantics, I came to a new understanding about where notional machines are not useful and another kind of support is needed.
I joined a breakout group on “Notional Machines for everything else.” There had been discussions about notional machines for popular programming languages for Scratch and Python, and one breakout group was formed around that goal. This group was about exploring where else notional machines could be useful, like trying to understand machine learning, generating proofs, and JavaScript for Web development. Joe Politz was our group leader.
After the first round of discussion, we all decided to focus on JavaScript. We had some serious experts on JavaScript and the DOM in our group, like Shriram Krishnamurthi and Titus Barik. The discussion was amazing! I was learning so much, and I took pages and pages of notes. Everyone noticed my feverish note-taking, so I got elected to report back to the group. That’s this blog post — it’s the work of the whole group (not just me). I just happened to be the guy who made the slides.
We had already come to the realization that there isn’t just one notional machine per language. A notional machine is about helping students understand a computational process, and there can be lots of processes in a given language. So we picked a specific scenario that we were aiming to explain: You (as a student) want to turn the background yellow when the button is clicked.
But the student makes a mistake.
And I came to realize that, without a lot of support:
The problem is that window.bg = "yellow"
isn’t wrong. Because there isn’t a previously defined bg
property, this assignment simply creates a property bg
for the window
object. No error. It just doesn’t do what the students wanted. How does the student figure out that the desired property is backgroundColor
? Get a list of all bindings on window
? There are hundreds or even thousands of them. How do you find backgroundColor
among all of those?
The breakout group started listing on the blackboard the things we might need to explain to students to help them understand when went wrong or what might go wrong with clicking on a button to turn the background yellow. It was a long list.
You probably can’t read all of those, so I’ll list a few of them here:
- What happens if you have two DOM elements with the same ID?
- Where did
window
as an object get defined at all? - If you have event handlers defined on an object, and you delete the object, what happens to the event handler?
- What happens if objects higher up in the DOM modify the event triggered by the event click?
- Something I heard students ask: If my JavaScript changed the DOM, how come my HTML file didn’t change?
- And Many More
I really had no idea just how complicated JavaScript and the DOM were! Amy Ko looked up the JavaScript definition of what ==
means (see link here). This isn’t the formal semantics. This is meant to be understandable. It’s insanely complicated.
At this point, Ben Shapiro raised a really interesting side question: What’s the cost of JavaScript’s overly-complicated rules? Is there a way of measuring the lost productivity of bad programming language design?
So, what’s the answer?
I realized that the answer is not a notional machine. The problem is that long list Amy found for us. I can teach part of that list as a notional machine, but I can’t teach all of it with a simplified model. Any simplification I create would be insufficient for the complexity of the reality. And even having a notional machine wouldn’t help if a student typed window.bg = "yellow"
. The student needs IDE’s and other supports to figure out errors that never trigger an error.
The solution is to reduce complexity to make it teachable. In an earlier talk at Dagstuhl, Ben Shapiro explained how Shriram and Joe and their collaborators did this with Pyret. In Pyret, they explicitly disallow some things that Python allows but are way too complicated to explain.
Probably the best idea for JavaScript, following Racket’s lead, is to have language levels. We should teach students a strict subset of JavaScript, where the really complicated things are simply disallowed. The goal is to help students to learn a real subset, then grow the subset. TypeScript offers an alternative model, because it offers a more sane way of doing JavaScript. For example, TypeScript’s type checking might help figure out the window.bg
bug. There are lots of other languages that are more reasonable and compile to JavaScript — but those are avoiding JavaScript entirely.
The very best idea would be to fix JavaScript and the DOM, but it’s probably too late for that.
This working group was useful to me for two reasons. First, I really do have to teach JavaScript and the DOM (again) in January 2020, and now I have a new sense of the challenges and my options. Second, this was a great example of where a notional machine is not the answer to a pedagogical problem.
Thanks to members of the group who reviewed an earlier draft of this summary. They’re not responsible for where I still didn’t get the details right.
Recent Comments