4.5.3 · D2Software Engineering

Visual walkthrough — Requirements — functional vs non-functional, user stories, acceptance criteria

2,171 words10 min readBack to topic

We start from literally nothing — a person saying "make me a thing" — and end at a line a test runner can print ✅ or ❌ against. Follow the pictures; the words only point at them.


Step 1 — Start from raw ambiguity

WHY we begin here. Every real project begins with a sentence that is too blurry to build. If you skip this and pretend the wish is already clear, you build the wrong thing perfectly — the most expensive mistake there is. So Step 1 is just: admit the input is fog.

PICTURE. Look at the figure. On the left is a single blurry cloud labelled "cart stuff". It has many arrows fanning out of it — each arrow is a different thing the stakeholder might have meant. The fog is wide because the sentence permits many interpretations.

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

The whole rest of the walkthrough is one job: shrink the fan of arrows down to one.

Related idea: this is where Stakeholder Analysis lives — deciding whose fog you are clearing.


Step 2 — Split the wish into WHAT and HOW-WELL

WHY this split and not some other. Because these two kinds of statement fail differently and are tested differently. A behaviour is missing or present (a feature test). A quality is met or not to some number (a benchmark). Mixing them hides the number and makes "fast enough" an opinion instead of a target. So we separate them first, before doing anything else.

PICTURE. The blurry cloud pours down onto a sieve. Purple droplets (verbs) fall through the left hole into the FR bucket; coral droplets (adverbs, each carrying a little number) fall through the right hole into the NFR bucket. Notice: the same verb can appear with several coral drops — one behaviour, many qualities.

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

Step 3 — Package each FR as a user story

Term by term, right where each appears:

  • — a named real human, e.g. shopper. Forces you to admit who uses this. If you can't name them, nobody wants it.
  • — the capability they want, phrased as a problem (remove an item), never a solution (not "add a delete button in React").
  • — the reason it's worth money. This is the value filter: no benefit ⇒ maybe delete the story.

WHY a mould at all. A free-form sentence lets you forget the who or the why. The three empty slots are three questions you are forced to answer. Empty slots = a visible gap.

PICTURE. A purple drop drops into a three-chamber mould. Each chamber lights up as it fills: who (mint), what (lavender), why (butter). The output is a neat brick labelled story. An unfilled chamber glows red — you can see the hole.

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

This packaging step is the heart of Agile and Scrum; how big each brick is feeds Estimation and Story Points.


Step 4 — Check the brick is well-formed (INVEST)

WHY these six. They are the six ways a story goes bad. If a brick is too big (fails S) you can't estimate it (fails E). If it has no benefit (fails V) it shouldn't exist. The last gate, Testable, is the bridge to the next step — a story that cannot be turned into a pass/fail check must be reshaped now.

PICTURE. The story brick rolls along a conveyor through six coloured arches. It passes clean through five. At the S(mall) arch it's too fat and gets sliced in half into two smaller bricks — showing that failing a gate doesn't kill the story, it reshapes it.

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

Step 5 — Convert the story into acceptance criteria

Term by term:

  • Given — the world before: the cart already has 2 items. Fixes the inputs.
  • When — the single action: I remove one item.
  • Then — the observable, checkable outcome: the cart shows 1 item and the total updates.

WHY this exact shape. A test needs three things: a known setup, one trigger, one expected output. Given/When/Then is those three things named. That's why the same sentence a human agrees to can be typed straight into an automated test — this is the doorway to Test-Driven Development.

PICTURE. The story brick sits at the top. Below it, an arrow feeds into a three-band strip: Given (mint band, showing "2 items"), When (lavender band, a finger removing one), Then (butter band, showing "1 item, total updated") ending in a green ✅. The fog from Step 1 has now collapsed to a single arrow.

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

Step 6 — Cover every case, especially the ugly ones

WHY. Bugs cluster at the edges — 0 items, maximum length, no network. A test suite that only checks the middle of the road silently permits crashes at the kerb. This is the same "cover all cases" discipline as checking every quadrant in trigonometry: the reader (and the user) must never hit a scenario you didn't show.

PICTURE. A branching tree grows out of the single happy arrow: one branch for 2 items → remove → 1 (green), one for 1 item → remove → empty-cart message (butter, the boundary), one for remove then refresh → still gone (mint, persistence), and one red branch for remove from empty cart → nothing breaks (the degenerate case). Each leaf ends in ✅.

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

Step 7 — Close the loop: "done" means all AC pass

WHY this is the whole point. We started (Step 1) with a fog of many possible meanings. We have now collapsed it to a finite set of objective yes/no checks. "Done" is no longer an opinion two people can disagree about; it's a count: passed = required.

  • — how many criteria currently return ✅.
  • — every criterion we wrote, edges included.
  • — "done" and "all green" are the same statement, not merely related.

PICTURE. A scoreboard: a progress bar filling as tests turn green. Only when the bar is 100% full does a lavender "DONE" stamp drop onto the story. A partially-full bar shows a grey "not done" — visually, done is binary.

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

This closing check is one exit gate of the Software Development Life Cycle; the design choices it unlocks (Redis? CDN?) belong to Software Design.


The one-picture summary

Everything above is one funnel: a wide blurry cloud on the left, squeezed through sieve → mould → gates → Given/When/Then → branch tree, narrowing to a single green ✅ on the right. Ambiguity in, testable "done" out.

Figure — Requirements — functional vs non-functional, user stories, acceptance criteria
Recall Feynman retelling — say it back in plain words

Someone says "make me cart stuff" — that's fog, it could mean a hundred things. First I run it through a sieve: verbs (what it does) fall in one bucket, measurable qualities-with-numbers (how well) in another. I take a verb and pour it into a three-slot mould: who wants it, what they want, why it's worth it — that's a user story. I check the story through six gates (INVEST); if it's too big I slice it. Then I nail concrete Given–When–Then criteria onto it — a known setup, one action, one exact result — which is literally a test a computer can run, and it's where the quality-numbers finally get a threshold. I don't stop at the happy path: I add the empty case, the boundary case, the invalid case, because bugs live at the edges. Finally, "done" just means every one of those checks is green — no opinions left. The fog became a single ✅.

Recall Rebuild the funnel order from memory

Fog → sieve (FR vs NFR) → mould (user story: role/goal/benefit) → six gates (INVEST) → Given-When-Then acceptance criteria → all cases (happy + boundary + degenerate + NFR threshold) → done = all AC pass. ::: That is the seven steps.


Flashcards

In one word, what does the requirements funnel remove from a stakeholder's sentence?
Ambiguity (the fan of possible meanings shrinks to one).
Which step is the only place a non-functional quality gets a measurable number?
The acceptance criteria (Given-When-Then Then-clause).
Why must every story pass the "Testable" gate before writing AC?
If it can't be phrased as an objective pass/fail check, the AC can't be automated — the story must be reshaped first.
"Done" is equivalent to which countable condition?
The number of acceptance criteria passed equals the total number written (all green, edges included).
Why add boundary/degenerate cases (empty cart, last item) to the AC?
Bugs cluster at the extremes; an unlisted edge case is an untested one and will break in production.