Introduction
In your journey through H2 Computing, you have already learned how to build algorithms. However, even the best programmers make mistakes. Writing code is a process of trial and error! This chapter focuses on identifying what went wrong, tracking how your code executes step-by-step, and building "safety nets" to keep your programs running even when the unexpected happens.
1. The Three Types of Programming Errors
When a program doesn't work as expected, it is usually due to one of three types of errors. Understanding which one you are facing is the first step to fixing it.
A. Syntax Errors
Definition: These are mistakes in the "grammar" or "spelling" of the programming language. If your code has a syntax error, the computer cannot understand it, and it will refuse to run at all.
Common Examples:
• Forgetting a colon : at the end of an if statement.
• Misspelling a keyword (e.g., writing whyle instead of while).
• Having mismatched parentheses ( ) or quotes " ".
B. Logic Errors
Definition: The program runs without crashing, but the output is incorrect. The computer is doing exactly what you told it to do, but your instructions were wrong.
Common Examples:
• Using the wrong mathematical operator, such as writing \(x - y\) when you meant \(x + y\).
• An "Off-by-one" error, where a loop runs one time too many or one time too few.
• Using AND instead of OR in a selection statement.
C. Runtime Errors
Definition: The program starts running, but it hits a "dead end" and crashes while it is executing. This usually happens when the program is asked to do something impossible.
Common Examples:
• Division by Zero: Trying to calculate \(10 / 0\).
• Index Out of Bounds: Trying to access the 10th item in a list that only has 5 items.
• Type Error: Trying to add a number to a string, like \(5 + "hello"\).
Quick Review:
• Syntax: Computer can't read it.
• Logic: Computer reads it, but gives the wrong answer.
• Runtime: Computer starts reading, but explodes halfway.
2. Tracing: Following the Code’s Footsteps
When you have a logic error, the best way to find it is to "trace" the code. This means acting like a computer and recording the value of every variable at every step.
Trace Tables (For Non-Recursive Programs)
A trace table is a manual technique where you create columns for your variables and rows for each line of code executed. This is particularly useful for tracking iteration (loops).
Example: Trace a loop that calculates the sum of numbers from 1 to 3.
Step-by-Step Tip: Every time a variable changes its value, write the new value in the next row of the table. If a variable doesn't change on a particular line, you can leave it blank or repeat the previous value.
Recursion Trees (For Recursive Programs)
Tracing recursion (where a function calls itself) is trickier because multiple versions of the same function are "open" at once. We use a recursion tree to visualize this.
• Each node in the tree represents a function call.
• Arrows pointing down show the function calling itself with a smaller problem.
• Arrows pointing up show the value being returned back to the caller.
Don't worry if this seems tricky at first! Just remember that recursion always goes down until it hits the base case, and then it "unwinds" back up to the top.
3. Error and Exception Handling
Sometimes, runtime errors are caused by things outside your control—like a user typing "abc" when the program expects a number. Instead of letting the program crash, we use Exception Handling.
The Try-Except Mechanism
In Python, we use the try...except block as a "safety net."
• Try block: Put the "dangerous" code here (the code that might crash).
• Except block: This code runs only if an error occurs in the try block. Instead of crashing, the program executes these instructions.
Real-world Analogy: Think of a try block like trying to catch a glass vase. The except block is like wearing thick gloves—if you drop it, the gloves prevent you from getting cut, and you can "handle" the mess gracefully.
Why use Exception Handling?
1. Robustness: It prevents the entire system from failing due to one small mistake.
2. User Experience: Instead of a scary computer error message, you can show a friendly message like "Please enter a valid number!"
Key Takeaway: Good programs don't just work when everything is perfect; they are designed to handle erroneous conditions without breaking.
4. Testing for Success
To ensure your error handling and logic are solid, you must design Test Cases. For the H2 syllabus, you should always test using three types of data:
1. Normal Data: Inputs that the program expects (e.g., entering "18" for an age variable).
2. Boundary (Extreme) Data: Inputs at the very edge of what is allowed (e.g., entering "0" or "100" if the range is 0 to 100).
3. Erroneous Data: Inputs that are clearly wrong (e.g., entering "hello" for an age variable) to see if your exception handling works.
Note: For more on the difference between Validation (Is the data sensible?) and Verification (Is the data exactly what the user intended?), please refer to the "Data Validation and Program Testing" chapter.
Summary Checklist
• Can you identify if an error is Syntax, Logic, or Runtime?
• Can you fill out a trace table for a loop?
• Can you draw a recursion tree for a recursive function?
• Do you know how to use try...except to catch exceptions?
• Have you prepared Normal, Boundary, and Erroneous test cases?