All A Level 22 60 min read 10 question quiz 19 exam marks

The Programming Project (NEA)

How the independent project is judged, and a worked example of every stage: analysis with measurable success criteria, design before code, a working solution built in small tested steps, unit tests, and an evaluation that argues from evidence.

What the project rewards

The programming project is non exam assessment: you choose a real problem, solve it by writing a program, and document the whole process. It is worth 20 per cent of both the OCR (H446) and AQA (7517) A Levels. Check your own board's current specification for the exact mark allocation, but every board marks the same five stages.

StageA top mark answer showsThe usual weakness
AnalysisA clear problem, real stakeholders who were consulted, research into existing solutions, and success criteria that can be measuredA description of the program instead of the problem
DesignThe problem decomposed, algorithms and data structures chosen and explained, interfaces drawn, and a test plan written before codingDesign drawn after the code was finished
DevelopmentA solution built in stages, with evidence of each, in code that is modular, validated, annotated and makes use of appropriate techniquesOne long program, with no record of how it grew
TestingA systematic test plan run against the solution, with evidence, and faults found and fixed, shownTesting that only shows the program working
EvaluationEach success criterion judged against evidence, stakeholder feedback, limitations stated honestly, and improvements suggested"It works well and I am happy with it"

Choosing the project

The project is marked on the technical difficulty of what you build as well as on how well you document it. A good project:

  • has a real user who will tell you what they need and tell you if you got it right
  • needs more than a form that saves to a file. Look for a real algorithm or data structure: a graph, a tree, a queue, a recursive solution, a database with several linked tables, a simulation
  • is small enough to finish. A working, tested solution to a modest problem beats an unfinished plan for a huge one
Do not borrow the solution

Using code you did not write is allowed only if it is clearly identified, and the marks are for your own work. A library such as sqlite3 is a tool. A tutorial program with the names changed is plagiarism, and the boards check.

Keeping the evidence

The documentation is not an extra written afterwards. It is made as you go.

HabitWhy
A project diary, dated, of what you did, what went wrong and how you fixed itIt becomes the evidence of iterative development, and it is the best source for the evaluation
Screenshots with annotations, after each stageMarks cannot be given for work that is not shown
Version control, with small commits and clear messagesA history of the code, and a way back from a mistake
Backups in two placesA lost project cannot be marked
A time plan that you revisitThe project has a deadline and you do not control it
The five stages of the programming project, with the evidence each one needsThe programming project runs through five stages. Analysis: the problem and who it is for, research into similar solutions, requirements and success criteria, and the limits and scope. Design: breaking the problem into parts, algorithms and data structures, screens and usability, and a test plan with test data. Development: building in small steps, annotated code as evidence, testing as you go and recording each change. Testing: running the test plan with normal, boundary and erroneous data, keeping tables and screenshots as evidence, and fixing and retesting. Evaluation: judging the work against each success criterion, feedback from the users, what works and what does not, and improvements and maintenance. An arrow shows that testing leads back to development to iterate. Keep your evidence as you go, because the evidence is what earns the marks.Analysis1the problem andwho it is forresearch intosimilar solutionsrequirements andsuccess criterialimits and scopeDesign2break the probleminto partsalgorithms anddata structuresscreens andusabilitya test plan withtest dataDevelopment3build it in smallstepsannotated code asevidencetest as you gorecord eachchangeTesting4run the test plannormal, boundaryand erroneousdatatables andscreenshots asevidencefix, then retestEvaluation5judge againsteach successcriterionfeedback from theuserswhat works, andwhat does notimprovements andmaintenanceiterate: test, then go back and improveKeep your evidence as you go. The evidence is what earns the marks.
  1. Analysis, design, development, testing and evaluation, in that order.
  2. Each stage has its own evidence.
  3. Testing leads back to development, so the project iterates.
  4. Collect the evidence as you work, not at the end.
Success criteria written at the analysis stage are what you test and evaluate against at the end.

Analysis and design: a worked brief

A worked example runs through the rest of this topic, a program that is small enough to read in full but has the features a real project needs. The problem is revision: students forget what they have learned, and revise by re reading, which does not help them remember.

Analysis

