Structured programming is a programming paradigm that builds every program from three fundamental control-flow constructs: sequence, selection, and iteration. By avoiding arbitrary jumps such as GOTO statements, structured programs are easier to read, test, and maintain — the principles that underpin every modern procedural and object-oriented language.
What was the problem with early programming?
Early programming languages such as FORTRAN and BASIC contained a GOTO statement — an instruction that jumped program execution to any labelled line in the code. A program with many GOTO statements could jump in all directions, making the flow of execution almost impossible to follow. Programmers coined the term spaghetti code for programs whose control flow looked like tangled spaghetti.
In 1968, the computer scientist Edsger Dijkstra published a famous letter titled Go To Statement Considered Harmful, arguing that GOTO statements made programs fundamentally harder to reason about. He advocated using only well-defined control structures instead. This letter marked the beginning of the structured programming movement.
What are the three control structures?
The Böhm-Jacopini theorem (1966) proved mathematically that any computable algorithm can be expressed using exactly three control structures, with no need for GOTO:
| Construct | Description | Example |
|---|---|---|
| Sequence | Statements execute one after another, top to bottom | Assigning variables, printing output |
| Selection | A condition determines which block of code runs | if, elif, else; case/switch |
| Iteration | A block of code repeats while a condition holds | for loops, while loops |
These three constructs are sufficient to express any algorithm, no matter how complex. Modern languages enforce this by either removing GOTO entirely (Python has no GOTO) or discouraging its use.
How does sequence work in practice?
Sequence is the simplest construct: statements run in the order they are written. Consider:
radius = float(input("Enter radius: "))
area = 3.14159 * radius ** 2
circumference = 2 * 3.14159 * radius
print(f"Area: {area:.2f}")
print(f"Circumference: {circumference:.2f}")
Each line runs in order, one after the other. The value of area is not available until the second statement has executed. This sequential execution is the backbone on which selection and iteration are layered.
How do selection and iteration extend sequence?
Selection branches the flow:
score = int(input("Enter score: "))
if score >= 70:
grade = "A"
elif score >= 55:
grade = "B"
elif score >= 40:
grade = "C"
else:
grade = "U"
print(f"Grade: {grade}")
Only one branch executes per run. The program's flow is entirely determined by the condition — no arbitrary jumps, always predictable.
Iteration repeats a block:
total = 0
for i in range(1, 6): # iterates i = 1, 2, 3, 4, 5
total += i
print(f"Sum 1 to 5: {total}") # Output: Sum 1 to 5: 15
Every iteration of the loop is controlled — the condition (i in range) determines when to stop. The program can be traced step by step with complete clarity.
What role do subroutines play in structured programming?
Subroutines (procedures and functions) are a fourth pillar of structured programming, extending the three constructs. They allow code to be:
- Decomposed — breaking large problems into smaller, manageable sub-problems.
- Reused — the same subroutine can be called from multiple places without duplicating code.
- Tested independently — each subroutine can be unit-tested in isolation.
def calculate_area(radius):
return 3.14159 * radius ** 2
def calculate_circumference(radius):
return 2 * 3.14159 * radius
r = 7.0
print(calculate_area(r))
print(calculate_circumference(r))
By naming the calculations as functions, the main program reads almost like plain English and the calculations can be tested independently. This decomposition approach is central to both structured and object-oriented programming.
How does structured programming improve code quality?
| Quality attribute | How structured programming helps |
|---|---|
| Readability | Top-to-bottom flow with named constructs is easy to follow |
| Testability | Each subroutine can be tested in isolation with known inputs and outputs |
| Maintainability | A bug in one function does not require changes across unrelated code |
| Reusability | Well-named subroutines can be reused within and across projects |
| Debuggability | The programmer can trace execution precisely without chasing GOTO jumps |
These qualities are not just theoretical: in practice, programs written without structured principles accumulate technical debt rapidly. The GCSE criteria for programming project quality explicitly reward clarity of structure, use of subroutines, and separation of concerns — all properties of structured programming.
Frequently asked questions
Is Python a structured programming language?
Yes. Python enforces structure through its syntax: it has no GOTO statement, and all control flow must use sequence, selection (if/elif/else), or iteration (for/while). Python is also multi-paradigm — it supports object-oriented and functional styles — but its core procedural layer is entirely structured. Every Python program you write at GCSE is a structured program.
What is spaghetti code and why is it a problem?
Spaghetti code is a derogatory term for programs whose control flow jumps unpredictably using GOTO statements or equivalent constructs, making the execution path resemble tangled spaghetti. It is a problem because no one — including the original programmer — can easily trace what the program does, making bugs nearly impossible to find and fixes likely to introduce new bugs. Structured programming eliminates spaghetti code by restricting control flow to well-defined constructs.
How does structured programming relate to the procedural programming paradigm?
They are closely related. Procedural programming organises code into procedures (subroutines) and uses structured control flow. Every procedural program is structured, but structured programming as a concept arose specifically as a rejection of GOTO — it is the theory that motivates why modern procedural languages are designed the way they are. At GCSE, the terms are sometimes used interchangeably.
What are the benefits of decomposing a program into subroutines?
Decomposition turns a large, unwieldy problem into smaller pieces that are easier to understand, write, and test. Each subroutine has a single, well-defined purpose, making it possible to verify that one piece of logic is correct without understanding the whole program. It also enables code reuse (the same calculation function used in multiple places) and makes collaboration easier in team projects because different people can work on different subroutines simultaneously.
Strengthen your programming foundations with Professor Turing's structured approach to GCSE Computer Science at aitutors.me.