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
BYVALUEandBYREF. - 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.
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 |
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
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.
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 |
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 |
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 |
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
Move Unchanging Work Outside a Loop
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.
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.
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 |
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
)
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.
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
Interactive: Efficient Module Refactoring Visualiser
Select a design problem and step through the changes that make the pseudocode clearer, more reusable or less wasteful.
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,BandDoIthide 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:
- Calculate the volume of a supplied box.
- Display a five-line session report.
- Test whether a supplied code is valid.
- 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
- Function: the caller needs one calculated volume.
- Procedure: the task performs several output actions.
- Boolean function: the returned value can be used in a condition.
- 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 |