A-Level Computer Science / Unit 11: Structured Programming

11.3.4 Passing Parameters and Writing Efficient Modules

πŸ”’ Lesson slides are available to signed-in users. Sign in

11.3.4 Passing Parameters and Writing Efficient Modules

A program is not efficient merely because it produces the correct output. Its design should also avoid unnecessary work, repeated code, unclear data dependencies and subroutines that perform several unrelated tasks.

Procedures, functions and parameters allow a larger algorithm to be divided into modules with clear responsibilities. A well-designed interface states what data enters a module, what result leaves it and which caller variables a procedure is permitted to change.

By the end of this section, you should be able to:

  • Explain what efficient pseudocode means in a modular program.
  • Choose appropriately between a procedure and a function.
  • Classify parameters according to their role in a module.
  • Choose between BYVALUE and BYREF.
  • Explain why unnecessary reference parameters should be avoided.
  • Reduce dependence on global variables.
  • Use local variables for temporary processing.
  • Remove repeated blocks by creating reusable subroutines.
  • Avoid recalculating the same function result.
  • Move loop-invariant work outside repetition.
  • Validate data at a suitable module boundary.
  • Give each module one clear responsibility.
  • Design interfaces with meaningful names and suitable types.
  • Combine procedures and functions into a complete modular algorithm.
  • Test individual modules before testing the whole program.
When asked why pseudocode is efficient, identify a specific design feature: reduced duplication, fewer repeated calculations, suitable control structures, clear interfaces or limited use of global state.

What Does Efficient Pseudocode Mean?

Efficiency includes the amount of processing performed, but it also concerns how clearly and reliably the algorithm is organised.

Aspect Efficient design Less effective design
Processing Performs each required calculation at an appropriate time Repeats calculations whose inputs have not changed
Code reuse Places repeated behaviour in one reusable module Copies the same statements into several locations
Data flow Passes required data through clear interfaces Depends on hidden global variables
Parameter modes Uses reference parameters only for deliberate caller updates Allows every parameter to modify caller state
Modularity Gives each module one coherent task Creates long subroutines with unrelated responsibilities
Control structures Uses structures that match the problem Uses unnecessary counters, branches or nesting
Testing Allows individual modules to be tested separately Requires the entire program to run for every test
Common misconception: fewer lines do not automatically mean greater efficiency. Very compressed pseudocode may perform unnecessary work or be difficult to understand and test.

Choose the Correct Type of Subroutine

Question Suitable design
Does the caller need one calculated or selected value? Use a function
Does the module mainly perform an action? Use a procedure
Must several caller variables be deliberately updated? Use a procedure with carefully selected reference parameters
Does the module display a report or menu? Usually use a procedure
Does the module test a condition? Consider a function returning BOOLEAN

Function: produce one value

FUNCTION CalculateCharge(
    EnergyUsed : REAL,
    RatePerUnit : REAL
) RETURNS REAL

    RETURN EnergyUsed * RatePerUnit
ENDFUNCTION

Procedure: perform an output task

PROCEDURE DisplayCharge(
    BayNumber : INTEGER,
    Charge : REAL
)
    OUTPUT "Bay ", BayNumber, ": $", Charge
ENDPROCEDURE
Do not choose a procedure merely because it can perform a calculation. Choose a function when the calculated value belongs naturally inside the caller’s expression.

Identify the Role of Each Interface Item

Before writing a subroutine header, decide what each item of data is meant to do.

Data role Description Likely design
Input-only data The subroutine reads the value but should not change caller state Value parameter
Caller value to update The procedure must change a variable belonging to the caller Reference parameter
Single calculated result The caller requires one value from the module Function return value
Temporary calculation Needed only while the module executes Local variable
Fixed program-wide value Does not change during execution Named constant

Example classification

PROCEDURE UpdateTotals(
    BYVALUE SessionEnergy : REAL,
    BYVALUE SessionCost : REAL,
    BYREF TotalEnergy : REAL,
    BYREF TotalRevenue : REAL
)
Parameter Role Reason for mode
SessionEnergy Input for the current session The procedure only reads it
SessionCost Input for the current session The procedure only reads it
TotalEnergy Accumulated caller value The procedure must update it
TotalRevenue Accumulated caller value The procedure must update it

