Experts Can Program Blindfolded

Bret Victor has written an essay entitled Learnable Programming that is already circulating quite rapidly. It’s worth reading, as much for the presentation as the content (I say that to compliment the presentation, not to disparage the content). The essay draws together various ideas about visualisation and programs, with very polished examples of executing the ideas, and it does make a very strong coherent argument for its ideals: mainly, that we should get a lot better at visualising programs to help beginners. My post title comes from his final line:

Maybe we don’t need a silver bullet. We just need to take off our blindfolds to see where we’re firing.

In this post I provide a commentary to the essay, along this theme: I believe that visualisation is often good for beginners but not for experts, and therefore transitioning from being a beginner into being an expert involves moving beyond visualisations.

Label Everything

One of the suggestions in the essay is to label lines of code to say what they do:

One of the first things beginners do in any area is learn the terms, after which I believe the labelling of program constructs becomes annoying rather than helpful. We wouldn’t have a mouse-over helper in Maths saying ” ‘+’ is the symbol meaning add two numbers” or in French saying “Je means I” — you learn it early on, quite easily, and then you’re fine. The point of the notation is to express concisely and unambigiously what the program does. I can understand that the labels are a bit more approachable, but I worry that for most cases, they are not actually helpful, and very quickly end up unwieldy. I’m reminded of this quote from an anonymous Q&A page at Kent:

Q. Can you explain the mathematical formulae for the bisection method in english please?

A. Take the values of the two end-points of the interval, add them together and divide by 2 and call this value c, evaluate the function at the point c. If this value is the same sign as the value obtained by evaluating the function at the left hand end-point overwrite the left hand endpoint with c otherwise overwrite the right hand end-point with c. Carry on doing this until you have an accurate enough result.

The above is the reason people invented mathematics.

In summary: being that being able to read code straight off the page is a skill that is part of programming, and I believe is it one that you need to learn so early on that this labelling will not be useful.

(The suggestion of labelling parameters does make a lot of sense in languages without named parameters — although you could avoid the need for this by just designing your beginners’ language to use named parameters.)

See Everything

The essay repeatedly makes consistent, strong statements about visibility:

If a programmer cannot see what a program is doing, she can’t understand it.

If you are serious about creating a programming environment for learning, the number one thing you can do… is to show the data.

All state must be eliminated or shown… An environment that does neither… is irresponsible design, and disrespectful to the learner.

I propose that visualisation doesn’t scale to large programs. It’s quite easy to visualise an array of 10 elements, or show the complete object graph in a program with 5 objects. But how do you visualise an array of 100,000 elements, or the complete object graph in a program with 50,000 objects? You can think about collapsible/folding displays or clever visual compression, but at some point it’s simply not feasible to visualise your entire program: program code can scale up 1000-fold with the tweak of a loop counter, but visualisations are inherently limited in scale. At some point they are all going to become too much:

Beginner systems like Scratch or Greenfoot are deliberately designed to visualise lots of state implicitly. The location of sprites/actors and their rotation are implicitly visible, and usually the early examples deal with manipulating this visible state. But at some point you will probably need to introduce state to the actors — perhaps an internal counter of how many worms a crab is eaten. So maybe this could be visualised — perhaps you could have it floating above the actor. But add a thousand crabs to the world and the visualisation is ruined. Add more than about three variables and it’s not going to work well. (Greenfoot allows digging down through objects to visualise them, but after a point in scaling your program, it becomes unusable through sheer mass of data.)

So if visualisation doesn’t scale to expert-level programs, then at some point on the transition from beginner to expert, you will have to leave behind visualisation. I don’t think this should be taken as a bad thing — in fact, I think going beyond visualisation is a necessary and positive learning step in programming. Stopping needing to visualise the program and instead just understanding the implications of the code is, I believe, a sign of deep understanding.

Algorithm visualisation has been explored many times, but has never shown particularly convincing results. Someone once proposed to me that being able to create a visualisation of an algorithm is a sign of understanding, but that understanding cannot be gained from seeing the visualisation. Visualisation as a manifestation of understanding, rather than understanding as a consequence of visualisation. I wonder if there’s something in that?

Modularise!

Of course, computing is sometimes referred to as a fight against complexity. The programmers’ defense against complexity is modularisation. If your class or your function or your program gets too big to understand, break it down into smaller connected components. Make each module small enough to understand — and thus small enough to visualise. But fairly inherent to modularisation is the idea of encapsulating, or hiding, detail — and state! This goes against Victor’s suggestion that all state must be eliminated or shown.

