AS & A Level Computer Science · Area 1 · AS Level content

Program development life cycle, design, testing and maintenance

A program is built in stages, and the model you choose for those stages has to fit the problem: fixed, well-understood requirements suit the waterfall, while requirements that will change need an iterative or RAD approach. This topic takes you through the five stages, the three life cycles the syllabus names, the design tools you are examined on (structure charts and state-transition diagrams), the three types of error and the testing that exposes them, and the maintenance that keeps a delivered system useful. Marks are lost by describing a model without saying when it suits a program, by drawing a flowchart where a structure chart was asked for, by writing test data with no expected result, and by giving a maintenance change the wrong label.

Not started

Syllabus coverage

  • The purpose of a program development life cycle
  • The need for different development life cycles depending on the program being developed, including waterfall, iterative and rapid application development (RAD)
  • The principles, benefits and drawbacks of the waterfall, iterative and RAD life cycles
  • The analysis, design, coding, testing and maintenance stages in the program development life cycle
  • The purpose of a structure chart: to decompose a problem into sub-tasks and to express the parameters passed between the modules, procedures and functions
  • Construct a structure chart for a given problem, and derive equivalent pseudocode from a structure chart
  • The purpose of state-transition diagrams to document an algorithm
  • Ways of exposing and avoiding faults in programs
  • The different types of error - syntax, logic and run-time - and how to locate, identify and correct them
  • The methods of testing available and the selection of appropriate data for a given method: dry run, walkthrough, white-box, black-box, integration, alpha, beta, acceptance and stub
  • The need for a test strategy and a test plan and their likely contents
  • Choosing appropriate test data for a test plan: normal, abnormal and extreme/boundary
  • The need for continuing maintenance of a system and the differences between perfective, adaptive and corrective maintenance
  • Analyse an existing program and make amendments to enhance functionality

Part of the AS & A Level Computer Science syllabus 9618.

Why a program needs a development life cycle

A program development life cycle is the set of stages a program passes through from the moment somebody recognises a problem to the moment the finished system is retired, together with the order those stages are carried out in. It is a framework for managing the work, not a way of writing code: it says what has to be produced at each stage, who reviews it, and what the next stage is allowed to assume.

Its first purpose is to make a large job controllable. A program of any size is too big to hold in one person's head, so the life cycle cuts it into stages, and each stage ends with something concrete that the next stage uses - a requirements specification, then a design, then working code, then a tested system, then a maintained system. Because each stage has a deliverable, progress can be measured, budgeted and reviewed, the client can agree what is being built before the expensive part starts, and several people can work on different parts without losing track of how they fit together.

Its second purpose is to catch faults early, because the cost of a fault rises steeply the later it is found. A misunderstood requirement corrected during analysis costs a sentence in a document. The same misunderstanding discovered after the system is in use costs a redesign, rewritten modules, a full retest and retraining of the users, and it may already have damaged data.

Every model in this topic contains the same five stages - analysis, design, coding, testing and maintenance - and the models differ in how often they go round them and in how much has to be finished before the next stage can start. The table below summarises what each stage does and what it hands on to the next one.

StageWhat happensWhat it produces
AnalysisThe current system and the problem are investigated; requirements are gathered from the client and the users; inputs, outputs, processing, data volumes and constraints are identifiedA requirements specification and success criteria, agreed with the client
DesignThe solution is planned before any code is written: the problem is decomposed into modules, each algorithm is designed, and the data, the interfaces and the tests are designedStructure charts, pseudocode, state-transition diagrams, data and screen designs, a test plan
CodingEach designed module is written in the chosen language, keeping to the design and to the team's coding standardsWorking modules, unit tested as they are written
TestingThe whole system is tested against the requirements with planned test data, and faults are recorded, fixed and retestedA fault log, test results and evidence that the specification has been met
MaintenanceThe delivered system is corrected, adapted and improved while it is in useNew versions of the system, with updated documentation
Examiners rarely want the stages listed. They ask what a stage produces, or why the same fault costs more to fix in maintenance than in analysis.

The waterfall model

The waterfall model carries out the stages in strict sequence. Analysis is completed, reviewed and signed off before design begins; design is completed and signed off before coding begins; and so on to testing and maintenance. The output of each stage is the input to the next, the client sees a working program only at the end, and going back to an earlier stage is treated as an exception rather than a normal part of the process.

Each stage produces documentation - the requirements specification, the design documents, the test plan, the user manual - and each stage has a milestone that management can check against a plan.

One detail is worth remembering because it explains a lot of the model's behaviour: the test plan is written during design, from the specification, before any code exists. Tests are therefore derived from what the system is supposed to do rather than from what the programmer built, so testing can find a missing requirement and not just a mistyped line.

  • Benefit - simple to manage: one stage at a time, with clear milestones and deliverables, so progress, cost and staffing are easy to plan and report.
  • Benefit - thorough documentation: every stage leaves a written record, which is what maintenance needs years later and what regulators and auditors demand for safety-critical systems.
  • Benefit - requirements settled first: because design starts only when the requirements are signed off, the design can be complete and consistent, and a fixed-price contract is possible.
  • Benefit - planned testing: the test plan is written from the specification, so every requirement has a test waiting for it.
  • Drawback - requirements must be right at the start: if the client cannot state them, or states them wrongly, the error is built in and carried through every later stage.
  • Drawback - no working software until late: the client cannot try anything until coding and testing are nearly finished, so misunderstandings surface when they are most expensive to fix.
  • Drawback - change is expensive: once a stage is signed off, a change means reopening it, and every later stage may have to be repeated.
  • Drawback - testing at the end: faults in the design are found only after all the code is written, and risk is concentrated in the last stage.
  • Drawback - unsuitable for unclear or interactive work: it fits a problem that is well understood and stable, not one whose requirements will emerge as users see the system.
