Learnable Programming (2012)
worrydream.com
worrydream.com
Coming from a technical programming background Middle Out is the methodology I often use BTW
Which level are you teaching at? I would expect University students to be capable of "taking a problem and dividing it into small tasks "
I think the author presented a very insightful take on teaching some of the important aspects of programming.
And I think there are good programmers who are lacking in those domains, notably math beyond the intro level, where problem solving involves recognizing the "form" of a problem, and remembering the algorithm for solving it. The guides I've read on making programs more understandable recommend eliminating abstraction, for instance by making sure that the names of things are concrete and self explanatory.
So I actually think it's still a puzzle why programming is hard, or easy. The paradox is that programming is super easy, but only for a randomly selected group of people, otherwise it's prohibitive.
Then again, if you can think of a subject, like programming, where we've tried a new way to teach it in every generation, with no sign of widespread success, it's math.
This is not an article about how to teach or learn programming, this is about creating an environment inside of which learning is made easier.
Try giving a freshman a binary search program with an interactive visualization like the ones shown in this article that they can play with, and see if they still struggle with it. Same goes for the permutations. You don't have to teach anything when you can let someone experiment and teach themselves how something works. At the end of the day, true learning always hinges on personal insight, and the best teaching methods are those that make it easiest for a person to extract insight.
Looks kinda the opposite to me. It's criticizing a particular learning environment because it doesn't actually help with learning programming.
Right in the middle of the opening section:
> Thus, the goals of a programming system should be:
> * to support and encourage powerful ways of thinking
> * to enable programmers to see and understand the execution of their programs
> A live-coding Processing environment addresses neither of these goals.
We have to stop looking at computers as machines with mice and keyboards and small screens that we conquer with code and start thinking of them as abstract entities that execute things, and then think of how best to manipulate those entities to do what we want.
"The computer is an instrument whose music is ideas" (Alan Kay) - Can you imagine what music would look like today if all we could do was write it down and hit play? Where's the emotion and playfulness in that?
I'd like to see Bret's brilliance tackle visualising those types of examples.
Maybe most of it simply can't be visualised, but I feel like there's a lot of unrealised potential in that space.
I feel like having programmed consistently since I was 9 (24years now, wow) this is my biggest strength. When it comes to code and architecture I sortof just see it in my mind. It’s very plastic. Like a malleable thing that my brain does without really knowing how or why. It’s just there.
Can’t even put it into words. Can’t draw it either. Like when you ask math people how they do some of the really complex stuff
1) I also started programming very young, maybe eight or nine years old.
2) My first language was Python and I still program in Python today, the programming language with the motto "there's only one way to do it". At some point I had to write Perl for a summer job and it's TMTOWTDI attitude and many symbols nearly broke my brain, I hated it for most of the summer.
3) I used vim and then emacs for a very long time, and recently started using Visual Studio Code and Pycharm. This made me realize that one of my favorite features of any editor was actually the minimap VSC provides on the side by the scrollbar (which Pycharm does not by default provide). Not having it, having it, and then not having it again made me realize I utilized it a surprising amount even though it's a seemingly trivial feature compared to, say, code completion or syntax highlighting. It was just very fast for me to jump around a large file by clicking on the minimap; I knew where to click to jump to the function or class I wanted.
4) I am a vicious style guide zealot. I got poo-poo'ed once by a coworker for submitting a large commit where the only changes were renaming things to snake_case. But the code just looked wrong to me, I had to do it. I write C/C++ in K&R style and find it difficult to read code not indented as such.
I was sitting on my lunch break and all these things kind of crashed together into a great epiphany - maybe the reason I program in this specific way is because the code has to look a certain way in my head. Like I'm literally imagining a sort of minimap in my brain and if the syntax, conventions, order, spacing, etc. are wrong it screws up my very visual model because it literally looks wrong. The more rigidly the code follows the rules, the more visually consistent it is and the easier it is to structure.
Your comment makes me wonder if there really is some semi-visual, semi-textual model that certain programmers form of their code, which is ever-present but really hard to express in other ways. I also wonder if this is a common thing, and if it helps or hurts when programming.
I've been through the "code case and bracket style must match" period, but eventually my brain abstracted over it, and it's now a free variable - I can work with any style, but it must be consistently used, or else it'll trigger that visual feeling of literal ugliness.
I also had a visual enlightenment with Lisp code, where one moment, I thought it was clumsy, and then something clicked, and ever since I consider a (properly formatted) Lisp code beautiful.
I've done literally all my best work for the past 25 years in Emacs. Recently I decided to switch to Visual Studio Code because "that's where the momentum is now". Well, it lasted a few weeks and then it was back to Emacs. I wondered why this was.
I realized that despite using Borland and Microsoft IDEs in the 90s, I never acclimated to the way IDEs in general handle small tasks like bracket matching and indentation. Emacs does these things right in a way that virtually every other IDE-like editor does wrong. I can work with vim, but working with VSCode has a sort of tactile (instead of visual) "ugliness" about it that increases friction and makes me actually less productive.
That and the wrong way VSCode handles File / Open by default made me frustrated enough to go back to Emacs.
?
> the wrong way VSCode handles File / Open by default
?
Wrong: Hit return and the next line is automatically indented; other than that you're on your own.
Right: Flash the opening bracket or quote when you type the closing bracket or quote.
Wrong: "Helpfully" close opening brackets or quotes, but do not provide Paredit-like structured editing features, leaving the user to accidentally type spurious extra brackets/quotes. (Some IDEs skip over the preinserted closing mark when you type the same mark with point on the closing mark. But they're woefully inconsistent about this and Visual Studio Code does not do this.)
Right: Visiting a file does not otherwise affect editor state.
Wrong: All state for the editing session in the current window is clobbered when you do File / Open from the menu. User must spawn a new window in order to preserve editing state in this window.
Speaking only for myself, I’m a wee bit “on the spectrum,” and basically work in some kind of “symbolic IDL,” inside my head.
As long as I never need to verbalize my design, I can keep a pretty massive architecture completely unwritten, in my mind. This makes it possible to work extremely quickly, with big “on the fly” changes to my implementations; performed “inline,” as I work.
The moment that I need to verbalize or “overall” document things, though, the whole gravy train comes to a screeching halt, as my brain needs to do some kind of “context switch.”
BTW: my code is pretty “anal.” Highly formatted and documented. I actually feel physically uncomfortable, if it isn’t formatted the way I like.
His talk "Media for thinking the unthinkable" goes into detail on this, especially from minute 10 to minute 17: https://youtu.be/oUaOucZRlmE?t=600
The essay Magic Ink: INFORMATION SOFTWARE AND THE GRAPHICAL INTERFACE also goes into detail about this topic http://worrydream.com/MagicInk/
Re mentally visualising, I'm reading a book called Mathematician's Delight[1] at the minute, and its first chapter has one of the neatest pieces of writing on abstract reasoning that I think I've ever read, it's reified a lot of instinctual ideas I had about how I program. I've clipped quite a lot of notes from it -- this in particular is relevant I think:
"Beginners in geometry are sometimes puzzled by being told that straight lines have no thickness. We shall never, we are told, meet a straight line in real life, because every real object has a certain thickness. One of Euclid's lines, however, has no thickness. Two lines meet in a point, and a point has no size at all, only position. We shall never meet a point in real life, either, for all real objects have a certain size, as well as a certain position It is not surprising that pupils wonder how we know anything about objects which no one has ever seen or ever can see.
This difficulty is a good example of the confusion which can come from misunderstanding the methods of abstract thought. We have seen that Euclid's geometry grew out of the methods used for building, surveying and other work in ancient Egypt, This work was done with actual ropes or strings, real linen threads with actual thickness. What does Euclid mean when he says that a line has no thickness, although he is using results suggested by the use of thick ropes? He means that in laying out a football field or in building a house you are not interested in the size or the shape of the knots made where one rope is joined to another. If you allowed for the fact that ropes possess a definite thickness, if you carefully described all the knots used by a bricklayer, you would make the subject extremely complicated, and no advantage would be gained. Euclid therefore says, if an actual rope has thickness, neglect this in order to keep the subject reasonably simple.
The position is not that Euclid's straight lines represent a perfect ideal which ropes and strings strive in vain to copy. It is the other way round. Euclid's straight lines simplified account of the complicated way in which actual ropes present a rough, behave."
[1] https://archive.org/details/mathematicians-delight-w.-w.-saw...
Another set of analogies I use is that the data, to me, is like clay or a block of wood, and I'm either forming or carving it depending on the context. For example, if I am doing some calculation where I take several bits of data and combine them to get a result then I'll imagine "forming" the data like clay in my mind as I apply mathematical operations to it like `*` or `sin`. If I'm doing stream operations in some "rules engine" where I need to sort through the data, rather than a straightforward equation like the former example, then I imagine "carving" the data like wood with `filter` or `reduce`.
I also get a "feeling" when I look at code or architecture as to better ways to do it, I don't have evidence at the time to support my feeling, but later on they are often correct.
Also, I don't break things down into tasks as such, but I do start a project/task by commenting with TODO at high level and then drill down, much like a functional programmer would do so. For example, if I'm writing a tool to count the number of lines in a file, I would start with something like:
# TODO: initialize the program
# TODO: load the file
# TODO: count the lines
# TODO: output the count
# TODO: finalize the program
Then, as I go along, I add the more-specific steps to replace the "load the file" (or I just remove the TODO prefix and it acts as a organizational sectioning comment), and eventually I'll start taking those comments and turning them into code/functions when they're sufficiently atomic. I kind of imagine this as a combination of clay and wood, I'm building up the comments like clay, but also sort of "carving" the raw comments into code (the block of wood is an empty file, and I'm carving it bit by bit into the form it will eventually become: a file that compiles into a program that does what it should).[1] https://www.khanacademy.org/computer-programming/drawing-bon...
Once a person learns how to think about programming problems, they become better at creating their own mental models and visualizations. And maybe someday they'll figure out how to create visualizations of these complex things you and I can't yet :)
I think about this all the time. In my area I see a lot of programmers who don't do a great job at writing optimal code but it's not because they are lazy or stupid but because they cannot understand something they cannot see. This is why some kind of appropriate visual idiom for efficient core usage and time spent is a necessity in any project that cares about efficiency. I still don't think we have found the best visual idiom but we have to keep trying to make obvious visually, the way a computer really works.
This article was written eight years ago, and every year since, it has been dutifully posted to Hacker News, where we all stare in wonder at the concept... and yet nothing like this exists yet?
"Why has no one else done a ton of work (that I'm also not planning to do)?" is never a great question, so I don't want to be too flippant... but seriously, it would be an excellent project, either for someone stuck at home in lock down, or possibly even as the basis for some sort of coding education startup.
I'd rather see focus in making our current batch of tools way better rather than looking for direct manipulation methods, A.I. assisted no-code environments, novel user interfaces, retro-futuristic hypercard-excel mashups, etc etc</grinch> :-p
To be fair "seeing" doesn't necessarily mean drawing vector graphics, any advance helping reveal hidden structure of a codebase or generate better documentation would also allow us to better "see" the working of the code... I'm all for that!
I hope things like model driven development get a second renaissance at some point, without the burden of UML, the sad XML reputation, "extreme programming" BS and such.
One project I like that's futuristic, and yet has reasonable goals, is Unison [1].
This is basically what a good debugging environment is. Some of the best tooling out there is the dev-tools of modern browsers: you get a regular debugger where you can step through code and see the state, you also get some performance and memory visualization tools, you get an interactive html editor in which changes are reflected in real time, you get color pickers when modifying css colors, you can visualize the timing of requests, and you get autocomplete propositions all over the place.
Debuggers are about the dynamics of the program... I'm thinking more about the static structure of the codebase. Tools like sourcegraph [1] address some of that. The STEPS report [2] comes to mind for other cool ideas in this direction: it is easier to navigate the code if there's less of it!
1. See how state changes
2. See what hidden state there is
3. See how state changes if I interact with it. E.g. in C by changing register values or variables. In Python by changing variables.
Shameless plug: I'm also trying to implement these ideas at Low-Level Academy [2], teaching systems programming concepts in a visual way.
[1] http://worrydream.com/refs/Papert%20-%20Mindstorms%201st%20e...
Suppose I want to minimize the time taken from someone having not done any programming, to implementing a B+ tree. Is this really what you would recommend?
Also, sometimes code takes a long enough time to run that one can't instantly show the results upon changing some code. That's not something you can dismiss with "that's just asking the wrong question". There are actually things that need computing, and some of them can't be done quickly.
I wonder if a good measure of a programming curriculum might be, how quickly can a student become able to make something self-hosting (though, the curriculum should have various natural stopping points before this point, depending on what skills they personally need).
That’s true, but it’s not a good argument for not giving instant feedback when it is possible.
> Likewise, guessing the third argument of the "ellipse" function isn't "learning programming". It's simply a barrier to learning.
It's even worse than that. The "ellipse" function should only take 2 arguments - a point and a size (or 2 points if that's your thing).
I see so much of this sort of terrible API design, especially in graphics where good API design makes things so much clearer and easier to use. Writing out a point and a size as 4 variables is madness.
How do you handle ellipses with different eccentricities?
There are several equivalent representations of ellipses, one of which is the two foci and the sum of the distances from the edge to the two foci... so two points and a distance (or you could use two points and the major axis, etc., etc.) A pair of points don't uniquely define one ellipse. Likewise, a center and a "size" doesn't uniquely define an ellipse.
What if the two points were the corners of an enclosing rectangle? This is how, for example, Gimp does the ellipse selector tool.