Things like a file-access API (often used as one of the first examples in programming) hide away state such as whether a file is open or closed, the location of the file pointer, and so on. I believe that again, dealing with this hidden state is part of learning to program. I agree that it’s a good idea to avoid hidden state at the very beginning, but you eventually will run into hidden state, and again — it’s part of programming to be able to deal with hidden state. Good API design involves minimising the use of magic modes (such as the Processing color mode that Victor mentions) and making this state sensible so that it does not become a problem when using the API. Well-hidden state does not need to be seen.

Understanding Does Not Require Seeing

Victor is fairly clear in the concluding remarks that he considers seeing to be almost synonymous with understanding:

A better attitude is to assert that we have to be able to understand the state of our programs. We can then ask: How do we design data structures that can be visualized? Can we invent data structures that are intended to be visualized? How do we move towards a culture where only visually-understandable data is considered sound?

I disagree with this idea. Let me borrow an example from Maths. A two-dimensional vector can be visualised as a point on a two-dimensional plane (e.g. the screen). A three-dimensional vector can be visualised as a point in 3D space. A four-dimensional vector, or a ten-dimensional vector, cannot easily be visualised. If we limited ourselves to only dealing with what we could visualise, we could never move beyond three-dimensional vectors. And yet maths frequently deals with vectors of arbitrary length, because understanding vectors is decoupled from visualising them (see also: dealing with infinity). I believe that taking an attitude that visualisation is the be-all and end-all would be unnecessarily limiting for experts. We can, and should, go beyond what we can visualise.

Don The Blindfold

I like the blindfold metaphor, because it fits with our understanding of expertise: “he can do that with his eyes closed” is already a common idiom for expertise in a task. Beginner typists look at the keys. Expert typists can type blindfolded. Therefore at some point in the transition from beginner to expert typist you must stop looking at the keys. So it is with programming: you must reach a stage where you can accept the blindfold. The role of early teaching environments should be to supply approachable visualisations and beginner’s aids, but the aim should always be to take the beginner beyond them.

Advertisements

7 Comments

Filed under Uncategorized