Choose Parameter Passing Deliberately

Passing mode should communicate the intended relationship between the module and its caller.

Input-only value

PROCEDURE DisplayStock(
    BYVALUE ProductName : STRING,
    BYVALUE StockLevel : INTEGER
)
    OUTPUT ProductName, ": ", StockLevel
ENDPROCEDURE

The procedure should not alter either caller value, so both parameters are passed by value.

Deliberate caller update

PROCEDURE RecordDelivery(
    BYREF StockLevel : INTEGER,
    BYVALUE Delivered : INTEGER
)
    StockLevel ← StockLevel + Delivered
ENDPROCEDURE

StockLevel is passed by reference because the purpose of the procedure includes changing the caller’s stock variable.

A useful explanation is: β€œThe parameter is passed by reference because the procedure must update the caller’s variable, and the changed value is needed after the call.”

Do Not Use BYREF Without a Reason

Over-permissive interface

PROCEDURE DisplayItem(
    BYREF ItemName : STRING,
    BYREF Quantity : INTEGER
)
    OUTPUT ItemName, ": ", Quantity
ENDPROCEDURE

The procedure only reads the values. Reference passing gives it unnecessary permission to change both caller variables.

Clearer interface

PROCEDURE DisplayItem(
    BYVALUE ItemName : STRING,
    BYVALUE Quantity : INTEGER
)
    OUTPUT ItemName, ": ", Quantity
ENDPROCEDURE
Problem caused by unnecessary BYREF Why it matters
Unexpected caller changes A later edit to the procedure might alter data unintentionally
Less clear interface The caller cannot easily see which variables are intended outputs
Harder testing More caller state must be checked after every call
Fewer valid arguments Literals and calculated expressions cannot act as writable caller variables
Common mistake: reference passing is not automatically more efficient merely because it avoids describing a value as a copy. At this level, choose the mode according to whether caller state should be changed.

Avoid Hidden Dependence on Global Variables

A global variable can be accessed from several parts of a program. This may make a module depend on data that is not visible in its interface.

Hidden dependencies

FUNCTION CalculateCharge() RETURNS REAL
    RETURN GlobalEnergyUsed * GlobalRate
ENDFUNCTION

The header does not reveal that the function needs two global values.

Clear dependency through parameters

FUNCTION CalculateCharge(
    EnergyUsed : REAL,
    RatePerUnit : REAL
) RETURNS REAL

    RETURN EnergyUsed * RatePerUnit
ENDFUNCTION
Feature Global dependency Parameter-based module
Required data visible in header? No Yes
Easy to test with different values? Requires global state to be changed Arguments can be supplied directly
Risk of unexpected changes? Higher Reduced
Reusable in another program? Depends on matching globals Depends only on its stated interface
Explain that parameters make dependencies explicit. The caller can see which values a module requires without examining its internal statements.

Use Local Variables for Temporary Processing

FUNCTION CalculateAverage(
    Total : REAL,
    Count : INTEGER
) RETURNS REAL

    DECLARE Average : REAL

    Average ← Total / Count

    RETURN Average
ENDFUNCTION

Average is needed only while the function calculates its result. It should therefore be local to the function.

Data Best location Reason
Temporary intermediate result Local variable Used only by one call
Input supplied by caller Parameter Part of the module interface
Single result required by caller Return value Leaves a function through its interface
Caller total deliberately updated Reference parameter Must remain changed after the procedure
Do not create a global variable merely so that a function can expose an intermediate value. Return the required result and keep temporary data local.

Remove Duplicated Code

Repeated statements

OUTPUT "Bay 1"
OUTPUT "Energy used: ", Bay1Energy
OUTPUT "Charge: $", Bay1Charge

OUTPUT "Bay 2"
OUTPUT "Energy used: ", Bay2Energy
OUTPUT "Charge: $", Bay2Charge

