Requirements and Project Terminology
Before you start
You need: the team roles from Article 01 — the BA and Product Owner appear throughout.
Time: about 45 minutes, plus the practice.
Learning objective
Turn a vague business request into a user story with acceptance criteria that a developer can build and a tester can verify.
Topics
- Why requirements go wrong
- Requirement types
- Scope vocabulary — epic, feature, story, task
- Writing a user story
- Acceptance criteria
- Ready and done
- Bugs and change requests
- The clarification checklist
Why requirements go wrong
"We need a student report."
Six words. At least eight unanswered questions:
- Which students — all, one class, one section?
- Which data — marks, attendance, fees, all three?
- For one exam or the whole year?
- Who can see it — principal only, or class teachers too?
- On screen, printed, or downloaded?
- Are absent students included, and how are they shown?
- What about students who transferred mid-year?
- How current must it be — live, or overnight?
Every unanswered question becomes a guess, and a guess is a rework. A developer who builds a live on-screen report for one class discovers three days later that the principal wanted a printable year-end summary for the whole school.
The cost of a misunderstanding multiplies with how late it is found. Caught in conversation, it costs five minutes. Caught in code review, an afternoon. Caught in production by the principal, a rushed fix, a redeploy and a loss of trust.
Requirement types
| Type | Describes | School example |
|---|---|---|
| Business requirement | The outcome the organisation wants | "Reduce the time the office spends locating student records" |
| Functional requirement | What the system must do | "The student list can be filtered by name or roll number" |
| Non-functional requirement | How well it must do it | "Search returns within two seconds for 800 students" |
| Constraint | A limit that is not negotiable | "Must run on the school's existing SQL Server 2019" |
| Assumption | Something believed true but unverified | "Every student has exactly one fee account per year" |
Non-functional requirements are the ones freshers ignore and production punishes. A search that works beautifully on the 20 students in your development database and takes 40 seconds on the 800 in production has met the functional requirement and failed the real one.
Write assumptions down. "Every student has one fee account per year" looks harmless until a student repeats a year and has two — which is precisely the bug the C# and SQL tracks use as their worked example.
Scope vocabulary
Epic: Student Management
│
├── Feature: Student search
│ ├── Story: Search students by roll number
│ ├── Story: Search students by name
│ └── Story: Show "no results" when nothing matches
│
└── Feature: Student records
├── Story: Add a new student
└── Story: Transfer a student to another section
| Term | Size | Example |
|---|---|---|
| Epic | Months; several features | Student Management |
| Feature | Weeks; a coherent capability | Student search |
| Module | A part of the system, by structure | The fees module |
| Story | Days; one piece of user value | Search students by roll number |
| Task | Hours; a technical step within a story | Add the search endpoint |
| Bug | Something built that does not work | Search ignores the section filter |
| Spike | Timeboxed investigation | Find out whether SQL full-text search is available |
Module and feature are not the same thing. A module is a structural part of the system — the fees module, the attendance module. A feature is a capability users get. The fee defaulter report is a feature within the fees module.
A story should be finishable in a few days. Larger than that and it hides risk: at day six nobody knows whether it is 50% or 90% done. Split it.
Splitting "Student search" badly and well:
Bad split — layers, none independently useful:
- Build the search API
- Build the search UI
- Connect them
Good split — each delivers something:
- Search by exact roll number
- Search by partial name
- Handle no-results and errors
Each good-split story could ship on its own. Exact-roll-number search alone already saves the office ten minutes a day.
Writing a user story
As an office administrator
I want to search students by name or roll number
So that I can find a student's record without scrolling through the full list
| Part | Answers |
|---|---|
| As a | Who — a specific role, never "user" |
| I want | What capability |
| So that | Why — the value |
The "so that" is the part people drop, and it is the most useful part. It tells the developer what actually matters, which shapes every decision that the story does not specify.
Knowing the office administrator wants to find one student fast tells you: results should appear as they type, the roll number should match exactly, and 800 results are useless — the top ten are what is wanted.
Bad: As a user, I want a search box, so that I can search.
Good: As an office administrator, I want to search students by name or
roll number, so that I can find a student's record during a phone
call from a parent, without scrolling through 800 rows.
"As a user" tells you nothing. Every role uses the system differently — a principal searching to review results has different needs from an office clerk on a phone call.
Acceptance criteria
The definition of done for one story. If every criterion passes, the story is finished.
Story: Search students by name or roll number
Acceptance criteria
1. Entering a full roll number (NCA-2024-0012) returns exactly that student
2. Entering a partial name ("Rav") returns all active students whose name contains it
3. Search is case-insensitive — "ravi" and "RAVI" return the same results
4. Leading and trailing spaces are ignored
5. Searching something with no match shows "No students found"
6. Only students of the signed-in user's school are returned
7. Transferred and graduated students are excluded unless "include inactive" is ticked
8. Results are ordered by roll number
9. Search returns within two seconds for a school with 800 students
Each criterion is a test someone can run. "The search should be fast" is not a criterion; "returns within two seconds for 800 students" is.
Criteria 4, 6 and 7 are the ones that come from experience. A trailing space in a pasted roll number silently returns nothing. A missing school filter returns another school's children. A transferred student appearing in the active list confuses the office.
Criterion 6 is a security rule, not a filter. Whoever wrote it prevented a data breach with one line.
The Given/When/Then form is common and useful for anything conditional:
Given a student NCA-2024-0012 exists in my school
When I search for "NCA-2024-0012"
Then exactly that student is shown
Given a student NCA-2024-0012 exists in another school
When I search for "NCA-2024-0012"
Then "No students found" is shown
The second scenario is the one that matters — testing that something is not returned is as important as testing that something is.
Ready and done
Definition of Ready — a story may not be started until:
- The acceptance criteria are written and unambiguous
- Dependencies are identified
- Designs or wireframes exist, if the story needs them
- The team has estimated it
- Nobody has an open question about it
Definition of Done — a story is not finished until:
- The code is written and reviewed
- Every acceptance criterion passes
- Tests are written and passing
- It is merged and deployed to the QA environment
- QA has verified it
- Documentation is updated where needed
"It works on my machine" is not done. Neither is "the code is merged". The definitions exist because everyone's private idea of finished is different, and a shared one prevents an argument at the end of every sprint.
Bugs and change requests
| Bug | Change request | |
|---|---|---|
| Means | Built, does not meet the agreed criteria | The agreed criteria are being changed |
| Who pays | The team, within the sprint | Prioritised as new work |
| Example | Search ignores the section filter, which criterion 8 required | "Actually, also search by parent phone number" |
Calling a change request a bug is how sprints overrun. "The search doesn't look for parent phone" is not a defect if nobody ever asked for it — it is new work that deserves an estimate and a place in the backlog.
A useful bug report:
Title: Student search returns students from other schools
Steps: 1. Sign in as priya.sharma@nca.test (School 1)
2. Open /students
3. Search "NCA-2024-0012"
Expected: No results — that roll number belongs to School 2
Actual: School 2's student record is displayed
Severity: Critical — cross-school data exposure
Scope: Every search; reproduced on QA and production
Since: Sprint 14 deployment
Steps, expected, actual, scope, since. A report missing "expected" forces the developer to guess what correct looks like.
The clarification checklist
Before starting any story, you should be able to answer:
| Question | Why |
|---|---|
| Who uses this, and for what? | Shapes every unspecified decision |
| What does success look like? | The acceptance criteria |
| What happens when it fails? | The error path is half the work |
| What data does it touch? | Which tables, which permissions |
| Who is allowed to do it? | Authorisation is not optional |
| How much data, realistically? | 20 rows and 800 rows need different solutions |
| What is explicitly out of scope? | Prevents gold-plating |
| How will this be tested? | Ask QA before you build, not after |
If you cannot answer these, you are not ready to start — and the right move is a five-minute conversation, not a day of guessing.
"What is out of scope" is worth asking every time. It is how you learn that pagination is deliberately deferred, and stop yourself building it.
Where this goes wrong
| The mistake | Why it costs | Instead |
|---|---|---|
| A "requirement" that is really a solution | Locks in a design before anyone understood the problem | Ask what problem it solves |
| "As a user, I want..." | Every role uses the system differently | Name the actual role |
| Dropping the "so that" | The developer cannot make the unspecified decisions | Always state the value |
| Untestable criteria | "Should be fast" cannot be verified | "Under two seconds for 800 students" |
| No criterion for the empty case | The feature breaks on day one with no data | Cover empty, error and unauthorised |
| Calling a change request a bug | The sprint overruns and nobody knows why | New work gets estimated and prioritised |
| Assumptions never written down | "Every student has one fee account" — until one does not | Write them where the team can challenge them |
The commonest of all is starting work with unclear acceptance criteria and discovering on day three that the thing being built was never what was wanted.
Common mistakes
- Starting work with unclear acceptance criteria
- "As a user" instead of a specific role
- Dropping the "so that"
- Criteria that cannot be tested — "should be fast", "should be user-friendly"
- No criterion for the empty, error or unauthorised case
- Ignoring non-functional requirements until production
- Assumptions never written down
- Splitting stories by layer instead of by value
- Treating a change request as a bug
- A bug report with no "expected"
- Building beyond the scope because it seemed useful
Practice
The course exercises are convert a business request into a feature and tasks and write one user story with acceptance criteria.
- Take "We need a student report" and write the eight questions you would ask.
- For each of the five requirement types, write one example from the School system.
- Write down three assumptions the School system makes, and how you would verify each.
- Break the epic "Fee Management" into two features, then one feature into three stories.
- Split "Fee defaulter report" by layer and by value, and explain which split lets you ship sooner.
- Write a user story for the accounts clerk who wants a defaulter list, including the "so that".
- Rewrite it as "As a user, I want a report" and note what information is lost.
- Write eight acceptance criteria for that story, including one for the empty case, one for the unauthorised case, and one non-functional.
- Write two Given/When/Then scenarios — one where a defaulter is returned, one where a student from another school is not.
- Write your team's Definition of Ready and Definition of Done.
- Classify each of these as bug or change request: search ignores the section filter; search should also match parent phone; search takes 40 seconds on 800 students; search shows transferred students.
- Write a bug report for cross-school data exposure with steps, expected, actual, severity, scope and since.
- Take a story you would build and answer all eight clarification questions. Note which you cannot answer.
Exercise 13 is the habit. The questions you cannot answer are exactly what to ask the BA.
You can now
- Turn a vague business request into a user story with a real "so that"
- Write acceptance criteria someone else can test
- Include the empty, error and unauthorised cases
- Split a story by value rather than by layer
- Tell a bug from a change request, and say why it matters
- List what you must clarify before starting
Review questions
- Why is the "so that" the most useful part of a user story?
- What makes "the search should be fast" unusable as an acceptance criterion?
- Why is splitting a story by layer worse than splitting it by value?
- What distinguishes a bug from a change request, and why does the distinction matter?
Next: Application layers