7 responses to “Experts Can Program Blindfolded

  1. yaxu

    Great thoughts, thanks! I’d just highlight one assumption – that beginner programmers necessarily need or desire to transition to professional programmers.

    Remember that programming skills are useful for everyone whether or not they become professional programmers. Consider the spreadsheet for example, arguably the most used programming environment, mostly used by non-professional programmers who often are professionals in their own domain of work. This is end-user programming, where programs often do not grow to a significant size, do not need modularisation and so on.

    I think your points are valid, but some of them need tempering with this in mind.

  2. yaxu

    By the way I think a useful comparison is novel writing. An expert author is likely to turn off any grammar checking or suggestions in their text editor. Someone typing up a technical report is more likely to keep it switched on.

    There are plenty of software tools to help with narrative development but there is no one-fits-all approach, and many of the most successful authors will do best with pencils and post-it notes.

  3. You’re right that many will not become professional programmers, or rather many will never transition to experts. I think one slight problem with the original essay is that it’s not clear when he’s talking about beginners (in which case some of the points are fine) and when he’s talking about all programmers (in which case some of the points are not fine).

    I think one of the reasons that spreadsheets have been so successful is that they do follow his principle that the data should be visualised — a spreadsheet is a giant functional program that visualises the value of every single assignment in the program. And I think the reason that so many people continue to use spreadsheets past the point when a database would be the “right” solution is because of this visualisation. The other advantage to spreadsheets is that they have no concept of state, mutation or assignment — maybe this functional aspect is actually part of the reason for the success? Several of Victor’s visualisation are about tracking mutation over time, but maybe the way to make programming more accessible is to dispense with the notion of time? Interesting ideas.

  4. Expert and programmers write lots of buggy and insecure code, then spend far too much time patching our work to keep it together. We’re quite notorious for it, so much so that it has been accepted as the way things are (that’s what happens for any any systemic evil: war, slavery, spam). Rather than bolstering hubris with bold claims of what we can achieve with unnecessary handicaps, we should be a more humble about what we – as experts – are actually achieving.

    We should recognize that majority of time most experts spend on code is not writing it, but rather maintaining it and repairing it. And, even if we have big fragile egos that can’t accept our own mistakes, we should at least realize that we spend much time fixing buggy code written by other programmers.

    Scaling to lots of state doesn’t mean hiding it, but does require new ways to visualize it – ability to highlight outliers, record traces. Also, modularization means hiding details and state from other code, not from programmers. (Modularity is not about protecting intellectual property.)

    Use of `new` to encapsulate and modularize state has been a terrible mistake. A filesystem metaphor (where state in code is associated with a path) would be easier to debug, audit, extend, compose, persist, reset, clone, version, and secure. A filesystem metaphor is also better for declarative observation and influence, and for live coding. Secure encapsulation in the filesystem metaphor comes from eliminating the `..` path – i.e. every path is chroot’d, and thus subprograms can be securely partitioned.

    Someone who is focused visualization or learnable programming more learnable will recognize easily that `new Object()` is a problem, even if they’re sure how to replace it. But you with your blindfold? Well, you probably won’t see it even when I point it out to you.

    Take off the effing blindfold.

    • This is not an issue of “real programmers don’t need no extra tools”. Tools for experts are a good thing, and better debuggers is one thing that we could do with. But part of the problem is that it seems to be difficult to create a debugger that visualises just the bit that you are interested in. There will always be (in any reasonable program) more state than you can visualise at one time, and choosing the right filters or metaphors to narrow down that display is a hard problem.

      The idea behind modularisation is to hide the code that you are not currently working on and that you do not need to know about. If I’m using someone’s File object (or whatever), I should never have to look inside it because it should be working correctly, fulfilling an easy to understand API. If I ever had to look inside the File object, then there is a problem. So the state of the File object should be hidden because (a) I shouldn’t need to look at it, and (b) it’s fine if the internal state is completely altered, as long as the interface is still fulfilled. Hiding is a good step, and yes — part of that is hiding detail from programmers, because otherwise they rely on private implementation details that are not part of the public interface, and that is a bad thing.

      The latter idea about treating state as a filesystem-style thing is interesting — I would be happy to see it explored in some research.

  5. Dear Neil, thanks for another interesting post. My take on what you are arguing is about abstraction: one thing which expert programmers use to manage (“not think”, “not see”) with a complex system is the use of ‘abstraction barriers’. This is classic material in “Structure and Interpretation of Computer Programs” [http://mitpress.mit.edu/sicp]. I also like the writing of Uri Leron (computer science and maths educator – also perhaps not surprisingly an associate of the Papert/MIT/Logo group) about this. For example:
    “Programming in an appropriate level of abstraction means choosing “primitives” that are appropriate for the problem (and to the programmer) at hand. Since there is no reason to expect that the suitable primitives will just happen to be there as the primitives of the language we are using, this mostly means creating our own primitives—in essence creating a special purpose language for the problem at hand … In refusing to deal with lower-level detail while thinking of the (high-level) problem to be solved, we have constructed a metaphoric “abstraction barrier” that separates the programming task into two nearly independent tasks: Above the barrier we deal with solving the original problem in terms of the “abstract primitives” we have selected; below, we deal with the details of implementing these abstract primitives.” [Leron, U. (1987). “Abstraction barriers in mathematics and computer science”. In J. Hillel (Ed.), Proceedings of the Third International Logo and Mathematics Education Conference (Montreal), pages 12-26] (sorry for hard-to-find reference – I need to find my original and get a scan of it). Also see: Leron, U. and Hazzan, O. (1998). “Computers and applied constructivism”. In D. Tinsley & D. Johnson (Eds.) Information and Communication Technologies in School
    Mathematics. London: Chapman & Hall. Pages 195-203. (More of my own musings about this can be found here: http://www.phillipkent.net/sites/default/files/Kent-TrajectoriesForLearning-1999.pdf )

  6. ptodd

    Since you apparently like the blindfold metaphor, I feel compelled to point out that while an expert typist may happily be able to type blindfolded, it still tends to be useful for them to have use of their eyes; consider transcribing a text for example. Their ability to type without seeing doesn’t mean that blindfolds will not impair them in their work as a typist, as it’s probably rare that the only thing they have to do at a given moment is type.

    I’d argue that blindfolds do have a useful function for typists, programmers, musicians, artists and perhaps countless other disciplines. That function is mostly as part of the learning process, for exercise and to test one’s abilities. Perhaps some experts may find full use of their senses an unnecessary burden, but it seems likely that in general most would prefer not to be blindfolded on a day-to-day basis.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s