Skip to content

When It's Wrong

The most useful skill there is: finding out why a program misbehaves by looking at what it did, not by guessing.

  • Foundations

Every program you write will, at some point, do the wrong thing. Every one.

We do not need to avoid every mistake. We need a way to investigate one without changing things at random.

A bug you can see

Here is a program meant to double a number:

Code
ASK "A number? " INTO n
SHOW "Double it: ", n + 2

Type 5. Double five is ten, so you expect 10:

Output
A number? 5
Double it: 7

Predict before changing it

Keep this deliberately broken example separate from any working program. We can run it again from the beginning with 5: we expect 10, but get 7. That gives us a small, repeatable case.

Our hypothesis is specific: the program adds two instead of doubling the input. Before changing it, predict both the intended answer and the answer from n + 2 for 2, 0 and -3. Trace the two-line program on paper; if we try it in a language, use that language’s input and output instructions.

Would getting the right answer for 2 disprove our hypothesis? Which of the other inputs would help us tell the two calculations apart?

Compare the predictions
Input Intended double Broken calculation: add two
2 4 4
0 0 2
-3 -6 -1

Both calculations give 4 for 2. That success cannot tell us which calculation the program used. Zero and a negative number distinguish them. If the actual results differ from the last column, our hypothesis does not explain everything: check the value read into n and the version of the program being run before making another change.

Now change only the calculation:

Code
ASK "A number? " INTO n
SHOW "Double it: ", n * 2

Repeat the original input 5, then the three comparison inputs. Write the expected answers first: 10, 4, 0, -6. Checking cases that already worked helps us spot a regression: a change that breaks behaviour we previously relied on.

We have a reason for this repair: multiplication expresses the intended rule for all these inputs. Hard-coding 10 would pass our first test and fail the others. These few checks are useful evidence, not proof about every possible number or every language’s numeric limits.

The recurring method is to describe expected and actual behaviour, reproduce the problem, form a specific hypothesis, predict evidence, change or measure one relevant thing, interpret the result, then repair and check again. A short note is enough; this example does not need a testing framework.

When you cannot see it

Sometimes the wrong answer does not tell you enough. Then you make the program show you more of its working:

Code
LET prices = [10, 25, 5]
LET total = 0
FOR EACH price IN prices
  SHOW "adding ", price, " to ", total
  LET total = total + price
END
SHOW "Total: ", total

That extra SHOW is not part of the program you want. It is there to let you watch the values change, and you take it out afterwards. Doing it on paper works too:

Passpricetotal beforetotal after
110010
2251035
353540

Work through it a line at a time, writing down what each box holds. The first disagreement gives us a place to investigate. Check the paper calculation too: our prediction can be mistaken.

Read what the machine tells you

When a program stops with an error message, it may name a problem and a place.

Read the message and the location together. They tell us what the tool detected; the cause may be earlier. Some failures produce no useful message, which is why observing values and reducing the example matter too.

When the evidence disagrees

Start with the smallest piece we can understand and repeat. Check its inputs, the program actually loaded, and our expected result. Reduce it further while keeping the failure: removing the symptom as well as the extra code would not help.

Trying another emulator or computer can give us another observation. Agreement with one emulator does not prove that a hardware detail is correct. If results conflict, record the machine model and tool version, consult the original documentation, and compare a small focused test with real hardware results when available. We can leave a question open when the evidence does not settle it.

What you’ve learnt

  • Describe what we expected and what actually happened, with an input we can repeat.
  • Predict evidence that could support or contradict a specific explanation.
  • Inspect one relevant value or change one thing, then explain the result.
  • Repair the cause and repeat the failing case and previously working cases.
  • A successful output is evidence; choose other cases that could reveal a hidden fault.

For a later investigation with a real machine, Meet Assembly’s debugger lesson uses the same method to investigate movement. It introduces registers and stepping when they become useful.

Where to go from here

That completes this introduction. We have practised instructions and order, output and memory, input, arithmetic, decisions, loops, lists, named jobs, and how to find our way when one goes wrong. Later projects will give us reasons to deepen these ideas.

None of it was about a language. You saw each idea in plain words so that you would know it again wherever you meet it.

So that is what comes next: pick a language to say these ideas in properly, on a machine you like the look of. Meet BASIC teaches the Spectrum’s own, and builds real games with it. The same ideas wear the Commodore 64’s BASIC, the Amiga’s AMOS, and others besides. Or head for the metal, down through the number systems a machine counts in and on into assembly.

Whichever you pick, you are not starting from nothing. You already have the ideas, and every language is a way of writing them down.