I was just teaching a workshop at CIID in Copenhagen where we introduced designers of various sorts, industrial, graphic, service, to Processing, generative design, and to the idea of Natural User Interfaces, i.e. the Kinect. I was happy with the results, what the students learned and what they produced (here for instance), but I walked away wondering the same thing I always wonder when I teach non-CS students programming: what’s the difference between thinking about code as a tool for doing things and thinking about code as a tool for thinking? What does that mean for making things and for talking about and teaching people code? Since I write about code, teach workshops, do documentation, these questions are, as they say, relevant to my interests.
Lots of times we, and by “we” I mean “programmers” think of code as a tool for doing stuff, we don’t care about the implementation underneath, we blindly reach into boost::asio, we fire up Rails without actually looking at what ActiveRecord actually does, we just do things. Make a website, a routine phone app, a CRUD application, these are things that I and I suspect many others, often do on auto-pilot. When I use code to think, I find myself usually looking at weird compiler behavior, hidden or little-known features of languages (example). I think about code, about computation, about what it means to think in code when I think in code. Sometimes I think about algorithms, but rarely. Sometimes I think about the behavior of an algorithm or the pattern in a signal or dataset, but then I’m not thinking in code, I’m looking through code, but I’m not really thinking with it, I want it out of the way so I can see what I’m looking at. So there’s really a few different levels of involvement here:
- Running Code
- Using Code
- Thinking Code
And those are interesting things to try to explain to students. I didn’t do a good job of it this time, and I regret that, and I’m going to rectify that mistake next time because, particularly in design and for designers, it’s important to tell people what the tool they’re picking up actually is. When you pick up a library in Processing that has clearly defined behavior, you’re usually doing something like #1: just running code. Maybe you change some colors, some parameters, tweak what things do, off you to see how your thing works. To someone raised on reading Hackers Delight, that’s complete heresy. To someone raised to think of tools as being nothing more than elements of a task, then that’s of course what you do. If you buy a hammer that doesn’t hammer your nails, then you go back to the hardware store and get another one, no? And that sort of makes sense, except that it also cripples you. You end up with the rote permutations on the low-lying fruit of algorithms. You treat programming like you treat Excel. Instead of invention, discovery, and experimentation, you get expressions, behaviors, and pre-defined routines that you can mix and match, but never alter. So, is that wrong? I’m not sure. I teach people to think of code as tools because it gets them started thinking that code is interesting. They can do things with it. They are, without a doubt, horrible programmers, and they will continue to be horrible programmers hamstrung by their tools, for perhaps years, or in all likelihood, forever. They implement things they barely understand, leverage things they don’t appreciate, and run into mistakes that they can’t comprehend. And, I think, that’s probably ok. It’s not a failure of mental capability on their part or failure to communicate on the part of their professors: it’s simply not necessary for being a designer working with interaction.
Thinking about things is using a medium to formulate an expression. Grammar, syntax, norms. These tools for creating novel expressions of the medium itself. Algorithms, data types and containers, device drivers, protocols, fundamental objects of a mode of interaction, I could go on, but these are a few things that strike me as being to code what poetry is to written language. A tool for thinking has codified norms and rules but generally a limited interface because the more complex the interface, the more limited the possibilities for expression. We limit the interfacing mechanics because to do so frees the mind. A tool for making something on the other hand has an intentionally limited interface, because we’re primarily concerned with having blocks of functionality be legible to us. It’s that last word that sums up what I think designers and non-traditional technical people need to have and what I was trying to teach at CIID: code literacy. Code fluency is a vital and profound tool for interaction design, but it’s a necessary one. Code literacy increasingly is a necessary tool, though how exactly that sits at the intersection of “thinking” and just “doing”, how to best fit tools to both of those scenarios, is something that I’ve yet to parse out completely. I’m far from the only one thinking of this. In fact, a great number of people who do interaction design, whether they know it or not, are working on this problem. That’s what makes it a good problem: it’s big, there’s a lot of ways to be wrong and right, and a lot of fruit that can be born from it, both in terms of thinking about how we learn things and thinking about how we think. Which is a long way of saying: I had fun in my workshop, and I’m looking forward to doing it again next year.