The problem. A student revising for several exams wants to practise recalling facts, and to spend time on the facts they are most likely to forget, instead of the ones they already know.

Stakeholders. Students revising for A Levels, who use the program, and a teacher who may recommend it. A questionnaire to twenty students, and an interview with a teacher, would give the requirements. It matters to write down what they said and what you decided as a result.

Research. Paper flashcards have no memory of which cards are hard. Some apps use spaced repetition: the better you know a card, the longer until it is shown again. The Leitner system does it with boxes. A new card is in box 1. Answer it correctly and it moves up a box, wrong and it returns to box 1. The higher the box, the longer the gap before it is due again.

Success criteria. These are the heart of the analysis, because the evaluation will judge the finished program against each one. A good criterion is measurable: someone else can test it and agree whether it was met.

No.Success criterion
S1A card with a question and an answer can be added. A blank question or answer, or a question already in the deck, is refused with a clear message
S2A card answered correctly moves up one box, to a maximum of box 5, and is next due after 1, 2, 4, 8 or 16 days for boxes 1 to 5
S3A card answered wrongly goes back to box 1 and is due the next day
S4Only the cards due today are offered for review, with the lowest boxes first
S5The cards survive closing the program
S6A summary shows how many cards are in each box

Compare "the program should be easy to use", which no one can say they have measured, with S2, which can be checked in a minute.

Design

Decomposition. Break the problem into parts that can be built and tested separately.

Structure diagram for the projectA structure diagram for the flashcard program. The whole program is split into three modules. main.py starts the program and runs the menu loop. ui.py asks the user, checks input and shows results. deck.py holds the rules of the boxes and the database, with add, due and record. main.py calls ui.py, and ui.py calls deck.py, which stores the data in a card table in SQLite. A fourth file, tests.py, uses unittest to test deck.py against the test plan.Decomposing the flashcard program into modulesFlashcard programthe whole solutionmain.pystarts the program,runs the menu loopui.pyasks the user, checksinput, shows resultsdeck.pythe box rules and thedatabase: add, due, recordcallscallscard tableSQLitestorestests.pyunittest, from the test plantestsEach part has one job and can be built, run and tested on its own.
A decomposition shows the marker how the problem was broken down before any code was written.

Data. Cards are stored in a database table, so they survive (S5) and can be searched by due date.

ColumnTypeRule
card_idintegerprimary key
questiontextnot empty, and unique, for S1
answertextnot empty
boxintegerbetween 1 and 5
duetext, in the form 2025-03-01the date the card is next shown

Algorithm. Written in pseudocode before any Python:

OCR reference language
procedure record(card, correct, today)
    if correct then
        card.box = min(card.box + 1, 5)
    else
        card.box = 1
    endif
    card.due = today + interval[card.box] days
endprocedure

Test plan, written now and not after:

TestPurposeDataExpected
T1Add a card (S1)"What is RAM?" and "Memory"Added
T2Blank question refused (S1, erroneous)Question of three spacesRefused, with a message
T3Duplicate refused (S1)The same question twiceSecond is refused
T4Correct answer in box 1 (S2)Box 1, answered rightBox 2, due in 2 days
T5Correct answer in box 5 (S2, boundary)Box 5, answered rightStays in box 5, due in 16 days
T6Wrong answer in box 4 (S3)Box 4, answered wrongBox 1, due in 1 day
T7Only due cards offered (S4)Cards due today and tomorrowOnly today's offered

Development: a working solution in small steps

Build it in stages, and make each stage work and be tested before the next begins. Stage 1 is storage. Stage 2 is the rules of the boxes. Stage 3 is the review. The interface comes last, because the parts it depends on are then known to be right.

The program below is the solution so far, as it might appear in the final version, and a short demonstration of three days of use. Read the code before you run it, and notice what is in it that is there for the marks.

Python
import sqlite3
from datetime import date, timedelta

BOX_INTERVALS = {1: 1, 2: 2, 3: 4, 4: 8, 5: 16}     # days until a card is due again
MAX_BOX = 5


class DeckError(Exception):
    '''Raised when the user asks the deck to do something it cannot.'''


