December 6, 2010

Enthused About: Programming as Problem Solving

As an undergrad researcher, I did some development with the ACT-R cognitive architecture. I soon began to daydream about the combination of cognitive psychology and software engineering, and three years later, my entire MS degree had focused on that particular area. Here are a few things I think every software engineer should know about cognitive psychology.

  1. Programming is a problem-solving task. Cognitive psychologists have been studying problem-solving tasks for several decades now. In fact, it's safe to say they have a pretty good idea about the general limitations of human performance in problem-solving tasks. If you want to be a better programmer, go look at some of these ideas about how programming is done in your mind. Search terms: General Problem Solver 1972, Atkinson and Shiffrin short term memory, Baddeley and Logie working memory
  2. Working memory has a capacity. You can only think about so many things (psychologists call then chunks) at once. Empirical studies indicate that the capacity is "5 + or - 2," and that working memory capacity is an individual difference that carries across tasks. As a programmer, this means that your performance is limited by how many chunks you're having to concurrently recall and work with at the moment. There are many strategies we employ to limit the number of items in our working memory:
    • Get another brain's worth of capacity (i.e. use pair programming ... not Frankenstein)
    • Have an API window open on one monitor, limiting what you have to recall about function/class specifics
    • Use auto-complete functionality to make API information available "in-line"
  3. Chunks are hierarchical. The information we are trying to recall exists in a hierarchy. This is how we get better at programming. When learning to program, you're thinking about how to write the for loop, step by step. A year later, you're thinking about iteration structures as a class of operators (e.g. for, while, do/while, etc.). This represents a difference in chunking, and it's one way of developing expertise and becoming a better programmer. A simple example: phone numbers. Instead of recalling 10 separate digits, we usually group together the area code, exchange, and last four for easier recall. If you want to be a better programmer, pay attention to how you're chunking information. If one way is causing you to make a lot of mistakes, try another.
  4. Memory also works for tasks. This is no surprise to most people, that if you want to learn how to do something, practice makes perfect. I put it here though to connect it to everything else that's already been said. Hierarchy and capacity also happen with tasks. If you want to be a more efficient programmer, practice can indeed make perfect as you learn to recognize and repeat increasingly complex tasks.
  5. Working memory also has severe time limitations. The generally accepted time span of working memory is 1-2 seconds. That seems unbelievably short, and many times this leads to the constant murmuring that can be heard from programmers' cubicles throughout the day (psychologists call this verbal rehearsal). Other than talking to yourself or writing things down, there's not much that can be done about this, but it does help explain that feeling of flow/in-the-zone. Most programmers will tell you that their most effective work is done in a small part of their day (or week!) when something clicks.
  6. Metaphor is an effective problem-solving strategy. Thanks to object-oriented programming, most programmers are used to having some kind of metaphors (we tend to call them paradigms) involved in our programming. Personally, when I first studied design patterns and software architectures, I was downright disappointed at the lack of orthogonality. It seemed like you could express any system within any architecture, for example. But the point of these paradigms isn't to describe a system that was previously indescribable (not exactly that many paradigms within assembly language!), but to describe the system in a way that makes programming it more familiar to developers. The fewer paradigm-busting caveats you have, the smoother the programming will likely go. More experienced programmers have likely seen more paradigms and can apply them more easily, and learning and applying them sounds like a decent idea.
So there's a crash course on some cognitive insights into programming. There are many more things I learned, but really, this blog post was already getting to be too long.  Have you seen examples of these ideas in your own work?

No comments:

Post a Comment