All subjects · Computer Science · WCP04 Advanced Practical Programming and Problem-solving

Designing programs: decomposition, modularity and scope

Edexcel IAL Computer Science · WCP04 Advanced Practical Programming and Problem-solving

Unit 4 marks reward programs that are well designed, not just ones that work. Design means splitting the problem sensibly, keeping each part focused, controlling what each part can change, and choosing efficient structures.

Practise this in the app: instant marking and a fix for every mistake. Free, no email needed to start.

Practise this lesson

Decompose, then choose structures

Modularity and separation of concerns

Side effects and scope

A side effect is any change a subprogram makes outside itself: altering a list passed in, changing a global variable, printing or writing a file. Minimise them so each part is predictable. Lists are passed by reference, so changing one inside a function changes the caller's list.

def add_bonus_in_place(scores, bonus):
    for i in range(len(scores)):
        scores[i] = scores[i] + bonus      # side effect: changes the caller's list
    return scores

def add_bonus(scores, bonus):
    return [s + bonus for s in scores]     # no side effect: returns a new list

marks = [60, 72, 85]
boosted = add_bonus(marks, 5)
print(marks, boosted)
add_bonus_in_place(marks, 5)
print(marks)

Output:

[60, 72, 85] [65, 77, 90]
[65, 77, 90]

Scope: a variable created inside a function is local to it. Use global only when unavoidable; pass values in and return results instead.

total = 0

def add_global(x):
    global total          # avoid where possible
    total = total + x

def add_pure(current, x):
    return current + x

add_global(5)
print(total, add_pure(total, 5), total)

Output:

5 10 5

Efficiency

banned = ["spam", "scam", "fake", "fraud"]
banned_set = set(banned)
words = "this is not spam or a scam".split()
print([w for w in words if w in banned_set])

Output:

['spam', 'scam']

Worked example

A program reads diving scores, calculates totals and prints a table, all in one 60-line block of code. Suggest a better design.

  1. Decompose into `load_dives(filename)` (input), `dive_score(judge_scores, difficulty)` (processing, returns a number), `rank(totals)` (processing, returns a sorted list) and `show_table(ranking)` (output).
  2. Keep the original data unchanged: processing functions return new values instead of modifying their inputs.
  3. Use named constants for fixed values such as the number of judges.
  4. Each function can now be tested on its own with known data.

Answer: Separate input, processing and output into focused functions with parameters and return values, and no hidden side effects.

Key idea: Decompose into focused subprograms; pick fitting types, structures and constructs; keep input, processing and output separate; minimise side effects and globals; respect scope; avoid repeated work and choose efficient structures.

Check yourself

  1. What does this program print? ```python def double_all(nums): for i in range(len(nums)): nums[i] = nums[i] * 2 data = [1, 2, 3] double_all(data) print(data) ```
    Show answer

    [2, 4, 6]. The function changes the list it was given, and that is the same list object as data, so the caller sees the change: `[2, 4, 6]`

  2. What does this program print? ```python def doubled(nums): return [n * 2 for n in nums] data = [1, 2, 3] new = doubled(data) print(data, new) ```
    Show answer

    [1, 2, 3] [2, 4, 6]. The function builds and returns a new list, so data is unchanged. Output: `[1, 2, 3] [2, 4, 6]`

  3. What does this program print? ```python total = 0 def add_global(x): global total # avoid where possible total = total + x def add_pure(current, x): return current + x add_global(5) add_global(3) print(total, add_pure(total, 10)) ```
    Show answer

    8 18. add_global changes the global total: 5 then 8. add_pure returns 8 + 10 without changing total. Output: `8 18`

  4. Which function design best follows separation of concerns?
    • `def average(scores): print(sum(scores) / len(scores))`
    • `def average(): scores = input(); print(...)`
    • `def average(scores): return sum(scores) / len(scores)`, with printing done by the caller
    • One function that reads the file, calculates every statistic and prints them
    Show answer

    `def average(scores): return sum(scores) / len(scores)`, with printing done by the caller. A function that only calculates and returns its result can be tested and reused; input and output are handled elsewhere.

  5. Which of these is a side effect of a function?
    • It appends an item to a list that was passed in as an argument
    • It returns a new list
    • It creates a local variable
    • It calls another pure function
    Show answer

    It appends an item to a list that was passed in as an argument. Changing a mutable argument alters data outside the function.

  6. A loop checks 50 000 product codes against a list of 20 000 valid codes. What change makes it most efficient?
    • Sort the product codes
    • Use a while loop instead of a for loop
    • Convert the valid codes to a set once, before the loop
    • Print each code as it is checked
    Show answer

    Convert the valid codes to a set once, before the loop. Set membership is fast regardless of size; list membership checks items one by one.

  7. An exam question asks you to add a function that calculates a median. You also add a menu and colour output. What is the problem?
    • The program now does more than was asked, which the instructions say not to do
    • Menus are not allowed in Python
    • Colour output always crashes
    • There is no problem; extra features earn extra marks
    Show answer

    The program now does more than was asked, which the instructions say not to do. Fitness for purpose: meet the requirement exactly. The Unit 4 instructions say not to add functionality beyond what is asked.

Practise with instant feedback

Sources

Last updated 8 November 2026. Spotted a mistake? Tell us.