Guideline 3: Read Code

Decorative image showing the text "Guidelines for Teaching Programming" and the number 3

The third guideline of teaching programming is to read code, lots of it, and early.

I have already talked about this in Guideline 2, which was about not starting with a blank screen. While Guideline 2 was aimed primarily at avoiding the empty-screen paralysis (and discussed code reading as a side issue), this one is explicitly about the importance of code reading as a skill, and not limited to the first example.

Many programming courses concentrate solely on code writing, and assume that – somehow – code reading will follow. Either it is assumed that this is an easy skill that exists automatically, or that it is acquired by osmosis somehow. More often teachers do not think about this much at all.

Code reading is, in fact, a valuable and separate skill that should be practiced. And it should be practiced early, since it is of great value to learning to write code.

For the first few projects (spanning weeks, if not months), start each project by handing out to students a partial, half written application, and make the goal to fix/complete/extend. In this way, the first task required is to read and understand the existing code, before working out what to extend and write. Discuss and require code reading explicitly.

A large amount of peripheral learning happens when reading well written code. We get benefits from an apprenticeship approach, where learners can copy the master’s practices at many levels, and learn by example.

This approach is also much more realistic as preparation for actual work: No new programmer joining a software company will, as their first task, be asked to write a new system from scratch. It is always the reading and extending of existing software.

Of course, this requires teachers to show students code that is worth reading, that embodies good practice, from which also techniques can be gleaned that are not the current focus of discussion. It requires teachers to use a significant number of well-written examples that exemplify good practice. Not all teachers will always be able to write such examples, but resources can be shared. Look for resources that support this approach.

Guideline 2: Don’t start with a blank screen

Decorative image showing the text "Guidelines for Teaching Programming" and the number 2

The second guideline from my 23-year-old paper told teachers not to make students start with a blank screen.

Putting learners in front of an empty screen and saying “Today we are going to write a program” always seemed very strange to me. I think programming may be the only discipline that that would ever approach learning this way. It is the equivalent of teaching English Literature, and making students write a story before they have ever read a story. (Or, indeed, heard a story, or know what a story is.)

Imagine French learners writing French before reading it. Or children learning to play the violin being taught to play without ever having heard music before.

Code reading is a skill that is (at least) as important as code writing.

So: Start by giving your students a small program that does something (hopefully interesting! – more on that later), and get them to execute and experiment. Then get them to make small modifications. Let them experiment.

And free yourself from that idea that you have to completely explain everything they see on screen before they are allowed to look at it! Young learners are resilient – they can cope with a bit of intrigue and mystery.

Sitting in front of an empty screen as a beginner can have a paralysing effect. Being able to experiment and play is an easier, less intimidating approach. Bonus: The quick learners can make guesses and experiment.

Starting with a blank screen requires knowledge, planning and design. Tinkering is easier and gets you further quicker. And it makes it easier to show interesting examples early. (More on interesting examples later.)

In your first class, creating curiosity and engagement is more important than teaching the first bit of syntax. At the end of the class, you want them wanting to come back wanting to know more, not running away from a dispiriting experience.

Guideline 1: Objects First

Decorative image showing the text "Guidelines for Teaching Programming" and the number 1

The first of the guidelines for programming teaching from 2001 stated that you should start teaching objects from the start.

This, perhaps, is the least convincing of the guidelines today. In 2001, when I was thinking about teaching beginners, I was thinking about teaching first-year university students. Thus, it was a selective audience who had chosen to become software professionals.

Today, novice programming teaching is mainly an affair happening at school age. And we have to be aware of the difference it creates: most of the pupils do not want to become software professionals, and they do not all have to learn about best practice in software engineering.

Thus, it is a perfectly fine path today to teach an introduction to programming without objects. (More on this in a later post.)

But I would maintain: IF you want to end up with object-orientation, then you should START with objects. Object-based programming is not a language construct that can be added on to procedural programming later. It requires a different structure of the program, a different way of thinking, a different approach to algorithmic problem solving. If it is not done from the start, it would require unlearning habits later, and start again in a new way. This rarely works well.

So, I would maintain my advice from 23 years ago: If you want to teach object-orientation, start with objects on day 1!

Guidelines for Teaching Programming

Decorative image showing the text "Guidelines for Teaching Programming" as the heading of an academic paper

How to teach programming is a hot topic again. 23 years ago (!) I wrote a paper titled “Guidelines for Teaching Object Orientation with Java” that provided some guidelines (eight, to be exact).

And although, as the title suggests, this was specific to OO and Java, I was wondering how many of these would stand up today. I was surprised to see that almost all of it – I think – is still relevant, and almost all of it we still cannot take for granted.