class Deck:
    '''A set of flashcards stored in a database, using the Leitner system.'''

    def __init__(self):
        self.db = sqlite3.connect(":memory:")
        self.db.execute('''CREATE TABLE card (
            card_id INTEGER PRIMARY KEY,
            question TEXT NOT NULL UNIQUE,
            answer TEXT NOT NULL,
            box INTEGER NOT NULL DEFAULT 1 CHECK (box BETWEEN 1 AND 5),
            due TEXT NOT NULL)''')

    def add(self, question, answer, today):
        '''Add a card, due today. Refuses a blank or duplicate question.'''
        question, answer = question.strip(), answer.strip()
        if not question or not answer:
            raise DeckError("a card needs a question and an answer")
        try:
            self.db.execute("INSERT INTO card (question, answer, due) VALUES (?, ?, ?)",
                            (question, answer, today.isoformat()))
        except sqlite3.IntegrityError:
            raise DeckError("that question is already in the deck")
        self.db.commit()

    def due(self, today):
        '''The cards to be reviewed today, lowest box first.'''
        rows = self.db.execute(
            "SELECT card_id, question, box FROM card WHERE due <= ? ORDER BY box, card_id",
            (today.isoformat(),))
        return rows.fetchall()

    def record(self, card_id, correct, today):
        '''Move a card after it has been answered, and return its new box and due date.'''
        (box,) = self.db.execute("SELECT box FROM card WHERE card_id = ?", (card_id,)).fetchone()
        box = min(box + 1, MAX_BOX) if correct else 1
        due = today + timedelta(days=BOX_INTERVALS[box])
        self.db.execute("UPDATE card SET box = ?, due = ? WHERE card_id = ?",
                        (box, due.isoformat(), card_id))
        self.db.commit()
        return box, due

    def summary(self):
        '''How many cards are in each box.'''
        return self.db.execute("SELECT box, COUNT(*) FROM card GROUP BY box ORDER BY box").fetchall()


day1 = date(2025, 3, 1)
deck = Deck()
deck.add("What does CPU stand for?", "Central processing unit", day1)
deck.add("What is the base of hexadecimal?", "16", day1)
deck.add("Which sort has an O(n log n) worst case?", "Merge sort", day1)

for bad in [("   ", "blank"), ("What is the base of hexadecimal?", "sixteen")]:
    try:
        deck.add(bad[0], bad[1], day1)
    except DeckError as error:
        print("refused:", error)

print("Day 1, due:", len(deck.due(day1)))
deck.record(1, True, day1)
deck.record(2, True, day1)
deck.record(3, False, day1)
print("after day 1:", deck.summary())

day2 = day1 + timedelta(days=1)
print("Day 2, due:", [q for _, q, _ in deck.due(day2)])
box, due = deck.record(3, True, day2)
print("card 3 is now in box", box, "due", due.isoformat())

day3 = day2 + timedelta(days=1)
for card_id, question, box in deck.due(day3):
    deck.record(card_id, True, day3)
print("after day 3:", deck.summary())

What the code shows, for the marks

FeatureWhereWhy it earns credit
Meaningful names and a constantBOX_INTERVALS, MAX_BOX, due, recordThe code reads like the design, and the rules are changed in one place
Docstrings and commentsThe triple quoted linesAnother programmer, or a marker, can see what each part is for
Classes, one job eachDeck holds the data and the rulesA coherent, maintainable structure
Validation that refuses bad dataadd checks for blank and duplicate questions, S1Robust against the erroneous data in the test plan
A custom exceptionDeckErrorA clear signal to the interface, which decides how to tell the user
Parameterised SQLEvery ?No SQL injection, and no quoting errors
An appropriate data structureA dictionary of intervals, a database tableThe choices are justified in the design
Dates in ISO form2025-03-01They sort and compare correctly as text, which the due <= ? test relies on

A development log

This is the sort of dated entry that turns into evidence of iterative development. It records the problem as well as the progress.

DateStageWhat I didProblem foundHow I fixed it
3 Oct1. StorageCreated the table and addTwo cards with the same question were acceptedAdded UNIQUE and caught IntegrityError
10 Oct2. RulesWrote recordA card in box 5 moved to box 6 and caused a key errorUsed min(box + 1, MAX_BOX) after test T5
17 Oct3. ReviewWrote dueCards due tomorrow were being offeredThe comparison was < instead of <=, and after fixing it test T7 passed

