4.1.2.1–4.1.2.2 - Procedural design and hierarchy charts (Python)

4.1.2.1–4.1.2.2 - Procedural design and hierarchy charts (Python)

Learn how to decompose a program into cooperating modules, represent that design with a hierarchy chart, and construct a procedural solution with clear interfaces.

Procedural and object-oriented paradigms

A programming paradigm provides a way to organise a solution, rather than a different set of problems the program can solve.

Procedural programming

Organising a program around procedures and functions that carry out operations on data. A main routine coordinates calls, using sequence, selection and iteration.

For example, a procedural score report passes a list to calculate_mean(scores) and passes the returned mean to display_report(mean). The data and operations are connected by explicit parameters. A well-designed procedural program need not use shared global variables.

Object-oriented programming groups related state and behaviour in objects created from classes. An object representing a score report can hold its scores as attributes and provide a mean() method. Here is a small working contrast; later lessons explain constructors, access and relationships in depth.

Python
def calculate_mean(scores):
    return sum(scores) / len(scores)

class ScoreReport:
    def __init__(self, scores):
        self.scores = list(scores)

    def mean(self):
        return sum(self.scores) / len(self.scores)

scores = [60, 80]
print(calculate_mean(scores))
report = ScoreReport(scores)
print(report.mean())

Both output lines are 70.0. In the procedural version the data is passed to a function; in the object-oriented version a method acts on the receiving object's state. Both can use loops, conditions and subroutines. Python supports both paradigms, and a program can combine them. Procedural decomposition often fits a clear sequence of transformations; objects can be useful when many entities each have lasting state and related operations. Choose boundaries that match the problem.

Structured design

A structured approach begins with a whole task and repeatedly decomposes it into smaller tasks with clear responsibilities.

A score-report requirement is: read integer scores from a file, retain values from 0 to 100, calculate their mean, then display either the mean to two decimal places or an empty-data message. Decompose it into read_scores, calculate_mean and display_report. The reader has its own subtask, valid_score. Define the interfaces before coding:

ModuleInputOutput or effect
valid_scoreOne integerBoolean validity
read_scoresFilenameList of accepted integers
calculate_meanList of integersMean, or None if empty
display_reportMean or NonePrints one report line

These boundaries allow the calculation to be tested with a known list without opening a file. During top-down construction, start with the coordinating routine and use temporary stubs for unfinished modules: a reader stub might return [60, 80]. Replace each stub with its implementation and test the integrated calls. A stub is a deliberate temporary stand-in, not a finished solution. Bottom-up construction implements and tests small routines first, then joins them into larger ones. Both rely on compatible interfaces.

Keep each module focused: its statements should contribute to one task. Reduce dependence on another module's private working variables. Meaningful names and explicit interfaces make code easier to understand; independent modules make faults easier to isolate; a correction is localised; programmers can work on separate modules and reuse them. Integration testing still matters: two correct routines can be combined incorrectly if, for example, one supplies pounds while the other expects pence.

Continue this lesson.

You’re previewing NovaLearn without an account. Create a free account to read the rest.

Create free account