Learn
8.1.8 | MAINTAINABLE CODE, IDENTIFIERS AND COMMENTS
01 | WORKING TODAY IS NOT THE WHOLE JOB
A ticket program works correctly in September. In October the price changes, and a new programmer must update it. If every variable is called a single letter and the price appears in several places, even a small change becomes difficult to check.
Maintenance means modifying a program after it has been created: correcting faults, adapting it to new requirements or improving it. Maintainable code is code organised and written so those changes can be understood and made more easily.
Correctness asks whether the program produces the required result. Maintainability asks how easily someone can understand and change it. A program can work yet be hard to maintain; tidy presentation alone does not prove correctness.
02 | START WITH A CONFUSING BUT WORKING EXAMPLE
Assume the user supplies a valid non-negative INTEGER quantity. This short program multiplies the quantity by a ticket price, but its names provide little help. What do A, B and C represent? Why is 4.50 used?
You can work out its purpose by tracing the instructions. That extra effort grows when a program has hundreds of lines. A future reader should not need to reverse-engineer every name before making a simple change.
DECLARE A : INTEGER DECLARE B : REAL DECLARE C : REAL OUTPUT "Enter ticket quantity" INPUT A B ← 4.50 C ← A * B OUTPUT "Total cost: ", C
03 | AN IDENTIFIER IS A NAME IN THE CODE
An identifier is a name used to refer to an item in a program, such as a variable, constant, array, procedure or function. A meaningful identifier describes what that item represents or does.
Quantity and TotalCost communicate more than A and C. Their names help a reader connect the instructions to the ticket scenario without changing the calculation.
A name should be specific enough to distinguish related values. Total could mean money, points or passengers. TotalCost is clearer when the program contains several totals.
| Unclear name | Clearer identifier | Meaning conveyed |
|---|---|---|
| A | TicketQuantity | Number of tickets requested |
| B | TicketPrice | Price of one ticket |
| C | TotalCost | Calculated cost of all tickets |
| DoThing | ShowReceipt | Procedure displaying a receipt |
| Calc | CalculateCost | Function producing a cost |
04 | MEANINGFUL AND VALID ARE DIFFERENT
A valid name follows the notation’s rules. A meaningful name communicates a useful role. X1 may follow the rules but still be unhelpful for a ticket cost.
Cambridge pseudocode uses Pascal case, such as TotalCost: joined words with initial capitals. Identifiers contain letters and digits, start with a capital letter, and do not use spaces, underscores or accented characters. Do not use a reserved keyword such as INPUT.
Cambridge treats identifier names as case insensitive: CountDown and Countdown must not represent separate variables. Use one consistent spelling.
Short names can be appropriate where a convention makes their role clear, such as X and Y coordinates. Avoid turning the advice into “every name must be long”. Choose clarity in context.
| Candidate | Assessment |
|---|---|
| TicketQuantity | Valid and meaningful |
| Ticket2Quantity | Valid; may suit a clearly defined role |
| 2TicketQuantity | Starts with a digit |
| Ticket Quantity | Contains a space |
| ticket_quantity | Contains an underscore; not this Cambridge convention |
| INPUT | Reserved keyword |
05 | NAME CONSTANTS AND COLLECTIONS TOO
A constant names a value fixed during execution. Naming TicketPrice explains the meaning of 4.50 and gives a clear place to change the rule before a later run.
An array stores several related values under one identifier. The coming lessons cover its syntax; for now, recognise why StudentNames is clearer than Data when the collection contains student names.
Good names also distinguish a single item from a collection. StudentName suggests one name; StudentNames suggests several. Consistency helps the reader make a useful initial interpretation.
CONSTANT TicketPrice ← 4.50 DECLARE TicketQuantity : INTEGER DECLARE TotalCost : REAL TotalCost ← TicketQuantity * TicketPrice
06 | WHAT A COMMENT DOES
A comment is explanatory text in the code that is not executed as a program instruction. It helps the reader understand purpose, reasoning or an important assumption.
Cambridge pseudocode begins a comment with two forward slashes, //. It continues to the end of that line. The program still executes the instructions before an inline comment.
A comment is not output to the user. OUTPUT "Enter quantity" is an executed instruction; // Ask for quantity is a note to the programmer.
// Calculate the cost using the current ticket price TotalCost ← TicketQuantity * TicketPrice OUTPUT TotalCost // Display the calculated cost
07 | COMMENT SYNTAX MUST MATCH THE LANGUAGE
Use the commenting feature provided by the language. In Cambridge pseudocode, each line of a multi-line comment begins with //. Normally place a comment before the code it describes, at the same indentation level. A short note can also appear at the end of a line.
Python commonly uses # for a line comment. JavaScript uses // and also supports block comments. These are language-specific features; do not assume a symbol from one language works everywhere.
The // shown inside a quoted STRING is text, not a comment marker. Quotation marks determine that the slash characters belong to the value being output.
// This function calculates ticket cost. // Quantity must already be a valid non-negative INTEGER. FUNCTION CalculateCost(Quantity : INTEGER, Price : REAL) RETURNS REAL RETURN Quantity * Price ENDFUNCTION OUTPUT "Use // for Cambridge pseudocode comments"
08 | EXPLAIN THE REASON OR NON-OBVIOUS RULE
A useful comment adds information the code does not already communicate clearly. “One extra box is needed only when items remain” explains the reason for a conditional extra box.
A note such as “Add one” beside BoxesNeeded ← BoxesNeeded + 1 merely repeats an obvious instruction. It may help a beginner while learning syntax, but a maintained program usually benefits more from the business rule behind the instruction.
Comments can also state assumptions: “Capacity must be positive” tells a reader a required input condition. That comment does not perform validation; code must carry out any check the program actually requires.
// Leftover items need another box; exact division needs no extra box.
IF MOD(Items, Capacity) <> 0
THEN
BoxesNeeded ← BoxesNeeded + 1
ENDIF09 | KEEP COMMENTS ACCURATE
A wrong comment can be more misleading than no comment. If the code accepts zero but a note says “Only positive values are accepted”, a maintainer may misunderstand which behaviour is intended.
When changing a rule, check its nearby comments, tests and documentation too. Do not describe a future intention as if it were already implemented.
Appropriate commenting means relevant and accurate explanation, not a comment on every line. Meaningful names communicate routine facts; comments explain assumptions, decisions or syntax that needs extra context.
10 | USE ROUTINES TO GIVE TASKS CLEAR BOUNDARIES
A procedure or function groups a coherent task under a meaningful name. A function CalculateCost receives the quantity and price and returns a cost. A procedure ShowReceipt displays the result.
This separates calculation from presentation. If the receipt wording changes, the calculation need not be rewritten. If the pricing calculation changes, there is one definition to inspect.
Splitting every single instruction into its own routine is not automatically clearer. Aim for tasks with a useful purpose, visible inputs and understandable outputs.
FUNCTION CalculateCost(Quantity : INTEGER, Price : REAL) RETURNS REAL RETURN Quantity * Price ENDFUNCTION PROCEDURE ShowReceipt(Cost : REAL) OUTPUT "Total cost: ", Cost ENDPROCEDURE
11 | SEE THE IMPROVED TICKET PROGRAM
This version preserves the original behaviour while making its roles explicit. Definitions come first; the main program receives input, calculates the cost and displays it.
The comment states the input assumption. It does not claim this program validates the quantity. The constant supplies the price, the function handles calculation and the procedure handles output.
With three tickets, both versions calculate 13.5. A clearer organisation should retain the required behaviour unless the task explicitly changes it.
FUNCTION CalculateCost(Quantity : INTEGER, Price : REAL) RETURNS REAL RETURN Quantity * Price ENDFUNCTION PROCEDURE ShowReceipt(Cost : REAL) OUTPUT "Total cost: ", Cost ENDPROCEDURE CONSTANT TicketPrice ← 4.50 DECLARE TicketQuantity : INTEGER DECLARE TotalCost : REAL // This example assumes a valid non-negative INTEGER quantity. OUTPUT "Enter ticket quantity" INPUT TicketQuantity TotalCost ← CalculateCost(TicketQuantity, TicketPrice) CALL ShowReceipt(TotalCost)
12 | COMPARE EDITS WITHOUT CHANGING THE RESULT
Choose which readability improvements to apply to a small calculation. Each version computes the same cost for three tickets. Notice how meaningful names and a named constant explain different parts of the task.
This is a fixed before-and-after illustration, not a pseudocode interpreter. Renaming must be applied consistently to every reference; inserting a helpful comment cannot fix a wrong calculation.
13 | CHANGE A PRICE AND CHECK THE BEHAVIOUR
Suppose the ticket price changes from 4.50 to 5.00. Update the named constant and check all callers using it. Do not change the quantity or rewrite the calculation just to alter one price rule.
For zero, one and three tickets, the new expected costs are zero, five and fifteen. Comparing these expected results with actual results helps detect an accidental change elsewhere.
Refactoring means improving a program’s internal structure while preserving its intended behaviour. Renaming A to TicketQuantity is a refactoring change; changing the price is a requirement change. Both still need appropriate checking.
| Quantity | Old price 4.50 | New price 5.00 |
|---|---|---|
| 0 | 0 | 0 |
| 1 | 4.5 | 5 |
| 3 | 13.5 | 15 |
14 | READABLE STRUCTURE SUPPORTS MAINTENANCE
Indentation shows which instructions belong inside a loop, selection branch or routine. Consistent layout makes it easier to spot a misplaced ENDIF or RETURN.
Use blank lines to separate related tasks and keep names consistent across definitions and calls. If you rename a function, update every call, not just its header.
Avoid unexplained repeated literal values, unnecessary global dependencies and routines that do many unrelated jobs. Each can make a small update require understanding more code than necessary.
These habits support the syllabus’s emphasis on meaningful identifiers, appropriate comments, procedures and functions. They improve maintainability alongside correctness checks.
15 | EXPLAIN THE BENEFIT IN CONTEXT
Instead of “good names are better”, write: “TicketQuantity identifies the number of tickets, therefore a maintainer can understand the multiplication without tracing an unexplained A.”
For a comment: “The note explains why a leftover needs an extra box, so a programmer updating the capacity rule can preserve the intended behaviour.” For a routine: “The calculation is defined once, therefore changes can be made in one place rather than in duplicated copies.”
Before finishing, check that the names are valid and meaningful, comments match the code, routine boundaries represent clear tasks and the required results remain correct. The next lesson introduces one-dimensional arrays.