If a question describes fixed, fully agreed requirements and a system that must be certified or audited, waterfall is the answer - and the reason is the documentation and sign-off, not that it is old-fashioned.

Iterative development and rapid application development

Iterative development goes round the stages more than once. Each iteration is a short pass through analysis, design, coding and testing that produces a working version of part of the system, which the users try. What they say feeds the next iteration, so the requirements are allowed to become sharper as the system grows.

An iteration can add a feature (incremental development) or refine an existing prototype (evolutionary development); either way the project delivers working software early and repeatedly instead of once.

Rapid application development (RAD) is the fastest form of this idea. A small team works closely with the users, often in workshops where the users sit with the developers and agree screens and reports on the spot, and it uses prototyping tools, reusable components and code generators so that a working prototype can be produced in a very short time and then refined. Work is timeboxed: each cycle has a fixed short deadline and delivers something usable, and features that do not fit are moved to a later cycle rather than the deadline being extended.

The benefits follow from the feedback. Working software appears early, so a misunderstanding is discovered in the first cycle rather than after delivery; the user tests real screens instead of reading a specification, which is far more reliable; change is expected, so it is cheap; and the highest-priority features can be delivered first. The drawbacks follow from the same speed.

Iterative work needs the user available throughout and able to make decisions, it invites scope creep as new requests appear in every cycle, and the overall design can drift if nobody takes responsibility for keeping the modules consistent. RAD adds its own limits: it needs skilled developers and good tools, it is a poor fit for very large or safety-critical systems where behaviour must be proved and documented, and speed can be bought by skimping on performance, robustness or documentation - which is then paid for in maintenance.

ModelHow the work is organisedBest suited toMain drawback
WaterfallOne pass through the stages, each completed and signed off before the next beginsRequirements fixed, well understood and unlikely to change; safety-critical or regulated systems; fixed-price contractsThe client sees nothing working until late, and change after sign-off is expensive
IterativeRepeated short cycles, each producing a working version that users try; requirements sharpen as the work goes onRequirements unclear or expected to change; medium to large systems built over several releasesNeeds continuing user involvement and discipline, or scope creep and an inconsistent design follow
RADVery short timeboxed cycles with users in workshops, prototypes, reusable components and code generatorsSmall to medium systems with an available, decisive user and a tight deadlineUnsuitable for large or safety-critical systems; documentation, performance and robustness can be sacrificed for speed
Choose the model from the characteristics of the project - how well the requirements are known, how likely they are to change, size, criticality, and whether the user can be involved - and say which characteristic decided it.

The analysis and design stages in detail

Analysis is about the problem, never the solution. It establishes what the current system does and what the new one must do: the inputs the system receives, the outputs it must produce, the processing in between, the volume of data, who uses the system and how often, and the constraints of hardware, software, money, law and time. The information is gathered by interviewing the client and the users, by questionnaires where there are many users, by watching people do the job, and by studying the documents, forms, reports and files the existing system produces.

If a program already exists, its code is read as evidence of the current rules. The stage ends with a requirements specification agreed with the client, plus success criteria that say how everyone will know the system works. A short feasibility check runs alongside it - whether the system is technically possible, affordable, legal, and worth doing compared with improving what already exists - because everything later is measured against this document, and an error here is the most expensive error in the whole life cycle.

Design plans the solution in enough detail that coding becomes translation rather than invention. It decides the module structure - the decomposition recorded in a structure chart - the logic of each module, written as pseudocode or a flowchart, and a state-transition diagram where the system's response depends on its current state. It also designs the data (variables, records, arrays, files or tables and their validation), the interface (input screens with validation and output reports), and the test plan with its test data.

Design is done on paper because paper is cheap: if you cannot write the pseudocode for a module, you do not yet understand the problem well enough to code it, and it is far easier to redraw a structure chart than to unpick 200 lines of code.

Coding turns each designed module into the chosen language, keeping to the design instead of inventing as you type. Good practice at this stage is what makes the program maintainable: meaningful identifiers, named constants rather than unexplained numbers, indentation that shows the structure, comments that explain why rather than what, one job per procedure or function, and unit testing each module as soon as it is written. Coding is usually the shortest of the five stages; the time saved by skipping design is spent several times over in debugging.

Analysis answers what the system must do; design answers how it will do it. An answer that starts proposing screens, files or code during analysis has confused the two stages.

Structure charts: decomposing a problem and passing parameters

A structure chart records the design of a program as a hierarchy of modules. The top box is the main program, the boxes below it are the sub-tasks it calls, and the boxes below those are the sub-tasks of those sub-tasks, down to modules small enough to be written as a single procedure or function. Each box is labelled with what the module does, as a verb phrase such as CalculateAverage or ValidateMark, and each line joins a module to the one that calls it.

The arrows on the lines are the important part: they are labelled with the data that passes between the modules, so the chart shows the parameters as well as the structure.

