Feedback matters

Here is the next in our series of tips about learning to learn (to program).

TIP 8 :  Immediate, Frequent Feedback Matters

Paul Curzon, Queen Mary University of London

The real key to deliberate practice, to putting in hours of practice that is as effective as possible, is to have immediate and frequent feedback. You need to find ways to be sure what you are doing is right (or wrong). You need to practice the right things and fix the causes when you get things wrong. Otherwise, with all that practice you could just  be getting better and better at doing it badly.

Building appropriate mental models of sub-skills is an important part of this as it can give a basis of being able to providing feedback yourself. The understanding you have can help you work out what you must have done wrong. When a musician plays the wrong note, if they can hear it sounds wrong, they have some feedback. They can work on that note until they consistently get it right.

Programming provides natural forms of feedback. If you write nonsense that isn’t a program at all, perhaps because a single bracket is missing, or because something was mis-spelled, then when you compile the program, the compiler will tell you about your mistakes. The feedback is immediate.  Compile your program frequently and you will get frequent feedback.

Similarly with a good test plan, and knowing what you are trying to implement you can get immediate feedback as to whether a program does the thing you intended or not in all situations.

This will only be helpful if you were not trying to do too much at once. If you spend days (or even hours) trying to write complex programs, before compiling and running then the feedback is not immediate. You only get feedback when you finally finish the whole thing. Therefore it is really, really important you practice by writing small programs, not large ones bigger than anything you’ve tried before.

When you do write larger programs, it is important that you build them a step at a time, adding to them a little at a time, then recompiling and testing them. This requires you to have understanding of the structure of programs as you need with each change to still have what you think is a valid program. This is a skill to gradually develop too.

So again we see that it is important to not try and make too large steps at once, to learn to program effectively.

It is because there are these natural feedback mechanisms in programming that many people teach themselves to program. As long as they are not put off by making mistakes and see them as learning opportunities they can use feedback from compiling and running programs to get better and better.

If you are a:

  • student
    • Practice writing small programs that introduce single new things at a time.
    • Write programs a little at a time, recompiling, running and testing frequently.
    • Don’t be frustrated by compiler messages, see them as feedback to help you improve.
    • Test programs thoroughly, not just once and then assume it works
  • teacher:
    • Set programming exercises that are small
    • For large programs encourage iterative development.
    • Provide exercises with test plans, teaching debugging skills.
    • Provide other mechanisms for immediate feedback if you can, eg marking programs on the spot as a student completes them, not having them handed in with feedback days or weeks later.

More on Learning to Learn (to program)


IoC logo on white

 

 

 

Draw Concept Maps

Here is the next in our series of tips about learning to learn (to program).

TIP 7 :  Reinforce understanding with concept maps

Paul Curzon, Queen Mary University of London

Once you have worked out the basics of a mental model (such as what a programming construct does), you need to reinforce and refine that understanding. You need to do that actively. Weak learners often try and memorise explanations by repetition but that doesn’t help understanding. Reading an explanation and then drawing a concept map, by contrast, is a powerful way to reinforce your understanding.

A concept map is just a simple kind of diagram. It has:

  • circles which represent concepts (think nouns) and
  • arrows between circles that show their relationship (think verbs)

You start by making a list of all the concepts (the nouns) that are relevant. For example, having encountered a print statement you might (based on your initial limited understanding) include in your list:

  • A print statement
  • A print command
  • A String

and draw them as circles. Then you work out how they are related with those links giving you the arrows. So you might draw a concept map of a print statement as:

PrintStatement1

This focusses on the structure – the bits that make up a print statement – rather than what it does. There are lots of ways to draw a concept map around any given concept or area – its not about right and wrong so much as getting down your current personal understanding. However, in programming you will get most benefit if the concept map focusses on what a programming construct does when it is executed.

Including what the print statement does may lead your next version of the concept map to be a little more sophisticated, so something like:

PrintStatement2

As you understand more then future versions will be more sophisticated still – for example you might in a later version include how the print statement actually takes a string expression not just a string and it is evaluated first to give a string value.

Reading (or listening to) the explanations of experts is important when creating concept maps as that is how you pick up the terminology of an expert – and so the concepts that matter like “statements” and “expressions”. To become an expert you need to talk the language of experts, not just have the skill of an expert. Concept maps can help bring together the terminology and your developing mental models.

Having created a concept map you can now turn it in to your own explanation, in your own words. From the above we get an explanation in our own words such as:

A print statement consists of a print command and a string. The execution of the print statement makes the string appear on the screen.

The benefit of drawing concept maps is it helps reinforce your understanding of the relationships of concepts to each other and to the concepts you have come across previously….and that is the core of what understanding is about.