Testing and evaluation

Run the plan

Testing is where the plan from the design is carried out and recorded. Python's unittest can run the plan, and the output is the evidence. The program repeats the Deck class so that it runs on its own, and then runs the tests from the plan.

Python
import sqlite3
import unittest
from datetime import date, timedelta

BOX_INTERVALS = {1: 1, 2: 2, 3: 4, 4: 8, 5: 16}
MAX_BOX = 5

class DeckError(Exception):
    pass

class Deck:
    def __init__(self):
        self.db = sqlite3.connect(":memory:")
        self.db.execute('''CREATE TABLE card (card_id INTEGER PRIMARY KEY,
            question TEXT NOT NULL UNIQUE, answer TEXT NOT NULL,
            box INTEGER NOT NULL DEFAULT 1 CHECK (box BETWEEN 1 AND 5), due TEXT NOT NULL)''')

    def add(self, question, answer, today):
        question, answer = question.strip(), answer.strip()
        if not question or not answer:
            raise DeckError("a card needs a question and an answer")
        try:
            self.db.execute("INSERT INTO card (question, answer, due) VALUES (?, ?, ?)",
                            (question, answer, today.isoformat()))
        except sqlite3.IntegrityError:
            raise DeckError("that question is already in the deck")
        self.db.commit()

    def due(self, today):
        return self.db.execute("SELECT card_id, question, box FROM card WHERE due <= ? ORDER BY box, card_id",
                               (today.isoformat(),)).fetchall()

    def record(self, card_id, correct, today):
        (box,) = self.db.execute("SELECT box FROM card WHERE card_id = ?", (card_id,)).fetchone()
        box = min(box + 1, MAX_BOX) if correct else 1
        due = today + timedelta(days=BOX_INTERVALS[box])
        self.db.execute("UPDATE card SET box = ?, due = ? WHERE card_id = ?", (box, due.isoformat(), card_id))
        self.db.commit()
        return box, due

TODAY = date(2025, 3, 1)

class TestDeck(unittest.TestCase):
    def setUp(self):
        self.deck = Deck()
        self.deck.add("What is RAM?", "Memory", TODAY)

    def test_t2_blank_question_refused(self):
        with self.assertRaises(DeckError):
            self.deck.add("   ", "anything", TODAY)

    def test_t3_duplicate_refused(self):
        with self.assertRaises(DeckError):
            self.deck.add("What is RAM?", "Random access memory", TODAY)

    def test_t4_correct_in_box_1_moves_to_box_2(self):
        self.assertEqual(self.deck.record(1, True, TODAY), (2, TODAY + timedelta(days=2)))

    def test_t5_correct_in_box_5_stays_in_box_5(self):
        for _ in range(4):
            self.deck.record(1, True, TODAY)
        self.assertEqual(self.deck.record(1, True, TODAY), (5, TODAY + timedelta(days=16)))
        self.assertEqual(self.deck.record(1, True, TODAY)[0], 5)

    def test_t6_wrong_answer_returns_to_box_1(self):
        for _ in range(3):
            self.deck.record(1, True, TODAY)
        self.assertEqual(self.deck.record(1, False, TODAY), (1, TODAY + timedelta(days=1)))

    def test_t7_only_due_cards_offered(self):
        self.deck.add("What is ROM?", "Read only memory", TODAY)
        self.deck.record(2, True, TODAY)
        self.assertEqual([q for _, q, _ in self.deck.due(TODAY)], ["What is RAM?"])

suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestDeck)
result = unittest.TestResult()
suite.run(result)
print(result.testsRun, "tests,", len(result.failures), "failed,", len(result.errors), "errors")
for test, trace in result.failures + result.errors:
    print("  FAILED", test.id().split(".")[-1])

The test names carry the numbers from the test plan, so the evidence can be matched to the plan. Test T5 is the boundary: the top box, where a careless box + 1 would reach 6 and fail the database's CHECK.

The test table

