Code Doesn't Happen to You
While teaching new programmers, I have observed two attitudes:
- A machine deterministically executes source code according to language semantics and existing library code. Programs achieve the goal of the programmer when they produce correct outputs on all valid inputs.
- When executed, source code causes a machine to produce a myriad of unpredictable results. With enough empirical data we can attempt to understand the behavior of the code based on how a machine “decides what to do”.
Attitude 2 is what I refer to as “the code happening to me”, as it minimizes the agency that a programmer has as they attempt to create software. This post is in no way meant to be a judgment on anyone with Attitude 2 or a proclamation that students who quickly adopt the Attitude 1 are somehow superior. Our goal is to understand the cause of "the code is happening to me" attitude and to give our students tools to overcome it.
Selected Bad Metaphors for Programming
“Learning to program is like learning a foreign language”
- The learner forms an idea in their primary language
- The learner translates those words into the foreign language
- The learner produces speech based on the translated words for a listener
- The listener perceives the speech and determines the meaning of the learner’s words
- (and vice versa)
- The primary difficulty is in performing the translation of one natural language to another natural language
- The goal is to communicate ideas to a conscious agent who will succeed in interpreting an utterance with many errors
- The primary role of creativity is in the idea that the learner chooses to communicate
“Learning to program is like putting together a puzzle”
- A set of pieces is given to the learner
- Through trial and error, the learner physically manipulates pieces and composes them into larger shapes
- When all shapes are correctly composed, the puzzle is finished
- The learner exercises no creativity
- The problem can be decomposed and partial solutions compose to create a complete solution
- There is a single, correct way to assemble the pieces
- There is a significant degree of trial and error required
Why Does the Code Happen to Me
Given these bad metaphors (and they likely hear many more), what should a new programmer believe? Elements of each of the preceding metaphors are instructive, but they paint a very poor picture of the full process that the student will be engaging in. Misapplication of these metaphors is a primary cause of the “code happens to me” phenomenon.
Foreign language learning
Programming does require knowledge and application of technical vocabulary and application of structural rules that loosely resemble the grammars of natural languages. However, the receiver of the translated ideas is not a conscious agent, and most errors result in an unrecoverable failure of a program.
Python, gcc, the JVM, or the Scratch cat do not have the ability to think or feel. They do not “decide” to be pleased by your choice of parameters to a method call or choice of brackets. As Dijkstra put it, “The question ‘Can machines think?’ is regularly raised; we can —and should— deal with that by pointing out that it is just as relevant as the equally burning question 'Can submarines swim?'”.
Programming does require the decomposition of a problem and the subsequent composition of smaller solutions into a complete one. However, there are many correct ways to assemble a program. While puzzle solving and programming both require trial and error in assembling a solution, only the programmer can exercise significant creativity.
The puzzle solving metaphor is possibly more pernicious than that of foreign language learning. While solving a puzzle, two pieces belong together in the solution if and only if they fit together. (The Puzzle Theorem) “Getting the puzzles to fit together" is best mapped to the programming task of writing syntactically correct code. While block based programming successfully leverages the puzzle metaphor for helping reduce syntax errors, a learner can become quickly confused when faced with the falsehood of The Puzzle Theorem while trying to code. “Making the pieces fit” is only one piece of the puzzle (pun intended), and more crucially, there is no one correct way to implement a program in code. If one expects programming to be a journey towards a single correct answer by rearranging puzzle pieces, they are in for quite a long ride. (Google “combinatorial explosion”)
To give students the ability to succeed, we must provide them the proper context for the role of programming in the creation of software.
A Better Model for Programming
- The programmer is given (or identifies) a goal and is given (or identifies) a specification for a program that will achieve that goal
- The programmer translates that specification into source code
- The machine executes the source code (“runs the program”) with a set of inputs
- The creator of the specification interprets the output of the program as either meeting or failing to meet the original goal
- The creator of the specification (possibly the programmer themselves) exercises a large degree creativity
- The program specification may be incomplete and require selected elements of creativity by the programmer
- There is a significant challenge in translating natural language specification into a formal programming language (“coding”)
- The programmer can exercise a large degree of creativity in the use of the formal programming language during implementation
- The program may behave correctly given certain inputs, but fail given other inputs
The primary cause of the “code is happening to me” phenomenon is confusion as to where the programmer can exercise creativity and how a program is deemed to be correct. Many beginning programmers produce code and ask “is this right?” without once testing it. If one is translating Chinese to German or building a puzzle, this question is at least sensible, but in the context of programming this question demonstrates a categorical misunderstanding.
In programming, the source code is the primary independent variable under the programmer’s control. Without a means of assessing whether a change to that variable has a positive or negative effect, programming will feel at best mysterious, and at worst a useless exercise in the arbitrary arrangement of abstract symbols. Once the relationship between code and program behavior is identified and understood, the learning process is far from over, but without that understanding I don’t think it can even begin.
- Place a strong emphasis on testing code and determining whether the resulting program’s behavior matches its specification.
- Demonstrate clear examples of syntactically correct code that nevertheless has errors in its behavior
- Make assignments in which a program has a clear specification and in which the goal of the program can be clearly identified.
- Be clear about when lessons are meant to introduce syntax or language constructs, and communicate directly what are tangible benefits of using such syntax or construct
- After students have mastery over some aspects of a programming language, prompt them to create specifications for their own programs to implement using their new knowledge