Its purpose is top-down design, also called decomposition. A problem that is too big to solve is broken into sub-tasks, each sub-task is broken again if it is still too big, and the work is finished when every remaining task is small enough to write and test on its own. That gives three practical advantages: different programmers can take different modules, each module can be unit tested separately, and a module can later be rewritten or replaced without disturbing the rest, provided the parameters on its arrows stay the same.

A structure chart is not a flowchart. It shows what the parts of the program are and which module calls which; it does not show the order in which instructions run, decisions, loops or the code inside a module. Those belong in pseudocode or a flowchart for that module, and a chart that tries to show the sequence of events has stopped being a structure chart.

To build one, start with a single box for the whole task and write the sub-tasks the main program must carry out underneath it. For each sub-task ask whether it can be written as one procedure; if not, decompose it again one level down. Then work through every line and decide what data passes along it - what the module needs from the module that calls it (input parameters, arrow pointing down) and what it sends back (a returned value, or an updated variable passed by reference, arrow pointing up).

A value that only tells a module which of several jobs to do, such as a flag or a menu choice, is a control parameter. Every arrow must end up as a parameter in the header of the derived procedure or function, and a module with no arrows takes no parameters.

  • PROCEDURE ProcessStudentMarks()
  • NumberOfStudents <- GetStudentCount()
  • Marks <- InputMarks(NumberOfStudents)
  • Average <- CalculateAverage(Marks, NumberOfStudents)
  • Grade <- AssignGrade(Average)
  • CALL DisplayReport(Average, Grade)
  • ENDPROCEDURE
  • FUNCTION ValidateMark(Mark : INTEGER) RETURNS BOOLEAN
  • IF Mark >= 0 AND Mark <= 100 THEN RETURN TRUE ELSE RETURN FALSE
  • ENDFUNCTION
LevelModuleCalled byParameters passed
0ProcessStudentMarksnothing - the main programnone
1GetStudentCountProcessStudentMarksdown: none; up: NumberOfStudents
1InputMarksProcessStudentMarksdown: NumberOfStudents; up: Marks
2ValidateMarkInputMarksdown: Mark; up: IsValid
1CalculateAverageProcessStudentMarksdown: Marks, NumberOfStudents; up: Average
1AssignGradeProcessStudentMarksdown: Average; up: Grade
1DisplayReportProcessStudentMarksdown: Average, Grade; up: none
Deriving pseudocode is mechanical if the chart is right: one box becomes one procedure or function, every down arrow becomes a parameter, every up arrow becomes a return value, and the parent module's body is just calls to its children.

State-transition diagrams

A state-transition diagram documents an algorithm whose next action depends on the state the system is currently in. It shows every state the system can be in, drawn as a circle labelled with what is true in that state, and every event or input that moves it from one state to another, drawn as an arrow labelled with that event. Where an action or output happens on the way, it is written on the arrow as well, so the diagram records state, event and response together.

The diagram is used for event-driven systems: a vending machine, a cash machine, a lift, a ticket barrier, a traffic light sequence, a washing machine program, a network protocol, or the menu and game states of an application. In all of these the same input means different things at different times - pressing the coin return is valid while money is held and meaningless when the machine is idle - and that is exactly what a state-transition diagram makes explicit. It also shows which events are illegal in each state, which is where a great many bugs live.

A flowchart is a poor substitute here. A flowchart traces one run through a program from start to finish; a state-transition diagram shows all the states at once and the moves between them, including moves back to an earlier state. For a system that waits for events and can return to where it started, the state diagram is both a better design document and a ready-made source of test cases: every arrow is a transition that has to be tested, including the ones that should be refused.

Current stateEventNext stateOutput or action
Idle20p coin inserted20p creditnone
Idle50p coin insertedDispensingdispense item, no change
20p credit20p coin inserted40p creditnone
20p credit50p coin insertedDispensingdispense item, return 30p change
40p credit20p coin insertedDispensingdispense item, no change
20p creditcoin return pressedIdlereturn 20p
40p creditcoin return pressedIdlereturn 40p
Dispensingitem takenIdlenone
If the same input can be accepted in one state and rejected in another, the algorithm is state-dependent and a state-transition diagram is the right document for it.

Errors: finding them, fixing them, avoiding them

A syntax error breaks the grammar of the language, so the translator cannot turn the source into an executable at all. A missing ENDIF, an unbalanced bracket, a mistyped keyword, a comma where a semicolon belongs or a call with the wrong number of arguments will stop the compile, and the translator reports the line - sometimes the line after the real mistake, because that is where the error only becomes obvious. Syntax errors are the easy ones: they are found every time the program is translated, and they are found before it runs.

A logic error is a program that runs to completion and produces the wrong answer. The condition uses < where it needed <=, so the loop runs one time too few; the total adds when it should multiply; the average divides by the wrong counter; the wrong variable is displayed. Nothing in the language forbids any of it, so the translator is silent and the fault is exposed only by comparing the output with the expected result - in testing, in a dry run with a trace table, or in a walkthrough of the code.

A run-time error happens while the program is running, and only when a particular instruction is reached with particular data: dividing by zero, indexing an array outside its bounds, opening a file that is not there, converting text that is not a number, or recursing until the stack overflows. The program usually halts with an error, which is why a fault that never showed in testing can appear the first week the system is used - the test data never took that path.