In the write up, results are shown as a table, with a screenshot beside it for each test. A test that failed first time, and the fix, is worth more than a table in which everything passed first time.

TestExpectedActualResultAction
T4Box 2, due in 2 daysBox 2, due in 2 daysPassNone
T5Stays in box 5Raised an error, box 6FailUsed min(box + 1, MAX_BOX)
T5, againStays in box 5Stays in box 5PassNone, and all tests re run for regression

Evaluating the solution

The evaluation is not a review of how you felt. It judges the solution against the success criteria, one by one, and backs each judgement with evidence.

CriterionMet?Evidence
S1: add, refuse blank and duplicateMetTests T1 to T3 all pass. In the feedback session, one user typed a question with trailing spaces and it was still caught as a duplicate
S2: correct answers move up, to a maximum of 5MetT4 and T5, after the fix
S5: cards survive closing the programNot metThe prototype uses an in memory database. Changing the path to a file is the next step
S6: summaryPartly metIt shows the count in each box, but the users wanted it shown as a bar chart

After the table, the evaluation covers:

  • Stakeholder feedback: what the users said, in their words, and what you would change because of it
  • Limitations: there is no way to edit a card, and no import from a spreadsheet
  • Maintenance and future development: how the structure would let another programmer add an interface or a new rule for the boxes
  • Your own process: what you would do differently with the time again
Evidence in, judgement out

Every claim in an evaluation should have a test result, a screenshot or a quotation behind it. "Users liked it" is an opinion. "Four of five users completed a review without help, and the fifth asked how to add a card" is evidence.

Key terms you must be able to define

Stakeholder
A person or group with an interest in a system, such as a user, the client or the people who maintain it.
Success criteria
Measurable statements of what the finished solution must do, used to judge it in the evaluation.
Decomposition
Breaking a problem down into smaller parts that can be designed, built and tested separately.
Iterative development
Building a solution in repeated stages, with testing and review, each building on the one before.
Modular
Built from separate parts, each with one job, which can be developed and tested independently.
Test plan
A table of tests, with their data and the expected results, written before the solution is tested.
Remedial action
The change made to the solution to fix a fault that testing has revealed.
Maintainability
How easily a solution can be understood, corrected and extended by somebody else.
Version control
A system that records the history of changes to code, so that earlier versions can be recovered.
Evaluation
A reasoned judgement of the finished solution against its success criteria, supported by evidence.

Flashcards

Say the definition out loud before you flip the card. Retrieving it from memory is what builds recall, reading it again is not.

DefineStakeholder
AnswerA person or group with an interest in a system, such as a user, the client or the people who maintain it.
DefineSuccess criteria
AnswerMeasurable statements of what the finished solution must do, used to judge it in the evaluation.
DefineDecomposition
AnswerBreaking a problem down into smaller parts that can be designed, built and tested separately.
DefineIterative development
AnswerBuilding a solution in repeated stages, with testing and review, each building on the one before.
DefineModular
AnswerBuilt from separate parts, each with one job, which can be developed and tested independently.
DefineTest plan
AnswerA table of tests, with their data and the expected results, written before the solution is tested.
DefineRemedial action
AnswerThe change made to the solution to fix a fault that testing has revealed.
DefineMaintainability
AnswerHow easily a solution can be understood, corrected and extended by somebody else.

Reach the top grade on this topic

The project is marked on evidence, so work towards documents that prove each claim.

  • Write every success criterion so that someone else could test it and agree if it was met
  • Finish the design, including the test plan, before writing the code it describes
  • Keep a dated log of what went wrong as well as what worked, with annotated screenshots
  • Show the faults that testing found, and the changes that fixed them
  • Judge every success criterion in the evaluation, with evidence, including the ones not met

Mistakes that cost marks here

Avoid these
  • Writing success criteria that cannot be measured, such as the program should be easy to use.
  • Producing the design and the test plan after the code has been written.
  • Showing only tests that pass first time, which suggests that nothing was found or tested.
  • Evaluating how the project felt, without judging the solution against each success criterion.
  • Using code from elsewhere without identifying where it came from.
Fun fact

The project is worth a fifth of the A Level and is the part of the course where every student has the same chance to beat the exam: the marks are for work you can plan, and none of it is lost to nerves. The students who do best usually start it earlier than they think they need to.

