9.2.5 Modular Algorithm Design
Large computing problems are difficult to understand when every requirement is considered at once. Decomposition reduces this difficulty by separating the overall problem into smaller sub-problems with clear purposes. These parts can then be analysed, designed, tested and improved more systematically.
By the end of this section, you should be able to:
- Explain decomposition and why it helps when solving complex problems.
- Break a stated problem into meaningful sub-problems.
- Organise sub-problems into a clear hierarchy.
- Identify dependencies and information passed between parts of a solution.
- Explain how a sub-problem can lead to a program module, procedure or function.
- Evaluate whether a decomposition is clear, complete and appropriately detailed.
What Decomposition Does
Decomposition divides one large problem into smaller problems that can be considered separately. Each smaller part should contribute to the overall solution and should have a recognisable responsibility.
The result is usually hierarchical. The original problem appears at the top, major sub-problems form the next level, and any part that is still too broad can be divided again. Decomposition stops when each part is manageable enough for the next stage of design.
Why Decompose a Problem?
| Benefit | How decomposition provides it |
|---|---|
| Reduced complexity | Only one smaller responsibility needs to be considered at a time. |
| Clearer planning | Each part can be given its own requirements, inputs and expected outputs. |
| Easier testing | Individual parts can be checked before the complete solution is assembled. |
| Team development | Different people can work on separate parts when responsibilities and interfaces are clear. |
| Maintenance and reuse | A well-defined part can be replaced, improved or reused without redesigning everything else. |
A Practical Decomposition Process
A useful decomposition can be developed through five decisions.
- State the overall goal. Define the result the complete solution must achieve.
- Identify major responsibilities. Find the main tasks that must occur for the goal to be reached.
- Refine broad parts. Divide any sub-problem that still contains several distinct responsibilities.
- Define connections. Record what information each part needs, produces or receives from another part.
- Check the whole design. Confirm that the parts cover the complete problem without unnecessary overlap.
This process is not always completed in a single pass. Discovering a missing dependency may require a new sub-problem, while two overlapping parts may need to be combined.
Choosing Useful Sub-Problems
A good decomposition uses a suitable level of detail. Parts that are too broad do not reduce complexity enough, while parts that are too narrow may describe individual implementation steps rather than useful units of responsibility.
| Candidate part | Judgement | Reason |
|---|---|---|
| Manage the entire competition | Too broad | It still contains many unrelated responsibilities. |
| Calculate the current standings | Useful sub-problem | It has one clear purpose and produces a defined result. |
| Add three points to Team 4 | Too narrow | It is a possible processing step inside a wider standings calculation. |
A strong sub-problem normally has:
- a meaningful name based on what it accomplishes;
- one main responsibility;
- clear information entering and leaving it;
- limited overlap with other parts;
- a size that can be designed and tested independently.
Worked Example: School Robotics Competition System
A school needs a system to organise a one-day robotics competition. Teams must register, matches must be scheduled, scores must be recorded, standings must be calculated and information must be published for participants.
1. Identify the overall goal
Manage the competition from team registration to the publication of confirmed results.
2. Identify the major sub-problems
| Sub-problem | Responsibility | Main result |
|---|---|---|
| Team registration | Collect and validate team details | Approved team list |
| Match scheduling | Create fixtures that respect time and venue constraints | Competition timetable |
| Result capture | Record and confirm the score for each match | Confirmed match results |
| Standings calculation | Use confirmed results to update rankings | Ordered standings |
| Information publishing | Show schedules, notices and rankings to users | Current public display |
3. Refine one broad sub-problem
Match scheduling can be divided further:
- read the approved team list;
- read available arenas and time slots;
- generate candidate fixtures;
- detect team, arena or time clashes;
- resolve clashes and save the final timetable.
Dependencies and Information Flow
Sub-problems are easier to examine separately, but they are rarely isolated. A dependency exists when one part needs information or a result produced by another part. These connections must be identified so that the complete solution works correctly.
| Sub-problem | Information required | Information produced | Important dependency |
|---|---|---|---|
| Team registration | Submitted team details | Approved team list | None at the start |
| Match scheduling | Approved teams, arenas and time slots | Competition timetable | Requires registration to be complete |
| Result capture | Match identifier and entered scores | Confirmed result | The match must exist in the timetable |
| Standings calculation | Confirmed results | Ordered rankings | Uses output from result capture |
| Information publishing | Timetable, notices and rankings | Updated public information | Uses outputs from several other parts |
From Sub-Problems to Program Modules
During implementation, a clearly defined sub-problem can become a program module. A module groups the instructions and data handling needed for one part of the solution behind a clear interface. This page introduces the connection; complete procedure and function syntax is studied later in Unit 11.
| Concept | Introductory purpose | Competition example |
|---|---|---|
| Procedure | Groups instructions that perform a named task | Validate and store submitted team details |
| Function | Produces one value for use elsewhere in the solution | Return the points awarded for one confirmed result |
A good decomposition does not require every sub-problem to become exactly one module. A large sub-problem may need several modules, and a very small responsibility may be combined with another. The important idea is that the decomposition provides a logical starting structure for implementation.
Interactive: Decomposition Builder
Choose a scenario and work through the stages of decomposition. The visualiser shows how an overall goal becomes a hierarchy of connected sub-problems and then suggests possible program modules.
Common Mistakes and Misconceptions
- Confusing decomposition with abstraction. Decomposition divides the problem; abstraction filters detail.
- Using vague sub-problem names such as “process data” without stating the actual responsibility.
- Creating parts that overlap so heavily that responsibility is unclear.
- Making every individual instruction a separate sub-problem.
- Ignoring dependencies and assuming all parts can work without exchanging information.
- Writing full procedure or function code when the question only asks for a decomposition.
Practice
Try these questions
- Define decomposition and give one benefit.
- Explain why “build the whole booking system” is not a useful sub-problem.
- Decompose a school equipment-loan system into at least five major sub-problems.
- Choose one of your sub-problems and divide it into three smaller responsibilities.
- Identify two dependencies between your proposed parts.
- Suggest one sub-problem that could become a procedure and one that could become a function. Explain your choices.
- Explain the difference between decomposition and stepwise refinement.
Modularity: Organising a Solution into Parts
Decomposition helps identify the different parts of a problem. Modularity is the next step: organising those parts into independent units that can be designed, tested and maintained more easily.
A well-designed module should have one clear responsibility. It should receive the information it needs, perform its task, and provide a useful result or action for the rest of the program.
Example: Online Booking System
| Module | Responsibility |
|---|---|
| CheckAvailability | Determine whether spaces are available. |
| CalculatePrice | Calculate the cost based on booking information. |
| SendConfirmation | Send confirmation information to the user. |
Procedures and Functions
Modules can be implemented in different ways. Two common types are procedures and functions.
| Type | Purpose |
|---|---|
| Procedure | Performs an action. It may change data or produce an effect but does not return a value. |
| Function | Performs a task and returns a value that can be used elsewhere. |
For example, a module that displays a confirmation message would usually be a procedure. A module that calculates and returns a final price would usually be a function.
Common Misconceptions About Modularity
-
"More modules always mean a better design."
Too many small modules can make a system difficult to understand. Modules should be created when they represent meaningful responsibilities. -
"A module should never depend on another module."
Modules often need to exchange information. Good design means the dependency is clear and controlled. -
"A module is the same as one step in an algorithm."
A module usually represents a complete responsibility, not just one instruction. -
"Decomposition and modularity are identical."
Decomposition identifies smaller parts of a problem. Modularity organises those parts into reusable program components. -
"A function is always better than a procedure."
The choice depends on the purpose. If a task only performs an action, a procedure may be more suitable.
Review
| Question | Strong answer |
|---|---|
| What is decomposition? | Dividing a complex problem into smaller, manageable sub-problems. |
| What makes a useful sub-problem? | A clear responsibility, suitable size, meaningful name and defined information flow. |
| Why identify dependencies? | To show what one part needs from another and how the complete solution fits together. |
| How does decomposition relate to modules? | A defined sub-problem can guide the design of a self-contained program module. |
| When should decomposition stop? | When each part is manageable enough for the next design or implementation stage. |