Lesson 13 of 13
Lesson 13

Defensive Design and Validation

Real users will type the wrong thing. Defensive design is the discipline of writing programs that anticipate misuse, validate every input, refuse to continue with bad data and produce code that other people can maintain. Required by OCR (2.3.1), AQA (3.2), Edexcel (1CP2 2.5) and CIE (8.4).

Validation, authentication, anticipating misuse, maintainability
Language:

In 2017 a single user pasted 65,000 characters into a Twitter status field and crashed every Twitter app on iOS. The bug had been there for years. The input was never length-checked. One bad input took down a whole product. Defensive design is the difference between code that handles real users and code that breaks the moment it leaves the developer's machine.

Think about it: If your program asks for a user's email address, what could go wrong if you trust whatever they type? List five concrete things.
Defensive design
Writing code that anticipates misuse and protects itself against unexpected input.
Input validation
Checking input against a rule before accepting it. Reject anything that does not meet the rule.
Range check
Ensures a number falls between a minimum and maximum, e.g. 0 <= age <= 130.
Presence check
Ensures a required field is not empty.
Length check
Ensures a string is not too short or too long, e.g. password must be at least 8 characters.
Format check
Ensures input matches an expected pattern, e.g. an email contains an @ symbol; a postcode looks like a postcode.
Type check
Ensures input is the right type (number, string, date) before being used.
Authentication
Confirming a user is who they claim to be, usually with a username and password.
Maintainability
Writing code with clear names, comments, indentation and modularisation so other people can read and fix it.
Anticipating misuse
Asking "what if the user does the wrong thing?" before they actually do it.

1. The five kinds of validation check

All four boards expect you to know these by name and apply them.

CheckWhat it testsExample
RangeNumber between a min and maxAge between 0 and 130
PresenceField is not emptyUsername must be entered
LengthString length within limitsPassword 8-20 characters
FormatMatches an expected patternEmail contains @ and a dot
TypeRight data typeQuantity must be an integer
# Range check
age = int(input("Age: "))
if age < 0 or age > 130:
    print("Age must be between 0 and 130.")

# Presence check
name = input("Name: ")
if name == "":
    print("Name cannot be empty.")

# Length check
password = input("Password: ")
if len(password) < 8 or len(password) > 20:
    print("Password must be 8-20 characters.")

# Format check
email = input("Email: ")
if "@" not in email or "." not in email:
    print("That does not look like a valid email.")

# Type check (using try/except)
try:
    qty = int(input("Quantity: "))
except ValueError:
    print("Quantity must be a whole number.")
// Range check
int age = int.Parse(Console.ReadLine());
if (age < 0 || age > 130) Console.WriteLine("Age must be between 0 and 130.");

// Presence check
string name = Console.ReadLine();
if (string.IsNullOrEmpty(name)) Console.WriteLine("Name cannot be empty.");

// Length check
string password = Console.ReadLine();
if (password.Length < 8 || password.Length > 20)
    Console.WriteLine("Password must be 8-20 characters.");

// Format check
string email = Console.ReadLine();
if (!email.Contains("@") || !email.Contains("."))
    Console.WriteLine("That does not look like a valid email.");

// Type check
if (!int.TryParse(Console.ReadLine(), out int qty))
    Console.WriteLine("Quantity must be a whole number.");

2. Validate-until-valid using a while loop

Printing an error and continuing is rarely enough. The standard pattern is to loop until the user gives valid input. This combines validation with exception handling.

age = -1
while age < 0 or age > 130:
    try:
        age = int(input("Enter age (0-130): "))
        if age < 0 or age > 130:
            print("Out of range, try again.")
    except ValueError:
        print("Whole numbers only.")
        age = -1

print(f"Age accepted: {age}")
int age = -1;
while (age < 0 || age > 130)
{
    Console.Write("Enter age (0-130): ");
    if (!int.TryParse(Console.ReadLine(), out age))
    {
        Console.WriteLine("Whole numbers only.");
        age = -1;
    }
    else if (age < 0 || age > 130)
    {
        Console.WriteLine("Out of range, try again.");
    }
}
Console.WriteLine($"Age accepted: {age}");
Validation vs exception handling

Validation handles bad values (an age of -5). Exception handling handles bad types (the user typed letters). A robust program needs both: try catches the type error, the while loop catches the value error.

3. Authentication: a basic login

Authentication asks "are you who you say you are?". The simplest version compares a typed password to a stored one. Real systems hash passwords (Lesson 6 of the CS series), but the GCSE concept is the comparison plus the design choices around it.

users = {
    "alice": "Sunset!42",
    "ben":   "Pa55word!"
}

attempts = 0
while attempts < 3:
    username = input("Username: ")
    password = input("Password: ")
    if username in users and users[username] == password:
        print("Login successful.")
        break
    attempts = attempts + 1
    print("Username or password incorrect.")
else:
    print("Account locked. Try again later.")
Dictionary<string, string> users = new Dictionary<string, string>
{
    {"alice", "Sunset!42"},
    {"ben",   "Pa55word!"}
};

int attempts = 0;
while (attempts < 3)
{
    string u = Console.ReadLine();
    string p = Console.ReadLine();
    if (users.ContainsKey(u) && users[u] == p)
    {
        Console.WriteLine("Login successful.");
        break;
    }
    attempts++;
    Console.WriteLine("Username or password incorrect.");
}
Why a generic error message

Real systems never tell you whether the username or the password was wrong. Saying "yes, that username exists, but the password was wrong" gives an attacker half the secret for free. The exam expects you to identify this.

4. Anticipating misuse

