Software Engineering Project

Applying the software development lifecycle to address an identified real-world problem — with an emphasis on project management, software design, and client collaboration.

Year 12 — HSC Major Project Outcomes: SE-12-01 to 09
24Dot points
4Parts
9Outcomes
MajorProject
See a complete example The Example Major Project follows every step on this page, from brief and requirements to tests and evaluation, for a smart greenhouse controller you can run in your browser.
Running scenario: the Library Loans project The worked examples on this page follow one student project from first meeting to final review. A Year 12 student builds a loans and overdue system for the school library. The client is Mrs Chen, the teacher-librarian. Today loans are stamped on paper cards and she types up the overdue list by hand each Friday. The project runs for seven weeks (35 school days) and one student builds it. The people, dates and numbers are invented for practice, and each worked example can be reproduced with the tables and Python code shown.
How this project relates to assessment Only facts NESA has published are stated here (checked 29 September 2026).
  • There is no HSC practical exam or submitted major work for Software Engineering. The HSC exam is a single online written exam worth 80 marks (2 hours 30 minutes including 10 minutes reading time), with objective-response and short-answer items. Everything on this page can be examined there, including reading and completing a data dictionary, choosing and justifying a development approach, and interpreting test data. NESA: HSC examination specifications ↗
  • NESA does not publish a compulsory project task, weighting or length. Schools decide the number, type and weighting of school-based tasks, so the marking criteria for any project or documentation task come from your school's assessment notification.
  • One rule applies to every school: a course may have no more than one take-home task, worth at most 15%. For HSC courses the limit started in Term 4, 2026, and Software Engineering is not on NESA's list of exempt courses. NESA: school-based assessment ↗
  • Marks must reflect your own knowledge, skills and understanding, not the use of generative AI. Each school sets its own policy on AI tools, so ask before using one on any task.
Syllabus Part 1 Identifying and defining

Defining and Analysing Requirements

🎯 (SE-12-01, SE-12-06)

📌 Define and analyse the requirements of a problem

  • demonstrating need(s) or opportunities
  • assessing scheduling and financial feasibility
  • generating requirements including functionality and performance
  • defining data structures and data types
  • defining boundaries

Problem Requirements

Before coding begins, a software engineer must define the core requirements:

  • 🎯 Demonstrating needs or opportunities: Clearly identifying the real-world problem the software solves for the client.
  • 💰 Assessing scheduling and financial feasibility: Determining if the project can be completed within the allocated timeframe and budget.
  • 📝 Generating requirements: Defining functionality (what the system must do) and performance (how well/fast it must do it).
  • 🗄️ Defining data structures and types: Specifying how information will be securely collected and stored.
  • 🚧 Defining boundaries: Establishing the scope to prevent "scope creep" during development.

Demonstrating a need or an opportunity

A need is a problem that real people have now. An opportunity is a chance to do something better that nobody has complained about yet. Either way you must demonstrate it with evidence from the people affected, not assume it. Useful evidence is an interview, an observation of the current process, samples of the current records, a short survey, or a measurement (such as how long a task takes today).

TermWhat it isLibrary Loans example
NeedThe problem to be solved, in the client's words"I type the overdue list by hand every Friday, and I can't tell from the desk whether a book is in."
RequirementA testable statement of what the solution must do (functional) or how well (non-functional)"Staff can view a list of every overdue loan with the member, title and days overdue."
ConstraintA limit on how the project may be done: time, money, skills, technology, law, policy"Seven weeks, one developer, free tools only, no student data leaves the school network."
BoundaryThe line around what the system will and will not do"Loans, returns, search and overdue lists are inside. Email reminders and fine payment are outside."
Worked example: a need statement
  • Who: Mrs Chen (client), library volunteers, and students who borrow books.
  • Problem: loans are stamped on paper cards, so checking whether a book is in means walking to the shelf or searching the cards. The overdue list is typed by hand each Friday, and some due dates on old cards cannot be read.
  • Evidence: an interview with Mrs Chen (notes filed in the process diary), an observation of one lunchtime at the desk, and three photographed cards with unreadable dates.
  • Need: record a loan or a return in seconds and produce the overdue list automatically.
  • Opportunity: once loans are stored as data, the library could later see which titles are borrowed most. Nobody has asked for this yet, so it is an opportunity and not a requirement.

Assessing scheduling and financial feasibility

Feasibility asks whether the project can realistically be finished with the time and money available. Estimate the effort task by task, add a contingency for things that go wrong (10% to 20% is common), and compare the total with the time you actually have. Do this before promising features to the client.

TaskEstimate (hours)
Requirements and feasibility5
Design and modelling (data dictionary, structure chart, wireframes)7
Loan module7
Search module5
Interface7
Testing and fixes6
Documentation and evaluation5
Core scope total42
Extra feature: email reminders to members8
  • Time available: 7 weeks × 7 hours a week (class time plus home study) = 49 hours.
  • Core scope with 15% contingency: 42 × 1.15 = 48.3 hours. This is less than 49 hours, so the core scope is schedule-feasible, with only 0.7 hours to spare.
  • Core scope plus email reminders: (42 + 8) × 1.15 = 57.5 hours. This is more than 49 hours, so it is not feasible.
  • Financial feasibility: the project uses only free tools (VS Code, Python, SQLite, Git and GitHub) and the library's existing computer, so the cash cost is $0. A costed budget for a paying client is worked through in Applying Project Management.
  • Decision: email reminders are put outside the boundary for version 1 and recorded as a possible later version. Mrs Chen agrees, because the overdue list she needs most is still delivered.

Requirements Analysis

Requirements must be clearly categorised before development starts. ⚙️ Functional requirements describe what the system must do; ⚡ Non-functional requirements describe how well it must do it (quality attributes). Documenting both types ensures the solution is both complete and fit for purpose.

Type Requirement Example (Library System) Priority
Functional User registration A member must be able to create an account with their name, email, and student ID. Must Have
Functional Book search Users can search the catalogue by title, author, or ISBN and view availability. Must Have
Functional Loan management Staff can issue a loan, record a return, and calculate overdue fines automatically. Must Have
Functional Reporting Generate a report of all overdue books, sortable by due date or member name. Should Have
Non-Functional Performance Search results must return within 2 seconds for a catalogue of up to 10,000 books. Must Have
Non-Functional Security All passwords must be stored as bcrypt hashes; no plaintext credentials in the database. Must Have
Non-Functional Usability The interface must be operable by a new staff member with no training within 15 minutes. Should Have
Non-Functional Maintainability Code must include docstrings for all functions and follow PEP 8 style guidelines. Should Have

Generating requirements: the Library Loans list

Give every requirement an ID, a priority and a way it will be verified. Requirements that cannot be checked ("the system should be fast") are not yet requirements. The IDs let the test plan and the final evaluation point back to them, as in the later sections of this page.

IDTypeRequirementPriorityHow it is verified
FR1FunctionalStaff can search the catalogue by title or ISBN. Partial, case-insensitive matches are returned.MustTest cases on search
FR2FunctionalStaff can issue an available book to a member. The due date is set 14 days after issue.MustTest cases on issuing
FR3FunctionalA loan is refused if the book is already on loan or the member already has 5 active loans.MustBoundary tests: 4 and 5 loans
FR4FunctionalStaff can record a return, and the book becomes available.MustTest cases on returns
FR5FunctionalStaff can view a list of overdue loans with the member, title and days overdue.MustTest with dated sample loans
FR6FunctionalThe fine is 20 cents for each day overdue, up to a maximum of $10.00.ShouldBoundary tests: 0, 1, 50 and 51 days
FR7FunctionalThe overdue list can be exported as a CSV file.ShouldExport a sample and open it
NFR1PerformanceSearch results appear within 2 seconds for a catalogue of 10,000 titles.MustTimed test
NFR2Security and privacyOnly signed-in staff can use the system. Passwords are stored as salted hashes. Only a member's name and student ID are stored.MustInspect the database; try to use the system while signed out
NFR3UsabilityA new staff member can operate the system without training within 15 minutes.ShouldTimed walkthrough with a volunteer
NFR4MaintainabilityAll functions have docstrings and the code follows PEP 8.ShouldLinter report and code review

User Stories and Acceptance Criteria

User stories capture requirements from the end-user's perspective in plain language. They follow the format: "As a [role], I want [feature], so that [benefit]." Each user story is accompanied by acceptance criteria — specific, testable conditions that confirm the story has been implemented correctly.

User Story Acceptance Criteria
As a library member, I want to search for books by title so that I can quickly check if a book is available.
  • Search returns results within 2 seconds
  • Results display title, author, and availability status
  • Partial title matches are returned (e.g., "Harry" returns all Harry Potter books)
  • A "no results found" message displays for unmatched queries
As a staff member, I want to issue a loan so that the member can borrow the book and a return date is recorded.
  • System prevents issuing a loan if member already has 5 active loans
  • Due date is automatically set to 14 days from issue date
  • Book availability status changes to "On Loan" immediately
  • A confirmation message is displayed on success
As an administrator, I want to generate an overdue report so that I can contact members with outstanding returns.
  • Report lists all loans where current date exceeds the due date
  • Report can be filtered by member name or overdue duration
  • Report can be exported as a CSV file

Try it

Requirement, constraint or boundary?

Classify nine Library Loans statements. Enable JavaScript to use this tool. In short: a functional requirement is what the system does, a non-functional requirement is how well, a constraint limits the project and a boundary sets what is out of scope.

Defining data structures and data types

Requirements say what information the system handles. You then decide how each item is typed (text, whole number, decimal, date, true/false) and how items are structured (a single variable, a list, a dictionary of records, a database table). Choose the simplest type that stores the value correctly and lets you validate it.

Python: structures for Library Loans
from datetime import date

# A dictionary gives direct lookup by member ID; a list keeps loan records in order.
members = {
    "S0012345": {"name": "Alice Chen", "active_loans": 1},
    "S0012346": {"name": "Ben Ortiz", "active_loans": 5},
}
loans = [
    {"isbn": "9780743273565", "member_id": "S0012345", "due": date(2026, 3, 17)},
]

print(members["S0012346"]["name"])       # direct lookup by key
print(len(loans))                        # a list of records
print(type(loans[0]["due"]).__name__)    # a real date, not text

Expected output: Ben Ortiz, then 1, then date.

ItemType chosenReason
Member ID (S0012345)StringIt starts with a letter and is never used in arithmetic. An identifier is text even when it looks like a number.
ISBNStringIt can begin with 0, and leading zeros vanish in an integer.
Due dateDateDates can be compared and subtracted (days overdue), which text cannot do reliably.
Active loansIntegerIt is counted, so it is always a whole number from 0 to 5.
FineDecimal (or integer cents)Money needs exact cents. In Python, 0.1 + 0.2 gives 0.30000000000000004, so many programs store cents as integers. NESA's example data dictionary uses Floating Point for a pay rate; either choice is acceptable if you justify it.
Book availableBooleanThere are exactly two states.
Members, loansDictionary, list of recordsMembers are looked up by ID many times; loans are added and scanned in order.

Constraints and boundaries

A constraint limits how the project may be carried out. A boundary defines what the system will and will not do. Together they protect the project from scope creep, the slow growth of requirements that nobody has costed.

Kind of constraintLibrary Loans example
TimeSeven weeks, with a 15-minute client review every second Friday.
MoneyNo budget: free tools only.
SkillsOne developer who knows Python, SQLite and Flask, but not mobile apps.
TechnologyMust run on the library's existing computer, with no internet needed at the desk.
Law and policyStudent names and IDs are personal information, so the school's privacy obligations apply. Data stays on the school network.

The system boundary is shown on the Level 0 data flow diagram in Using Modelling Tools: students, the librarian and the school admin system are outside the boundary, and the Library Loans system is inside. A written scope statement makes the same boundary explicit.

Inside the boundary (version 1)Outside the boundary
Search the catalogue, issue and return loans, view the overdue list, calculate fines, export CSV, staff sign-inEmail or SMS reminders, online payment of fines, a student login, a mobile app, ordering new books

Handling a change request. When Mrs Chen asks for something outside the boundary: (1) write the request down; (2) estimate its hours; (3) show the effect on the schedule (the email reminders in the feasibility example added 8 hours and made the project infeasible); (4) let the client decide to swap it for something else, extend the deadline or defer it; (5) record the decision in the process diary. Boundaries also exist inside the data. "A member may hold at most 5 loans" is a boundary that later becomes boundary test data at 4, 5 and 6.

A strong requirements section includes
  • A clear problem statement backed by evidence that a real person has the problem, not just "I made an app because it is interesting".
  • Both requirement types. Documenting only functional requirements is a common gap, and non-functional requirements (performance, security, usability, maintainability) are what you evaluate against later.
  • Evidence of client involvement: meeting notes, interview notes or a survey summary.
  • Feasibility worked out with numbers for time and money, and the decision it led to.
  • Measurable wording (Specific, Measurable, Achievable, Realistic, Time-bound). Avoid "the system should be fast". Write "search returns within 2 seconds".

Your school's assessment notification says which of these it marks. Use it alongside this checklist.