OUTPUT "Bay 3"
OUTPUT "Energy used: ", Bay3Energy
OUTPUT "Charge: $", Bay3Charge

Reusable procedure

PROCEDURE DisplayBaySummary(
    BayNumber : INTEGER,
    EnergyUsed : REAL,
    Charge : REAL
)
    OUTPUT "Bay ", BayNumber
    OUTPUT "Energy used: ", EnergyUsed
    OUTPUT "Charge: $", Charge
ENDPROCEDURE

CALL DisplayBaySummary(1, Bay1Energy, Bay1Charge)
CALL DisplayBaySummary(2, Bay2Energy, Bay2Charge)
CALL DisplayBaySummary(3, Bay3Energy, Bay3Charge)
Benefit Effect
One definition Formatting changes are made in one place
Meaningful calls The main program shows its intention clearly
Consistent behaviour Every call follows the same output format
Simpler testing The report procedure can be checked independently

Store and Reuse Function Results

Repeated function calls

IF CalculateCharge(EnergyUsed, Rate) > 15
THEN
    OUTPUT "High charge: $",
           CalculateCharge(EnergyUsed, Rate)
ENDIF

The same function may perform the same multiplication twice.

Calculate once

Charge ← CalculateCharge(EnergyUsed, Rate)

IF Charge > 15
THEN
    OUTPUT "High charge: $", Charge
ENDIF
Stored result: a function result assigned to a variable so that it can be reused without repeating the call.
Repeating a function call may be necessary when its arguments or relevant program state have changed. Store the result when the same value is needed several times without such a change.

Move Unchanging Work Outside a Loop

Loop-invariant calculation: a calculation whose result does not change between iterations.

Repeated unnecessarily

FOR SessionNumber ← 1 TO SessionCount
    RateInDollars ← RateInCents / 100

    INPUT EnergyUsed

    Charge ← EnergyUsed * RateInDollars
NEXT SessionNumber

Improved placement

RateInDollars ← RateInCents / 100

FOR SessionNumber ← 1 TO SessionCount
    INPUT EnergyUsed

    Charge ← EnergyUsed * RateInDollars
NEXT SessionNumber

The rate does not change while the sessions are processed, so the conversion should occur once before the loop.

Before moving a statement, confirm that none of the values used by its expression change inside the loop.

Validate Data at a Suitable Boundary

A module should receive data that satisfies its stated assumptions. Validation can be performed before the call or by a dedicated validation function.

Boolean validation function

FUNCTION IsValidEnergy(
    EnergyUsed : REAL
) RETURNS BOOLEAN

    RETURN EnergyUsed > 0
       AND EnergyUsed <= 40
ENDFUNCTION

Caller validates before processing

REPEAT
    OUTPUT "Enter energy used from 0.1 to 40: "
    INPUT EnergyUsed
UNTIL IsValidEnergy(EnergyUsed) = TRUE

Charge ← CalculateCharge(EnergyUsed, Rate)

CalculateCharge can now focus on its calculation rather than mixing calculation, keyboard input, validation and error messages.

Common design problem: repeating the same validation logic in several modules increases duplication and may lead to inconsistent rules.

Give Each Module One Clear Responsibility

Procedure with mixed responsibilities

PROCEDURE ProcessSession()
    INPUT EnergyUsed

    WHILE EnergyUsed <= 0 OR EnergyUsed > 40 DO
        INPUT EnergyUsed
    ENDWHILE

    Charge ← EnergyUsed * GlobalRate
    TotalRevenue ← TotalRevenue + Charge

    OUTPUT "Charge: $", Charge
ENDPROCEDURE

This procedure obtains input, validates it, performs a calculation, modifies a global total and produces output.

Separated responsibilities

FUNCTION IsValidEnergy(EnergyUsed : REAL)
    RETURNS BOOLEAN

FUNCTION CalculateCharge(
    EnergyUsed : REAL,
    Rate : REAL
) RETURNS REAL

PROCEDURE UpdateTotals(
    BYVALUE EnergyUsed : REAL,
    BYVALUE Charge : REAL,
    BYREF TotalEnergy : REAL,
    BYREF TotalRevenue : REAL
)