Knowledge check

0 of 10 answered
1What makes a success criterion good?
2Who are the stakeholders of a project?
3What is decomposition?
4When should the test plan be written?
5What is iterative development?
6Why is a test that failed and was then fixed valuable evidence?
7How should an evaluation judge the finished solution?
8Which of these is evidence of good maintainability?
9What is the purpose of version control in a project?
10What should a student do if they use a piece of code from a website in their project?
Score 0 / 10

Check you could explain this

Five written questions in the style of the real paper. Write a full answer, then let the marker check it against the mark scheme.

19 marks
1Explain why success criteria should be measurable, and write one measurable success criterion for a program that stores a student's revision flashcards.4 marks
Explain

Mark scheme0 / 4
  • LThe finished solution is judged against the success criteria in the evaluation
  • LA measurable criterion can be tested, so there is evidence of whether it was met
  • LA vague criterion, such as easy to use, cannot be tested and so cannot be judged
  • LA suitable example, such as a card answered correctly moves up one box and is due again after the interval for that box
Model answer

Success criteria are what the finished solution is judged against in the evaluation. A measurable criterion can be tested, so there is evidence of whether or not it was met, whereas a vague criterion, such as the program being easy to use, is an opinion that cannot be tested. A measurable criterion for the flashcard program is that a card answered correctly moves up one box and is next due after the number of days set for that box.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
2Describe two things that should be included in the design of a programming project before any code is written.4 marks
Describe

Mark scheme0 / 4
  • LA decomposition of the problem into smaller parts, such as a structure diagram
  • LThis shows how the program will be organised, so that each part can be built and tested separately
  • LA test plan, listing the test data and the expected results
  • LWritten before coding so that the expected results are worked out from the design and not from the program's output
  • LOther acceptable items, such as algorithms in pseudocode, data design or interface designs
Model answer

The design should include a decomposition of the problem into smaller parts, for example a structure diagram, which shows how the program will be organised so that each part can be built and tested on its own. It should also include a test plan, listing the test data and the expected results, which are worked out from the design before the code is written, so that the tests are not just a copy of whatever the program happens to output. Algorithms in pseudocode, data design and interface designs would also be suitable.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
3Explain what is meant by iterative development, and why it is a suitable way of building a project.4 marks
Explain

Mark scheme0 / 4
  • LThe solution is built in stages, and each stage is tested before the next is started
  • LEach stage builds on a part that is already known to work
  • LFaults are found while only a small amount of new code could be responsible
  • LFeedback from the stakeholders can be used to change what is built next, and the stages give evidence of the development
Model answer

Iterative development means that the solution is built in stages, with each stage tested, and reviewed before the next is started, so that each stage builds on a part that is already known to work. It is suitable for a project because faults are found early, when only a small amount of new code could be the cause, and feedback from the stakeholders can be used to change what is built next. The record of the stages is also the evidence of development.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
4A student's evaluation says that the project was successful and the users liked it. Explain why this would earn few marks, and describe what the evaluation should contain instead.4 marks
Explain

Mark scheme0 / 4
  • LIt makes a claim with no evidence to support it
  • LIt does not judge the solution against the success criteria
  • LIt should say whether each success criterion was met, with evidence such as test results or user feedback
  • LIt should also describe limitations and possible improvements
Model answer

The statement makes a claim without any evidence to support it, and it does not judge the solution against the success criteria. A good evaluation goes through each success criterion in turn and says whether it was met, with evidence such as the results of the tests, screenshots or quotations from the stakeholders. It should also describe the limitations of the solution, and the improvements that could be made to it.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
5Describe how the use of version control and regular backups helps a student who is developing a programming project.3 marks
Describe

Mark scheme0 / 3
  • LVersion control records a history of the changes made to the code
  • LAn earlier working version can be recovered if a change breaks the program
  • LBackups mean that the work is not lost if a file or device fails
Model answer

Version control keeps a history of the changes made to the code, so that if a change breaks the program an earlier working version can be recovered. Regular backups, stored in more than one place, mean that the work is not lost if a file is deleted or a device fails.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
Machine mark 0 / 19