Errors are exposed by testing with data chosen to reach the awkward paths, by dry running the algorithm with a trace table before it is ever coded, by structured walkthroughs in which colleagues read the code aloud and question it, by a debugger with breakpoints, single stepping and watched variables, by temporary output statements, and by unit testing each module as it is written rather than saving everything for the end. They are avoided earlier and more cheaply: design the module before coding it, use structured code with one job per module, choose meaningful identifiers and named constants, declare variables with the right types, validate every input, check for zero, empty and out-of-range values before dividing or indexing, handle exceptions where a failure is possible, review each other's code, and test as you go. Correcting a fault means fixing its cause rather than the symptom, then rerunning the whole test plan, because a fix in one module is a favourite way of breaking another.

  • Syntax: found by the translator at compile time; the program cannot run until every one is fixed.
  • Logic: found only by comparing output with the expected result - testing, dry run, walkthrough, trace table.
  • Run-time: found only when the offending instruction executes with the offending data; hard to reproduce, so record the exact input that triggered it.
  • Expose: planned test data, dry run, walkthrough or code review, debugger, unit tests, regression tests.
  • Avoid: design first, modular structured code, meaningful names and constants, validation, bounds and zero checks, exception handling, peer review.
Name the error by what went wrong and when it is detected. 'The program crashes' is a symptom; a run-time error with the input that triggers it earns the mark.

Testing: the methods, the plan and the data

Testing is not one activity but a family of them, and the mark usually comes from saying who does it and what it can find. A dry run is a person working through the pseudocode or code by hand, recording every variable in a trace table, with no computer involved: it finds logic errors while the design is still on paper. A walkthrough is a structured review in which the programmer presents the code to colleagues who step through it and challenge it; it finds faults the author cannot see and spreads knowledge of the code.

White-box testing is done with knowledge of the code and aims to execute every statement, branch and path, so coverage can be measured. Black-box testing ignores the code entirely and tests inputs against the expected outputs from the specification, which is why it can find a requirement that was never implemented. Integration testing joins modules together and tests the joins, looking for faults in the parameters passed between them, and a stub is a dummy module that stands in for one not yet written, returning fixed values so that the module that calls it can be tested - the standard tool of top-down integration testing.

The last three methods move outward to the customer. Alpha testing is carried out in-house, by the developers and their own testers, in controlled conditions before release. Beta testing releases the near-final software to real users outside the organisation, who use it on their own hardware and report faults; it finds what no laboratory can, because the variety of machines, data and habits of real users cannot be simulated.

Acceptance testing is the client testing the system against the requirements specification to decide whether it is fit for purpose and can be accepted - and paid for - and it is normally done with the client's own data.

A test strategy is the overall approach: what will be tested, at which stage, by whom, with which methods, how much coverage is enough, what counts as a pass, how faults are logged and closed, and what must be true before testing starts and before the system is released. A test plan is the document that applies the strategy to one system or one phase. It lists the features to be tested and the order they will be tested in, the test data for each test, the expected result for each test, and space to record the actual result, whether it passed, who ran it, when, and what was done about any failure.

Both are needed because unplanned testing is not repeatable: without a written plan nobody can prove what has been tested, the same tests are not rerun after a change, and the tests that are left out are always the awkward ones.

Test data is chosen deliberately, not invented as you go. Normal data is typical valid data that the system should accept and process correctly. Abnormal data is invalid data that the system should reject - wrong type, wrong sign, impossible value, missing value - and it tests the validation rather than the calculation.

Extreme or boundary data is the data at the edges of the acceptable range, and one step outside it, because faults collect at boundaries: a field that accepts 11 to 18 should be tested with 11 and 18 (accepted), and with 10 and 19 (rejected). For every item of data the plan states the expected result, so that a failure is a disagreement between two written statements rather than an opinion.

MethodWhat happensWhat it is good at finding
Dry runA person works through the algorithm by hand with a trace table, no computerLogic errors, while the design is still on paper
WalkthroughThe programmer presents the code to colleagues, who step through and question itLogic and design faults, poor structure, missing cases
White-boxTests are designed from the code to execute every statement, branch and pathUnreachable code, untested paths, faults in conditions and loops
Black-boxTests are designed from the specification, with no knowledge of the codeMissing or wrong functionality, validation faults
IntegrationModules are tested together as they are combined into larger unitsFaults in the interfaces - wrong parameters, wrong order, wrong type
StubA dummy module replaces one that is not yet written and returns fixed valuesLets a calling module be tested before its subordinates exist (top-down integration)
AlphaIn-house testing by developers and internal testers before releaseFaults in controlled conditions, with the developers on hand
BetaNear-final software released to real users outside the organisationFaults caused by real hardware, real data and real user behaviour
AcceptanceThe client tests the system against the requirements specification with their own dataWhether the system is fit for purpose and can be accepted
The distinction is the mark: white-box knows the code, black-box does not; alpha is in-house, beta is real users; integration tests the joins; a stub stands in for a module that does not exist yet.

Maintenance, and changing a program that already works

Maintenance is everything that happens to a system after it is delivered. It is needed because a system lives for years while the world around it does not stand still: users find faults that testing missed, the organisation changes what it wants, the hardware, operating system or file formats are replaced, and the law or tax rules change. Maintenance usually lasts far longer than development and accounts for the largest share of the total cost of a system over its life, which is why the documentation produced in the earlier stages matters so much - a change cannot be made safely in code nobody can read.