If you are a:

  • student
    • Draw a concept map for each new programming concept you learn
    • Keep redrawing it again later as you understand more: you will probably be able to draw a more complex concept map.
    • Write explanations based on your concept map
  • teacher:
    • Show students how to draw concept maps
    • Provide some simple examples to show the idea, but remember the biggest benefits come when students create their own concept maps.
    • Set exercises to create concept maps for each new concept, once students have done some experimentation.
    • Set exercises to write prose explanations from concept maps.

More on Learning to Learn (to program)


IoC logo on white

 

 

 

Learning to Learn (to program): Experiment to learn

Here is the next in our series of tips about learning to learn (to program).

TIP 6 :  Build mental models by experimenting

Paul Curzon, Queen Mary University of London

Before you can practice effectively you need to have built the right mental models. Knowledge and skill join. One way to do this is to read explanations written by others. Sometimes there is a much better way: work it out for yourself! Learn by experimenting! For programming, this is a really powerful way to learn. Instead of building a mental model of constructs from explanations, first try and build your own mental models by reading programs others have written (simple ones to start with), and trying to work out how they work. Learn by making changes based on that and predicting what will happen, then trying by running the program.

This works well with programs because you can execute them and see what they do. Take a program, execute it, then look back at the program and see if you can see how it does what you can see it doing. Make a small change with a clear idea in your head now of what you think it wilo now do, then execute it again. If you were right then you have some confirmation of the mental model you have started to form. Try a different change, and so on.

To take a simple example, here is a Python program.

print "Hello World"

If you execute it, the following appears on your screen:

Hello World

Looking back at the program form an idea of what is happening… Try it before reading on.

 

The program prints messages, and there is only one line so that line must be a command to do so. Based on that, make a change to the program with a prediction that the new program will make Hello Paul (or perhaps your name) appear:

print "Hello Paul"

You execute it. It does. Now try a different change to the program:

print "Hello World"
print "Hello World"

What do you think it will do now? And so on…

You are working like a scientist, gradually building a theory based on experiment. As a good scientist you should look for changes that don’t just confirm your idea, but that will show you are wrong if you are, you want to stretch the edges of your understanding.

Once you have run out of experiments or are really stuck, then read (or listen to) the explanations. Now you have a solid basis to understand what they say. You know what they are talking about as you’ve seen it. You are also in a position to understand subtleties you have missed. If the explanations do tell you something you hadn’t worked out, go back and experiment with those aspects.

It is important that you don’t try and do too much in one go. Programs you start experimenting on should only be a little more complicated than you already understand. Changes you make should only be small and one at a time. If things go wrong, revert to a version that did work and you did understand.

Do this learning by experimentation with each new programming construct as you start to learn about it (having mastered the earlier ones first). Only read the explanations after you have experimented a little. You will understand and remember the explanations so much better that way round.

If you are a:

  • student
    • Don’t just rely on explanations, experiment with existing programs.
    • Don’t spend your time copying programs, spend it making small changes to existing programs and predicting what will happen.
  • teacher:
    • Encourage students to experiment and give them time to do so.
    • Provide a series of starting programs for them to experiment with.
    • Give them that code – don’t waste their time making them type it in.

Further Reading

A programming pedagogic framework that follows a similar investigative approach to this is PRIMM.

https://blogs.kcl.ac.uk/cser/2017/09/01/primm-a-structured-approach-to-teaching-programming/

A difference is we advocate above a first stage of Run code first to start a PRIMM like cycle with new constructs. The most important point though in both is that reading and predicting code in an experimental cycle matters.


More on Learning to Learn (to program)


IoC logo on white

 

 

 

Learning to Learn (to program): Mental Models Matter

Here is the next in our series of tips about learning to learn (to program).

TIP 5 :  Focus on mental models.

Paul Curzon, Queen Mary University of London

To get the best out of practice, when learning a skill, you need to have the right mental models. That is where knowledge and skill can work together in tandem. The right sort of knowledge can be used both to base skills on, and to hone them. Practicing the right skills can develop the right kind of knowledge. What you need are good mental models, good understanding, of what you are trying to do.

You must focus on developing the right knowledge, the right mental models, if you are to get the most out of practice.

As a novice programmer, the first and most important mental models are those of the different programming constructs.  How does a variable work? What does a while loop do?

People often think syntax (spelling, punctuation) is what you have to learn first to program and they focus on that and worry most about missing semicolons or whether things should be in capitals or not. Actually far more important to get right first is semantics (what the constructs do) and structure (how programs are organised). Worrying about trying to remember the words and symbols turns programming in to a rote learning task with no real understanding – and nothing to base the right sort of practice on. That’s the wrong thing to do.

