All subjects · Computer Science · WCP04 Advanced Practical Programming and Problem-solving
Clean code: consistency, readability and controlling behaviour
Edexcel IAL Computer Science · WCP04 Advanced Practical Programming and Problem-solving
Clean code is code another programmer (or an examiner) can read, trust and change. The specification groups it into consistency, readability and controlling how the program behaves at its edges.
Consistency
Follow one style throughout, normally Python's style guide (PEP 8):
- Indent with 4 spaces; use blank lines to separate functions and logical sections; one statement per line.
- Naming conventions:
snake_casefor variables and functions,CapWordsfor classes,UPPER_CASEfor constants. - Spaces around operators and after commas:
total = price * quantity. - Keep lines to a fixed maximum length (PEP 8 recommends 79 characters). Break long lines inside brackets, which Python continues automatically, or with a backslash at the end of the line.
Readability
- Meaningful identifiers:
average_score, notaorx2. - Named constants instead of magic numbers:
if age >= SENIOR_AGEexplains itself;if age >= 65does not. - Named subprograms that say what they do:
is_valid_date(),calculate_total(). - Informative comments that explain why, not what:
# judges' extremes are removed to reduce biashelps;# add 1 to idoes not. A short comment at the top of each subprogram states its purpose, parameters and return value.
Guard clauses and less nesting
Deeply nested if statements are hard to follow. A guard clause deals with a special or invalid case at the start and returns (or raises) straight away, so the main logic is not indented.
Before:
def ticket_price(age, is_member):
if age >= 0:
if is_member:
if age >= 65:
return 4
else:
return 6
else:
return 9
else:
return NoneAfter, with guard clauses and named constants:
FULL_PRICE = 9
MEMBER_PRICE = 6
SENIOR_MEMBER_PRICE = 4
SENIOR_AGE = 65
def ticket_price(age, is_member):
if age < 0:
raise ValueError("age cannot be negative")
if not is_member:
return FULL_PRICE
if age >= SENIOR_AGE:
return SENIOR_MEMBER_PRICE
return MEMBER_PRICE
print(ticket_price(70, True), ticket_price(30, True), ticket_price(30, False))Output:
4 6 9Loops can be flattened in the same way, using continue to skip invalid items at the top of the loop body.
Boundaries, exceptions and type conversion
- Boundary value analysis: errors cluster at the edges of ranges. For a valid range of 1 to 99, test 0, 1, 99 and 100. Check whether each comparison should be < or <=.
- Exception handling: catch the specific exception you expect, close to where it can happen, and decide what the program does next.
- Managing type conversion: convert input once, at the point it enters the program, inside a try block, and work with the correct type afterwards.
def read_quantity(text):
try:
quantity = int(text)
except ValueError:
return None
if quantity < 1 or quantity > 99:
return None
return quantity
for raw in ["0", "1", "99", "100", "12.5", "seven"]:
print(raw, read_quantity(raw))Output:
0 None
1 1
99 99
100 None
12.5 None
seven NoneWorked example
Rewrite this code cleanly: `def f(l):` then `t=0`, `for i in range(len(l)): t=t+l[i]*1.2`, `return t`.
- ```python VAT_MULTIPLIER = 1.2 def total_with_vat(prices): # Returns the sum of the prices with VAT added. return sum(price * VAT_MULTIPLIER for price in prices) print(round(total_with_vat([10, 20]), 2)) ```
- Output: ``` 36.0 ```
Answer: Meaningful names, a named constant for 1.2, a purpose comment, spaces around operators and a direct loop over the items.
Check yourself
- What does this program print?
```python
FULL_PRICE = 9
MEMBER_PRICE = 6
SENIOR_MEMBER_PRICE = 4
SENIOR_AGE = 65
def ticket_price(age, is_member):
if age < 0:
raise ValueError("age cannot be negative")
if not is_member:
return FULL_PRICE
if age >= SENIOR_AGE:
return SENIOR_MEMBER_PRICE
return MEMBER_PRICE
print(ticket_price(65, True), ticket_price(64, True), ticket_price(65, False))
```
Show answer
4 6 9. 65 is a senior member (>= 65): 4. 64 is a member but not senior: 6. A non-member pays the full price whatever their age: 9. Output: `4 6 9`
- Using read_quantity from the lesson, what does this print?
```python
def read_quantity(text):
try:
quantity = int(text)
except ValueError:
return None
if quantity < 1 or quantity > 99:
return None
return quantity
print(read_quantity("1"), read_quantity("100"), read_quantity("3.0"))
```
Show answer
1 None None. 1 is the lower boundary and is valid; 100 is just outside the range; '3.0' is not a whole-number string, so int() fails. Output: `1 None None`
- Following PEP 8, which name suits a class that represents a diving competition?
- `DivingCompetition`
- `diving_competition`
- `DIVING_COMPETITION`
- `divingcompetition()`
Show answer
`DivingCompetition`. Classes use CapWords; snake_case is for variables and functions; UPPER_CASE for constants.
- A field accepts whole numbers from 10 to 50 inclusive. Which set of test values carries out boundary value analysis?
- 10, 30, 50
- 1, 25, 100
- 0, 10, 20, 30, 40, 50
- 9, 10, 50, 51
Show answer
9, 10, 50, 51. Test each boundary and the value just beyond it on the invalid side.
- Why is `if len(scores) == NUM_JUDGES:` better than `if len(scores) == 5:`?
- It runs faster
- The constant explains the meaning of 5 and lets it be changed in one place
- Python does not allow numbers in comparisons
- It stops the list from changing
Show answer
The constant explains the meaning of 5 and lets it be changed in one place. Named constants remove magic numbers, improving readability and maintenance.
- Which comment is most informative?
- `# sort the list`
- `# this is a loop`
- `# x = x + 1`
- `# drop highest and lowest so one generous judge cannot skew the score`
Show answer
`# drop highest and lowest so one generous judge cannot skew the score`. Good comments explain the reason for code; the others restate what the code already says.
- How can a long expression be split over two lines in Python without a syntax error?
- Indent the second line by 8 spaces with no brackets
- Put it inside brackets and break the line inside them, or end the first line with a backslash
- Put a semicolon at the end of the first line
- Use a # at the end of the first line
Show answer
Put it inside brackets and break the line inside them, or end the first line with a backslash. Python continues a line implicitly inside (), [] or {}, or explicitly after \ at the end of the line.
Sources
- Pearson Edexcel International Advanced Subsidiary/Advanced Level in Computer Science specification, Issue 1 (March 2026)
- Pearson Edexcel IAL Computer Science Unit 4 Programming Language Subset (PLS)
- Pearson Edexcel IAL Computer Science sample assessment materials (Unit 3 and Unit 4)
Last updated 8 November 2026. Spotted a mistake? Tell us.