There are three types, and they are told apart by why the change is made: corrective maintenance fixes a fault - a calculation that is wrong, a report that crashes on a particular customer, a validation rule that lets through a value it should reject. Adaptive maintenance changes the system because something outside it has changed: a new version of the operating system, replacement hardware, a new file format, a change in the law such as a new rate of tax, or moving the system to a network. Perfective maintenance improves a system that is already working: a faster search, a clearer screen, an extra report the users have asked for, or the code tidied up so that future changes are easier.

The awkward cases are decided by cause, not by effort: adding a report the users requested is perfective, because nothing was wrong and nothing outside changed, while changing the program because the government altered the tax rate is adaptive, because the program was correct for the old rule. A program that crashes when a customer's name contains an apostrophe needs corrective maintenance, however small the fix. Getting the label wrong loses the mark even when the example is sensible.

Enhancing an existing program - the practical skill in this section - follows the same discipline in miniature. Read the documentation and the code until you can say which modules are involved; identify the interfaces, because the parameters on the structure chart tell you what a module may safely be given and what it must return; plan the smallest change that does the job instead of rewriting what works; keep to the existing style and naming; update the structure chart, pseudocode, test plan and user documentation; add test data for the new behaviour; and then rerun the whole existing test plan, not just the new tests, because a change in one module is the commonest way of breaking another. Keep a copy of the working version before you start, so that a failed change can be undone.

  • Corrective: the system is wrong - fix the fault, retest, update the version.
  • Adaptive: the environment changed - new platform, new law, new format; the program was right before.
  • Perfective: the system works - make it faster, clearer or more capable.
  • Before amending: back up, read the design and code, find the modules and interfaces, plan the minimum change.
  • After amending: update the design documents, test plan and user guide, then rerun every existing test as well as the new ones.
Classify maintenance by its cause: something was wrong (corrective), something outside changed (adaptive), or something working is being improved (perfective).

Key terms you must be able to define

Program development life cycle
The stages a program passes through from recognising the problem to retiring the system, and the order in which they are carried out - analysis, design, coding, testing and maintenance. Its purpose is to make development planned, reviewable and costed, and to find faults as early as possible.
Waterfall model
A life cycle in which each stage is completed, reviewed and signed off before the next begins, so the output of one stage is the input to the next. It suits fixed, well-understood requirements and produces heavy documentation, but the client sees no working software until late and change after sign-off is expensive.
Iterative development
A life cycle built from repeated short cycles, each passing through analysis, design, coding and testing to produce a working version that users try. Feedback from each iteration shapes the next, so requirements can sharpen as the system grows and change is absorbed rather than resisted.
Rapid application development (RAD)
A fast, iterative approach in which a small team works closely with users in workshops, using prototypes, reusable components and code generators in short timeboxed cycles. It delivers working software quickly but needs an available, decisive user and is unsuitable for very large or safety-critical systems.
Structure chart
A design diagram showing a program as a hierarchy of modules, with each box a module that will become a procedure or function, lines showing which module calls which, and labelled arrows showing the parameters passed between them. It records the decomposition of the problem, not the order in which instructions run.
State-transition diagram
A diagram showing every state a system can be in as a circle, and every event that moves it from one state to another as a labelled arrow, with any output or action written on the arrow. It documents the behaviour of an event-driven algorithm whose response depends on its current state.
Syntax error
A fault that breaks the grammar of the programming language, so the translator cannot produce an executable - a missing ENDIF, an unbalanced bracket, a mistyped keyword. It is detected at translation, before the program can run.
Logic error
A fault in the reasoning of the program, so that it runs to completion but gives the wrong output - a < used instead of <=, a wrong formula, the wrong variable displayed. It is not detected by the translator and is found by testing against expected results, by a dry run or by a walkthrough.
Run-time error
A fault that occurs while the program is executing, when a particular instruction is reached with particular data - division by zero, an array index out of range, a missing file. It usually halts the program and may only appear with data that testing never used.
White-box testing
Testing designed with knowledge of the internal code, aiming to execute every statement, branch and path so that coverage can be measured. Also called structural testing, and normally carried out by the developer.
Black-box testing
Testing designed from the specification with no knowledge of the code, feeding inputs in and comparing the outputs with the expected results. It can therefore detect a requirement that was never implemented, and it can be done by an independent tester.
Corrective maintenance
Maintenance that fixes a fault discovered after the system is in use - a wrong calculation, a crash with a particular record, a validation rule that accepts invalid data. The system was wrong and is being made right.
Adaptive maintenance
Maintenance carried out because something outside the system has changed - a new operating system, new hardware, a new file format, or a change in the law such as a new tax rate. The system was correct for the old environment and is changed to fit the new one.
Perfective maintenance
Maintenance that improves a system which already works - making it faster, using less memory, improving the interface, adding a feature users have asked for, or tidying the code to make future changes easier. Nothing was broken and nothing outside changed.

Applied to real systems

9618 sets its questions inside systems you already use - a phone, a school network, a supermarket till, a website, a bank. These show how to apply the theory to a context you have not seen before, then you write your own.

Waterfall where the requirements really are fixed: certified airborne software

Software in civil aircraft is developed to standards such as RTCA DO-178C, which require a documented requirement behind every piece of code, a design traceable to those requirements, and test evidence for each one. That traceability pulls development towards a sequential, document-heavy process: requirements and design are agreed and reviewed before code is written, because the certification evidence has to show what the software was supposed to do and prove that it does it. It is the clearest real case of the waterfall assumption holding - the requirements can be known and fixed before coding starts.

