Java was my first programming language, and grappling with different semantics for what I thought were similar things, like the difference between reference and primitive types, was a serious hurdle for me. Looking back, and approaching computer science education as something to facilitate the process of building a mental model of computation, I think starting with something low-level like assembly would have been more rewarding and would have given me the building blocks to understand Java. There are lots of people who think that your first lesson in computer science should be in abstraction, but you cannot abstract what you do not understand.

To draw an analogy, look at the language used for mathematical proofs. Before you learn how to write proofs, you’re exposed to how mathematical computation works with the calculus sequence. Then you’re introduced to logic, and then the axioms for, say, calculus, and you build up the definitions from there. Math is a large language built from small pieces, but nobody expects you to understand the large pieces first.

Something like nand2tetris teaches CS the same way math is taught now: you start at the lowest relevant abstractions, logic and circuits, and then build layers of abstraction on top of that foundation.

I also don’t see the point of teaching object-oriented design to students just learning how to program. Though to be fair, I didn’t see the point of OO when I was taught it, and I still don’t see how traditional OO solves any more problems than it creates.

The above analogy with math is a layperson’s view, let me know if you notice anything off about it :)