PROCEDURE DisplaySession(
    BYVALUE SessionNumber : INTEGER,
    BYVALUE EnergyUsed : REAL,
    BYVALUE Charge : REAL
)
Module Single responsibility
IsValidEnergy Test one energy value
CalculateCharge Calculate one session charge
UpdateTotals Update the two caller accumulators
DisplaySession Display one session summary
Main program Coordinate input, validation and module calls
Single responsibility: a module should have one clear reason to be used or changed.

Design Clear and Minimal Interfaces

Interface principle Application
Use meaningful identifiers EnergyUsed is clearer than E
Declare suitable data types Use REAL for measured energy and calculated cost
Include only required data Do not pass a session name to a calculation that does not use it
Use a logical parameter order Place related inputs together and keep the order consistent
Limit reference parameters Mark only intended caller updates as BYREF
Return one natural function result A charge function returns the calculated charge

Unclear interface

PROCEDURE DoIt(
    BYREF A : REAL,
    BYREF B : REAL,
    BYREF C : REAL,
    BYREF D : INTEGER
)

Clearer interface

PROCEDURE UpdateTotals(
    BYVALUE SessionEnergy : REAL,
    BYVALUE SessionCharge : REAL,
    BYREF TotalEnergy : REAL,
    BYREF TotalRevenue : REAL
)
An efficient interface should reveal what the module needs and what it may change without requiring the reader to inspect its full body.

Allow Modules to Cooperate Through Clear Data Flow

EnergyIsValid ← IsValidEnergy(EnergyUsed)

Charge ← CalculateCharge(EnergyUsed, Rate)

CALL UpdateTotals(
    EnergyUsed,
    Charge,
    TotalEnergy,
    TotalRevenue
)

CALL DisplaySession(
    SessionNumber,
    EnergyUsed,
    Charge
)
Data Produced by Used by
EnergyIsValid IsValidEnergy Input-validation loop
Charge CalculateCharge UpdateTotals and DisplaySession
TotalEnergy Main-program initialisation Updated through UpdateTotals
TotalRevenue Main-program initialisation Updated through UpdateTotals

Each module communicates through arguments, parameters, return values and deliberate reference updates rather than relying on hidden state.

Test Modules Independently

Small modules can be tested with focused inputs before they are integrated into the complete algorithm.

Testing a function

Call Expected result Purpose
IsValidEnergy(0) FALSE Below valid range
IsValidEnergy(0.1) TRUE Lower valid boundary
IsValidEnergy(40) TRUE Upper valid boundary
IsValidEnergy(40.1) FALSE Above valid range

Testing a procedure with reference parameters

TestEnergy ← 10
TestRevenue ← 5

CALL UpdateTotals(
    3.5,
    1.75,
    TestEnergy,
    TestRevenue
)

OUTPUT TestEnergy
OUTPUT TestRevenue

The expected caller values are 13.5 and 6.75.

Tests for a module should follow its interface. Supply known arguments, record the returned value or changed reference variables, and compare the result with the expected outcome.

Worked Example: Modular Charging-Station Report

A charging station processes between one and six charging sessions. For each session, it validates the energy used, calculates the charge, classifies the session, updates totals and displays a summary.

Constants and functions

CONSTANT RATE_PER_UNIT = 0.42

FUNCTION IsValidEnergy(
    EnergyUsed : REAL
) RETURNS BOOLEAN

    RETURN EnergyUsed > 0
       AND EnergyUsed <= 40
ENDFUNCTION

FUNCTION CalculateCharge(
    EnergyUsed : REAL,
    RatePerUnit : REAL
) RETURNS REAL

    RETURN EnergyUsed * RatePerUnit
ENDFUNCTION

FUNCTION GetUsageBand(
    EnergyUsed : REAL
) RETURNS STRING

    IF EnergyUsed <= 8
    THEN
        RETURN "Light"
    ELSE
        IF EnergyUsed <= 22
        THEN
            RETURN "Standard"
        ELSE
            RETURN "Heavy"
        ENDIF
    ENDIF