Iterative development with real users: Minecraft in alpha and beta

Minecraft was sold to the public while still in alpha and beta between 2009 and 2011, and each update was shaped by what players reported and asked for. That is iterative development with beta testing built into it: a working version is released, real users run it on their own machines, and the feedback feeds the next cycle. It shows the strength - thousands of users find faults and unpopular features before the final release - and the weakness, that the design is decided as it goes, which only works because the program stays small enough to change quickly.

A state-transition diagram in a real protocol: the TCP connection

The behaviour of a TCP connection is documented in RFC 793 as a state-transition diagram, with states such as LISTEN, SYN-SENT, ESTABLISHED, FIN-WAIT and TIME-WAIT and arrows for the events - a segment arriving, the application closing the connection - that move the connection between them. The diagram is used because the correct response to an arriving segment depends entirely on the current state: the same segment is valid in one state and an error in another. It is a good reminder that a state-transition diagram documents behaviour over time, which is what an event-driven program needs and what a flowchart cannot show.

The cost of an unhandled run-time error: Ariane 5 flight 501

In June 1996 the first Ariane 5 launcher broke up shortly after lift-off. The failure came from software reused from Ariane 4: a value that had always fitted in a 16-bit integer on the earlier rocket did not fit on Ariane 5, and the conversion raised an operand error. That error was not handled because the designers had no reason to expect it on that path, so the inertial reference systems shut down and the launcher was lost. It is the standard case for teaching that a run-time error can sit in a path nobody tested, and that software reused in a new environment has to be retested in that environment.

Testing that was not independent enough: the Therac-25

The Therac-25 radiotherapy machine was involved in a series of overdoses in the mid-1980s, several of them fatal. The faults were in the control software: under particular sequences of keystrokes a race condition let the machine fire in a configuration the operator had not selected, and the hardware interlocks that would have stopped it had been removed on the assumption that the software made them unnecessary. The case is used to show why software controlling a physical process needs planned testing of unusual sequences of events, and why removing a safety check because the software handles it is a maintenance decision with consequences.

Flashcards

Click a card to flip it. Mark honestly — the tracker uses this.

Q1What is a program development life cycle, and what are its five stages?
The stages a program passes through from recognising a problem to retiring the system, and their order. Analysis defines the problem and produces a requirements specification; design plans the solution as structure charts, pseudocode, state-transition diagrams, data and interface designs and a test plan; coding writes each module in the chosen language; testing checks the system against the specification with planned test data; maintenance corrects, adapts and improves the system while it is in use. Its purpose is to make the work planned and reviewable and to find faults as early as possible, because a fault costs more the later it is found.
Q2How does the waterfall model work, and what are its main benefit and drawback?
Stages run in strict sequence: each is completed, reviewed and signed off before the next begins, and the output of one stage is the input to the next. The test plan is written during design from the specification, and the client sees working software only at the end. Benefit: simple to manage, with clear milestones, thorough documentation and requirements settled before design - which is why it suits fixed-requirement, safety-critical or certified systems. Drawback: if the requirements are wrong or change, the error is carried through every stage, and change after sign-off is expensive.
Q3How does iterative development work, and what does it need to succeed?
The project is built from repeated short cycles, each passing through analysis, design, coding and testing to produce a working version that users try; what they say shapes the next cycle, so requirements sharpen as the system grows. It delivers working software early, absorbs change cheaply, spreads risk and lets the most important features go first. It needs the user available throughout and someone keeping the overall design consistent, or scope creep and an inconsistent design follow.
Q4What is RAD, when is it appropriate, and what is its main limitation?
Rapid application development: a fast iterative approach using a small team, users in workshops agreeing screens and reports directly, prototypes, reusable components and code generators, in short timeboxed cycles that each deliver something usable. Appropriate for small to medium systems with an available, decisive user and a tight deadline. Limitation: unsuitable for very large or safety-critical systems, and speed can be bought by sacrificing performance, robustness and documentation, which is then paid for in maintenance.
Q5What is a structure chart for, what does it show, and how do you derive pseudocode from one?
It records the design as a hierarchy of modules: one box per module, labelled with what it does, lines showing which module calls which, and labelled arrows showing the parameters passed - data going down to a module and values returned up to its caller. Its purpose is top-down decomposition: break the problem into sub-tasks until each module can be written and tested as a single procedure or function. It does not show the order of execution, decisions or loops. To derive pseudocode, one box becomes one procedure or function, each down arrow becomes a parameter in its header, each up arrow becomes a return value (a function) or a parameter passed by reference, and a parent module's body is just calls to its children in the order they must happen.
Q6What is a state-transition diagram for, and what does it show?
It documents an algorithm whose response depends on the state the system is currently in: each state is a circle labelled with what is true in it, and each event that moves the system between states is an arrow labelled with that event, plus any output or action. It is used for event-driven systems - vending machines, cash machines, lifts, ticket barriers, traffic lights, protocols - because it shows which inputs are valid in each state, including the illegal ones. Every arrow is a transition that must be tested.
Q7Distinguish syntax, logic and run-time errors, and say how each is detected.
Syntax: breaks the grammar of the language, so the translator cannot produce code (missing ENDIF, unbalanced bracket, mistyped keyword) - detected at compile time with a line number. Logic: valid code that produces the wrong result (a < instead of <=, wrong formula) - the program runs, so it is found only by testing against expected results, a dry run or a walkthrough. Run-time: occurs while running, with particular data (division by zero, index out of range, missing file), and halts the program - it may appear only with data the tests never used.
Q8What is the difference between a dry run and a walkthrough?
A dry run is one person executing the algorithm by hand with no computer, recording every variable in a trace table step by step and comparing the final output with the expected output; it can be done on the design before code exists and it finds logic errors. A walkthrough is a structured review in which the programmer presents the code or design to colleagues, who step through it, question it and look for faults; it finds faults the author cannot see and spreads knowledge of the code.
Q9Distinguish white-box and black-box testing, and say where integration testing and a stub fit.
White-box (structural) testing uses knowledge of the code and aims to execute every statement, branch and path, so coverage can be measured; it is done by the developer. Black-box (functional) testing ignores the code and feeds inputs in, comparing outputs with the specification, so it can find a missing requirement and can be done independently. Integration testing joins modules and tests the interfaces between them, and a stub is a dummy module returning fixed values that stands in for one not yet written, so the calling module can be tested in top-down integration.
Q10Distinguish alpha, beta and acceptance testing.
Alpha: in-house testing by the developers and internal testers in controlled conditions before release. Beta: the near-final version is released to real users outside the organisation, who use it on their own hardware and data and report faults - the only way to find problems caused by real machines, data and habits. Acceptance: the client tests the system against the requirements specification with their own data to decide whether it is fit for purpose and can be accepted.
Q11What is the difference between a test strategy and a test plan, and what test data must a plan contain?
A test strategy is the overall approach: what is tested, at which stage, by whom, with which methods, how much coverage is enough, what counts as a pass, and how faults are logged and closed. A test plan applies it to one system: the features to test and their order, the test data for each test, the expected result, and space to record the actual result, pass or fail, tester, date and action taken. The data must include normal data (typical and valid), abnormal data (invalid, to test rejection) and extreme or boundary data (the exact limits and one step outside them).
Q12Name and distinguish the three types of maintenance, and say what a change to an existing program requires.
Corrective: fixes a fault found after release. Adaptive: changes the system because something outside it changed - new operating system, hardware, file format, or a change in the law. Perfective: improves a system that already works - faster, clearer, a requested new feature, tidier code. Any change means backing up first, reading the design and code to find the modules and their interfaces, making the smallest change that works, keeping the existing style, updating the design documents, test plan and user guide, and then rerunning the whole existing test plan as well as the new tests.
0 of 12 marked as known

