4.5.3 · D4Software Engineering

Exercises — Requirements — functional vs non-functional, user stories, acceptance criteria

2,564 words12 min readBack to topic

Level 1 — Recognition

Goal: can you spot which bucket a statement belongs in, with no rewriting.

Exercise 1.1

For each statement, label it FR or NFR:

  • (a) "The system shall let a user log in with email and password."
  • (b) "Login shall complete within 1 second for 95% of attempts."
  • (c) "The system shall send a receipt email after purchase."
  • (d) "The site shall be available 99.9% of each month."
Recall Solution 1.1
  • (a) FR — it names a behaviour ("let a user log in"), a verb, no number attached.
  • (b) NFR — same login verb, but now constrained by a measurable quality: "within 1 second, 95%". That threshold is the tell.
  • (c) FR — "send a receipt email" is a behaviour the system performs.
  • (d) NFR — "99.9% availability" is a measurable reliability quality, not a feature. Nothing new is done; existing features must simply keep running.

Pattern: whenever a statement pins a number+unit onto a verb, the number part is the NFR.

Exercise 1.2

Which FURPS+ category does each NFR belong to? (Functionality, Usability, Reliability, Performance, Supportability, +security/scalability/legal)

  • (a) "Handles 10,000 concurrent users."
  • (b) "A new user completes checkout without help in under 3 minutes."
  • (c) "All passwords stored hashed and salted."
Recall Solution 1.2
  • (a) Scalability (the "+") — capacity to grow with load. (Some teams file it under Performance; scalability is specifically about load growth.)
  • (b) Usability — measures how easily a human succeeds ("without help, under 3 minutes").
  • (c) Security (the "+") — protects data. Note it is measurable-ish ("hashed and salted" is a verifiable state).

Level 2 — Application

Goal: produce the artefact yourself, not just recognise it.

Exercise 2.1

Rewrite this raw stakeholder request as a proper user story using As a <role>, I want <goal>, so that <benefit>:

"People keep asking us to save their card so they don't retype it."

Recall Solution 2.1

As a returning shopper, I want to save my card details securely, so that I can checkout faster without retyping them each time.

  • Role = "returning shopper" (a real person, not "the system").
  • Goal = "save my card details" — a capability, not an implementation (we did NOT say "store in a Stripe token vault"; that's a design choice for later).
  • Benefit = "checkout faster without retyping" — this is the value test; it also silently signals a security NFR ("securely") that must get its own acceptance criterion.

Exercise 2.2

Write three acceptance criteria in Given-When-Then form for the story:

As a shopper, I want to apply a discount code, so that I pay less.

Include at least one edge case.

Recall Solution 2.2
  • Given a valid code "SAVE10", When I apply it to a £100 cart, Then the total shows £90. (happy path)
  • Given an expired or invalid code, When I apply it, Then an error "code not valid" shows and the total is unchanged. (negative/edge case)
  • Given an already-applied code, When I apply the same code again, Then it is not applied twice and a message explains why. (boundary — prevents double-discount bug)

Each line is objective pass/fail: a machine could check "total = £90". That's what makes them acceptance criteria and not opinions.


Level 3 — Analysis

Goal: find what's wrong / missing and explain WHY.

Exercise 3.1

Critique this user story against INVEST and list every letter it violates:

"As the system admin, I want the whole reporting, billing, and notification subsystem redesigned so that everything is better."

Recall Solution 3.1

Violations:

  • S (Small): "whole reporting, billing, and notification subsystem" is three subsystems — far too big for one story. Split into three+.
  • E (Estimable): because it's huge and vague, no one can size it. (See Estimation and Story Points — un-slicable stories can't be pointed.)
  • T (Testable): "everything is better" has no pass/fail condition. What does "better" measure?
  • V (Valuable): benefit is empty ("better" is not a value statement).
  • Arguably N (Negotiable) survives and I (Independent) is unclear.

Verdict: at minimum it fails S, E, T, V — four of six. A story failing "Testable" and "Small" is the classic "epic disguised as a story".

Exercise 3.2

This AC set is incomplete. Identify the missing category of case and add one criterion to fix it. Story: As a user I want to upload a profile photo. Given a valid JPG under 5 MB, When I upload, Then it appears as my avatar.

Recall Solution 3.2

