In Making Badass Developers (recommended!), Kathy Sierra highlights the limited capacity of our working memory, and shares some learning strategies to deal with it. In this post, I want to ponder the last of her three strategies: what she calls "bypassing B". In her talk, she separates your skills into one of three boards: A, B, and C - imagine kanban boards if you are familiar with the agile methodologies. On board A are skills you have yet to learn, on B are skills you are in the process of learning, and on C are skills you have mastered. Thus, bypassing B means:
... going straight from "I have no idea what I'm doing." to "I am an absolute expert."
I know what you are thinking: is this sort kind of voodoo magic? This technique is called perceptual learning. It is a technique that's been used successfully to teach people chick sexing (determining the sex of baby chicks by looking at their butt), plane spotting (at war times, determining whether or not an incoming plane is an enemy plane), and interpreting the state of a plane based on its instruments readings. All of these tasks are non-trivial and cannot be solved simply by following a set of rules. The teaching technique works by exposing the learners to many many examples in a short period of time. For each example examined
- The student sees the example.
- The student guesses an answer for that example.
- The teacher gives the actual correct answer.
- Repeat.
That's it! This is also essentially how you train neural networks or any kind of machine-learning-based system. Given that this is an artificial intelligence technique, isn't it apt that it also works on us humans? In one study, it was found that a group of flight trainees were able to learned how to read their instruments with greater accuracy than even seasoned pilots in merely two hours (note, that still doesn't mean the trainees can fly a plane).
Why My Red Flags Went Off
When I viewed the video, a couple of things set of red flags in my head.
- With an approach like this, you will end up with people who "don't know how they know". To be a good programmer, it's very important to understand things from first principles and being able to derive the world from the ground up on-demand. Understanding things at a basic level allows you to adapt to different situations and changing environments - both of which are a fact of life in the software industry.
- As Kathy admits, this will not work for everything, but only some subset of the skills that we need to learn. In a way, it's too good to be true.
Despite this, after reading about more examples for which this concept is applicable, I am convinced that this is more widely applicable than I first thought. One of those examples is reading: when we read a passage in a book, we recognize whole words at a time, rather a letter at a time. How did we learn to do this? Lots, lots, lots of practice of seeing and identifying.
How Can We Use This?
So how can we apply this concept to learning to code? Here are some ideas.
When To Refactor?
Kathy mentioned as an idea: the detection of "code smell". A problem with this idea is that simply knowing that something "smells" doesn't tell you how to fix it. Perhaps what could be done is to narrow down the specificity and do this for each type of refactoring - i.e. in what situations one should use a particular refactoring vs not. Since many of the refactorings in Fowler's book have a corresponding inverse refactoring - an example being extract method vs inline method. One could create a "training set" - a set of code examples tagged with the correct answer specifying whether in this case it is better to extract a method or to inline it. There are already some heuristics we use in the industry, such as the rule of three, but this technique could potentially teach these skills more granularly.
However, one objection does come to mind. In my understanding of refactoring based on the way that I approach it, the best solutions to refactoring are not found instinctively, but rather by first gaining an understanding of the problem, then mentally reflecting on the problem (brainstorming), and then coming up with an alternate solution. Then, even after the alternate solution comes to mind, to really know if it will work out or not, one sometimes has to first actually implement it, or at least prototype it, and then juxtaposition it with the original code. Often times when I do this, if I am unhappy with the outcome, I would undo the refactoring attempt. In order to judge how good a particular code solution is, you have to balance various different trade-offs you made, and you have to look at the solution as a whole. So, while this method could teach some rule-of-thumbs for refactoring, I don't think it is able to teach all of its different nuances.
Classifying Error Messages
Another idea that could work is to teach students to recognize and classify error messages. Errors are often confusing and intimidating to junior developers. A lot of developers - even some experienced ones - when they see an error, their first instinct is not to read it. I think there is a lot of value to having a training program that effectively teaches someone to tell - based on reading the error message - what subsystem might be causing the problem, and therefore, what they should investigate as the next step.
For example, if you are working on a Rails app, and you get an error in your web browser, can you tell whether this is
- a web browser error (it couldn't even connect to your app)
- a routing error (404)
- a syntax / runtime error in your JavaScript
- an error in your HTML
- an error in your CSS
- a syntax error in your web template
- a syntax / runtime error in your controller
- a syntax / runtime error in your model
- a runtime error from active record
- an error coming from one of the gems (libraries) you are using
- a database error (PostgreSQL, MongoDB, etc)
For seasoned developers, each of these types of errors have certain special characteristics which they've internalized so well that they know them subconciously - it is instinctual. I think this skill is something that could be taught using an intensive perceptual learning training program such as described by Kathy. The training program would need to be specific to the specific programming environment that the students are targeting to learn, because the error messages coming from Rails would look very different from the ones coming from Django. Given this, fragmentation of the open source ecosystem makes it more difficult to share training material. Companies that use non-mainstream programming environments may have to put together their own training materials.
However, with that said, I think it wouldn't be very hard to put together a training set for any individual who is interested in training their junior developers. All that is required is for some developer(s) to be mindful of taking a screenshot each time they get an error screen during their own development time. Over time, you would have a good collection of screenshots of error messages. Tag each screenshot with the correct subsystem, and you have what you need to train your apprentices!
Syntax Correctness
Seasoned developers swim in code. They know code so well that they can tell instinctively if a piece of code is syntactically wrong. This ability allows them to self-correct their mistakes before they even attempt to run it, thus speeding up their development process. This instinct is something we also can train by using lots of examples and lots of practice. I can imagine a syntax training program where the student is asked to look at code snippet after code snippet in succession, and are asked to spot any syntax errors in the code, or to verify that the code is indeed syntactically correct. To build something like this, we need a large set of code snippets containing examples of both valid syntax and invalid syntax. I think that for this to work best, the code snippets would need to be small - anywhere between 5 to 15 lines - so that you can scan it quickly. Ideally, the set would contain examples of all the various types of language constructs and various common ways of making syntax errors. Also ideally, we would have a profile of the most common types of syntax errors that developers make. For example, one common mistake is to forget to close your paranthesises, especially in cases where multiple closing parans are required:
if (user.isLoggedIn() {
...
}
Some JS beginners would simply forget that parans are required at all in the conditional clause of an if statement:
if user.isLoggedIn {
...
}
It could be that they are coming from a language like Ruby or Python where this is indeed the case.
Another kind of common mistake is typos: the mispelling of a variable name or a language keyword.
funtion greet(person) {
console.log(`Hello, ${persn}!`);
}
Yet another kind of mistake is not realizing you are using a language keyword for a variable name - to avoid this mistake basically requires you to know instinctively what words are "specially" and cannot be used.
var function = 'greet';
bob[function]();
I made a tool called tupo which randomly introduces errors to valid programs, which although doesn't get us all the way there, could be helpful if someone were to build a training set for this purpose. If this approach is successful, it can also be extended to include coding style, picking good names for things, and dangerous or undesirable code patterns which linters would otherwise catch.
Touch-Typing
Touch-typing: the ability to type without having to look at the keyboard is an underrated skill. Even if you already know touch typing, there are benefits to practicing it and continuing to improve. The ability to produce words or code at or near the speed of thought is extremely powerful, and will - in video game terms - unlock you a new level in both your productivity and your creativity. The process of learning to touch-type can be modelled as a perceptual learning task: you are shown a letter you have to type, and you have to move the correct finger to the correct position in order to push the correct key. With enough practice of enough examples, you will get really good at this, and the beauty is: that's all you need to do. You don't need to read any books or try to build things that work - things that require thinking at a deeper level. Just practice, and you will get better. That's the whole point of this teaching technique, isn't it?
Here are some touch typing resources:
- typing.io - this a typing practice program specifically for programmers. Typing in programming requires an emphasis on punctuation and special symbols, which most typing-teacher software de-emphasize.
- GNU Typist - GNU typist is a terminal-based unix program for learning to type. It supports QUERTY, DVORAK, and COLEMAK. If you are on mac, you can install it with
brew install gtypist
. On Windows, you can probably run it in cygwin, although I haven't personally tried it. - typing.lk - this looks like a good, relatively distraction-free web-based typing tutor.
Closing Thoughts
Perceptual learning is a technique that seems to be largely untapped in the field of teaching/learning to code. I think it's time that we tap into it. Although it isn't a silver bullet, perceptual learning can give learners a big speed boost in mastering certain specific skills. If we can apply this technique to some subset of the essential skills that developers need in their day to day work, this would have the effect of reducing the cognitive load of the learners so that they can use that extra cognitive power to learn the rest of what they have to learn.
Any Ideas?
I think that any skill that exclusively uses our fast thinking, instinctual, reflexive, reactive brain as opposed to our slow thinking, logical, analytical, number crunching brain is a candidate for this technique. Do you have any ideas what other skills could be taught using this technique? Please let me know in the comments or tweet me @airportyh.