It is vital to avoid this trap. Instead practice should be based on understanding the concepts. This has to be the big, early focus to learn the deep skills of programmers. If you do not understand what a programming construct does, you won’t be able to write programs using it…and it is really, really easy to misunderstand if all you have is a basic technical explanation.

Luckily, there are a series of ways to build the right mental models. The first step is to have good explanations, and then make sure you can explain those things in your own words. Explaining is a skill too. As a learner you can practice explaining yourself either in writing or to others. If in a group everyone can then benefit. We will talk about more good explanations in a later blog. You can also draw concept maps that show the way concepts link. More on that later too. For now though actively read explanations. Make notes of some kind as you go, then take a blank sheet and without the original try and write your own explanation.

Another important way to build accurate mental models is to practice reading programs and fragments of programs based on what understanding you do have, and try and predict what they do (then see if you are right). Treat programs as a mini-scientific experiment. Closely related to this is to trace (or dry run) programs. Here you act like a computer stepping through the program. More on this later too.

Notice these are skills too – the sub-skills we identified earlier – so you can practice them.

When you are stuck and do not understand a construct, when you cant write a program, can’t do the dry run and can’t predict what a program will do, it is easy to be dispirited. It doesn’t mean you can’t program though … it means you have just learnt something important – you have learn’t something you do not understand (yet). You’ve found something to work on. It just means you need to get a little bit of help. That might be from a teacher, from a good book or video, or another student (needing to practice their ability to explain), or possibly even the right, simpler exercise to try. You can understand and when you do you will have made another big step forward.

With the right mental models in place then you are in a much stronger position to practice all the programming sub-skills (including writing programs). You are also much more able to learn from your future mistakes.

It is absolutely vital you do focus on getting a clear understanding of the semantics. Then all your other practice will be so much more effective.

If you are a:

  • student
    • Focus on making sure you understand what each new construct does, then do lots of practice of all the sub-skills around until until you have mastered it.
  • teacher:
    • Make sure you make it clear to your students that understanding meaning matters, not memorising syntax.

More on Learning to Learn (to program)


IoC logo on white

 

 

 

Identify the sub-skills

Paul Curzon, Queen Mary University of London

Here is the next in our series of tips about learning to learn (to program).

TIP 4: Know the sub-skills and practice them.

Paul Curzon, Queen Mary University of London

To learn a complex skill you need to practice, and so master, the right things a little at a time. That means you need to break it into sub-skills that you can work on separately. This is the idea behind deliberate practice too. What sub-skills have experts mastered? Practice those.

What are the sub-skills to practice to learn to program effectively? It is not just to write programs. For a novice there are a whole series of sub-skills that matter and that you can practice separately:

  • Being able to explain the basic programming concepts (like variables, loops, etc).
    • This matters as it is closely linked to the idea of mental representations of deliberate practice. This is building the basic mental representations.
    • Being able to compare and contrast related concepts is a useful extension to this.
  • Being able to read / trace simple programs and program fragments using each concept.
    • Reading a program doesn’t just mean read the words but being able to work out what the program does.
    • This helps ensure you have the right mental representations the skills are based on
  • Being able to think logically and focus on detail
    • This is actually a foundation to all the others
  • Being able to debug a program. There are two completely different skills here:
    • Being able to interpret compiler messages and correct compile time errors
    • Being able to find and correct run-time errors.
  • Being able to choose the right programming concept to do a task.
  • Being able to modify a program to do something slightly different, including
    • using the same constructs in a slightly different way, and
    • incorporating a new programming construct into an existing program so that it has a little more functionality
  • Being able to take simple problems and write simple programs that solve them using the appropriate concepts.

Bearing in mind the need to do things a little at a time, and the need to practice a lot, you should practice all these sub-skills on fairly small bits of code to start.

This does NOT mean that you shouldn’t be writing programs at all. It is in writing programs that you get the motivation to do the practice. Its also where you practice putting it all together. A tennis player still plays matches, but in between they practice serves, and hitting the ball to precise places, as well as general fitness, and so on. Similarly a programmer needs to both practice and write interesting programs.

It’s a bad idea to start on a large, complex programming project though, that may then be way beyond your current skill level. Instead master the skills for individual constructs and then build a small program gradually in to a larger project as you master each level of skill.

Once you have mastered the basic concepts and skills, then there is another level of skills to master. These are essentially what people talk about as computational thinking. There are lots of sub-skills involved (which is why academics argue a lot about what it actually is) but here is one list used:

  • algorithmic thinking
  • decomposition
  • generalisation including pattern matching
  • abstraction
  • evaluation

Much of this is applying advanced versions of the earlier set of skills, and you certainly do need to practice more complex versions of the original set including:

  • Reading real programs
  • Writing more complex programs