So I will, over the next few days, revisit the guidelines here, one at a time, and add my comments outlining how much of each I think still applies in “modern times”.

Watch this space over the next week or two for the discussion.

A brief history of programming languages

While I was thinking about the history of programming languages recently, I remembered slides I once made, showing a (simplified) family/influence/history diagram of languages.

Shared he in case it’s useful to anyone.

(It was made many years ago, so not up to date after 2010 – sorry. And I fully expect your comments correcting my interpretations…)

A graph showing several programming languages from 1957 to 2012 and their relationships

Some programming languages and their relationships (up to 2010)

The same graph as above, but with languages highlighted that use C-style syntax

Languages with C-style syntax

The same graph as above, but with functional languages highlighted

Functional languages (some languages intentionally on the border…)

The same graph as above, but with object-oriented languages highlighted

Object-oriented languages (some languages intentionally on the border)

Here is a PDF file with the same diagrams.

In Honour of Niklaus Wirth

Niklaus Wirth died in Zürich on 1st January 2024. He was one of the great pioneers of programming language design, and specifically design of languages for education.

His languages were a huge influence on me, and on my thinking. Pascal was one of the first languages I learned, and Modula-2 and Oberon also opened worlds to me when I understood what lay behind their design.

The Informatics in Education journal has just published a special edition to honour Wirth’s tremendous contribution to our community. I contributed an article to this edition, titled Principles of Educational Programming Language Design.

I invite you to read it; it might be of interest to you if you are interested in programming language history, in the design of programming languages or in programming education.

The entire special edition is worth a look. It contains many other interesting contributions.


In 2002, I had the honour to introduce Wirth’s keynote address at the ITiCSE conference in Aarhus, and to have dinner with him. One of my treasured memories.

Image of Niklaus Wirth and Michael Kölling, sitting at a table at dinner.

Niklaus Wirth and I (in much younger years), at the conference dinner at ITiCSE 2002, in Aarhus

Sitting at a dinner table, chatting, are (from left to right): Michael Kölling, Niklaus Wirth, Michael E Caspersen, David Gries

At the ITiCSE 2002 conference dinner (left to right): Michael Kölling, Niklaus Wirth, Michael E Caspersen, David Gries

Designing a programming language: Don’t Be Clever

One lesson of programming language design? Don’t try to be too clever!

Here is an example from JavaScript​:

When you compare

0 == ‘0’

the system tries to be clever: “Comparing a number and a string? You probably meant to see whether the string contains the character ‘0’, so let’s just say ‘yes’!”, it thinks. So the result is true.

When you compare

0 == ”

it tries to be even cleverer: “Ahh, perhaps you meant to check whether the length of the string is zero! Let’s just help the user here and not require them to call a ‘length’ function. So tedious. It’s true!”

But of course

‘0’ == ”

“Comparing two strings – got it. Are they the same? No! Returning false.”

The result of all this: The fundamental property of transitivity of equality is broken in JavaScript!

a == b and b == c, therefore a == c ?

Not in JavaScript, it isn’t! How can anyone voluntarily program in a language like this?!

The lessons for me? Give me static typing any day. And don’t try to be clever when designing a language. Spelling things out is a good thing, not a bad thing.

The terrible state of MCQs

In academia – as in many other contexts – Multiple Choice Questions (MCQs) are a fact of life. We have many situations in which we need to assess a large cohort of learners, and MCQs make this easier.

Here, I don’t want to debate the value of MCQs as an examination technique in general, but talk about how they are written. If we accept that they are part of our work, let’s at least make them not terrible.

There are three very common ways in which MCQs can be obviously bad. I see them all the time.

They are:

  1. The question only examines surface knowledge
  2. The distractors are random
  3. The off-by-one way of writing distractors

Let’s look at each briefly.

The question only examines surface knowledge

This is quite an easy and obvious shortcoming to recognise: Often, MCQs just ask questions about terminology. They do not touch on concepts or deeper understanding. This is a very common trap to fall into for people who are not used to writing MCQs. Writing MCQs that test understanding is harder, and it’s easy to slip into the trap of just testing surface issues.

We have probably all seen it.

When you write your questions, examine each question critically in this light. Strive for meaningful questions.

The distractors are random

Another very common gripe of mine is that the distractors (the incorrect options in MCQs) are chosen at random. Let’s consider an example. Assume we have this question:

Question 54:

What is the output of the following segment of code?

        int sum = 0;   
        for (int i=0; i<=5; i+=2) {
            sum = sum + i;
        }
        System.out.println(sum);