Exam tip: "Define" and "analyse" requirements Expect scenario questions such as "Identify one functional and one non-functional requirement for the system described" or "Outline two constraints the developer must consider". A full-mark answer names the item and ties it to the scenario: "Non-functional: search must return within 2 seconds for 10,000 titles (performance), because staff use it at a busy lunchtime desk." Common mistakes are writing a feature ("has a search bar") as a non-functional requirement, giving a requirement that cannot be tested ("user friendly"), and confusing a constraint (a limit on the project, such as the deadline) with a boundary (a limit on the system's scope).

Tools to Develop Ideas and Generate Solutions

🎯 (SE-12-01, SE-12-06)

📌 Explore tools used to develop ideas and generate solutions

  • brainstorming, mind-mapping and storyboards
  • data dictionaries, including selecting appropriate data types
  • algorithm design
  • code generation
  • testing and debugging
  • installation
  • maintenance

Tools for Idea Generation & Solution Development

Explore the tools used to develop ideas and guide the project lifecycle:

Idea GenerationBrainstorming, mind-mapping, and Storyboards to visualise user interfaces.
Data DefinitionUtilising Data dictionaries to select appropriate data types and formats.
DevelopmentAlgorithm design (flowcharts/pseudocode), code generation, and rigorous testing and debugging.
Post-DevelopmentInstallation and ongoing maintenance procedures.

Brainstorming and mind-mapping

Brainstorming is a short burst of ideas with no judging, so quantity comes before quality. Mind-mapping then organises the ideas around a central topic, with branches for groups and sub-branches for detail. The two steps work as a pair: diverge (collect everything), then converge (sort, cut and choose using the requirements and constraints).

Worked example. In five minutes the student and Mrs Chen list everything the library system could do: scan barcodes, email reminders, search by title, fines, staff sign-in, student photos, reserve a study room, print the overdue list, reading recommendations, renew a loan. The mind map below groups those ideas, and the constraints from the previous section decide which branches are built now.

  • Library Loans
    • Loans (build now): issue, return, loan limit; renew (later)
    • Catalogue (build now): search by title or ISBN, availability
    • Reports (build now): overdue list, fines, CSV export
    • Members (build now): name and ID only; staff sign-in
    • Later versions: email reminders, reserving a study room, recommendations
    • Rejected: student photos (privacy risk and no client need)

Storyboards and Wireframes

A storyboard visually maps the sequence of screens a user encounters when completing a task. A wireframe is a low-fidelity layout sketch of a single screen, showing the placement of UI elements without colour or detailed styling. Together, they allow client feedback on the interface before any front-end code is written.

Storyboard vs Wireframe — Key Differences
  • Storyboard: Shows a sequence of interactions — e.g., the steps a user takes from the login screen to completing a book search. Think of it as a comic strip of your application's workflow.
  • Wireframe: Shows the layout of a single screen — where headers, navigation, input fields, and buttons are positioned. It does not include colour, fonts, or images.
  • Prototype: A clickable, interactive mock-up of the interface, often built in a tool like Figma or Canva. It simulates real user interaction without any back-end code.
  • Why include them: They show that you consulted the client about the UI before coding, which is a hallmark of professional software engineering practice.

Worked storyboard. NESA describes a storyboard as showing the screens and the links between them. This one covers issuing a loan.

ScreenWhat the user seesLink to the next screen
1. Sign inUsername and password boxes, a Sign in buttonCorrect details lead to 2. A wrong password stays on 1 with an error message.
2. HomeFour large buttons: Issue loan, Return book, Search, Overdue listIssue loan leads to 3. Each other button leads to its own screen.
3. Issue loanA member ID box, an ISBN box and an Issue buttonSuccess leads to 4. A refusal shows the reason (on loan, limit reached) and stays on 3.
4. ConfirmationBook title, member name and the due dateDone returns to 2.

Data Dictionary

A data dictionary formally defines every data item used in the system — its name, data type, size, valid range, and description. It ensures consistency between the design documents and the code implementation, and establishes the data structures required for the project.

Field Name Entity / Class Data Type Size / Range Required? Description & Validation Rules
member_id Member Text 8 characters Yes Unique identifier for each member. Format: "S" followed by 7 digits (e.g., "S0012345"). Generated automatically on registration.
name Member Text 1–100 characters Yes Member's full name. Must not be blank. Must be validated before storage.
email Member Text 5–254 characters Yes Member's email address. Must match email format pattern. Must be unique.
isbn Book Text 13 characters Yes International Standard Book Number (ISBN-13). Must be exactly 13 digits. Validated against ISBN checksum algorithm.
title Book Text 1–300 characters Yes Full title of the book. Must not be blank. Case-insensitive search support.
available Book Boolean True / False Yes Whether the book is available for loan. Default: True. Set to False when issued; reset to True when returned.
issue_date Loan Date Valid calendar date Yes The date the loan was issued. Automatically set to current date. Cannot be a future date.
due_date Loan Date Valid calendar date Yes The date the book must be returned. Automatically calculated as 14 days after issue date.
fine_amount Loan Number 0.00 to 10.00 No Overdue fine in Australian dollars. Default: 0.00. Calculated as $0.20 per day overdue, capped at $10.00 (requirement FR6).

Selecting appropriate data types: NESA's data dictionary layout

NESA's Course Specifications (p. 8) describe a data dictionary as a comprehensive description of each variable, and give a layout with these columns: variable, data type, format for display, size in bytes, size for display, description, example and validation. The table above is a working format for a project. In the exam, complete or read a dictionary in the NESA layout, as below. A date and time is always stored as 32 bits (4 bytes), whatever format it is displayed in.

VariableData typeFormat for displaySize in bytesSize for displayDescriptionExampleValidation
MemberIdStringSNNNNNNN88A primary key that uniquely identifies a memberS0012345First character S, then 7 digits
MemberNameStringXX..XX100100Full name of the memberAlice Chen1 to 100 characters, not blank
DueDateDate and TimeYYYY/MM/DD410Date the book must be returned2026/03/17Valid date, 14 days after the issue date
ActiveLoansIntegerN21Number of books the member has on loan3Integer between 0 and 5
FineFloating Point$NN.NN46Overdue fine owed on a loan$1.40Decimal from 0.00 to 10.00
AvailableBooleanX1 bit1Whether the book is inYY or N

Selecting the type: ask what the value means and what you will do with it. If you will calculate with it, use a number; if you compare it in time, use a date; if it is an identifier or a code, use a string even when it looks numeric; if there are two states, use a Boolean. Then write the validation so the type can only hold legal values.

Project Structure Chart

A structure chart breaks the software solution into its major components before coding begins. It shows how the top-level system is decomposed into modules, and how those modules relate to each other. The chart below illustrates a typical school library management system.

Structure chart

Structure chart: a school library system

The library system refined into modules, based on the example in the NESA course specifications.

What to notice
  • Two curved arrows: the system repeats until the library closes, and Process books repeats for each book.
  • Filled circles are flags, such as Overdue; open circles are data, such as Student ID.

Try thisRefine Check book into its own structure chart, using the same module name at the top.

Algorithm design

An algorithm is the step-by-step logic of a solution, written before the code. NESA's Course Specifications ask for algorithms as pseudocode or flowcharts, built from sequence, selection and repetition. In pseudocode keywords are capitals, structures come in pairs (every IF has an ENDIF, every BEGIN has an END), indentation shows the structure, and a subroutine is called by name with its own algorithm written separately. Start with a short mainline that calls subroutines.

pseudocode: mainline
BEGIN LibraryLoans
    SignIn
    REPEAT
        DisplayMenu
        Get choice
        CASEWHERE choice evaluates to
            1: IssueLoan
            2: ReturnBook
            3: SearchCatalogue
            4: OverdueReport
            5: Display "Goodbye"
            OTHERWISE: Display "Choose a number from 1 to 5"
        END CASE
    UNTIL choice = 5
END LibraryLoans

One subroutine in detail: the fine for a loan (requirement FR6, 20 cents a day up to $10.00). The fine is held in cents so the arithmetic is exact. This is a nested IF, with one ENDIF for each IF.

pseudocode: subroutine with a nested IF
BEGIN CalculateFine (daysOverdue, fine)
    IF daysOverdue <= 0 THEN
        fine = 0
    ELSE
        IF daysOverdue > 50 THEN
            fine = 1000
        ELSE
            fine = daysOverdue * 20
        ENDIF
    ENDIF
END CalculateFine (daysOverdue, fine)

Desk-check it with a trace table before writing any code. The four inputs below sit on the edges of the rules (0 and 1 for overdue, 50 and 51 for the cap).

daysOverduedaysOverdue <= 0 ?daysOverdue > 50 ?fine (cents)
0Truenot tested0
1FalseFalse20
50FalseFalse1000
51FalseTrue1000
Python: the same algorithm
def calculate_fine_cents(days_overdue):
    """Return the fine in cents: 20 cents a day, capped at 1000 (ten dollars)."""
    if days_overdue <= 0:
        fine = 0
    else:
        if days_overdue > 50:
            fine = 1000
        else:
            fine = days_overdue * 20
    return fine


for days in (0, 1, 50, 51):
    print(days, calculate_fine_cents(days))

Expected output: 0 0, 1 20, 50 1000, 51 1000, matching the trace table.

Code generation

Code generation is turning a design into working code. It can be done by hand, guided by the design documents, or with tools that produce code from a description: templates and project scaffolds, IDE features that create class or function outlines, tools that create database code from a schema, and generative AI assistants. Whatever produces the first draft, you remain responsible for understanding, testing and acknowledging it.

A good hand-generation habit is to create stubs straight from the structure chart, so the code matches the design from the first commit. A data dictionary row set turns directly into a class.

Python: code from the design
from dataclasses import dataclass
from datetime import date


def issue_loan(member_id, isbn):
    """Structure chart module: Borrowing. Not written yet."""
    raise NotImplementedError


@dataclass
class Loan:
    """One row of the Loan record in the data dictionary."""
    isbn: str
    member_id: str
    due: date
    fine_cents: int = 0


print(Loan("9780743273565", "S0012345", date(2026, 3, 17)))

Expected output: Loan(isbn='9780743273565', member_id='S0012345', due=datetime.date(2026, 3, 17), fine_cents=0)

Generative AI and your marks NESA's ACE rules say marks must reflect a student's own knowledge, skills and understanding, and not the use of generative AI. Each school decides whether AI tools may be used on a task. If your school allows them, read every line the tool produces, test it, and note in your process diary what you used it for.

Testing and debugging

Testing finds out whether the software fails; debugging finds out why and fixes it. Both are tools for developing solutions, not only a stage at the end: test each module as you write it. Common debugging tools are print statements or a logger, an IDE breakpoint with single-step execution, and a trace table on paper. Part 4 covers the full methodology.

Worked example (defect BUG-002). The loan limit test fails: a member with 5 loans is allowed a sixth. Reproduce it, isolate the condition, then fix it.

Python: reproduce, then fix
def can_borrow(active_loans, limit=5):
    return active_loans <= limit      # bug: 5 <= 5 is True, so a sixth loan is allowed


print(can_borrow(5))                    # expected False, actual True

# Fix: a member may borrow only while they hold FEWER than the limit
def can_borrow(active_loans, limit=5):
    return active_loans < limit


print(can_borrow(5))                    # False
print(can_borrow(4))                    # True

Expected output: True, then False, then True. The first line shows the defect. The last two show the boundary now behaves correctly.

Installation

Installation puts the finished software into the client's environment so they can use it. It is planned like any other task, because a solution that only runs on the developer's laptop is not delivered. Plan the install around the implementation method chosen (direct, phased, parallel or pilot).

Installation taskLibrary Loans example
Check the environmentThe library computer has Python 3; there is no internet at the desk, so all packages are copied over on a USB drive.
List the dependenciesA requirements.txt file names each package and version.
Write and test the install stepsFollow the steps below on a clean computer, not the development laptop.
Migrate existing dataType or import the current loan cards so the new system starts accurate.
Back up before switchingCopy the empty database and the paper card box (photograph the cards) before the first live day.
Train the usersA 15-minute demonstration for Mrs Chen and the volunteers, plus a one-page guide.
Plan a way backKeep the paper cards for two weeks so the library can revert if the software fails.
Bash: install steps in the README
python -m venv .venv
.venv\Scripts\activate            # Windows. On macOS or Linux: source .venv/bin/activate
pip install -r requirements.txt
python setup_database.py           # creates the empty database and the first staff account
python main.py

Maintenance

Maintenance is the work of keeping software useful after it is installed. It usually costs more effort over the life of a system than the original build, so design for it: clear structure, comments and docstrings, tests, version control and a defect log. Maintenance is commonly grouped into four types (these are widely used industry terms, not a NESA list).

TypePurposeLibrary Loans example
CorrectiveFix a defect found in useOverdue list wrongly shows a book returned on its due date (BUG-003).
AdaptiveChange the software because its environment changedThe school moves to a new student ID format, so the MemberId validation changes.
PerfectiveImprove or extend what worksAdd the email reminders that were outside version 1.
PreventiveReduce future problemsSplit a long function into smaller ones, add unit tests, update libraries.
Exam tip: "Explore" the tools for developing solutions A short-answer item may give a stage (for example installation or maintenance) and a scenario, and ask you to describe what happens or identify the tool that fits. Name the tool or stage, then say what it produces or achieves for this project: "A data dictionary lists each variable's type, size and validation, so the developer builds MemberId as an 8-character string and rejects anything else." In NESA's 2025 HSC exam a data dictionary item asked students to complete every drop-down correctly for 3 marks, so learn the layout above. Common mistakes are treating debugging as the same thing as testing, and describing maintenance as "fixing bugs" only.

Software Implementation Methods

🎯 (SE-12-01)

📌 Investigate types of software implementation methods

  • direct
  • phased
  • parallel
  • pilot
Method Investigation & Analysis
Direct (Big Bang) The old system is completely shut down and replaced by the new system instantly. High risk, but cost-effective if successful.
Phased The new system is introduced in stages or modules. Lower risk, as issues can be resolved per module, but implementation takes longer.
Parallel Both the old and new systems run simultaneously until the new system is proven stable. Safest method, but highly resource-intensive and costly.
Pilot The new system is trialled by a small subset of users (e.g., one department). Once refined, it is rolled out to the rest of the enterprise.

Animated diagram

Four ways to switch over: direct, phased, parallel and pilot

The same four teams move from an old system to a new one. Watch where a bug strikes under each method as the timeline chart builds.

What to notice
  • The timeline chart is the diagram to sketch in an exam: an old-system bar and a new-system bar for each group, showing where they hand over or overlap.
  • A bug hurts most under direct (everyone at once, with nothing to fall back on) and least under parallel (the old system keeps working).
  • Phased splits the system into modules; pilot splits the users. These two are easy to mix up.

Choose a method with the tabs. Step with ◀ and ▶ (or the arrow keys), play or pause with Space.

Try thisTry the Case Study Matcher below. For each scenario, sketch the timeline chart you would draw, and say what a bug in week 3 would cost.

Case Study Matcher: Justifying Your Method

Be ready to justify the method chosen for a specific scenario. Use the interactive examples below to match the scenario to the best implementation method.

Scenario 1: A hospital is upgrading its critical patient records database. The system cannot afford any downtime or lost data. Click to reveal method & justification
Method: Parallel
Justification: Parallel runs both systems simultaneously. This is the only acceptable method for critical life-safety systems, as it provides a fully operational fallback if the new system fails.
Scenario 2: A fast-food chain is rolling out new digital touchscreen ordering kiosks across 500 stores nationwide. Click to reveal method & justification
Method: Phased or Pilot
Justification: Pilot would involve testing in one store to catch bugs before a nationwide rollout. Phased would roll it out region by region to manage training and installation resources safely.
Scenario 3: A small local bakery is moving from a paper-based ledger to a simple iPad point-of-sale system on Monday morning. Click to reveal method & justification
Method: Direct
Justification: The size and complexity of the business are low. Direct implementation avoids the confusion of running two separate systems, and is the most cost-effective.

Try it

Which implementation method?

Choose direct, phased, parallel or pilot for six situations. Enable JavaScript to use this tool. In short: parallel runs old and new together, pilot tries the whole system with a small group, phased brings in parts in stages and direct switches over at once.

Comparing the methods against criteria

To investigate the methods, compare them against the same criteria every time. The differences below follow from how each method is built: what runs at the same time, and how many people are exposed to a fault.

CriterionDirectPhasedParallelPilot
What is splitNothing: everyone switches at onceThe system, in modules or stagesNothing, but both systems runThe users, or one site or group
Risk if the new system failsHighest: no fallbackLower: only the new module is affectedLowest: the old system carries onLow: only the pilot group is affected
CostLowestMedium: longer, and old and new must connectHighest: double running and double data entryMedium: one group is supported closely
Time to full useShortestLongMedium: until the new system is trustedMedium: pilot first, then a wider rollout
FallbackRestore a backup, if there is oneKeep using the old moduleSwitch off the new systemPilot group returns to the old system
Best whenThe system is small or the old one has already failedThe system is large and its parts are fairly independentErrors would be very costly, such as payroll or patient recordsMany users or sites, and lessons can be learned from a small group first

Phased and pilot are easy to confuse. Phased introduces the new features one stage at a time (for example the loans module first, then reports). Pilot introduces the whole system to a few users first (for example one class of borrowers), then everyone. Organisations sometimes combine them, piloting with one group and then rolling out in phases.

Worked example: switching the library over

Choose the method for Library Loans using facts from the scenario: one library, one desk with two volunteers, the paper cards are the only current record, and every loan must stay accurate.

MethodFit for this scenarioVerdict
DirectIf the software fails on the first day, loans would go unrecorded and the cards would be out of date.Rejected: too risky for an accurate record
PhasedLoans, search and overdue reports depend on the same data, so releasing them in stages gives little benefit.Rejected: little to phase
PilotThere is only one desk and one group of users, so there is no smaller group to pilot with.Rejected: nothing to pilot on
ParallelVolunteers enter each loan in the software and on a card for two weeks. The two records are compared each Friday.Chosen

Justification: parallel is chosen because accuracy matters most and the volume of loans is small enough for double entry to be affordable. What would change the decision: if the school wanted the system in five libraries, a pilot in one library followed by a rollout would become the better choice, because parallel running in every library would be expensive.

Exam tip: "Investigate" and justify a method Scenario questions give a situation and ask you to identify the method, or to justify or compare methods. Identify it, then give a reason drawn from the scenario, and mention what you give up. For a bank moving customer accounts to a new platform: "Parallel: the old and new systems run together so any error in the new one can be caught against the old, which matters because account balances must be correct. The cost is double running and extra staff time." Common mistakes are mixing up phased (split by module) with pilot (split by users), calling direct "the cheapest and best" without weighing its risk, and giving a definition with no link to the scenario.
Syllabus Part 2 Research and planning

The Waterfall Approach

🎯 (SE-12-01, SE-12-09)

📌 Research and use the Waterfall software development approach

  • logical progression of steps used throughout the life cycle
  • stages of ‘falling water’
  • advantages and disadvantages
  • scale and types of developments

Waterfall works through the development steps one at a time, in order. Each stage is finished and signed off before the next begins, so the project flows downwards like water over a series of ledges.

  • Logical progression of steps: requirements → design → development → testing → installation → maintenance. Each stage produces documents that the next stage relies on.
  • Stages of 'falling water': going back up is difficult and expensive. A change found during testing may mean redoing design and development.
AdvantagesDisadvantages
Clear milestones and deadlines that are easy to trackHard to respond when the client changes their mind
Thorough documentation at every stageThe client sees working software only near the end
Easy to estimate cost and time up frontProblems are often found late, when they cost the most to fix

Animated diagram

Waterfall and Agile: when does the client get working software?

The same twelve-week project run both ways, with the same change of mind in week 6.

What to notice
  • In Waterfall the value chart stays flat until the end; in Agile it climbs every sprint. This is the core trade-off to explain in an exam.
  • A late change is costly in Waterfall because finished stages must be reopened. Agile expects change and absorbs it in the next sprint.
  • Waterfall's strength is certainty: fixed requirements, clear milestones and documents at every stage. WAgile, later in this section, mixes the two.

Choose an approach with the tabs. Step with ◀ and ▶ (or the arrow keys), play or pause with Space.

Try thisFor your own project, which approach fits better? Justify it using the shape of the value chart and how likely your requirements are to change.

Scale and types of developments: Waterfall suits large projects with stable, well-understood requirements and strict regulation, such as a hospital records system or an aircraft control system.

Logical progression of steps: stages and sign-off

Each Waterfall stage ends with a deliverable that is reviewed and signed off before the next stage starts. That is what makes progress easy to track, and it is why going back is expensive. The Library Loans project would look like this.

StageDeliverable that ends the stageSign-off by
1. RequirementsRequirements specification (FR1 to FR7, NFR1 to NFR4), feasibility and scope statementMrs Chen
2. DesignData dictionary, structure chart, DFDs, wireframes, algorithmsMrs Chen and the teacher
3. DevelopmentCode committed to version control, with unit tests passingDeveloper
4. TestingTest report with the defect log closed or explainedDeveloper and teacher
5. InstallationInstalled system, data migrated, backup taken, users trainedMrs Chen
6. MaintenanceIssue log and version historyDeveloper

Stages of 'falling water': what going back costs

Suppose that at acceptance testing Mrs Chen asks for different loan periods for junior and senior students. In Waterfall the change reaches back through every finished stage.

Stage reopenedRework neededEstimate (days)
RequirementsAmend FR2 and get the specification signed again1
DesignAdd a LoanPeriod field to the data dictionary; update the structure chart and algorithm1
DevelopmentChange the loan module and its unit tests2
TestingRe-run integration and system tests, then retest with the client2
Total6

The plan has 3 spare days (32 days of critical work in a 35-day term, see Applying Project Management), so the change makes the release 3 days late. The same request in an Agile project is one new backlog item, done in the next sprint. This is the key trade-off to be able to explain.

Scale and types of developments: when Waterfall fits

ProjectWhy Waterfall suits it
Aircraft or medical device softwareRequirements are fixed by safety rules, every stage must be documented and approved, and mistakes found late can cost lives.
Government or bank system built to a contractScope, price and deadline are agreed in advance and audited.
Hardware and software built togetherPhysical parts cannot be redesigned cheaply after they are made.
Small school project with a fixed brief and one due dateThe requirements are set at the start and the milestones are easy to schedule. Waterfall is less suited if the client is likely to change their mind.
Using it in your project If your requirements are fixed by an assessment brief and a single due date, a Waterfall plan with dated milestones in a Gantt chart is a sensible choice. Justify it by pointing to those stable requirements.
HSC writing sample "Waterfall suited the exam-results portal because its requirements were set by school policy and had to be approved before development. Its logical progression of steps produced clear documentation at each stage. The disadvantage was that a change the deputy principal requested during testing required the design to be revisited, delaying release by two weeks."
Exam tip: "Research and use" Waterfall Expect to be given a project and asked to identify whether Waterfall suits it, to outline its stages, or to compare it with Agile. A full-mark answer links a feature to the scenario: "The requirements for the ticket-scanning system were fixed by the council contract, so Waterfall's sign-off at each stage gave clear evidence of progress." Then state a disadvantage in context: the client sees working software late, so a misunderstanding may not surface until testing. Common mistakes are listing the stages with no reference to the scenario, and calling Waterfall "old" or "bad" instead of naming the conditions in which it is the better choice.

The Agile Approach

🎯 (SE-12-01, SE-12-09)

📌 Research and use the Agile software development approach

  • rate of developing a final solution
  • method tailoring
  • iteration workflow
  • scale and types of developments

Agile builds software in short cycles called iterations or sprints. Each cycle delivers a small working piece that the client can try and give feedback on, so the plan keeps adjusting as the project goes.

  • Rate of developing a final solution: a usable version appears early and improves every sprint, so value arrives sooner than in Waterfall.
  • Method tailoring: teams adapt the process to suit the project, for example choosing one-week sprints or skipping formal ceremonies in a small team.
  • Iteration workflow: plan → build → test → review with the client → adjust, then repeat.
  • Scale and types of developments: best for small to medium projects where requirements are likely to change, such as a start-up's mobile app or a school's online booking system.

Process diagram

An Agile sprint cycle

How a team turns a backlog into working software, one sprint at a time.

What to notice
  • The client sees working software at every review.
  • The retrospective improves the process for the next sprint.

Try thisAt which point in the cycle can the client change priorities?

▶ Watch & Learn

A quick, plain-English overview of Agile and the Scrum framework — sprints, backlogs, and reviews — the iterative approach described above.

Rate of developing a final solution

Agile measures progress by working software, not documents. Requirements become a backlog of user stories, and each story is given a size in story points (a relative estimate of effort). The points a team finishes in a sprint are its velocity. Averaging past velocities gives a forecast that improves every sprint. The Library Loans backlog, with the stories tied to the requirement IDs:

StoryRequirementPoints
Issue a loanFR25
Refuse a loan at the limitFR33
Record a returnFR43
Search the catalogueFR15
Overdue listFR55
Calculate finesFR63
Staff sign-inNFR22
Total26
After sprintPlannedCompletedTotal doneRemainingAverage velocityForecast: sprints left
1888188.03 (18 ÷ 8 = 2.25, rounded up)
28614127.02 (12 ÷ 7 = 1.7, rounded up)
3772157.01 (5 ÷ 7 = 0.7, rounded up)
4552606.5Finished
Python: forecast from velocity
import math

completed = [8, 6, 7]                        # points finished in sprints 1 to 3
remaining = 26 - sum(completed)              # points still in the backlog
velocity = sum(completed) / len(completed)   # average points per sprint
print(round(velocity, 1), remaining, math.ceil(remaining / velocity))

Expected output: 7.0 5 1, meaning an average of 7.0 points a sprint, 5 points left, and 1 more sprint. The client had a working issue-and-return system after sprint 2, well before the final sprint. That early value is the difference from Waterfall.

Method tailoring

Method tailoring means adapting the framework to suit the project rather than following it rigidly. Scrum was written for small teams, so a solo student keeps the purpose of each practice and changes its form.

Scrum practicePurposeTailored for a solo student project
Product ownerDecides prioritiesMrs Chen orders the backlog
Sprint lengthA short cycle to get feedbackOne week, so there are four sprints in the build phase
Daily stand-upShare progress and blockersA five-line entry in the process diary at the start of each session
Sprint reviewClient sees working softwareA 15-minute demonstration to Mrs Chen at the end of the sprint
RetrospectiveImprove the processThree diary bullets: what went well, what did not, one change
Task boardMake work visibleA GitHub Projects or Trello board

Iteration workflow

Each iteration follows plan, build, test, review, adjust. Sprint 2 of Library Loans, as a plan:

  • Sprint goal: a returned book is recorded, fines are calculated and staff can sign in.
  • Sprint backlog: record a return (3 points), calculate fines (3 points) and staff sign-in (2 points), so 8 points planned.
  • Build and test: write each function with its unit tests, commit small changes, keep the board up to date.
  • Definition of done: the code is committed, unit tests pass, the acceptance criteria are met, and Mrs Chen has seen it working. A story that misses any one of these is not counted.
  • Review and adjust: at the demonstration the returns and fines worked, but password hashing for sign-in was unfinished. A story counts only when it is done, so 2 points were completed short and the velocity was 6, not 8. Sign-in moves to sprint 3 and the forecast is updated.
A task board part-way through sprint 2
To doDoingTestingDone
Sign-in: hash the passwordsFines: cap at $10.00Return: book becomes availableIssue a loan; refuse at the limit (sprint 1)

Scale and types of developments: when Agile fits

Agile suits small to medium projects, often with one team, where the client is available and requirements are likely to change. The Agile Manifesto (2001) states the values behind it: individuals and interactions over processes and tools; working software over comprehensive documentation; customer collaboration over contract negotiation; and responding to change over following a plan. The items on the right still matter, but the items on the left matter more.

Fits wellFits less well
A start-up's mobile app whose features are still being discoveredA fixed-price contract with a fixed scope and penalties for delay
An internal tool with a client who can attend reviewsSafety-critical systems needing formal evidence at each stage (often handled with a hybrid such as WAgile)
A school project where feedback from real users shapes the designA client who cannot attend reviews, so feedback never arrives
Exam tip: "Research and use" Agile Questions often ask you to explain why Agile suits a scenario, or to compare it with Waterfall. Tie each Including item to the scenario: the rate (a working version early), tailoring (short sprints, small team), the iteration workflow (plan, build, test, review) and the scale (small to medium). For a start-up food-ordering app: "Agile suits it because the client can review working screens each sprint, so changes to the menu design are absorbed cheaply. The risk is scope growth without a fixed end date." Common mistakes are saying Agile means "no planning or documentation", and stating a benefit without saying who gets the feedback.

The WAgile Approach

🎯 (SE-12-01, SE-12-09)

📌 Research the WAgile software development approach

  • understanding it is a hybrid model
  • analysis of the ‘when’ and ‘how’ intervention is applied during the development life cycle
  • scale and types of developments

WAgile is a hybrid model: it plans and closes a project the Waterfall way but builds the software in Agile sprints.

  • When intervention is applied: at fixed checkpoints, such as signing off requirements, approving a design, and a final security audit before release.
  • How intervention is applied: through formal reviews and sign-offs at those gates. Between them, the team works in sprints and adapts to feedback.
  • Scale and types of developments: medium to large projects that need both flexibility and firm control, such as a bank adding a new feature to an existing regulated system.

Timeline

WAgile: planned gates around Agile sprints

Waterfall-style gates at the start and end, with iterative sprints between them.

What to notice
  • The gates are the planned interventions; the sprints are where the software is built.

Try thisWhich gate would a government client insist on, and why?

WaterfallAgileWAgile
PlanningAll up frontEach sprintUp front, then refined each sprint
ChangeHardWelcomedWelcomed between gates
Control pointsEnd of each stageSprint reviewsFormal gates plus sprint reviews
Best forStable, regulated projectsChanging requirementsRegulated projects that still need flexibility

Analysing the 'when' and 'how' of intervention

Intervention is a planned point at which someone outside the build team checks or changes direction. In WAgile the when is the gate, and the how is the evidence and approval the gate requires. For Library Loans:

StageStyleWhen intervention happensHow it is applied
Requirements and feasibilityWaterfall gateEnd of week 1Mrs Chen signs the requirements specification, scope statement and estimate
DesignWaterfall gateEnd of week 2The teacher and Mrs Chen review the data dictionary, structure chart and wireframes
BuildAgile sprintsEnd of each one-week sprintDemonstration to Mrs Chen; backlog reordered within the agreed scope
Security and privacy checkWaterfall gateBefore releaseChecklist: only a name and ID stored, passwords hashed, no student data outside the school network
Acceptance and installationWaterfall gateWeek 7Acceptance test signed off, backup taken, users trained

Choosing a development approach: criteria

To choose between Waterfall, Agile and WAgile, rate each approach against criteria drawn from the project and weight the criteria that matter most. Here is a weighted decision matrix for Library Loans (each rating is out of 5, and the weight shows how much the criterion matters, from 1 to 3).

CriterionWeightWaterfallAgileWAgile
Requirements likely to change3254
Client can review often2254
Fixed deadline and scope3534
Documents and sign-offs needed2524
Fit for a solo developer1433
Weighted total394143

Each total is the sum of weight × rating. For Waterfall: 3×2 + 2×2 + 3×5 + 2×5 + 1×4 = 39. WAgile scores highest because the school needs sign-offs and a fixed deadline, yet Mrs Chen can still steer the build. The totals are close, and different weights could change the answer. What earns marks is the reasoning behind each rating, not the arithmetic.

Try it

Decision matrix: change what matters

Adjust the weights and see which approach scores highest. Enable JavaScript to use this tool. In short: the total for each approach is the sum of weight multiplied by rating, so changing what matters can change the winner.

HSC writing sample "WAgile is a hybrid model, so intervention is applied at planned gates rather than continuously. For the council permit system, requirements and the final security audit were Waterfall gates because the council must approve them, while the forms and dashboard were built in Agile sprints so staff feedback could shape them."
Exam tip: "Research" WAgile WAgile is a hybrid: say which parts are Waterfall (planned gates, sign-offs, fixed early planning) and which are Agile (sprints, feedback between gates). Questions may ask you to identify a stage that would be a gate, or to compare the three approaches for a scenario. A strong answer names the gate, when it happens and who approves it, then names the sprint work between gates. The most common mistake is defining WAgile as "a bit of both" without saying where each half applies.

Try it

Waterfall, Agile or WAgile?

Choose the approach that best fits six projects. Enable JavaScript to use this tool. In short: Waterfall plans first, Agile adapts constantly and WAgile uses planned gates around sprints.


Applying Project Management

🎯 (SE-12-05, SE-12-09)

📌 Apply project management to plan and conduct the development and implementation of a project and software engineering solution

  • scheduling and tracking using a software tool, including Gantt charts
  • using collaboration tools

Apply project management to plan and conduct the development of a software solution. This involves scheduling and tracking using software tools, notably 🛠️ Gantt charts, to allocate time to tasks, and using collaborative tools (e.g., GitHub, Jira) to track team progress.

▶ Watch & Learn

Meet the three key Scrum roles — Product Owner, Scrum Master, and Development Team — useful for understanding how project teams divide responsibility and communicate.

Gantt Chart — Project Schedule

A Gantt chart is a horizontal bar chart that maps project tasks against a timeline. It visually shows the start date, duration, and end date of each task, and can indicate task dependencies (where one task must complete before another begins). A useful Gantt chart for your project covers all four syllabus phases (identify and define, research and plan, produce and implement, test and evaluate), so it is easy to show that no phase was skipped.

Gantt chart

Gantt chart: a seven-week project

Tasks on a timeline, with dependencies and milestones.

What to notice
  • Each task starts after the task it depends on.
  • Diamonds mark milestones, such as specifications being signed off.

Try thisSprint 1 runs three days late. Which later tasks move?

What a Gantt chart must show

NESA's Course Specifications (p. 11) say a Gantt chart displays each component task on an estimated timeline, and list what it should show:

  • Self-explanatory task names ("Search module", not "Task 4").
  • The estimated time for each task and its dependent tasks, meaning tasks that cannot start until another finishes.
  • A time scale with dates, and important milestones clearly marked.
  • Optionally, resources: the chart can allocate team members to tasks and show each person's percentage completion.
  • Regular updates during development to compare actual with estimated times.

Worked example: dependencies, float and the critical path

Some tasks can run at the same time; others must wait. The critical path is the longest chain of dependent tasks, and it decides the earliest finish date. (The critical path is a standard planning technique; NESA's specification asks for dependencies and milestones and does not name it, but it is the way to find which dependencies matter most.) For each task, work out four times and one number:

  • ES (earliest start) is the latest EF of the tasks it depends on, or 0 if there are none. EF (earliest finish) = ES + duration. This is the forward pass.
  • LF (latest finish) is the earliest LS of the tasks that depend on it, or the project end if none do. LS (latest start) = LF − duration. This is the backward pass.
  • Float (slack) = LS − ES. It is how many days a task can slip without delaying the project. Tasks with zero float are critical.
TaskDaysDepends onESEFLSLFFloat
A Requirements5none05050 (critical)
B Feasibility and budget3A58580 (critical)
C Data dictionary, structure chart4B8128120 (critical)
D Wireframes, client review5B81313185
E Loan module8C122017255
F Search module6C121812180 (critical)
G Interface build7D, F182518250 (critical)
H Integration testing4E, G252925290 (critical)
I Documentation, process diary6C1218232911
J Client acceptance testing3H, I293229320 (critical)

Task G must wait for both D (finishes on day 13) and F (day 18), so G starts on day 18, and D has 5 days of float. The critical path is A → B → C → F → G → H → J = 5 + 3 + 4 + 6 + 7 + 4 + 3 = 32 days. The term gives 35 days, so the plan has 3 days of spare time.

Gantt chart

The critical path of the Library Loans project

The same ten tasks on a 32-day timeline. Red tasks are critical; green tasks have float.

What to notice
  • The red tasks form an unbroken chain from day 0 to day 32. Delay any one of them and the project finishes later.
  • The Loan module (E) looks longest, but it is not critical: it has 5 days of float because integration testing waits for the interface build.

Try thisThe Search module (F) takes 4 days longer. What happens to the finish date? Then try the same delay on the Loan module (E) in the checker below.

Critical path checker. This interactive tool needs JavaScript. Without it, use the table above: a 4-day delay to F (a critical task, float 0) moves the finish from day 32 to day 36, while a 4-day delay to E (float 5) changes nothing.

To reproduce the table in code, the passes are short. This program computes the same numbers.

Python: forward and backward pass
tasks = {
    "A": (5, []),
    "B": (3, ["A"]),
    "C": (4, ["B"]),
    "D": (5, ["B"]),
    "E": (8, ["C"]),
    "F": (6, ["C"]),
    "G": (7, ["D", "F"]),
    "H": (4, ["E", "G"]),
    "I": (6, ["C"]),
    "J": (3, ["H", "I"]),
}

early = {}
for name, (days, before) in tasks.items():          # forward pass
    start = max((early[p][1] for p in before), default=0)
    early[name] = (start, start + days)

project = max(finish for start, finish in early.values())

late = {}
for name in reversed(list(tasks)):                   # backward pass
    days = tasks[name][0]
    after = [n for n, (d, before) in tasks.items() if name in before]
    finish = min((late[n][0] for n in after), default=project)
    late[name] = (finish - days, finish)

print(f"Project duration: {project} days")
for name in tasks:
    spare = late[name][0] - early[name][0]
    print(name, "early", early[name], "late", late[name], "float", spare, "CRITICAL" if spare == 0 else "")

Expected output: Project duration: 32 days, then one line per task. Tasks A, B, C, F, G, H and J print CRITICAL; D and E print float 5 and I prints float 11. For example, the line for D is D early (8, 13) late (13, 18) float 5.

Tracking: actual versus estimated

A plan is only useful if you keep it up to date. At each check, record the actual time, work out the variance, and ask whether the task was on the critical path. Only a slip on a critical task (or a slip larger than the float) moves the finish date.

TaskPlanned (days)Actual (days)VarianceCritical?Response
A Requirements56+1YesClient meeting was rescheduled; recorded in the diary
B Feasibility and budget330YesNone needed
C Data dictionary, structure chart45+1YesExtra validation rules took longer than estimated

After three tasks the critical path has slipped by 2 days, so the forecast finish is day 34 of 35 and only 1 spare day remains. The response is to protect the critical path: trim the polish on the interface (task G) rather than the testing (task H), and tell Mrs Chen at the next review. The same figures can be shown on the chart by updating each bar to its actual length, as NESA's specification suggests.

Budgeting

A budget estimates what the project will cost and is then compared with what it actually costs. A school project usually has no cash budget, but time is a budget too (49 hours in the feasibility example). To practise costing, suppose a professional developer built the same core scope for a paying client at illustrative rates.

ItemBasisCost (AUD)
Developer time42 hours at $60 an hour2,520.00
Software licences and hosting for the first yearEstimate150.00
Subtotal2,670.00
Contingency15% of the subtotal400.50
Total budget3,070.50

The rate and the licence cost are invented for practice. In a real project you would use the organisation's rates and quotes. Track spending against the budget as the project goes, and report any variance: if 10 hours are used before the design is finished and only 5 were planned, the budget is already under pressure and the client should hear about it early. A project with free tools, like this one, still records its time budget and any costs avoided by using free software.

Using collaboration tools

NESA's glossary defines collaborate as working with others towards a shared goal, through a variety of modes of communication, which may be achieved using a range of technologies, tools and processes. A tool is worth using if it makes work visible, keeps a record, or makes it easy for the client and peers to respond.

PurposeExample toolsLibrary Loans use
Code history and reviewGit and GitHub (branches, pull requests, issues)Each feature on its own branch; a peer reviews the pull request before it merges
Task trackingGitHub Projects, Trello, JiraA board with To do, Doing, Testing and Done columns, one card per user story
Shared documentsGoogle Docs, Microsoft OneDriveThe requirements specification and meeting minutes, where Mrs Chen can comment
Design and prototypesFigma, CanvaWireframes the client comments on before any interface code is written
CommunicationEmail, Teams, Google ChatFortnightly review invitations and short questions; decisions are copied into the process diary

Before choosing a tool, check your school's rules on cloud services, because some tools store data outside Australia and student information must not be uploaded to them.

Process Diary Example Excerpt

The process diary (or log book) is a chronological record of your development journey. NESA's Course Specifications (p. 12) say entries, made at regular intervals, should include the date, the person making the entry, progress since the last entry, tasks achieved, stumbling blocks or issues and how they were managed, possible approaches for upcoming tasks, reflective comments and resources used. The excerpt below covers each of these.

Date and entry by Progress and tasks achieved Decisions Made & Reasoning Stumbling blocks and how they were managed Next steps and resources used
Week 1
Mon 2 Feb 2026
S. Nguyen
Initial client meeting with the school librarian (Mrs Chen). Discussed current paper-based system and pain points. Identified loan tracking and overdue reporting as the two highest-priority problems. Decided to focus the project scope on these areas. Client had difficulty articulating technical requirements — used guided questions: "What does a typical day look like?" and "What is most frustrating about the current process?" Draft functional and non-functional requirements for client review by Week 2. Resources used: interview notes and photographs of three cards.
Week 3
Wed 18 Feb 2026
S. Nguyen
Completed structure chart and Level 0 DFD. Began algorithm design for the book search module using pseudocode. Chose WAgile over pure Waterfall or pure Agile. The school needs signed-off requirements and a security check at fixed gates, but building in one-week sprints lets the client steer each iteration. Reflection: the decision matrix gave a close result, so I will review the choice after sprint 1. Initially designed the search as a sequential scan — after research, switched to a dictionary-based lookup for O(1) ISBN lookups, significantly improving efficiency on large catalogues. Build the search and loan modules in weeks 4 and 5. Resources used: Python documentation, the structure chart and the data dictionary.
Week 5
Tue 3 Mar 2026
S. Nguyen
Implemented LoanService class. Discovered BUG-002 (loan limit not enforced) during manual testing. Fixed the off-by-one error in can_borrow() — changed <= to < in the comparison. Added a unit test to prevent regression. The bug was caused by incorrect operator choice. Added this case to the test data table as a boundary test to ensure the limit is correctly enforced on future changes. Complete UI implementation; schedule the Phase 4 acceptance test with Mrs Chen for Week 7. Resources used: VS Code debugger, the defect log.
Process diary tips
  • Date every entry and sign it: A diary shows the work happened over time. An undated entry cannot show when a decision was made, and in a team the entry must say who made it.
  • Record decisions and reasoning: Don't just state what you did — explain why you chose one approach over another (e.g., "I chose a phased implementation because..."). This demonstrates higher-order thinking.
  • Include annotated screenshots: Annotate wireframes, Gantt charts, and planning documents to show your understanding of their purpose. A screenshot without annotation adds little evidence.
  • Record client feedback: Summarise every client interaction. Include what feedback was given and how you responded to it in your planning and design.
  • Reflect on setbacks: Note when tasks took longer than expected and how you adjusted the schedule. This demonstrates project management competency.

Social and Ethical Issues in Project Work

🎯 (SE-12-05, SE-12-09)

📌 Explore social and ethical issues associated with project work, including working individually, collaboratively and responding to stakeholders

Project work raises social and ethical questions about how people are treated, whether you work alone or in a team.

SituationIssues to manage
Working individuallyManaging your own time, being honest about progress, and acknowledging code or ideas you did not write yourself.
Working collaborativelySharing work fairly, respecting different skills and views, and crediting each person's contribution.
Responding to stakeholdersBeing transparent about what the software will and won't do, protecting users' data, and treating feedback respectfully.
Scenario A team member copies a login system from a tutorial without acknowledging it. The ethical response is to cite the source in the documentation and check that its licence allows reuse.

Working individually

Working alone removes team conflict but not responsibility. The issues are honesty, acknowledgement and self-management.

  • Honest reporting. Record what you did and what went wrong in the process diary. Do not present a feature that is half-working as finished, and do not claim testing you did not do.
  • Acknowledging others' work. Copying code, images or ideas without credit is plagiarism, and it may also breach copyright (the Copyright Act 1968). Open-source code can be reused under its licence, which usually requires you to keep the author's notice. Add a comment with the source and licence next to any borrowed code.
  • Tools that write code. If generative AI is allowed on a task, say how you used it and make sure you can explain every line. NESA's ACE rules require marks to reflect your own knowledge, skills and understanding.
  • Managing your own time. Tell the client early if a deadline is at risk instead of hiding it.

Working collaboratively

In a team the extra issues are fair distribution of work, credit, respect for different views and skills, and handling disagreement. Suppose a classmate, Ben, joins the Library Loans project to build the interface.

  • Agree roles and rules early: who owns which modules, how code is reviewed, and how disagreements are settled (for example, the client's stated requirements decide).
  • Make contributions visible. Version control records who did what, so credit can be shared accurately:
Bash: who contributed what (example output)
git shortlog -sn --no-merges
    14  Sam Nguyen
     9  Ben Ortiz

Commit counts are a starting point for a conversation, not a mark: one large, careful commit can be worth more than ten trivial ones. Combine them with the task board and diary entries.

  • Review kindly and specifically. "This loop will fail for an empty list" helps; "this is messy" does not. Criticise the code, not the person.
  • Handle an uneven workload by talking early, adjusting the plan, and telling the teacher if it is not resolved, rather than quietly redoing a partner's work or letting it slide.

Responding to stakeholders

A stakeholder is anyone affected by, or with an interest in, the software. They often want different things, so the ethical task is to be transparent, protect the people who have no voice in the room, and record how conflicts were settled.

StakeholderInterestPossible conflict
Mrs Chen (client)Accurate loans, less typing, a clear overdue listWants the overdue list to show every detail, which exposes more student data than needed
Students who borrowFast service, privacy about what they readAre not in the room when features are decided
Library volunteersA simple screen that needs little trainingNeed shortcuts that could weaken sign-in security
School IT and the principalSecurity, and data staying on the school networkMay reject a tool the developer prefers
Parents and carersTheir children's information kept safeUnaware the system exists unless the school tells them
  • Be transparent about what the software will and will not do, including its known limitations.
  • Protect personal information. Collect only what the requirements justify (data minimisation). Under the Australian Privacy Principles in the Privacy Act 1988, organisations covered by the Act must also keep personal information secure and use it only for the purpose it was collected. Which privacy law covers a school depends on the school, so check it. The Secure Software Architecture page explains this.
  • Design for inclusion. Consider users with low vision, motor difficulties or limited English: readable contrast, keyboard use, plain language.
  • Resolve conflicts openly: in the example, the overdue list shows the title and days overdue only to signed-in staff, which meets Mrs Chen's need and limits the exposure of student data. Record the decision.
HSC writing sample "Working collaboratively raised the ethical issue of fair credit. The team logged each member's commits and tasks in the project board, so the final report acknowledged everyone's contribution accurately. When a stakeholder asked for data the app did not need, the team explained the privacy risk and collected only what the requirements justified."
Exam tip: "Explore" social and ethical issues A short-answer item usually gives a scenario and asks you to identify, describe or discuss issues. Name the issue, say who is affected, and give a response. For a team app that uses a client's customer list: "Privacy: the list contains personal information, so the team should collect only what is needed and store it securely, because the customers never agreed to wider use." Cover all three settings (individual, collaborative, stakeholders) when the question asks for a range, and avoid vague words such as "unfair" or "unethical" without saying what should be done.

Communication Issues in Project Work

🎯 (SE-12-09)

📌 Explore communication issues associated with project work

  • involving and empowering the client
  • enabling feedback
  • negotiating

Good communication keeps the client, the team and the software pointed at the same goal.

  • Involving and empowering the client: invite the client to reviews and let them make decisions about priorities, so the solution is theirs as well as yours.
  • Enabling feedback: make it easy to comment, for example with a demo at the end of each sprint and a simple feedback form.
  • Negotiating: agree on what is realistic. If a feature won't fit the deadline, offer options, such as a simpler version now and the full feature later.
HSC writing sample "Fortnightly demonstrations involved the client in each iteration and enabled feedback early, which revealed that teachers needed a printable roll. Negotiating the scope moved the attendance graph to a later release so the printable roll could be delivered on time."
Scenario Halfway through the project, the client asks for SMS reminders. Instead of saying yes or no, the student explains the extra time and cost, offers email reminders now and SMS in a later version, and records the agreed decision in the process diary. That is negotiating, and it keeps the client involved in the choice.

Involving and empowering the client

Involving the client means including them in decisions from the start. Empowering them means giving them real authority over the things only they can judge, and the information to use it. The Library Loans project does this in four ways.

  • Mrs Chen owns the priorities. She orders the backlog and decides which stories come first.
  • Plain language. The student shows wireframes and a working demonstration, and avoids terms such as "ORM" and "endpoint" unless they are explained.
  • Options, not verdicts. "There are two ways to show overdue books. Here is what each costs in time. Which suits your Friday routine?"
  • Acceptance criteria written with her, so she knows exactly what "done" means for each story.

A communication plan

Decide in advance who needs what information, how, and how often. Written down, this is a communication plan.

AudienceWhat they needChannelWhen
Mrs Chen (client)Progress, working demos, decisions to make15-minute review in person, then a written summary by emailEvery second Friday and at the end of each sprint
TeacherEvidence of planning and progress, risksProcess diary and Git historyEvery lesson
Peer reviewerThe pull request and what to checkGitHub pull request commentsWhen a feature is ready
Library volunteersHow to use the systemOne-page guide and a short demonstrationBefore installation

Enabling feedback

Feedback only arrives if giving it is easy and the client can see what happens to it. Match the method to the question you are asking.

MethodBest forExample
Demonstration with questionsWhether the software behaves as expectedThe end-of-sprint demo: "Show me how you would return a book."
Observation of a real taskUsability problems users would not think to mentionWatch a volunteer issue a loan without helping, and note where they hesitate
Short surveyComparing views from several usersA 1 to 5 ease-of-use rating plus one open question
Shared comments on documents and prototypesDetailed, asynchronous feedbackMrs Chen comments on the wireframes in Figma

Close the loop: tell the client what changed because of their feedback and what did not, with a reason. People stop giving feedback that disappears.

Negotiating

Negotiating is reaching an outcome both sides can accept, usually by trading scope, time and quality rather than simply refusing or agreeing. A useful order: listen to the real need behind the request, show the effect on time and cost with numbers, offer options, agree in writing, and record it.

Worked example: a change request in week 3
StepLibrary Loans
RequestMrs Chen asks for email reminders to members before books are due.
Underlying needFewer overdue books, and less chasing on Fridays.
Effect shownThe feature is 8 more hours, and the project only has 0.7 hours to spare (see the feasibility example).
Options offered(a) add it and drop the CSV export; (b) print a "due next week" list from the existing overdue code now, and add email in version 2; (c) extend the deadline (not possible, the term ends).
AgreementOption (b): the printable list meets the underlying need within budget.
RecordDecision, date and reason written in the process diary and the change request log; requirement FR8 added as "later".
Exam tip: "Explore" communication issues Expect questions that give a client situation, such as a client who keeps changing requirements or never attends reviews, and ask you to describe how the developer should respond. Name the technique from the syllabus (involving and empowering the client, enabling feedback, or negotiating) and show it in action: "The developer offers two options with their time cost so the client decides, and records the choice." Common mistakes are answering with a generic "communicate more" and treating negotiating as saying no.

Quality Assurance

🎯 (SE-12-01, SE-12-06, SE-12-07)

📌 Investigate how software engineering solutions are quality assured

  • defining criteria on which quality will be judged
  • ensuring requirements are met using a continual checking process
  • addressing compliance and legislative requirements

Quality assurance (QA) is everything a team does to make sure the finished software is good enough, not just at the end but throughout the project. It has three parts.

Part of QAWhat it involvesExample for Library Loans
Defining quality criteriaAgree measurable targets with the client before buildingSearch returns in under 2 seconds (NFR1); issuing a loan takes no more than 3 clicks
Continual checkingTest against the requirements at every stage, not only at the endAutomated tests run on every commit; a client demo every sprint
Compliance and legislationMeet the laws and standards that applyPrivacy law for student data; WCAG 2.2 AA for accessibility

Defining criteria on which quality will be judged

Quality means "fit for the purpose the client has". It is judged against criteria agreed before building, each with a target that can be measured. Standard quality models, such as ISO/IEC 25010, list characteristics like functionality, performance, usability, reliability, security and maintainability. Turn each characteristic that matters into a measurable criterion and a check.

Quality characteristicMeasurable criterionHow it is checked
Functional correctnessEvery Must requirement passes its test cases (FR1 to FR5)Test plan results
PerformanceSearch returns in under 2 seconds for 10,000 titles (NFR1)Timed test on a generated catalogue
UsabilityA new volunteer issues a loan within 15 minutes of first use (NFR3)Timed walkthrough
SecurityNo plaintext passwords; signed-out users see nothing (NFR2)Database inspection, sign-out test
MaintainabilityEvery function has a docstring; linter reports no style errors (NFR4)Linter run and peer review
ReliabilityNo unhandled exception on any invalid input in the test dataErroneous-data tests

Quality assurance is about the whole process (planning, standards, reviews, testing during development) so that defects are prevented. Quality control checks the finished product for defects. A project needs both.

Ensuring requirements are met using a continual checking process

The later a defect is found, the more it costs to fix, so checks are built into every stage instead of waiting for the end. Every check points back to a requirement ID.

WhenCheckWhat it protects
Every save or commitRun the unit tests and a style checkerA new change has not broken an old rule
Before merging a branchPeer code review with the checklist in Part 4Logic errors, unclear code, security slips
End of each sprint or stageDemonstrate to the client against the acceptance criteriaBuilding the wrong thing
Before installationFull regression test, security and privacy checklistLate surprises and old defects returning
After installationDefect log reviewed with the clientProblems that only appear in real use

Addressing compliance and legislative requirements

Software must obey the law and relevant standards, so compliance is a quality criterion like any other. Identify what applies early and turn it into requirements. This table is a study aid and not legal advice.

RequirementWhat it means for a projectLibrary Loans example
Privacy Act 1988 and the Australian Privacy Principles (OAIC)Collect only what you need, use it for the stated purpose, keep it secure, and allow people to see and correct it. It covers Australian Government agencies and many private organisations; NSW public schools are covered by NSW privacy laws instead.Store only a name and student ID; passwords hashed; data stays on the school network
Notifiable Data Breaches schemeOrganisations covered by the Privacy Act must notify affected people and the OAIC about an eligible data breach likely to cause serious harm.The school has a plan for who is told if the database is exposed
Copyright Act 1968 and licencesYou may reuse others' code, images and fonts only as their licences allow.Credit the open-source libraries used and keep their licence files
Disability Discrimination Act 1992 and WCAGDigital services should be accessible. WCAG (from the W3C) is the technical standard for web accessibility.Keyboard-operable screens, readable contrast, labelled buttons
School and department policyRules about where data is stored, which tools may be used, and the use of AI.No cloud services without approval
HSC writing sample "Quality was assured by agreeing measurable criteria with the librarian, such as a two-second load time, and checking them continually through automated tests and fortnightly demonstrations. Storing only a student's name and ID helped the system comply with the Australian Privacy Principles."
Exam tip: "Investigate" quality assurance Cover all three parts: criteria, continual checking and compliance. A question may ask you to outline two ways a team could quality assure a scenario, or to explain why testing only at the end is risky. A full-mark answer states a measurable criterion (for example, a page loads within 2 seconds), a stage at which it is checked, and a law or standard where relevant. Common mistakes are treating QA as "testing at the end" and naming legislation without saying what the developer must do because of it.

Using Modelling Tools

🎯 (SE-12-06)

📌 Demonstrate the use of modelling tools

Modelling tools let you plan and explain a system before and while you build it. Choose the tool that answers the question you have: a data flow diagram for how data moves, a structure chart for how the program is divided into modules, and a decision tree or table for complex choices. In your project, show a model and explain how it shaped your code.

Data Flow Diagram (DFD)

A Data Flow Diagram (DFD) models how data moves through a system. It shows external entities (users or other systems), processes that transform data, data stores (databases or files), and the data flows connecting them. A Level 0 DFD (Context Diagram) shows the entire system as a single process with all external entities. A Level 1 DFD expands the main process into its sub-processes.

Data flow diagram

Data flow diagram: a library system (Level 0)

The whole system as one process, with the external entities that send and receive data.

What to notice
  • A Level 0 diagram shows no data stores and no internal processes.
  • Every arrow is labelled with the data it carries.

Try thisRefine the Library system process into a Level 1 DFD with three processes and a Loans data store.

Level 1 for Library Loans: a worked answer

A Level 1 DFD opens up the single process and shows the data stores. NESA's symbols are a circle for a process, a labelled curved arrow for a data flow, a data store, and a rectangle for an external entity. The canteen figure below uses the same notation on a different system, so you can check the symbols. The table gives the Library Loans answer flow by flow.

ProcessData inData outData stores used
1 Issue loanLoan request from Student; member details from D1 Members; book status from D2 BooksLoan receipt to Student; new loan to D3 Loans; updated book status to D2 BooksD1 Members, D2 Books, D3 Loans
2 Return bookReturned book from Student; loan record from D3 LoansClosed loan to D3 Loans; updated book status to D2 BooksD2 Books, D3 Loans
3 Produce overdue reportLoans from D3 Loans; request from LibrarianOverdue report to LibrarianD3 Loans

Data flow diagram

Level 1 data flow diagram: a canteen ordering system

A different system drawn in the same notation: two processes, one data store and two external entities.

What to notice
  • Data cannot flow directly between two data stores or between two external entities. Every flow starts or ends at a process.
  • Processes are numbered and the data store is labelled D1.

Try thisDraw the Library Loans Level 1 DFD from the table above, with three circles and three data stores.

Choosing the right tool

Question you need to answerToolNotation to remember (NESA)
How does data move around the system?Data flow diagramCircle for a process, data store, rectangle for an external entity, labelled curved arrows. Level 0 shows one process and no data stores.
How is the program divided into subroutines?Structure chartModules, open circle for data, filled circle for a flag, diamond for a decision, curved arrow for repetition.
What happens for each combination of conditions?Decision treeEvery branch labelled; each path ends in an action.
What are the classes, attributes and methods?Class diagramClass boxes with attributes and methods; inheritance and multiplicities.
Which screens exist and how do they link?StoryboardScreens and the links between them.
What is the exact logic of a step?Pseudocode or flowchartSequence, selection and repetition only; every IF has an ENDIF.

Decision tree: can this loan be issued?

The rules for FR2 and FR3 are decisions in sequence, so a decision tree shows every outcome. It also sets the number of test cases: there is one path to each outcome, and so three paths need at least three tests.

Decision tree

Decision tree: can this loan be issued?

Two questions lead to three outcomes.

What to notice
  • Every branch is labelled Yes or No, and each path ends in an action.
  • Three outcomes mean three paths, so a test plan needs at least one test for each.

Try thisAdd a third question: "Does the member have an unpaid fine over $5.00?" How many outcomes and paths are there now?

Show a model and explain how it shaped your code. Example: the structure chart named Borrowing, Returning and Search as separate modules, so the code has issue_loan(), return_book() and search_by_title() in separate files. A change to the search then cannot break the loan rules.

Exam tip: "Demonstrate" the use of modelling tools Exam items ask you to construct, complete or interpret a diagram, so use NESA's symbols exactly. NESA's HSC familiarisation questions include a structure chart true/false item, and the marker feedback on the 2025 class diagram question asked for appropriate symbols. Label every data flow and every decision branch, number the processes in a DFD, and do not draw a data store or internal process on a Level 0 diagram. Common mistakes are drawing a flowchart when a structure chart was asked for, and joining two external entities directly.

The Contribution of Back-End Engineering

🎯 (SE-12-02, SE-12-03)

📌 Explain the contribution of back-end engineering to the success and ease of software development

  • technology used
  • error handling
  • interfacing with front end
  • security engineering

Explain the contribution of back-end engineering to the success and ease of software development:

Technology Used

The selection of server-side frameworks and database technologies fundamentally determines a project's performance, scalability, and long-term maintainability. For example, a Django (Python) framework provides a built-in ORM, authentication system, and admin panel — reducing development time for data-driven applications. Alternatively, Node.js enables non-blocking I/O suited to high-concurrency environments, such as real-time chat applications. Database choice is equally critical: a relational database such as PostgreSQL enforces data integrity through foreign keys and ACID transactions, whereas a NoSQL database such as MongoDB offers flexible document schemas suited to rapidly evolving data models.

Error Handling

Robust error handling ensures the server remains stable and informative when unexpected inputs or system failures occur. Without it, an unhandled exception could crash the entire server process — making the application unavailable to all users simultaneously. For example, a try/except block in Python can catch a database connection timeout and return a user-friendly 503 Service Unavailable HTTP response, rather than exposing a raw stack trace to the client. Also, structured logging (e.g., Python's logging module) records error details for post-mortem debugging, without leaking sensitive system information to end-users.

Interfacing with Front End

Back-end engineers design Application Programming Interfaces (APIs) that define precisely how the front-end client requests and receives data. A RESTful API uses standard HTTP methods (GET, POST, PUT, DELETE) with JSON payloads, allowing any front-end technology — React, Angular, or a mobile app — to consume the same endpoints without modification. For example, a GET request to /api/students/42 would return a JSON object containing that student's profile. Efficient API design minimises data transfer by returning only required fields, and uses HTTP status codes correctly (200 OK, 404 Not Found, 401 Unauthorised) so the front end can respond appropriately to every outcome.

Security Engineering

The back end is the primary line of defence against malicious attacks. Password security is implemented through cryptographic hashing algorithms such as bcrypt, which store a one-way hash rather than plaintext — meaning a complete database breach still cannot reveal user credentials. Input sanitisation and parameterised SQL queries prevent SQL injection attacks, where an attacker might otherwise embed SQL commands in a form field to manipulate or delete database records. Also, implementing HTTPS with TLS certificates encrypts all data in transit, protecting against man-in-the-middle attacks on public networks.

Worked example: a small back-end endpoint

The Library Loans back end could expose one endpoint that the front end calls to look up a member. Each numbered comment marks one of the four Including items.

Python (Flask): one endpoint, four contributions
import logging
import sqlite3

from flask import Flask, jsonify            # (1) technology used: a small framework

app = Flask(__name__)
logging.basicConfig(level=logging.INFO, format="%(levelname)s %(message)s")
DB_PATH = "library.db"


@app.get("/api/members/<member_id>")       # (3) interface with the front end: URL, method, JSON
def get_member(member_id):
    """Return one member as JSON, or a clear error the front end can act on."""
    try:
        with sqlite3.connect(DB_PATH) as db:
            row = db.execute(
                "SELECT member_id, name FROM members WHERE member_id = ?",   # (4) security: parameterised query
                (member_id,),
            ).fetchone()
    except sqlite3.Error:
        logging.exception("Database error while looking up a member")     # (2) error handling: detail to the log
        return jsonify(error="Service temporarily unavailable"), 503       #     generic message to the user
    if row is None:
        return jsonify(error="Member not found"), 404
    return jsonify(member_id=row[0], name=row[1]), 200

Expected behaviour (using the database from the earlier examples): a request for S0012345 returns status 200 and {"member_id": "S0012345", "name": "Alice Chen"}. An unknown ID returns 404 and {"error": "Member not found"}. If the database file cannot be opened, the server logs the full error, returns 503 with a generic message, and stays running.

Passwords need the same care. The next program stores a random salt with a slow hash, so identical passwords give different stored values and a stolen database does not reveal them (libraries such as bcrypt do this for you and are the usual choice in a real project; this version uses only Python's standard library).

Python: salted, slow password hash
import hashlib
import hmac
import os


def hash_password(password):
    """Return salt + slow hash. The salt is random, so equal passwords give different results."""
    salt = os.urandom(16)
    digest = hashlib.pbkdf2_hmac("sha256", password.encode(), salt, 200_000)
    return salt + digest


def check_password(password, stored):
    salt, digest = stored[:16], stored[16:]
    attempt = hashlib.pbkdf2_hmac("sha256", password.encode(), salt, 200_000)
    return hmac.compare_digest(attempt, digest)


stored = hash_password("correct horse battery")
print(check_password("correct horse battery", stored))
print(check_password("Password1", stored))
print(hash_password("same") == hash_password("same"))

Expected output: True, False, False.

Contribution to success and ease of development

  • Separation of concerns. Because the front end only knows the URL and the JSON shape, the interface can be redesigned, or a mobile app added, without touching the loan rules.
  • Testability. Endpoints and functions with clear inputs and outputs can be tested without a screen, so defects are found early.
  • Reliability. Handled errors keep one bad request from stopping the service for everyone, and the log gives the developer what they need to fix it.
  • Trust. Security built in at the back end protects the client and the people whose data is stored, and avoids expensive retrofits later.
  • Speed of development. A well-chosen framework and database supply common features (routing, sessions, migrations), so effort goes into the client's actual problem.
Exam tip: "Explain" the contribution of the back end "Explain" needs a cause and an effect. State the back-end feature, then the result for the project: "Parameterised queries stop user input from being run as SQL, so an attacker cannot read or delete records through a form field, which protects the client's data and avoids a costly breach." Cover the Including items the question names, and give one concrete example for each. Common mistakes are describing what a back end is instead of what it contributes, and giving a list of technologies with no reason for choosing them.
Syllabus Part 3 Producing and implementing

Designing, Constructing and Implementing a Solution

🎯 (SE-12-02, SE-12-04, SE-12-06, SE-12-09)

📌 Design, construct and implement a solution to a software problem using appropriate development approach(es)

Modular Design — Python Example

A well-engineered solution separates concerns into distinct modules and classes. The example below shows how the Library Management System is implemented using modular Python, with each class responsible for a single aspect of the system.

Python — Modular Design: Library System
"""
Library Management System — Modular Python Design
Demonstrates separation of concerns across classes.
"""

# ── DATA LAYER ─────────────────────────────────────────────
class Book:
    """Represents a single book in the library catalogue."""
    def __init__(self, isbn: str, title: str, author: str):
        self.isbn = isbn
        self.title = title
        self.author = author
        self.available = True

    def __repr__(self):
        status = "Available" if self.available else "On Loan"
        return f"Book({self.title!r} by {self.author} — {status})"


class Member:
    """Represents a library member."""
    MAX_LOANS = 5

    def __init__(self, member_id: str, name: str, email: str):
        self.member_id = member_id
        self.name = name
        self.email = email
        self.active_loans = []

    def can_borrow(self) -> bool:
        return len(self.active_loans) < self.MAX_LOANS


# ── SERVICE LAYER ──────────────────────────────────────────
class LoanService:
    """Handles all business logic for issuing and returning loans."""

    def __init__(self):
        self.loans = []  # In a real system, this would query a database

    def issue_loan(self, book: Book, member: Member) -> str:
        """Issue a loan if the book is available and member can borrow."""
        if not book.available:
            return f"Error: '{book.title}' is currently on loan."
        if not member.can_borrow():
            return f"Error: {member.name} has reached the maximum loan limit."

        book.available = False
        member.active_loans.append(book.isbn)
        self.loans.append({"isbn": book.isbn, "member_id": member.member_id})
        return f"Success: '{book.title}' issued to {member.name}."

    def return_book(self, book: Book, member: Member) -> str:
        """Process a book return."""
        if book.isbn not in member.active_loans:
            return f"Error: No active loan found for '{book.title}'."
        book.available = True
        member.active_loans.remove(book.isbn)
        return f"Success: '{book.title}' returned by {member.name}."


# ── SEARCH MODULE ──────────────────────────────────────────
class Catalogue:
    """Manages the book catalogue and provides search functionality."""

    def __init__(self):
        self.books: list[Book] = []

    def add_book(self, book: Book):
        self.books.append(book)

    def search_by_title(self, query: str) -> list[Book]:
        """Case-insensitive partial title search."""
        query = query.lower()
        return [b for b in self.books if query in b.title.lower()]

    def search_by_isbn(self, isbn: str) -> Book | None:
        """Return the book matching the given ISBN, or None."""
        return next((b for b in self.books if b.isbn == isbn), None)


# ── MAIN PROGRAM ───────────────────────────────────────────
if __name__ == "__main__":
    catalogue = Catalogue()
    loan_service = LoanService()

    book1 = Book("978-0-7432-7356-5", "The Great Gatsby", "F. Scott Fitzgerald")
    member1 = Member("S001", "Alice Chen", "alice@school.edu.au")

    catalogue.add_book(book1)
    print(catalogue.search_by_title("gatsby"))
    print(loan_service.issue_loan(book1, member1))

Expected output:

[Book('The Great Gatsby' by F. Scott Fitzgerald — Available)]
Success: 'The Great Gatsby' issued to Alice Chen.

Design: from models to a module layout

Designing a solution means deciding its parts before writing them, using the models from Part 1 and Part 2. Each module in the structure chart becomes a file or class with one job, and each data store in the DFD becomes a table or file. The design decisions for Library Loans:

Design decisionChoiceReason
StructureSeparate data (Book, Member), service (LoanService) and search (Catalogue) classesOne responsibility each, so a change to search cannot break loan rules
StorageSQLite database in one fileNeeds no server, easy to back up, fits the library computer
InterfaceSimple web pages served on the library computer (Flask)No install on other computers; wireframes already approved
Business rulesConstants such as MAX_LOANS = 5 in one placeA rule change is one edit, and tests refer to the same constant

Construct: small, tested steps

  1. Set up first: a folder layout (for example src/, tests/, docs/), a Git repository, and a README.
  2. Build one story at a time from the backlog, on its own branch, in the order of the Gantt chart's critical path.
  3. Write the test, then the code, or at least write the tests for a function before moving to the next. Use the test data table from Part 4.
  4. Follow a coding standard: PEP 8 naming and layout, meaningful names (days_overdue, not d), a docstring on every function, comments that explain why.
  5. Commit small changes with clear messages and demonstrate a working piece to the client at each review.

Implement: use the appropriate development approach

"Implement" is the step that delivers the solution to the client, following the plan for the approach chosen. The approach changes how you construct and deliver.

ApproachHow construction proceedsHow delivery happens
WaterfallAll designed first, then all coded, then all testedOne release at the end, after sign-off at each stage
AgileStory by story in sprints, with tests each timeA working increment at every review
WAgileGated planning and design, sprint-based build, gated release checksIncrements to the client between gates, one final release after the gate
Exam tip: "Design, construct and implement" Where a question describes part of a project and asks how the developer should proceed, link your answer to the development approach in the scenario. Say what is designed, how it is built and checked, and how it reaches the client: "Using Agile, the developer builds the loan module first as a working increment with unit tests, demonstrates it to the client, then adds search in the next sprint." Code questions in the exam are answered in Python in an online editor, so practise writing and running short programs. Marker feedback on the 2025 paper asked for code that runs, correct indentation, and functions that are defined before they are called.

Presenting Your Solution

🎯 (SE-12-09)

📌 Present a software engineering solution using presentation software

At the end of the project you present your solution to an audience such as your client, class or teacher. Presentation software such as PowerPoint, Google Slides or Keynote helps you show the problem, the solution and the evidence that it works.

  • Open with the need or opportunity you addressed.
  • Demonstrate the key features, using a live demo or screen recording.
  • Show evidence from testing and client feedback.
  • Finish with an honest evaluation and next steps.
Tip Keep slides to one idea each, use screenshots rather than code listings, and have a recording ready in case the live demo fails.

A slide plan for the Library Loans presentation

SlideContentEvidence to show
1. The needOne sentence on the problem and who has itPhoto of a stamped card and the typed overdue list
2. Requirements and scopeThe Must requirements and what is outside the boundaryThe requirement table (FR and NFR IDs)
3. Approach and planWAgile, with the Gantt chart and critical pathThe chart, with milestones marked
4. DesignStructure chart, data dictionary extract, key wireframeOne diagram, labelled
5. DemonstrationIssue a loan, refuse at the limit, return, overdue listLive demo, with a recording as backup
6. TestingTest results against boundary and path dataA summary table: passed, failed and fixed
7. EvaluationEach requirement met, partly met or not met; client feedbackEvaluation table with a client quotation
8. Next stepsProposed innovation and maintenance planPrototype screen for reminders

Presenting well

  • Know your audience. A client wants to know what it does for them and what it cost; a teacher also wants the process evidence. Adjust the amount of technical detail.
  • Make slides accessible. Large text, strong contrast, no important information carried by colour alone, and alt text for images.
  • Rehearse against the clock, including the demo, and prepare answers to the likely questions ("What if two people borrow the same book?").
  • Be honest about limits. Naming what does not work yet builds more trust than hiding it.

Developing and Documenting Algorithms

🎯 (SE-12-02, SE-12-09)

📌 Develop, construct and document algorithms

Before and during coding, write the key parts of your solution as algorithms, then keep them with your documentation so others can follow your logic.

  • Develop: plan the logic in pseudocode or a flowchart before you write code.
  • Construct: turn each algorithm into code, one subroutine at a time.
  • Document: keep the final algorithms, with comments and a short description of inputs, outputs and purpose.

NESA's Course Specifications expect algorithms as pseudocode or flowcharts using the standard control structures. The March 2026 specifications show a nested IF as an ELSE that holds another IF, with one ENDIF for every IF. Write it that way.

Develop: plan the logic

Start with the decision rules. FR2 and FR3 say a loan needs an available book and a member under the limit. That is the decision tree from Part 2, now as an algorithm that returns a single value, so it is written as a function.

pseudocode: a function with a nested IF
BEGIN CanIssueLoan (bookAvailable, activeLoans, allowed)
    IF bookAvailable = False THEN
        allowed = False
    ELSE
        IF activeLoans >= 5 THEN
            allowed = False
        ELSE
            allowed = True
        ENDIF
    ENDIF
END CanIssueLoan (bookAvailable, activeLoans, allowed)

Construct: turn it into code

Each algorithm becomes one function with the same name and the same decisions, so a reader can lay the pseudocode beside the code. A second algorithm, for a feature proposed for a later version (reserving a study room), uses a repetition and a condition with AND. Times are in minutes after midnight, and a new booking clashes if it starts before an existing one finishes and finishes after it starts.

pseudocode: repetition with a condition
BEGIN CheckClash (newRoom, newStart, newFinish, clash)
    clash = False
    FOR i = 1 TO bookingCount
        IF bookedRoom[i] = newRoom AND newStart < bookedFinish[i] AND newFinish > bookedStart[i] THEN
            clash = True
        ENDIF
    NEXT i
END CheckClash (newRoom, newStart, newFinish, clash)
Python: the same algorithm
def has_clash(new_room, new_start, new_finish, bookings):
    """Return True if the new booking overlaps an existing one in the same room.
    Times are minutes after midnight."""
    clash = False
    for room, start, finish in bookings:
        if room == new_room and new_start < finish and new_finish > start:
            clash = True
    return clash


bookings = [(2, 600, 660)]                 # room 2, 10:00 to 11:00
print(has_clash(2, 630, 690, bookings))    # 10:30 to 11:30  -> overlaps
print(has_clash(2, 660, 720, bookings))    # 11:00 to 12:00  -> starts as the other ends
print(has_clash(3, 630, 690, bookings))    # same time, different room

Expected output: True, False, False. The second case shows why the comparison uses < and >, not <= and >=: two bookings that only touch do not overlap. It is also a boundary test case.

Document: keep the algorithm with its evidence

An algorithm that is not kept with the project cannot be reviewed or maintained. For each important algorithm record:

ItemExample for CanIssueLoan
Name and purposeCanIssueLoan: decides whether a loan is allowed
Inputs and outputsbookAvailable (Boolean), activeLoans (integer); returns allowed (Boolean)
Requirement it meetsFR2 and FR3
The algorithmThe pseudocode above, or a flowchart, stored in docs/
Test dataactiveLoans 4 and 5 with the book available; the book unavailable with 0 loans
Where it is in the codeloans.py, function can_issue_loan, with a docstring that quotes the rule

Allocating Resources

🎯 (SE-12-06, SE-12-09)

📌 Allocate resources to support the development of a software engineering solution

Allocating resources means deciding what time, people, hardware, software and money each part of the project will get.

ResourceExample allocation in a school project
TimeThree weeks for development, one week for testing, shown on a Gantt chart
PeopleThe client is available for a 15-minute review every second Friday
HardwareA laptop for development; a Raspberry Pi as the test server
SoftwareVS Code, Python with Flask, SQLite and GitHub
BudgetFree tiers only, such as GitHub and a free hosting plan

Worked example: allocating the 49 hours

Resources are allocated to tasks. This allocation puts the hours from the feasibility estimate against each task, with the tools and people each one needs, and keeps the contingency visible.

TaskHoursTools and hardwarePeople needed
Requirements and feasibility5Notebook, Google DocsMrs Chen (interview, 15 min)
Design and modelling7Draw.io, FigmaMrs Chen (review, 15 min)
Loan module7VS Code, Python, SQLite, GitNone (peer review of the pull request)
Search module5As aboveNone
Interface7As above, plus FlaskVolunteer (usability check)
Testing and fixes6unittest, VS Code debuggerPeer (test data review)
Documentation and evaluation5Google Docs, slidesMrs Chen (acceptance test)
Contingency (15%)6.3
Total48.3 of 49

NESA's Gantt chart specification also notes that a chart can allocate team members to tasks and show each person's percentage completion. In a team, add a "who" column and update each person's percentage complete at every check.

Resource risks and responses

RiskEffectResponse
Mrs Chen is unavailable in a review weekSign-off delayed; the interface cannot be approvedBook reviews for the whole term now; send a written summary and ask for a reply by email
Laptop fails or code is lostDays of work lostCommit to GitHub daily; programmed database backup
A task takes twice its estimateContingency is used upCut a Should requirement (CSV export) and tell the client
A free tool changes its termsA feature stops workingPrefer the standard library and open-source tools that run locally

Programmed Data Backup

🎯 (SE-12-04, SE-12-09)

📌 Demonstrate the use of programmed data backup

A programmed data backup copies your data automatically on a schedule or before a risky change, so you don't have to remember to do it.

Python — Programmed Data Backup Script
import shutil
from datetime import datetime

def programmed_backup(db_filepath, backup_directory):
    """Automates the backup of the project database with a timestamp."""
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    backup_file = f"{backup_directory}/db_backup_{timestamp}.sqlite3"
    
    try:
        shutil.copy2(db_filepath, backup_file)
        print(f"✅ Backup successful: {backup_file}")
    except IOError as e:
        print(f"❌ Backup failed: {e}")

# Execute backup before deploying a new feature
programmed_backup('app_data.sqlite3', './backups')
Tip Test your backups by restoring one. A backup you can't restore is not a backup.

Planning what to back up

Decide the answers to five questions before writing any code. Together they make a backup strategy.

QuestionLibrary Loans answer
What is worth keeping?The loans database (cannot be recreated), the code (in Git), the documents (in cloud storage the school approves)
How often?The database every weekday at 4 pm and before any install or update. The most that could be lost is one day's loans, which the paper cards also record for the first two weeks.
Where are copies kept?A second folder on the computer and a copy on a USB drive kept in the office. A copy on the same disk does not survive a disk failure. A common rule of thumb is 3 copies, on 2 kinds of storage, with 1 kept off-site.
How many versions are kept?The latest 5, and older ones are deleted automatically so the disk does not fill.
How is it tested?Once a term, restore a backup on another computer and check that the data is there.

Try it

Backup what-if: will this plan survive?

Choose a backup plan and test it against three emergencies. Enable JavaScript to use this tool. In short: keep a copy away from the disk and the office, keep enough versions to go back before a mistake, and test a restore.

A more robust backup program

Copying a database file with shutil.copy2 can produce a damaged copy if the application is writing at that moment. SQLite has a built-in backup method that is safe on a live database. This version also checks the copy and prunes old backups.

Python: safe, verified backup with retention
import sqlite3
from datetime import datetime
from pathlib import Path

KEEP = 5   # how many backups to retain


def backup_database(db_path, backup_dir):
    """Copy a live SQLite database safely, check the copy, and prune old copies."""
    backup_dir = Path(backup_dir)
    backup_dir.mkdir(exist_ok=True)
    stamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    target = backup_dir / f"library_{stamp}.sqlite3"

    source = sqlite3.connect(db_path)
    copy = sqlite3.connect(target)
    try:
        source.backup(copy)                      # safe even while the app is running
        ok = copy.execute("PRAGMA integrity_check").fetchone()[0] == "ok"
    finally:
        copy.close()
        source.close()

    if not ok:
        target.unlink()
        raise RuntimeError("Backup failed its integrity check and was deleted")

    old = sorted(backup_dir.glob("library_*.sqlite3"))[:-KEEP]
    for path in old:
        path.unlink()
    return target


if __name__ == "__main__":
    print("Backup written to", backup_database("library.db", "backups"))

Expected output (the file name holds the date and time of the run): Backup written to backups/library_20260930_160000.sqlite3. After more than five runs the backups folder still holds only five files.

Running it automatically

A backup that depends on someone remembering will be forgotten. Ask the operating system to run the program on a schedule.

Scheduling (Windows and Linux or macOS)
# Windows: run every day at 4 pm
schtasks /create /tn "LibraryBackup" /tr "python C:\LibraryLoans\backup.py" /sc daily /st 16:00

# Linux or macOS: add this line with crontab -e (minute hour day month weekday)
0 16 * * 1-5 python3 /home/library/LibraryLoans/backup.py

Prove the backup works: a restore check

Python: restore check
import sqlite3


def count_members(backup_path):
    """Open a backup and confirm the data is really there."""
    db = sqlite3.connect(backup_path)
    try:
        return db.execute("SELECT COUNT(*) FROM members").fetchone()[0]
    finally:
        db.close()


print(count_members("backups/library_20260930_160000.sqlite3"))

Expected output: the number of members in the live system at the time of the backup (for a test database holding one member, 1). If it prints 0 or raises an error, the backup is not usable. Record the result of each restore test in the process diary.


Implementing Version Control

🎯 (SE-12-06, SE-12-09)

📌 Implement version control when developing a software engineering solution

Version control is a fundamental professional practice. Git allows engineers to track every change made to the codebase, revert to earlier versions if bugs are introduced, and collaborate without overwriting each other's work. The workflow below demonstrates the standard Git feature-branch workflow used in professional software engineering.

Bash — Git Feature-Branch Workflow
# ── INITIAL SETUP ──────────────────────────────────────────
# Initialise a new repository and make the first commit
git init library-management-system
cd library-management-system
git add README.md
git commit -m "Initial commit: project structure"

# ── FEATURE DEVELOPMENT ────────────────────────────────────
# Always create a new branch for each feature
git checkout -b feature/book-search

# After writing code, stage and commit your changes
git add src/search.py tests/test_search.py
git commit -m "Add book search by title and ISBN with unit tests"

# ── MERGING A FEATURE ──────────────────────────────────────
# Switch back to main and merge the completed feature
git checkout main
git merge feature/book-search --no-ff -m "Merge feature/book-search into main"

# ── USEFUL COMMANDS ────────────────────────────────────────
git log --oneline --graph    # View commit history as a graph
git diff HEAD~1 HEAD         # See changes since the last commit
git status                   # Check which files are staged/unstaged
git stash                    # Temporarily save uncommitted changes

# ── TAGGING A RELEASE ──────────────────────────────────────
git tag -a v1.0 -m "Version 1.0 — submitted for client review"
git push origin main --tags
Version Control Best Practices for the SEP
  • Commit frequently: Commit after every logical unit of work (e.g., after implementing one function). Small commits are far easier to review and revert than large, multi-feature commits.
  • Write meaningful commit messages: Use the imperative mood and describe what the commit does: "Add login form validation" not "fixed stuff" or "wip".
  • Use branches for features: Never code a new feature directly on main. Always create a feature branch (git checkout -b feature/my-feature) so the main branch stays stable.
  • Link to your process diary: Your commit history in GitHub serves as timestamped evidence of ongoing development — reference it in your process diary entries.

Why use version control?

NeedHow version control meets it
Go back after a mistakeEvery commit is a saved version. git log lists them and any one can be restored.
Know what changed and whyEach commit records the author, the date and a message; git diff shows exact changes.
Try an idea safelyA branch is a separate line of work. Delete it if the idea fails.
Work as a teamBranches and merges let people change different files without overwriting each other.
Recover from a lost computerA remote copy on GitHub holds the whole history.
Show your processThe history is dated evidence of work over time.

Branches, merges and a merge commit

After the feature-branch workflow above, the history looks like this. The merge commit has two parents, because --no-ff records that a branch was merged.

Bash: the history as a graph (output; the codes are shortened)
git log --oneline --graph
*   a3f9c21 Merge feature/loan-limit into main
|\
| * 5be0d47 Add can_borrow with loan limit check
|/
* 1c7a8e2 Initial commit: project structure

Diagram

A feature branch merged into main

Each circle is a commit. The merge commit joins the feature branch back into main.

What to notice
  • Both branches start from the same commit, so nothing is lost or copied twice.
  • The main branch stays working while the feature is built.

Try thisSketch the history for two features, feature/search and feature/fines, built at the same time and merged one after the other.

When two changes collide: a merge conflict

If the same line changes on two branches, Git cannot choose, so it stops the merge and marks the file. Suppose main lowered the limit to 4 while another branch raised it to 6:

Bash and file contents: a conflict
git merge feature/limit-six
Auto-merging rules.py
CONFLICT (content): Merge conflict in rules.py
Automatic merge failed; fix conflicts and then commit the result.

# rules.py now contains:
<<<<<<< HEAD
MAX_LOANS = 4
=======
MAX_LOANS = 6
>>>>>>> feature/limit-six

Resolve it by deciding, not by picking a side automatically. The requirement (FR3) says the limit is 5, so neither is right. Edit the file to MAX_LOANS = 5, delete the three marker lines, then run git add rules.py and git commit. The Programming for the Web page covers this in more depth.

Try it

Git sandbox: branches, merges and conflicts

Make commits, branch, merge and resolve a conflict. Enable JavaScript to use this tool. In short: a branch lets you work on a feature without touching main, and a conflict happens when two branches change the same lines.

What not to commit, and how to write commits

  • Keep secrets and data out of the repository. Passwords, API keys and the live database (library.db) do not belong in Git, and once pushed they are hard to remove. List them in a .gitignore file and keep keys in environment variables. A repository on GitHub can be public.
  • One logical change per commit, with a message that says what and why: Fix off-by-one in can_borrow (BUG-002). Referring to the defect ID links the history to the defect log.
  • Review before merging. A pull request lets a peer read the change, comment and approve it before it reaches main.
  • Tag releases (git tag -a v1.0) so the exact version the client tested can always be recovered.
Exam tip: "Implement" version control Be ready to describe or explain how version control helps in a scenario, or to order or match commands. Tie each idea to the scenario: "Working on a branch meant the developer could try a new search without risking the working version, and the commit history let them go back when it failed." Know the difference between a commit (a saved version), a branch (a line of work), a merge (joining branches) and a repository (the project with its history). Common mistakes are treating version control as a backup only, and mixing up Git (the tool) with GitHub (a hosting service).

Responding to Difficulties

🎯 (SE-12-02, SE-12-04, SE-12-06, SE-12-09)

📌 Explore strategies to respond to difficulties when developing a software engineering solution

  • looking for a solution online
  • collaboration with peers
  • outsourcing

Every project hits problems. What matters is how you respond:

  • Looking for a solution online: start with official documentation, then trusted forums such as Stack Overflow. Test anything you find, and cite code you reuse.
  • Collaboration with peers: explain the problem to a classmate or ask for a code review. Often, explaining the problem is enough to spot the bug.
  • Outsourcing: use an existing service or library for a hard, non-core part, such as a payment provider or a login service.

"Buy vs. Build" Decision Guide

For a large difficulty, such as implementing secure logins, weigh up whether to build it yourself or outsource it:

FactorBuild (In-House)Buy / Outsource (Third-Party)
TimeTakes weeks to code and test.Instant integration via API.
CostHigh developer salary cost.Ongoing subscription / per-use cost.
RiskHigh risk of bugs / security flaws.Low risk (tested by provider).
Justification"I built the search algorithm because it's my core intellectual property.""I outsourced authentication to Auth0 because rolling my own crypto was an unacceptable security risk."

Looking for a solution online

  1. Read the error message and copy the last line exactly (for example KeyError: 'due'). Search for it with the name of the language or library.
  2. Try official documentation first (docs.python.org, the library's own site), then established communities such as Stack Overflow.
  3. Judge the source: is it recent, does it match your version, does an accepted answer explain why it works? An answer you do not understand is a risk.
  4. Test it in isolation in a small file before it enters your project.
  5. Acknowledge it: a comment with the URL and licence, and a process diary entry. Never paste passwords, real student data or the whole project into a public forum.

Collaboration with peers

  • Explain the problem aloud to a classmate (often called rubber-duck debugging). Putting it into words often exposes the fault.
  • Ask a good question: what you expected, what happened instead, what you already tried, and the smallest code that shows the problem.
  • Pair on the difficulty: one person types while the other reads the logic, then swap.
  • Ask for a code review when a fresh pair of eyes is needed; in the earlier example, a peer spotted the time zone error.
  • Keep the work your own. A peer may explain and suggest, but you must write and understand your solution, and record the help in the process diary.

Outsourcing

Outsourcing means handing a part of the work to an outside provider: a library, a hosted service or API, or another person or company. The developer keeps the part that is specific to the client. It is sensible for a hard, well-solved, non-core part such as secure login, payments or maps. The trade-offs to weigh are cost, control, security and privacy (where the data goes), reliability of the supplier, licence terms, and the effort to connect it.

Worked example: a difficulty log

DifficultyStrategyOutcomeRecorded
Overdue dates are wrong by one day for books returned on the due date (BUG-003)Peers: explained the rule to a classmateFound the comparison used >= when it should use >; fixed and testedDiary, week 5; commit message quotes BUG-003
Passwords must be stored safely, and I have not done this beforeOnline: official Python documentation for hashlib; outsourcing consideredUsed a salted slow hash from the standard library; a hosted login service was rejected because student data must stay on the school networkDiary, week 4, with the documentation link
Export to CSV shows garbled namesOnline: searched the exact messageThe file needed UTF-8 encoding; tested with a name containing an accentComment above the code with the source URL
Exam tip: "Explore" strategies for difficulties You may be given a difficulty and asked to identify or describe a strategy, or to discuss whether to build or outsource. Match the strategy to the problem (a code fault suits peers or a code review; an unfamiliar library suits official documentation; a security-critical component may suit outsourcing) and add a risk or a check: "test the online solution in isolation and acknowledge its source". Common mistakes are naming a strategy without saying how it would help in this case, and treating outsourcing as always better or always worse.
HSC writing sample "When the calendar display failed on mobile, the official library documentation showed the configuration option I had missed. A peer's code review then found that dates were stored in UTC but displayed without converting to Sydney time. Outsourcing payments to Stripe avoided building a secure payment system myself, which would have been a significant security risk."

Proposing an Innovative Solution

🎯 (SE-12-02, SE-12-04, SE-12-06, SE-12-09)

📌 Propose an additional innovative solution using a prototype and user interface (UI) design

Once your main solution works, propose one further idea that would make it better. Show it as a prototype, such as a clickable Figma mock-up or a paper sketch, with a clear UI design. You don't need to build it; you need to show it is worth building.

  • Describe the problem the idea solves, using evidence from feedback.
  • Show the prototype screens and explain the UI choices, such as layout, colour, font size and accessibility.
  • Explain how it would fit into the existing system.
Scenario Testers of the Library Loans system kept forgetting when their books were due. The student proposes a "My loans" view with due-date reminders, prototypes three screens in Figma, and tests them with two librarians before recommending the feature for version 2.

From opportunity to proposal

  1. Find the opportunity in evidence: feedback, the defect log, observation, or a feature that was outside the boundary (email reminders were).
  2. Sketch quickly on paper to explore several layouts.
  3. Make a wireframe (layout only), then a prototype that can be clicked through.
  4. Test it with real users on a small task and record what happened.
  5. Recommend whether to build it, with its cost, its benefit and its risks.

Worked example: the reminders proposal

Part of the proposalLibrary Loans
Problem and evidenceBooks are returned late, and Mrs Chen spends time each Friday chasing them. In feedback, 5 of 8 testers said they forget due dates.
Proposed featureA "My loans" screen showing each loan and its due date, and a reminder message two days before it is due.
PrototypeThree Figma screens: sign in, My loans (books sorted by due date, overdue in a clearly labelled red badge), Reminder settings (choose email or none).
Prototype testTwo librarians and a Year 9 student each find "when is my book due?" and turn on reminders. All three completed both tasks; one did not notice the settings link, so it was moved next to the loan list.
Fit with the existing systemA new email field in the data dictionary, a new "Notify" module in the structure chart called by a scheduled daily job, and no change to the loan rules.
RisksEmail addresses are extra personal information, so collect them only with consent and store them securely. Reminders sent to the wrong person disclose a loan. Estimated effort: 8 hours.
RecommendationBuild in version 2, after a privacy review.

Explain the UI choices

  • Layout and hierarchy: the most common task (see my due dates) is first and largest.
  • Consistency: the same button style and position on every screen, so users learn once.
  • Feedback: a clear message after "Turn on reminders" says what will happen and when.
  • Accessibility: text contrast of at least 4.5:1 for normal text (WCAG AA), meaning is never carried by colour alone (the overdue badge has the word "Overdue"), and every control can be reached with the keyboard.
  • Simplicity: no feature on the screen that a first-time volunteer does not need.
Exam tip: "Propose" an innovative solution "Propose" means to put forward an idea and support it. Give the idea, the evidence or need behind it, the UI choices and one benefit and one risk. If asked to construct a screen design in the online drawing or screen design tool, label each element and keep to the storyboard and wireframe conventions. Common mistakes are proposing a feature with no link to a need, and describing a prototype without saying what testing it showed.
Syllabus Part 4 Testing and evaluating

Methodologies to Test and Evaluate Code

🎯 (SE-12-08, SE-12-09)

📌 Apply methodologies to test and evaluate code

Methods for testing a system

NESA's Course Specifications (p. 30) name six methods for testing a software solution that students are expected to know and understand. Each answers a different question.

MethodWhat it isLibrary Loans example
Functional testingChecks that each function does what the requirements say, by giving inputs and comparing the outputs, without looking at the internal codeIssue a loan and check the book shows "On Loan" (FR2)
Acceptance testingThe client or users check that the finished software meets their needs and accept or reject itMrs Chen runs a set of real tasks and signs the result
Simulated dataMade-up data that imitates the real thing. It is safe, and you can design it to include extreme casesA generated catalogue of 10,000 books and 200 invented members
Live dataReal data from actual use. It shows real conditions, but real records could be damaged or exposed, so use it with care and permissionThe real loan cards, entered in the new system during parallel running
Beta testingA limited release to real users in real conditions, before the full release, to find defects the developer missedTwo volunteers use the system at the desk for a week
Volume testingTests behaviour with a large amount of data or users, to see whether performance still meets the requirementTime a search on 10,000 titles against the 2-second target (NFR1)

Levels of testing: unit, integration, system, acceptance

Testing also happens at different levels as the pieces are put together. These four levels are standard industry terms (only acceptance testing is in NESA's list above). Together with the methods, they form a test strategy.

LevelWhat is testedWhoLibrary Loans example
UnitOne function or class on its ownDevelopercan_borrow(5) returns False; calculate_fine_cents(51) returns 1000
IntegrationModules working together, including the data passed between themDeveloperIssuing a loan through LoanService changes the book's status in the catalogue
SystemThe whole system against all the requirements, end to endDeveloper, then a peerSign in, search, issue, return, and view the overdue list in one session
AcceptanceThe finished system against the client's needsClientMrs Chen completes her Friday routine using only the new system

Test Data Table

A comprehensive test plan uses three categories of test data to verify correctness across all scenarios. Normal data tests typical valid inputs; boundary data tests values at the exact edges of valid ranges; invalid (erroneous) data tests inputs that should be rejected.

# Req Test Case Input Data Category Expected Output Actual Output Pass/Fail
1 FR1 Valid book search — title exists query = "gatsby" Normal Returns list containing "The Great Gatsby" [Book('The Great Gatsby'...)] ✅ Pass
2 FR1 Valid book search — case insensitive query = "GATSBY" Normal Returns same result as lowercase query [Book('The Great Gatsby'...)] ✅ Pass
3 FR3 Loan issued — exactly at loan limit (boundary) member has 4 active loans; issue 1 more Boundary Loan issued successfully (5th loan allowed) "Success: book issued to Alice Chen." ✅ Pass
4 FR3 Loan refused — one over limit (boundary) member has 5 active loans; attempt 6th Boundary Error: maximum loan limit reached "Error: Alice Chen has reached the maximum loan limit." ✅ Pass
5 FR1 Empty search query query = "" Boundary Returns all books in catalogue (empty query matches all) All 12 books returned ✅ Pass
6 FR1 Search for non-existent book query = "xyznotabook" Invalid Returns empty list [] [] ✅ Pass
7 FR3 Issue loan for already-loaned book book.available = False; attempt issue Invalid Error: book is currently on loan "Error: 'The Great Gatsby' is currently on loan." ✅ Pass
8 FR4 Return a book not borrowed by that member member_id does not match loan record Invalid Error: no active loan found for this member "Error: No active loan found for 'The Great Gatsby'." ✅ Pass
9 FR6 Fine — not overdue days_overdue = 0 Boundary 0 cents 0 ✅ Pass
10 FR6 Fine — one day overdue days_overdue = 1 Boundary 20 cents 20 ✅ Pass
11 FR6 Fine — last day below the cap days_overdue = 50 Boundary 1000 cents ($10.00) 1000 ✅ Pass
12 FR6 Fine — first day the cap applies days_overdue = 51 Boundary 1000 cents ($10.00) 1000 ✅ Pass
13 FR6 Fine — returned early (negative days) days_overdue = -3 Invalid 0 cents (no fine) 0 ✅ Pass

Boundary testing: choosing the data

Boundary testing tests the values on and either side of each limit, because mistakes in a comparison (< where <= was meant) show up only there. For a range, test the value just below the minimum, the minimum, just above it, a typical value, just below the maximum, the maximum and just above it. Add data of the wrong type and empty input.

Worked example (FR3): a member may hold at most 5 loans, so the valid values for the number of active loans before issuing are 0 to 4, and the member at 5 is refused. Test the edges of that rule.

Input (active loans)CategoryExpected result
0Boundary (lowest possible)Loan allowed
3NormalLoan allowed
4Boundary (last allowed)Loan allowed
5Boundary (limit reached)Loan refused
6Boundary (above the limit)Loan refused
"abc"Invalid (wrong type)Rejected with a message, no crash

The fine rule (FR6) has its own boundaries at 0 and 1 (overdue or not) and at 50 and 51 (cap or not), which are test cases 9 to 12 above.

Path testing: covering every route through the code

Path testing chooses test data so that every path through the code runs at least once, which means every branch of every IF. Count the paths from the algorithm: each decision splits the route.

Paths through CalculateFine (see Part 1)
PathRoute through the codeTest inputExpected result
1daysOverdue <= 0 is true00
2daysOverdue <= 0 false, then daysOverdue > 50 false20400
3daysOverdue <= 0 false, then daysOverdue > 50 true601000

Two decisions in a nested structure give three paths, not four, because the second decision is reached only when the first is false. Path testing and boundary testing are complementary: three well-chosen inputs cover all the paths, but only the boundary values 50 and 51 would catch a mistake such as >= 50. Both inputs return 1000, so only the path and the neighbouring inputs reveal the fault.

Test data lab. This interactive tool needs JavaScript. Without it, use the tables above: boundary data for a range is the minimum and maximum, the values just outside them and just inside them; path data is one input for every route through the code.

Unit tests in Python: expected against actual

Python's built-in unittest module runs test cases and compares each actual output with the expected one. The test methods below cover the boundaries and paths worked out above.

Python: unit tests for the loan and fine rules
import unittest


def can_borrow(active_loans, limit=5):
    """A member may borrow only while they have fewer than the limit."""
    return active_loans < limit


def calculate_fine_cents(days_overdue):
    """Return the fine in cents: 20 cents a day, capped at 1000 (ten dollars)."""
    if days_overdue <= 0:
        fine = 0
    else:
        if days_overdue > 50:
            fine = 1000
        else:
            fine = days_overdue * 20
    return fine


class TestLoanRules(unittest.TestCase):
    def test_loan_limit_boundaries(self):
        self.assertTrue(can_borrow(4))      # one below the limit
        self.assertFalse(can_borrow(5))     # at the limit

    def test_fine_not_overdue(self):
        self.assertEqual(calculate_fine_cents(0), 0)
        self.assertEqual(calculate_fine_cents(-3), 0)

    def test_fine_below_cap(self):
        self.assertEqual(calculate_fine_cents(1), 20)
        self.assertEqual(calculate_fine_cents(50), 1000)

    def test_fine_capped(self):
        self.assertEqual(calculate_fine_cents(51), 1000)


if __name__ == "__main__":
    unittest.main(verbosity=2)

Expected output (the wording of the test names varies a little between Python versions):

test_fine_below_cap (__main__.TestLoanRules.test_fine_below_cap) ... ok
test_fine_capped (__main__.TestLoanRules.test_fine_capped) ... ok
test_fine_not_overdue (__main__.TestLoanRules.test_fine_not_overdue) ... ok
test_loan_limit_boundaries (__main__.TestLoanRules.test_loan_limit_boundaries) ... ok

----------------------------------------------------------------------
Ran 4 tests in 0.000s

OK

Defect Log

A defect log (also called a bug tracker or issue log) records every defect discovered during testing. Each entry includes enough information for the developer to reproduce and fix the defect. The defect log is evidence that you tested genuinely and responded to the results.

ID Defect Description Severity Steps to Reproduce Expected Actual Status
BUG-001 Search returns no results when query contains trailing whitespace Medium Enter "gatsby " (with trailing space) in search box The Great Gatsby returned Empty list returned ✅ Fixed — added query.strip() in search function
BUG-002 Loan limit not enforced — member can borrow 6 books High Issue loans until member has 5; attempt a 6th loan Error: maximum loan limit reached 6th loan issued without error ✅ Fixed — off-by-one error in can_borrow() condition corrected
BUG-003 Overdue report includes books returned today as overdue Medium Return a book on the exact due date; generate overdue report Book not included in report Book incorrectly listed as overdue ✅ Fixed — changed >= to > in the overdue comparison (overdue means today is after the due date)
BUG-004 Application crashes with unhandled exception when ISBN contains letters Critical Enter "ABC123" as ISBN in the add-book form Validation error message displayed ValueError: invalid literal for int() with base 10 ✅ Fixed — added try/except ValueError block in ISBN validation

Code Review Checklist

A code review is the systematic examination of code by a peer before it is merged into the main branch. It catches bugs, ensures style consistency, and improves overall code quality. The checklist below should be applied during every code review in a collaborative project.

Category Checklist Item Status
Functionality Does the code correctly implement the specified requirements? ☐ Pass / ☐ Fail
Functionality Are all edge cases and error conditions handled appropriately? ☐ Pass / ☐ Fail
Readability Are variable and function names clear and descriptive? ☐ Pass / ☐ Fail
Readability Does the code follow PEP 8 style conventions (Python)? ☐ Pass / ☐ Fail
Documentation Do all functions and classes have docstrings explaining purpose, parameters, and return values? ☐ Pass / ☐ Fail
Testing Are unit tests provided for all new functions, covering normal, boundary, and invalid inputs? ☐ Pass / ☐ Fail
Security Is all user input validated and sanitised before processing or storing? ☐ Pass / ☐ Fail
Security Are there any hardcoded passwords, API keys, or sensitive credentials in the code? ☐ Pass / ☐ Fail
Performance Are there any obviously inefficient algorithms (e.g., nested loops on large datasets) that should be refactored? ☐ Pass / ☐ Fail
Version Control Is the commit message clear and descriptive? Does the branch name follow the naming convention? ☐ Pass / ☐ Fail

Debugging Process

Debugging is the systematic process of identifying, isolating, and fixing defects in code. A structured debugging process is faster and more reliable than randomly changing code and hoping for improvement.

Flowchart

A systematic debugging process

Reproduce, isolate, test a hypothesis, fix, then retest everything.

What to notice
  • Every loop returns to a step that gathers more evidence, not to a random change.
  • Rerunning all tests checks the fix didn't break something else.

Try thisWhich debugging tools from Year 11 fit the Test it step?


Language-Dependent Code Optimisation

🎯 (SE-12-08, SE-12-09)

📌 Use a language-dependent code optimisation technique

A language-dependent optimisation uses a feature of your particular programming language to make code faster or clearer. In Python, list comprehensions and built-in functions such as sum() and sorted() run in optimised C code, so they are usually quicker than writing the same loop yourself. Measure before and after, for example with timeit, to show the change helped.

Python — Code Optimisation & Boundary Testing
import unittest

# OPTIMISED CODE: Using list comprehension instead of a slow for-loop
def get_valid_ages(age_list):
    """Returns ages between 18 and 65 (inclusive) using fast list comprehension."""
    return [age for age in age_list if 18 <= age <= 65]

# TESTING: Applying boundary testing methodology
class TestAgeValidation(unittest.TestCase):
    def test_boundaries(self):
        # Boundary data: 17 (invalid), 18 (valid), 65 (valid), 66 (invalid)
        test_data = [17, 18, 40, 65, 66]
        expected_output = [18, 40, 65]
        actual_output = get_valid_ages(test_data)

        # Comparing actual output with expected output
        self.assertEqual(actual_output, expected_output)

if __name__ == '__main__':
    unittest.main()

Language-dependent and language-independent optimisation

A language-independent optimisation improves the algorithm or the data structure and works in any language: for example, searching a sorted list with binary search instead of scanning it. A language-dependent optimisation uses a feature of your language's design or standard library. In Python that means built-in functions written in optimised C, comprehensions, and the standard data types.

Slower or clumsierPython techniqueWhy it helps
total = 0 then a for loop that adds each valuesum(values)The loop runs inside the interpreter's compiled code, not in Python bytecode
An empty list, a loop and appendA list comprehension: [x for x in data if x > 0]Less interpreter overhead per item, and shorter to read
Scanning a list for a match (if x in big_list)Store items in a set or dictHash lookup takes about the same time however large the collection is
Building text with += in a loop", ".join(parts)Builds the string once instead of copying it repeatedly
Building a huge list only to loop through it onceA generator expression: sum(x * x for x in data)Produces items one at a time without holding them all in memory

Worked example: measure before and after

The Library Loans catalogue searches by ISBN. Scanning a list of 10,000 books takes longer as the catalogue grows; a dictionary keyed by ISBN is a Python data type built for lookup. Use timeit to measure the difference instead of guessing.

Python: timing a scan against a dictionary lookup
import timeit

books = [{"isbn": str(9780000000000 + i), "title": f"Book {i}"} for i in range(10_000)]
target = books[-1]["isbn"]                       # worst case for a scan
by_isbn = {b["isbn"]: b for b in books}          # built once, when the catalogue loads


def scan():
    return next((b for b in books if b["isbn"] == target), None)


def lookup():
    return by_isbn.get(target)


assert scan() == lookup()                        # same answer: the optimisation is safe
print("scan  :", round(timeit.timeit(scan, number=200), 4), "seconds for 200 searches")
print("lookup:", round(timeit.timeit(lookup, number=200), 6), "seconds for 200 searches")

def total_loop(values):
    total = 0
    for v in values:
        total += v
    return total

data = list(range(100_000))
print("loop  :", round(timeit.timeit(lambda: total_loop(data), number=100), 3))
print("sum() :", round(timeit.timeit(lambda: sum(data), number=100), 3))

Expected output: four lines of timings. The exact numbers depend on the computer, so record your own. In a test run the dictionary lookup was thousands of times faster than the scan, and sum() was several times faster than the hand-written loop. The assert line matters as much as the timings: an optimisation that changes the answer is a defect.

Rules for optimising

  1. Make it correct first. Optimise only code that passes its tests.
  2. Measure, then change. Record the timing before and after, on the same data.
  3. Re-run the tests after every optimisation, to show behaviour is unchanged.
  4. Do not trade away readability for a trivial gain. Optimise where a requirement (such as NFR1's 2 seconds) is at risk.
Record the evidence in a table like this
TechniqueWhereBeforeAfterTests still pass?
Dictionary index by ISBNCatalogue.search_by_isbnYour timeit resultYour timeit resultYes (13 of 13)
Exam tip: "Use" an optimisation technique The exam refers to language-dependent optimisation, so name a feature of the language (for example a list comprehension or a built-in function in Python) and say what it improves (speed, memory or clarity). NESA's 2025 HSC exam included a question on session management and code efficiency (Q20). A full-mark answer gives the technique, the code, and the reason it is better, and it does not change the output. Common mistakes are describing a general idea such as "use fewer loops" with no Python feature, and forgetting to say how you would know the change helped.

Analysing and Responding to Feedback

🎯 (SE-12-08, SE-12-09)

📌 Analyse and respond to feedback

Feedback from your client, users and peers shows how well the solution meets its requirements. Analyse it to find patterns, then respond by deciding what to change, what to schedule for later and what to explain.

FeedbackAnalysisResponse
"I couldn't find how to cancel a loan I entered by mistake."Usability issue, raised by 3 of 5 testersMoved the button and relabelled it; retested
"Can it send reminders by SMS?"New feature, outside the original boundaryAdded to the backlog for a future version
"Search is slow on the library computer."Performance issue: every search scans the whole catalogueAdded an index by ISBN and title; search time down from 4 s to 0.3 s

Turning feedback into action

  1. Collect: use the same short questions after each round, such as a 1–5 ease-of-use rating plus one open question.
  2. Group: sort comments into usability, bugs, performance and new features.
  3. Prioritise: fix what blocks users first; schedule features for later versions.
  4. Respond: tell users what changed, and retest to check the fix worked.

Sources and types of feedback

SourceTypically tells youWatch out for
ClientWhether the software meets the business needOpinions from one person; needs may have changed
End usersWhether it is usable in real workUsers describe symptoms ("it is confusing"), not causes
Peers and teacherCode quality, design, documentation, gapsThey may not know the client's context
The software itselfTimings, logs, defect countsData says what happens, not why

Feedback can be quantitative (a rating, a time, a count) or qualitative (a comment). Use both: numbers show how big a problem is, comments show what it is.

Worked example: analysing survey results

Eight testers each rate ease of use from 1 (very hard) to 5 (very easy), before and after the navigation was changed to make the loan history easier to find.

Tester12345678Mean
Rating before334234333.1
Rating after454454544.4
Python: summarise the ratings
from statistics import mean

before = [3, 3, 4, 2, 3, 4, 3, 3]
after = [4, 5, 4, 4, 5, 4, 5, 4]
print(round(mean(before), 1), round(mean(after), 1))
print(sum(1 for r in before if r <= 3), "of", len(before), "rated 3 or lower before")

Expected output: 3.1 4.4, then 6 of 8 rated 3 or lower before. The mean rose by 1.3, and every tester's rating stayed the same or improved. With only eight testers this is evidence of improvement, not proof, and the report should say so.

Prioritising the response

Feedback itemEffect on usersEffortDecision
Loan history is hard to findBlocks a core task for 5 of 8 testersSmallFix now and retest
Search is slowFails NFR1 (2 seconds)MediumFix now; a Must requirement
SMS remindersNice to haveLarge, and outside the boundarySchedule for version 2, and tell the client why
A dark themePreference of one testerMediumDecline for now, keep on the backlog

Finally, respond to the people who gave the feedback: report what changed, what did not, and why. Record each item in the process diary or a feedback log.

Exam tip: "Analyse and respond" to feedback Analysis means finding the pattern and its cause, then deciding. Give the evidence (how many users, how large the effect), the cause, the response and how you would check it worked: "Five of eight users could not find the loan history, so the button was moved to the main menu and the task was retested with three new users." Common mistakes are listing comments without analysing them, acting on every comment equally, and ignoring feedback outside the original scope instead of scheduling it.
HSC writing sample "Analysis of feedback from eight users showed that five struggled to find the loan history, so the navigation was redesigned and retested; average ease-of-use rose from 3.1 to 4.4. A request for a dark theme was acknowledged but scheduled for a later version because it did not affect core functionality."

Evaluating the Effectiveness of Your Solution

🎯 (SE-12-08, SE-12-09)

📌 Evaluate the effectiveness of a software engineering solution

  • developing a report to synthesise feedback
  • developing a test plan
  • testing data used/generated based on path and boundary testing
  • comparing actual output with expected output

Effectiveness & Testing Data

Evaluation involves generating a test plan and executing it using rigorous testing data based on path testing (ensuring every path through the code, and so every branch, executes at least once) and boundary testing (testing the extreme limits of input constraints). Engineers evaluate success by comparing actual output with expected output, and develop a final report to synthesise client feedback.

Test Plan Template

A test plan is a document that outlines the testing strategy, scope, resources, schedule, and exit criteria for a software project. It is prepared before testing begins to ensure testing is systematic and complete.

Section Content
Project Name Library Management System v1.0
Test Objectives Verify all functional requirements are met; confirm boundary conditions are correctly enforced; ensure invalid inputs are gracefully handled.
Scope — In Scope Book search, loan issuance, loan return, overdue fine calculation, member registration, report generation.
Scope — Out of Scope Payment processing (deferred to v2.0), email notification system.
Testing Types Unit testing (individual functions), integration testing (modules working together), system testing (end-to-end user workflows), user acceptance testing (client feedback session).
Test Data Categories Normal (valid expected inputs), Boundary (values at the edge of valid ranges), Invalid/Erroneous (inputs that should be rejected).
Tools Python unittest framework, VS Code debugger, manual testing via the application UI.
Entry Criteria All Phase 3 code is complete and committed to the main branch.
Exit Criteria All test cases pass; no critical or high-severity defects remain open; client has signed off on UAT results.
Schedule Unit testing: Weeks 5–6. Integration testing: Week 6. Acceptance testing: Week 7.

Comparing actual output with expected output

Every test case has an expected output, written from the requirement before the test is run, and an actual output, recorded when it is run. A test passes only when they match. A mismatch is the start of debugging, not the end of testing. The unit test below is what BUG-002 looked like before it was fixed.

Python: a failing test (BUG-002)
import unittest


def can_borrow(active_loans, limit=5):
    return active_loans <= limit     # the bug


class TestLoanRules(unittest.TestCase):
    def test_loan_limit_boundaries(self):
        self.assertFalse(can_borrow(5))


if __name__ == "__main__":
    unittest.main()

Output:

FAIL: test_loan_limit_boundaries (__main__.TestLoanRules.test_loan_limit_boundaries)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "loans_test.py", line 10, in test_loan_limit_boundaries
    self.assertFalse(can_borrow(5))
AssertionError: True is not false

Ran 1 test in 0.000s

FAILED (failures=1)

Read it as: expected False (the member is at the limit), actual True. The traceback names the test and the line. After the fix (<= changed to <) the same test passes, and it stays in the suite so the defect cannot quietly return (regression testing).

Evaluating Against Requirements

A thorough evaluation compares what you built against what you planned from Phase 1. For each functional and non-functional requirement, document:

  • Was this requirement fully met? Partially? Not met?
  • What evidence demonstrates it is met? (test results, user feedback, system output)
  • If not fully met, what limited the implementation?

Developing an Evaluation Report

Your evaluation report should synthesise all feedback gathered throughout the project and systematically compare actual outputs with expected outcomes. This includes:

  • Requirement Coverage: Use your original requirements document and reference each requirement by number, demonstrating which were fully met, partially met, or deferred.
  • Testing Evidence: Present test results showing how the system behaves against your test data (path and boundary testing cases).
  • User Feedback: Document feedback from the client or stakeholders about whether the system meets their needs.
  • Technical Evaluation: Discuss decisions made, challenges encountered, and how they were addressed.

To synthesise feedback is to combine several sources into a few conclusions, not to list each comment. A worked excerpt for Library Loans:

Feedback came from Mrs Chen (two reviews and the acceptance test), two volunteers (observed tasks) and eight testers (a rating survey). Three themes appeared across sources. (1) Findability: five of eight testers could not find the loan history; after the menu change the mean ease-of-use rating rose from 3.1 to 4.4. (2) Speed: Mrs Chen and two testers said search felt slow, and a timed test confirmed 4 seconds against the 2-second target (NFR1); an index reduced this to 0.3 seconds. (3) Missing reminders: raised by Mrs Chen and three testers. This is outside the version 1 boundary, so it is recommended for version 2, after a privacy review. Because the sample was small, these results show a likely improvement, not a certain one.

Evaluation Best Practices
Be specific and evidence-based — reference your test results and requirements document by number.
Acknowledge any limitations honestly — explain what didn't work and why, demonstrating critical reflection.
Use actual data — show test output, user feedback quotes, and measurable results rather than general statements.

Evaluation Criteria Checklist

The final evaluation assesses whether the solution meets the original requirements. Evaluation must address every requirement documented in Phase 1, referencing specific test results and client feedback as evidence.

Evaluation Criterion Evidence Met?
FR1 to FR6: functional requirements implemented and verified by testing All 13 test cases in the test data table pass; no open critical defects ✅ Yes
NFR1: search returns results within 2 seconds (performance) Timed 10 searches on a 10,000-book catalogue; average response time was 0.3 seconds ✅ Yes
NFR2: passwords stored as salted hashes (security) Inspected the database — only salted hashes are stored, no plaintext passwords visible ✅ Yes
NFR3: interface usable by new staff within 15 minutes (usability) Client representative completed a new-user walkthrough in 11 minutes with no assistance ✅ Yes
NFR4: code follows PEP 8 and all functions have docstrings (maintainability) Ran pylint — score 9.2/10; all public functions and classes have docstrings ✅ Yes
FR7: CSV export implemented (should-have) Report module includes export_to_csv() function; tested with 50-record export ✅ Yes
Solution meets client's overall expectations (UAT sign-off) Client feedback: "The system is easy to use and covers all our needs. Minor improvement: add a print function for loan receipts (deferred to v2.0)." ✅ Mostly — 1 enhancement deferred

Evaluating means making a judgement

NESA's syllabus glossary defines evaluate as "make a judgement based on criteria; determine the value of." So an evaluation needs criteria (the requirements and quality targets set in Part 1), evidence against each, and an overall judgement with reasons. A worked judgement for Library Loans:

Overall, Library Loans is an effective solution. All Must requirements (FR1 to FR5, NFR1, NFR2) were met and verified: 13 of 13 test cases pass, search takes 0.3 seconds against a 2-second target, and no plaintext passwords are stored. The client accepted the system, and the evaluation also found limits. Usability (NFR3) was met in a timed walkthrough with one volunteer only, so it is less certain for other users. Fines are recorded but not paid through the system, which Mrs Chen still handles by hand. The most valuable improvement would be due-date reminders, which the prototype tests suggest students would use.

Post-project review

After delivery, review the process as well as the product, so the next project is better. Compare the plan with what happened and record lessons that can be acted on.

QuestionLibrary Loans findingAction for next time
Did the schedule hold? (planned against actual)Critical path slipped 2 days early on, and the buffer absorbed it; the finish was day 34 of 35Add a larger buffer after the requirements stage and estimate client-review waits
Was the approach appropriate?WAgile suited it: gates gave sign-off and sprints gave early feedbackKeep the gates; shorten the first sprint's scope
Were requirements complete?One late change request (reminders) exposed that the client's Friday routine was not fully understoodObserve the client's real routine before writing requirements
Which defects were found late?Two boundary errors (loan limit, overdue date) were found only in testing, not during designWrite boundary tests before the code
What is the maintenance plan?Issue log on GitHub; a weekly backup; the code and documents handed over to the schoolName who fixes defects after the project ends
Exam Tip — Evaluation vs Testing Many students confuse testing with evaluation. Testing verifies that the software works correctly (does it match expected outputs?). Evaluation assesses whether the completed solution meets the original client requirements and broader criteria such as usability, security, and maintainability. Your evaluation must explicitly reference the requirements from Phase 1, because those are the criteria "effective" is judged against.
Exam tip: "Evaluate" and "develop a test plan" Questions in this area often supply a test data table or a short function and ask you to complete expected outputs, identify which data is boundary or path data, or compare actual and expected results. NESA's familiarisation questions include a 3-mark test-data table item. For an "evaluate" question, give a judgement (for example "largely effective"), name the criteria, use evidence from the results, and state at least one limitation. In a test table, write the expected result from the requirement, not from what the code happens to output. Common mistakes are testing only normal data, choosing boundary values that are not at the edge, and writing an evaluation that only describes what was built.