Exam-style questions

8 questions, 29 marks. Write your answer, then reveal the mark scheme and tick each point you actually made. Answering honestly here is what makes the rest of the site useful.

StateAO11 mark
State what is meant by a program development life cycle.

Mark scheme — tick each point you actually made

Examiner tip: One mark, one sentence. You need both halves - the stages and the order - and naming the five stages without saying that it is a staged, ordered process is not the definition.
ExplainAO23 marks
A chemical company is replacing the software that controls the automatic safety shut-down of its plant. The requirements have been agreed in full with the company and with the safety regulator, and they cannot be changed. Explain why the waterfall model is suitable for developing this software.

Mark scheme — tick each point you actually made

Examiner tip: Take the two facts the question gives you - fixed requirements and a regulator - and turn each into a reason. A general description of the waterfall (stages in order, one at a time) is not an explanation of why it suits this project.
DescribeAO14 marks
Describe the purpose of a structure chart and how it records the design of a program. Include in your answer what a structure chart does not show.

Mark scheme — tick each point you actually made

Examiner tip: The last mark is the one most often thrown away: candidates describe the chart but never say what it leaves out. Finish with the contrast against a flowchart.
ExplainAO24 marks
A program has been written to calculate the average mark of a class. Explain how a syntax error, a logic error and a run-time error could each occur in this program, and state how each would be detected.

Mark scheme — tick each point you actually made

Examiner tip: Each type needs a mechanism and a detection method. Three definitions with no example, or three examples with no statement of how each is found, will not reach four marks.
DescribeAO14 marks
Describe the contents of a test plan.

Mark scheme — tick each point you actually made

Examiner tip: A test plan is a document, so list what is written in it. 'Testing everything carefully' is not a content point, and a plan with tests but no expected results cannot show a failure.
ExplainAO24 marks
An order form will only accept a quantity between 1 and 50 inclusive. Explain, with examples, how you would choose normal, abnormal and extreme data to test the validation of this field.

Mark scheme — tick each point you actually made

Examiner tip: Give a value and its expected outcome for every type, and make the boundary values exact. 'Test with valid and invalid data' earns nothing; 'test 50 and 51 to check the condition uses <= and not <' earns the mark.
ExplainAO13 marks
Explain the difference between corrective, adaptive and perfective maintenance, giving one example of each.

Mark scheme — tick each point you actually made

Examiner tip: One sentence per type, each with a cause and an example. The examples must match the type: a requested extra report is perfective, not adaptive, and a wrong total is corrective, not perfective.
EvaluateAO36 marks
A small chain of garden centres wants a stock-control and ordering system. The manager can give up two afternoons a week to work with the developers, is not sure exactly what reports are needed, and wants the system running before the busy spring season in three months. The stock data will be migrated from paper records. Evaluate whether rapid application development or the waterfall model should be used, and justify your recommendation.