Defensive design is more than validation. The exam wants you to think about what users will do wrong, not just what they should do right. Examples:

  • What if the user closes the program halfway through entering data? (Save progress; do not corrupt the file.)
  • What if the user enters their date of birth as 30 February 2010? (Validate dates.)
  • What if two users press "Save" at the same time? (Lock the file or warn one of them.)
  • What if the user types their password with caps lock on? (Warn them; do not silently fail.)
  • What if a teacher accidentally deletes a class? (Confirm dialog; soft-delete with undo.)

Each scenario is a defensive-design decision the developer makes before the user encounters it.

5. Maintainability matters too

Defensive design is not only about input. The exam also wants you to talk about maintainability: code that other people can read and change without breaking it.

Maintainability featureWhy it helps
Meaningful identifier names (student_score not s)The reader does not have to trace the code to learn what each variable means.
Comments that explain why, not whatThe code already says what it does; comments explain the reason behind the choice.
Consistent indentationReveals the logical structure visually so nesting is obvious at a glance.
Subroutines (functions/procedures)Each task is named and isolated, so changes are local.
Avoiding magic numbersA constant like MAX_AGE = 130 is changed in one place.
Examiner shorthand

"Discuss maintainability" means at least two named features above, each with a reason. Saying "good comments help" once is one mark; naming three distinct features with reasons is three marks.

"Validation makes a system secure"

Validation makes a system robust against accidents. Security against deliberate attack also needs hashing of passwords, encrypted transmission, rate limiting, and account-lockout, plus protection against injection attacks. Validation is part of defensive design but it is not the whole of security. The exam will not award security marks for a validation answer.

6. A six-mark question, fully marked

Question: A school is designing an online form to register new pupils. Discuss the defensive-design features the developer should include. [6 marks]

Mark scheme - up to 6 marks, one per valid point with justification
  • Range check on date of birth so that impossible dates (e.g. year 2030) are rejected.
  • Presence check on required fields (name, year group) so the form cannot be submitted half-empty.
  • Length check on password so it meets the minimum 8 characters.
  • Format check on parent email so an obvious typo (no @) is caught at the form rather than later.
  • Validate-until-valid loop so the user is prompted to fix mistakes rather than the form silently failing.
  • Confirmation step before final submission so accidental presses do not register a pupil with wrong data.
  • Maintainable code (clear names, subroutines, constants) so the form can be updated next year without breaking.

Beyond the basics

A developer adds a "max 50 characters" length check to a name field on a registration form. A user with the name "María José García-Hernández de la Vega" cannot register because her real name is 51 characters. Discuss the trade-off the developer made: when does input validation become a barrier rather than a safeguard, and what is a better design?
The trade-off: the 50-character cap was probably chosen to defend against the 65,000-character paste attack and to fit a database column. Both are valid concerns. But the cap is now excluding real users with legitimate long names, which is a worse failure than the attack would have been.

The better design:
- Choose a much higher generous limit for human names, e.g. 200 characters. Real names rarely exceed this and the database column can be sized to match.
- Combine the limit with a request-size cap at the server level so a 65,000-character paste is rejected before it reaches the validation logic.
- Warn the user gently if they type something unusual rather than blocking submission outright.

The principle: validation should reject impossible or malicious input, not unusual-but-legitimate input. When validation excludes real users, the developer has weighted the wrong risk.
Q1. A program requires a UK postcode. Which check ensures the user typed something in roughly the right shape?
Format checks compare the input to an expected pattern, which is what postcodes need.
Q2. Why does a real login show the same error for a wrong username and a wrong password?
Generic errors prevent attackers from learning which usernames are valid - they would otherwise have half the secret.
Q3. Which is a defensive-design feature that helps maintainability rather than input safety?
Maintainability is about other developers being able to read and edit the code later.
Q4. A program asks for a quantity. The user types "five". What kind of check would catch this?
"five" is the wrong type (a string instead of an integer). A type check rejects it before the program can try to do arithmetic on it.
Q5. Why should a "validate-until-valid" loop usually be combined with a try/except (or TryParse) block?
Validation handles values out of range; exception handling handles inputs of the wrong type. Robust input needs both.
Programming - Lesson 13
Defensive Design and Validation
Starter activity
Display a simple online form on the board (name, age, email, password). In pairs, students must come up with as many ways to break it as possible in three minutes. Collect responses and group them under the validation categories (range, presence, length, format, type). Reward the most creative misuse - the goal is to think like a misbehaving user.
Lesson objectives
1
Define defensive design and explain why anticipating misuse matters.
2
Name and apply five validation checks: range, presence, length, format, type.
3
Combine a validate-until-valid loop with exception handling for robust input.
4
Describe a basic authentication flow with attempt limiting and explain why error messages are deliberately generic.
5
List at least three maintainability features and justify each one.
6
Discuss when validation becomes too strict and excludes legitimate users.
Key vocabulary
defensive designvalidationrange checkpresence checklength checkformat checktype checkauthenticationmaintainabilitymisusesubroutinemagic number
Discussion questions
Why do real login forms not say which of username or password was wrong?
When does validation become too strict and start excluding legitimate users?
Maintainability does not affect what the program does. Why is it still examined?
Pick one app you use every day. Identify three defensive-design features it includes.
Exit tickets
Name three validation checks and give an example of where each is used. [3 marks]
Explain why a login system should limit the number of attempts. [2 marks]
Discuss two defensive-design features for a school registration form. [4 marks]
A program rejects the name "Anne-Marie O'Neill" as invalid. Explain what has gone wrong with the validation. [3 marks]
Homework suggestion
Design an online registration form for a school sports day. List every input the form needs, then choose the appropriate validation check(s) for each one. Write Python or C# code that validates one of the inputs using a validate-until-valid loop. Hand in the design, the code, and a paragraph explaining the trade-offs in your choice of validation rules.
Classroom tools