If you are a:

  • student
    • As a novice, practice all the above novice skills separately, focussing on one construct at a time.
    • Exercises to read/trace programs are especially important to practice.
  • teacher:
    • Set exercises that practice each of the skills separately, for each programming construct.
    • Exercises to read/trace programs are especially important to provide.

Mastering (programming) skills

Paul Curzon, Queen Mary University of London

Here is the next in our series of tips about learning to learn (to program).

TIP 3: Master skills a small step at a time

Working hard, putting in the time and effort is important … but it is NOT enough. You could jog every day for years and NOT get any faster or be able to run ever further. Similarly, you could spend hours trying to write programs but not get any better.  It isn’t just putting in the hours. You have to put in the right kind of hours.

You need to do the right kind of practice. The ideas behind deliberate practice suggest you should aim to master skills a small step at a time – but make sure you do master them before moving on.

(Sometimes you also need help to correct misunderstandings or just help you understand something critical. We will look in more detail at that in a later tip.)

Hours of jogging won’t improve your speed because you are not stretching yourself.  Switch to interval training where you run as fast as you can for a short distance and then recover for a short time, then do that again and again and again. Each session you are pushing yourself to your current limit… and you will improve. You are pushing your muscles and your brain just beyond what they can comfortably do at the moment. That’s the secret to improving.

Programming is the same. If you just spend hour after hour writing similar programs that you already know how to do, and never anything new, then again you won’t improve even if you do it for 10,000 hours. You need to practice what you are already capable of, but also push yourself to the things that you just can’t comfortably do (yet), programs you can’t comfortably write (yet). However this comes with a big BUT!

Don’t push too far beyond what you can do to quickly or you will just get hopelessly stuck and dispirited (the equivalent of collapsing on a run when you are a long way from home).

This is a mistake many students learning to program make. They are so keen to learn,  that having written a program that works, they rush straight on to the next concept. They are trying new things before they have actually mastered the current ones. You do need to write lots of programs with the simpler concepts to master them. If you move on too quickly you will start to struggle as you get more and more out of your depth, and the practice you do will be less and less effective.

There is no point trying to write programs that use while loops if you have not mastered the simpler if statements and so understand boolean expressions. And don’t move on to boolean expressions before you have mastered simple integer expressions and variables…

If you are told to try harder, don’t. Instead try smarter. That might mean stepping back to something simpler and make sure you have mastered it.

We will look in more detail what the right kind of practice is in future tips.

If you are a:

  • student
    • Practice lots, but master simple things before you move on to harder ones.
    • Do push just out of your comfort zone in your practice once you have mastered something.
    • Identify something just beyond what you can currently do and practice that until you can do it easily. Only then move on to the next thing. 
    • Don’t think that doing it once means you have mastered it!
  • teacher:
    • Set activities that gradually increase in difficulty with lots of exercises to practice at each stage.
    • Identify a progression in concepts to introduce.
    • Don’t let students rush on to writing ever more difficult programs to write before they have fully mastered the concepts in the previous ones.

More on Learning to Learn (to program)


IoC logo on white

 

 

“DELIBERATE” PRACTICE

Paul Curzon, Queen Mary University of London

Here is the next in our series of tips about learning to learn (to program).

TIP 2: THE RIGHT KIND OF PRACTICE IS “DELIBERATE” PRACTICE

10,000 hours of practice is often given as a rule of thumb to become an expert. However, if it is the wrong kind of practice then all those hours may not help. An effective kind of practice is “deliberate practice”. This is one of the top 10 or so educational approaches known to be effective as a way to improve learning, and is based on research in a lot of areas from elite sportspeople, virtuoso violinists, top medics and more. It is what elite people do to become one of the elite. It can help with learning to program too.

Some skills are more appropriate to apply deliberate practice to than others. However, even an incomplete version may make practice more effective.

Deliberate practice involves:

  • Identify the sub-skills that experts have; the ones that make them better than everyone else and practice those skills.
  • Aim to build accurate versions of the same “mental models” as the experts have for those sub-skills (early).

  • Practice doing things just beyond your current comfort zone until you have mastered them. Then move on.
  • Practice in a way that gives you immediate feedback on whether you are doing it right or wrong.
  • If you get it wrong (that’s good, its a chance to improve), focus on why you got it wrong (based on that accurate mental model) and practice until you can do it.

We will look at the separate elements of this in subsequent tips.

To learn to program you need not just to write program, but to do deliberate practice of the sub-skills.

If you are a:

  • student
    • Learn about deliberate practice and put it into practice when you learn, including as you learn to program.
  • teacher:
    • Set up learning resources and situations to support deliberate practice of programming skills.

Further reading: Ericsson, A & Pool, R, 2016, Peak: Secrets from the new science of expertise. The Bodley Head.


More on Learning to Learn (to program)


IoC logo on white