Mark scheme — tick each point you actually made

Examiner tip: An evaluate answer must use the facts of the scenario, admit the weakness of the model you recommend, and end with a clear judgement. Describing RAD and waterfall in general terms, with no reference to the manager's afternoons, the unclear reports or the spring deadline, cannot reach the top band.

Exam technique for this topic

  • For a question about choosing a life cycle, answer with the characteristics of the project - how well the requirements are known, how likely they are to change, the size and complexity, how critical correctness is, whether the user can be involved, and how tight the deadline is - then say which model those characteristics point to. Defining the model earns nothing.
  • In a structure chart question, count the modules and the parameter lists. Every box must become one procedure or function and every arrow must become a parameter, so if you are asked to derive pseudocode and your headers do not match the chart, the answer is wrong somewhere. Never draw a flowchart when a structure chart is asked for: a structure chart shows the hierarchy, not the order of execution.
  • For testing methods, always give the distinction rather than the definition: who carries it out, whether the tester sees the code, and what it can therefore find. White-box and black-box, alpha and beta, integration and unit testing, and the stub are the pairs that are most often confused.
  • In any test data question, write the value and the expected outcome together, label each item normal, abnormal or extreme/boundary, and always include the exact boundary values and one value just outside them. Test data with no expected result is not a test.
  • For maintenance, classify by cause and say why: was the system wrong (corrective), did something outside it change (adaptive), or is a working system being improved (perfective)? A good answer adds that every change means updating the documentation and rerunning the whole test plan, not just the new tests.

Why students lose marks here

A student wroteA student wrote: 'A logic error is when the program will not run because the programmer has typed the code incorrectly.'
Why it loses marksThat describes a syntax error. A logic error does not stop the program at all - the translator accepts it and the program runs happily and produces the wrong answer, which is why it is the hardest type to find.
The answer that scoresA syntax error breaks the rules of the language, so the translator cannot produce code and reports the fault at compile time - a missing ENDIF, an unbalanced bracket, a mistyped keyword. A logic error is valid code that does the wrong thing: it uses < where it needed <=, so a loop runs one iteration too few, or it adds where it should multiply. The program runs to completion and gives an incorrect result, so the fault is found by comparing output with the expected result, by a dry run with a trace table, or by a walkthrough - never by the translator. A run-time error is the third type: the code is valid and the logic may be right, but when a particular instruction executes with particular data, such as a division by zero or an array index out of range, the program halts.
A student wroteA student wrote: 'Before testing the program on a computer, we did a dry run, which means running the program slowly and watching each line.'
Why it loses marksA dry run involves no computer at all. The whole point is that a person executes the algorithm by hand and records the values, which can be done on the design before any code exists.
The answer that scoresA dry run is a person working through the pseudocode or code by hand, keeping a trace table with a column for each variable and a row for each step, writing down the value of every variable each time it changes, and comparing the final output with the expected output. No computer is used, so it can be done on the design before the program exists and it exposes logic errors early. Running the program slowly, or stepping through it in a debugger, is a different technique: the computer is executing the code and you are watching the values it produces.
A student wroteA student wrote: 'A structure chart shows the order in which the program carries out its steps, starting at the top and working down.'
Why it loses marksA structure chart shows hierarchy, not sequence. Reading it top to bottom tells you which module calls which, not what happens first at run time, and it contains no decisions or loops at all.
The answer that scoresA structure chart shows the solution decomposed into a hierarchy of modules: the main program at the top, the sub-tasks it calls below it, and their sub-tasks below them, with each box labelled with what that module does. The lines show calls, and the labelled arrows show the parameters passed - data passed down to a module and values returned up to the module that called it. It does not show the order in which instructions execute, and it contains no selection or iteration. The order of execution and the decisions belong in pseudocode or a flowchart for each individual module, which is why the two diagrams are used together, not instead of one another.
A student wroteA student wrote: 'Beta testing is when the developers test the finished program in their own office before it is released, and alpha testing is when customers try it.'
Why it loses marksThe two have been swapped. Alpha is the in-house testing; beta is the release to real users outside the organisation. Only beta can find faults that depend on the user's own hardware, data and habits.
The answer that scoresAlpha testing is carried out in-house by the developers and their own testers before release, in controlled conditions where the people who wrote the code are available to investigate anything that goes wrong. Beta testing releases the near-final version to real users outside the organisation, who use it on their own hardware with their own data and report the faults they find; it is the only way to discover problems caused by the variety of machines, configurations and patterns of use in the real world. Acceptance testing comes after both: the client tests the system against the requirements specification to decide whether it can be accepted.
A student wroteA student wrote: 'Perfective maintenance is when the programmers fix the errors that users report after the system has gone live.'
Why it loses marksThat is corrective maintenance. Perfective maintenance is work on a system that is already correct - making it better, not making it right.
The answer that scoresCorrective maintenance fixes a fault that has been found in use: a calculation that gives the wrong total, a report that crashes on one customer's record, a validation rule that lets through an impossible date. Perfective maintenance improves a system that is working as specified: making a search faster, using less memory, redesigning a screen that users find confusing, adding a report they have asked for, or restructuring the code so that future changes are easier. Adaptive maintenance is the third type and is caused from outside the system - a new operating system, replacement hardware, a new file format, or a change in the law such as a new tax rate. The test is to ask why the change is being made: something was wrong, something outside changed, or something working is being made better.