ENDFUNCTION

Procedures

PROCEDURE UpdateTotals(
    BYVALUE SessionEnergy : REAL,
    BYVALUE SessionCharge : REAL,
    BYREF TotalEnergy : REAL,
    BYREF TotalRevenue : REAL
)
    TotalEnergy ← TotalEnergy + SessionEnergy
    TotalRevenue ← TotalRevenue + SessionCharge
ENDPROCEDURE

PROCEDURE DisplaySession(
    BYVALUE SessionNumber : INTEGER,
    BYVALUE EnergyUsed : REAL,
    BYVALUE Charge : REAL,
    BYVALUE UsageBand : STRING
)
    OUTPUT "Session ", SessionNumber
    OUTPUT "Energy: ", EnergyUsed
    OUTPUT "Charge: $", Charge
    OUTPUT "Usage band: ", UsageBand
ENDPROCEDURE

Main program

DECLARE SessionCount : INTEGER
DECLARE SessionNumber : INTEGER
DECLARE EnergyUsed : REAL
DECLARE Charge : REAL
DECLARE UsageBand : STRING
DECLARE TotalEnergy : REAL
DECLARE TotalRevenue : REAL
DECLARE AverageEnergy : REAL

REPEAT
    OUTPUT "Enter the number of sessions from 1 to 6: "
    INPUT SessionCount
UNTIL SessionCount >= 1 AND SessionCount <= 6

TotalEnergy ← 0
TotalRevenue ← 0

FOR SessionNumber ← 1 TO SessionCount
    REPEAT
        OUTPUT "Enter energy used for session ",
               SessionNumber, ": "
        INPUT EnergyUsed
    UNTIL IsValidEnergy(EnergyUsed) = TRUE

    Charge ← CalculateCharge(
                 EnergyUsed,
                 RATE_PER_UNIT
             )

    UsageBand ← GetUsageBand(EnergyUsed)

    CALL UpdateTotals(
        EnergyUsed,
        Charge,
        TotalEnergy,
        TotalRevenue
    )

    CALL DisplaySession(
        SessionNumber,
        EnergyUsed,
        Charge,
        UsageBand
    )
NEXT SessionNumber

AverageEnergy ← TotalEnergy / SessionCount

OUTPUT "Total energy: ", TotalEnergy
OUTPUT "Average energy: ", AverageEnergy
OUTPUT "Total revenue: $", TotalRevenue

Why the design is efficient

Design decision Reason
RATE_PER_UNIT is a constant The fixed rate is named once and cannot be changed accidentally
IsValidEnergy returns a Boolean The validity rule is written once and reused by the loop
CalculateCharge is a function It produces one numeric value for the caller
The charge result is stored The calculation is not repeated for totals and output
GetUsageBand is separate Classification is independent of calculation and output
Session values use BYVALUE The procedures only need to read them
Totals use BYREF The procedure deliberately updates caller accumulators
Temporary session variables are local to the main flow No unnecessary global dependencies are introduced
Each module has one responsibility Modules can be understood and tested separately

Partial trace

Suppose two sessions use 6 units and 25 units.

Session Energy Charge at $0.42 Band Total energy Total revenue
1 6 $2.52 Light 6 $2.52
2 25 $10.50 Heavy 31 $13.02
AverageEnergy ← 31 / 2
AverageEnergy ← 15.5
When analysing a modular solution, explain both the behaviour of each module and the data transferred through its interface.

Interactive: Efficient Module Refactoring Visualiser

Select a design problem and step through the changes that make the pseudocode clearer, more reusable or less wasteful.

Before refactoring

Repeated output blocks

OUTPUT "Bay 1"
OUTPUT Bay1Energy
OUTPUT Bay1Charge

OUTPUT "Bay 2"
OUTPUT Bay2Energy
OUTPUT Bay2Charge
Repeated blocks 2
After refactoring

Reusable display procedure

CALL DisplayBaySummary(
    1,
    Bay1Energy,
    Bay1Charge
)