Missing category: the negative / boundary cases. Only the happy path is covered. Bugs cluster at boundaries (see the parent note's boundary mistake). Add, for example:

  • Given a file over 5 MB, When I upload, Then an error "file too large (max 5 MB)" shows and no avatar changes.
  • Given a non-image file (.pdf), When I upload, Then it is rejected with "images only".

The rule: for every "Then it works", write a "Given an invalid/empty/oversized input, Then it fails gracefully".


Level 4 — Synthesis

Goal: combine FR + NFR + story + AC into one coherent slice, and reason about cost.

Exercise 4.1

A stakeholder says: "Customers must be able to track their order, and it should never feel slow, and it must work even when 50,000 people check at once." Produce: (1) the FR, (2) two NFRs with measurable thresholds, (3) one user story, (4) one AC that encodes an NFR.

Recall Solution 4.1

(1) FR: The system shall let a customer view the current status of their order. (2) NFRs (given numbers — "never slow" and "50,000" must become measurable):

  • Performance: status page returns in ≤ 1.5 s for the 95th-percentile request.
  • Scalability: the feature sustains 50,000 concurrent status checks with no errors. (3) Story: As a customer, I want to see my order's current status, so that I know when to expect delivery. (4) AC encoding an NFR: Given 50,000 concurrent users, When each requests order status, Then 95% of responses arrive in ≤ 1.5 s and none return an error.

Note how the vague words "never slow" / "50,000 people" were forced into numbers — that conversion is the whole point of splitting NFRs out. See Test-Driven Development for turning that last AC into an automated load test.

Exercise 4.2 (cost reasoning)

The parent note models the cost of fixing a misunderstanding as where counts stages: requirements , design , code , test , production . A bug that costs £200 to fix if caught at requirements () is instead caught in production. Using , how much does it cost in production, and how many times more expensive is that?

Recall Solution 4.2

Look at the figure below: each stage multiplies the cost by . The multiplier is , so it is 81× more expensive. Interpretation: every stage you let a misunderstanding survive triples the repair bill. Writing requirements well is cheap leverage against the steep right-hand tail of this curve.

Figure — Requirements — functional vs non-functional, user stories, acceptance criteria

Level 5 — Mastery

Goal: design the whole requirements slice for a fresh feature and defend every choice.

Exercise 5.1

Green-field feature: "Let users reset a forgotten password by email." Produce a complete, defensible package:

  1. one user story (INVEST-compliant),
  2. the FR list,
  3. at least two NFRs with thresholds and FURPS+ categories,
  4. an AC set covering happy path + two edge/negative cases + one NFR threshold,
  5. name one downstream artefact each item feeds into.
Recall Solution 5.1

1. Story: As a registered user who forgot my password, I want to reset it via a link sent to my email, so that I can regain access without contacting support. (INVEST check: Independent of other auth features; Negotiable wording; Valuable — self-service saves support cost; Estimable — small and clear; Small — one flow; Testable — see AC below.)

2. FR list:

  • The system shall let a user request a reset by entering their registered email.
  • The system shall email a unique, single-use reset link.
  • The system shall let the user set a new password via that link.
  • The system shall invalidate the link after use or after it expires.

3. NFRs:

  • Performance: the reset email is queued within ≤ 5 s of the request, 99% of the time. (FURPS: Performance)
  • Security: the reset link expires ≤ 30 minutes after issue and is single-use. (FURPS: +Security)
  • (bonus) Reliability: email delivery success ≥ 99.5% monthly. (FURPS: Reliability)

4. AC set (Given-When-Then):

  • Happy path: Given a registered email, When I request a reset and click the fresh link, Then I can set a new password and log in with it.
  • Edge — unknown email: Given an email not in the system, When I request a reset, Then I see the same neutral "if the email exists, a link was sent" message (so we don't leak which emails are registered — a security subtlety).
  • Edge — expired link: Given a link older than 30 minutes, When I click it, Then it is rejected with "link expired, request a new one".
  • NFR threshold: Given a valid request, When submitted, Then the email is queued in ≤ 5 s for ≥ 99% of requests.

5. Downstream artefacts:

  • The story feeds Estimation and Story Points (sizing) and the Agile and Scrum backlog.
  • The FR list feeds Software Design (the flow/state machine of link lifecycle).
  • The NFRs feed load/pen-test plans in Test-Driven Development.
  • The AC set feeds the automated acceptance tests and the Software Development Life Cycle "definition of done".
  • The whole package originated from Stakeholder Analysis (who asked, and why it's valuable).

Quick self-test recap

Which side of the split gets a number?
Non-functional — it must be measurable (number + unit + context).
In As a <role>, I want <goal>, so that <benefit>, which part is the prioritisation filter?
The benefit ("so that ..."), it states the value.
Why must acceptance criteria include edge/negative cases?
Most production bugs live at boundaries (empty, max, invalid, no-network); happy-path-only AC hides them.
With , , , production , what is the cost?
(81× more).
What un-obvious NFR forces "unknown email" resets to show a neutral message?
Security (prevents account enumeration).