If you speak Java, then you can work out that the answer is 6. So we use 6 as one of the possible options, and add a few random distractors:

Answer:

(A) 1
(B) 896
(C) 6
(D) -4
(E) 5

In this case, if students have a common misconception, they may arrive at an answer that is not on the list. For example, a student who does not understand that this definition makes the loop increment by 2 might assume that the answer is 15. But 15 is not on the list. So the student is implicitly told that they are wrong, and they can discard unlikely options (“Negative? – No.” “More then 800? – No.”) and make a random guess between a few remaining options.

This question is even worse in a way: Another common mistake is not being able to correctly distinguish between <= and < in the loop condition, and getting the answer wrong because of this. The way the question is written, however, it is not even possible to expose this misconception, because both variants happen to result in the same output!

A badly written question.

The off-by-one way of writing distractors

The other very common pattern I see all the time has an example in this question.

Question 31:

 Which of the following code segment would execute the stored procedure “getPassword()” located in a database server?

  1. CallableStatement cs = con.prepareCall("{call.getPassword()}");
    cs.executeQuery();
  2. CallabledStatement callable = con.prepareCall("{call getPassword()}");
    callable.executeUpdate();
  3. CallableStatement cab = con.prepareCall("{call getPassword()}");
    cab.executeQuery();
  4. Callablestatement cstate = con.prepareCall("{call getpassword()}");
    cstate.executeQuery();

The way questions like this are written is usually this: The question setter writes the correct response, and then creates three distractors by introducing one error in each.

It is trivial to reverse-engineer the correct answer from this. To do this, we spot the differences, and for each differences discard the odd one out. For example:

  • One difference is that “{call getpassword()}” is written with a dot in the middle once, but without the dot three times. So the dot is the odd one out, we discard Answer 1.
  • Another difference: CallableStatement is written with w capital S three times, with lowercase s once. So we discard answer 4.
  • Last one: The second line calls executeQuery() three times, and executeUpdate() once. Answer 2 is out.

And voilà – there is our answer: 3. We can do this without any knowledge or understanding of the subject matter. Keep your eyes open for this pattern in MCQ tests. It is astonishing how often you will see this question pattern.

A better example

Here is an example of something you could do:

Question 8:

HashMap<Integer, String> myMap = new HashMap<>();

myMap.put(2, "Tiger");
myMap.put(4, "Lion");
myMap.put(13, "Lion");
myMap.put(2, "Elephant");
myMap.put(3, "Chicken");

System.out.println(myMap.get(2));

When you try to compile and run this code, what will happen?

    1. The code has an error, because the value “Lion” is used twice in the HashMap.
    2. The code has an error, because the key 2 is used twice in the HashMap.
    3. The code will run and print “Tiger”.
    4. The code will run and print “Lion”.
    5. The code will run and print “Elephant”.

 In this case, the question tests an understanding of how maps work.

  • Option 1 tests the possible misconception that values cannot appear twice in a map.
  • Keys, on the other hand, are unique in a map. Option 2 tests the misconception that they cannot be replaced by a new entry.
  • Option 3 tests the misconception that the first entry for a given key persists.
  • Option 4 tests the misconception that the get(n)-parameter is an index, mirroring list-behaviour (referring to either the second or third element entered, depending whether the list is zero-based or one-based).
  • And Option 5 is correct.

This is by far not all that there is to say about MCQ writing. But it’s a start. It is the absolute minimum you should consider if ever you find yourself in the position to write and MCQ test.

Announcement: Strype – a frame-based Python system

Strype logoLast week, we have officially released Strype 1.0, a new Python editor and runtime system running entirely in a web browser. After being in development and available for preview and testing for some time, the system is now fully supported for use in classrooms or for individuals wishing to learn Python programming.

Strype’s most unique feature is its frame-based editor, a novel code entry and manipulation technique which makes writing of code quicker, easier and less error prone. In a manner similar to block-based systems, statements are entered and manipulated as single entities, and are laid out on screen automatically. Many syntax errors are avoided, indentation errors are not possible.

Sample of Strype code

While frame-based editing profits from some of the same advantages as block-based programming, it does not, however, suffers the same restrictions: programs in Strype have to full power of the Python language, purely keyboard-based efficient editing is supported, and programs retain the readability, navigability and maintainability of standard Python systems.

Strype is available free of charge, with no installation needed.

Links:

Strype webpage

The Strype editor

The Strype editor for micro:bit

Strype user community

Strype was developed by the Programming Education Tools Group at King’s College London. Team members: Pierre Weill-Tessier, Neil Brown, Michael Kölling