CALL DisplayBaySummary(
    2,
    Bay2Energy,
    Bay2Charge
)
Procedure definitions 1
Identify behaviour that is repeated with different data.
Step 1: identify the duplicated responsibility.
For each scenario, identify the original design problem, the refactoring decision and the specific improvement produced.

Common Mistakes and Misconceptions

  • Equating fewer lines with efficiency: compressed code may still repeat calculations or hide dependencies.
  • Using a procedure when one value is required: a function may express the result more clearly.
  • Using a function mainly to alter global variables: return the natural result through the function interface.
  • Passing every procedure parameter by reference: only deliberate caller outputs should normally use BYREF.
  • Using BYREF for input-only data: this grants unnecessary permission to alter caller state.
  • Depending on global variables: required data becomes hidden from the interface.
  • Creating global temporary variables: intermediate calculations should normally be local.
  • Copying repeated code: corrections must then be made in several locations.
  • Calling the same function repeatedly: store its result when the arguments have not changed.
  • Moving changing calculations outside loops: only loop-invariant work should be moved.
  • Mixing validation, calculation, updating and output in one large module.
  • Passing data that the module never uses: unnecessary parameters make an interface harder to understand.
  • Using vague identifiers: names such as A, B and DoIt hide intent.
  • Testing only the complete program: errors are harder to isolate when individual modules have not been checked.

Practice

Question 1: choose procedure or function

Choose and justify the better design:

  1. Calculate the volume of a supplied box.
  2. Display a five-line session report.
  3. Test whether a supplied code is valid.
  4. Update two caller totals.

Question 2: choose parameter modes

PROCEDURE AddSale(
    SaleValue : REAL,
    SaleCount : INTEGER,
    RevenueTotal : REAL
)

The procedure reads SaleValue and must update SaleCount and RevenueTotal. Rewrite the header using suitable passing modes.

Question 3: remove unnecessary BYREF

PROCEDURE ShowResult(
    BYREF Name : STRING,
    BYREF Score : INTEGER
)
    OUTPUT Name, ": ", Score
ENDPROCEDURE

Rewrite the interface and explain the improvement.

Question 4: remove a global dependency

FUNCTION CalculateTax() RETURNS REAL
    RETURN GlobalPrice * GlobalTaxRate
ENDFUNCTION

Rewrite the function with a clearer interface.

Question 5: remove duplication

OUTPUT "Sensor A"
OUTPUT SensorAValue
OUTPUT SensorAStatus

OUTPUT "Sensor B"
OUTPUT SensorBValue
OUTPUT SensorBStatus

Create and use a suitable procedure.

Question 6: store a function result

IF CalculateDeliveryCost(Mass, Distance) > 25
THEN
    OUTPUT CalculateDeliveryCost(Mass, Distance)
ENDIF

Rewrite the pseudocode so that the function is called once.

Question 7: loop-invariant calculation

FOR Item ← 1 TO ItemCount
    ConversionRate ← 1000 / 60
    ConvertedReading ← Reading[Item] * ConversionRate
NEXT Item

Improve the placement of the fixed calculation.

Question 8: separate responsibilities

A single procedure obtains a temperature, validates it, classifies it, updates a warning total and displays a report. Suggest a more modular design.

Question 9: interface review

PROCEDURE Process(
    BYREF A : REAL,
    BYREF B : REAL,
    BYREF C : STRING
)

The procedure receives an energy value and rate, then displays a status. It does not update caller data. Suggest a clearer name, parameter names and passing modes.

Question 10: trace reference totals

PROCEDURE UpdateTotals(
    BYVALUE Amount : REAL,
    BYREF Total : REAL,
    BYREF Count : INTEGER
)
    Total ← Total + Amount
    Count ← Count + 1
ENDPROCEDURE

RunningTotal ← 12.5
ItemCount ← 3

CALL UpdateTotals(
    4.75,
    RunningTotal,
    ItemCount
)

State the final values of RunningTotal and ItemCount.

Question 11: explain efficiency

Explain three ways in which modules with clear interfaces can improve a large algorithm.

