Structured Programming
Learning Objectives
- You know the key concepts of structured programming and know of the influence of ALGOL on modern programming languages.
Structured Programming Concepts
Structured programming sought to bring clarity and order to code. At the core, structured programming is based on the idea of decomposing programs into well-defined blocks or modules, each responsible for a single task. By enforcing clear control structures — such as loops, conditionals, and subroutines — structured programming minimizes the reliance on unstructured jumps like the infamous GOTO.
The first programming language that provided structured programming constructs was ALGOL (Algorithmic Language). ALGOL introduced a formal syntax and block structure that set the standard for writing clear and maintainable code. Although modern ALGOL code is rarely seen today, its influence is evident in almost all modern programming languages.
The following ALGOL program illustrates the use of structured control constructs (we assume the existence of a print
function, which actually did not exist) and the use of blocks to group statements:
begin
integer num, i;
num := 5;
if num > 0 then
begin
print("The number is positive.")
end
else
begin
print("The number is zero or negative.")
end;
for i := 0 step 1 until num - 1 do
begin
print("Iteration ");
print(i)
end
end.
As you notice, blocks were started and ended with begin
and end
keywords, and the program’s flow was controlled using if-then-else
and for
constructs. This structure made it easier to understand the flow of the program and the scope of variables.
The above program is equivalent to the following C program:
#include <stdio.h>
int main() {
int num = 5;
if (num > 0) {
printf("The number is positive.\n");
} else {
printf("The number is zero or negative.\n");
}
for (int i = 0; i < num; i++) {
printf("Iteration %d\n", i);
}
return 0;
}
And to the following Rust program:
fn main() {
let num = 5;
if num > 0 {
println!("The number is positive.");
} else {
println!("The number is zero or negative.");
}
for i in 0..num {
println!("Iteration {}", i);
}
}
Note the presence of the keywords
if
,else
, andfor
in the C and Rust programs, which are direct descendants of the ALGOL constructs.
The first ALGOL implementation did not have functions, but functions were introduced in ALGOL 60. Functions encapsulate a specific task or operation, making the code more modular and easier to understand. The use of functions is a key aspect of structured programming, as it allows for the decomposition of complex tasks into smaller, more manageable units.
The following ALGOL program demonstrates a function is_positive
— early ALGOL did not feature an explicit return
statement; instead, functions returned a value by assigning it’s own name.
begin
integer num;
num := 5;
if is_positive(num) = 1 then
begin
print("The number is positive.")
end
else
begin
print("The number is zero or negative.")
end;
for i := 0 step 1 until num - 1 do
begin
print("Iteration ");
print(i)
end
end.
integer function is_positive(n)
integer n;
begin
if n > 0 then
is_positive := 1
else
is_positive := 0
end.
As you might notice from the above example, early ALGOL also did not have boolean types; instead, it used integers to represent boolean values. The function is_positive
returns 1
if the number is positive and 0
otherwise.
The above ALGOL program is equivalent to the following C program:
#include <stdio.h>
int main() {
int num = 5;
if (is_positive(num)) {
printf("The number is positive.\n");
} else {
printf("The number is zero or negative.\n");
}
for (int i = 0; i < num; i++) {
printf("Iteration %d\n", i);
}
return 0;
}
int is_positive(int n) {
return n > 0;
}
Readability, Maintainability, and Reliability
One of the key benefits of structured programming is improved code readability. When code is organized into blocks with a single entry and exit point, it becomes easier to understand. This is in contrast, for example, to BASIC, where GOTO
statements could lead to spaghetti code that was difficult to follow.
For example, the following program showcases a non-structured approach in BASIC that uses GOTO when calculating the factorial of a number (we intentionally did not use FOR to illustrate the point):
10 LET F = 1
20 LET I = 1
30 IF I > N THEN GOTO 70
40 LET F = F * I
50 LET I = I + 1
60 GOTO 30
70 PRINT "FACTORIAL", F
A similar program in a structured language like Python is easier to follow (although the range
function might need some explanation, and one might stumble with the intendation at first):
def factorial(n):
result = 1
for i in range(1, n + 1):
result *= i
return result
print(factorial(5))
Structured programming helps maintainability by encouraging modular design. Functions encapsulate specific tasks, making it easier to update or modify code without affecting other parts of the program. This modular approach also simplifies testing and debugging, as each function can be tested in isolation.
Functions can also be reused across different parts of the program, reducing duplication and promoting consistency.
As an example of modular design, a small program that reads, processes, and displays data from a file can be structured into distinct functions:
def read_data(filename):
"""Read and return the contents of the given file."""
with open(filename, 'r') as file:
return file.read()
def process_data(data):
"""Process data by converting it to uppercase."""
return data.upper()
def display_data(data):
"""Display the processed data."""
print(data)
def main():
data = read_data('data.txt')
processed = process_data(data)
display_data(processed)
if __name__ == '__main__':
main()
In the above example, each function has a clear responsibility, while the main
function orchestrates the flow of the program. Structured programming — and later object-oriented programming — encourages separation of concerns, leading to more maintainable and reliable code.
Structured Programming Legacy
Structured programming has influenced nearly all modern programming languages and paradigms. The principles of structured programming — modularity, clear control flows, and single-entry, single-exit constructs — have become a fundamental part to writing clean and maintainable code.
Even with newer paradigms (when compared to structured programming) like object-oriented programming, the key ideas are still present. For example, Java — like many other languages — follows a structured format where each method or function is clearly separated from the others.
public class Calculator {
public int add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
var calc = new Calculator();
System.out.println("Sum: " + calc.add(5, 7));
}
}