Question 12: design a modular solution

A program receives several delivery masses. It must validate each mass, calculate a delivery cost, classify the delivery, update total mass and total revenue, and display a summary for each delivery.

Propose suitable procedures, functions, parameters and passing modes.

Show suggested answers

Question 1

  1. Function: the caller needs one calculated volume.
  2. Procedure: the task performs several output actions.
  3. Boolean function: the returned value can be used in a condition.
  4. Procedure: selected reference parameters can update both caller totals.

Question 2

PROCEDURE AddSale(
    BYVALUE SaleValue : REAL,
    BYREF SaleCount : INTEGER,
    BYREF RevenueTotal : REAL
)

Question 3

PROCEDURE ShowResult(
    BYVALUE Name : STRING,
    BYVALUE Score : INTEGER
)

The procedure only reads the values, so reference passing is unnecessary. The revised interface makes it clear that caller variables will not be changed.

Question 4

FUNCTION CalculateTax(
    Price : REAL,
    TaxRate : REAL
) RETURNS REAL

    RETURN Price * TaxRate
ENDFUNCTION

Question 5

PROCEDURE DisplaySensor(
    SensorName : STRING,
    SensorValue : REAL,
    SensorStatus : STRING
)
    OUTPUT SensorName
    OUTPUT SensorValue
    OUTPUT SensorStatus
ENDPROCEDURE

CALL DisplaySensor(
    "Sensor A",
    SensorAValue,
    SensorAStatus
)

CALL DisplaySensor(
    "Sensor B",
    SensorBValue,
    SensorBStatus
)

Question 6

DeliveryCost ← CalculateDeliveryCost(
                   Mass,
                   Distance
               )

IF DeliveryCost > 25
THEN
    OUTPUT DeliveryCost
ENDIF

Question 7

ConversionRate ← 1000 / 60

FOR Item ← 1 TO ItemCount
    ConvertedReading ← Reading[Item] * ConversionRate
NEXT Item

Question 8

One possible design is:

  • IsValidTemperature: Boolean function that tests a value.
  • GetTemperatureBand: function returning the classification.
  • UpdateWarningCount: procedure with the count passed by reference.
  • DisplayTemperatureReport: procedure using value parameters.
  • Main program: coordinates input, validation and calls.

Question 9

PROCEDURE DisplayEnergyStatus(
    BYVALUE EnergyUsed : REAL,
    BYVALUE RatePerUnit : REAL,
    BYVALUE Status : STRING
)

A stronger design might calculate the cost in a separate function and pass the completed cost to the display procedure.

Question 10

RunningTotal ← 12.5 + 4.75
RunningTotal ← 17.25

ItemCount ← 3 + 1
ItemCount ← 4

Question 11

Suitable explanations include:

  • required data is visible in module headers;
  • modules can be tested independently;
  • repeated behaviour is defined once;
  • changes are limited to the responsible module;
  • meaningful calls make the main algorithm easier to read;
  • limited reference passing reduces unexpected caller changes.

Question 12

One possible module design is:

  • IsValidMass(Mass): Boolean function.
  • CalculateDeliveryCost(Mass, Rate): real-valued function.
  • GetDeliveryBand(Mass): string-valued function.
  • UpdateDeliveryTotals: receives the current mass and cost by value and updates total mass and total revenue by reference.
  • DisplayDelivery: receives all report values by value.
  • Main program: validates the delivery count, controls the loop and coordinates the calls.

Review

Design decision Efficient approach
One calculated result Use a function and return the value
Action without a direct result Use a procedure
Input-only parameter Pass by value
Caller variable deliberately updated Pass by reference
Temporary processing data Use a local variable
Repeated code block Create one reusable module
Repeated identical function result Store the result and reuse it
Calculation unchanged across iterations Move it before the loop
Hidden global dependency Pass required data through the interface
Large mixed-purpose module Separate coherent responsibilities
Final exam tip: efficient modular pseudocode makes data movement visible, performs necessary work at the correct time, avoids duplication and gives each procedure or function a clear responsibility.