Joining the Backend Team
User Stories and Acceptance Criteria
In the previous lesson, we separated our requirements into functional and non-functional concerns.
We now have a broad understanding of the capabilities the system needs to support.
But a broad requirement is usually too vague to use directly as an implementation ticket.
For example:
Customers should be able to place orders.
This is an important requirement.
But if an engineer starts implementing based only on that sentence, many behaviours remain undefined.
Real software teams therefore break broad requirements into smaller, understandable, and testable units.
In this lesson, we will work with two common concepts:
User Story
and:
Acceptance Criteria
Their purpose is not to create process-heavy documentation.
Their purpose is to make sure everyone understands the same expected behaviour and knows when a change can reasonably be considered complete.
From Product Requirement to Engineering Work
Our current progression looks like this:
Product Requirement
↓
Requirement Analysis
↓
Functional Requirements
↓
User Stories
↓
Acceptance Criteria
↓
Engineering Tickets
↓
Implementation
This is not a rigid process.
Different companies work differently.
A small team may skip formal User Stories and move directly from a requirement to an engineering ticket.
But the underlying principle remains the same:
Before implementation starts, the expected behaviour must be sufficiently clear.
What Is a User Story?
A User Story is a short description of a desired capability from the perspective of a user.
A common format is:
As a <type of user>,
I want <some capability>,
so that <some outcome>.
For example:
As a Customer,
I want to place an Order,
so that I can purchase available Products.
This tells us three things.
Who?
Customer
What?
Place an Order
Why?
Purchase available Products
It does not describe the implementation.
It captures the intent behind the behaviour.
A User Story Is Not a Technical Specification
This distinction is important.
Consider:
As a Customer,
I want to view my previous Orders,
so that I can review my purchase history.
The story does not say:
GET /api/v1/orders
It does not say:
Use Spring Data JPA.
And it does not say:
Query orders by customer_id.
Those are implementation decisions.
A User Story primarily answers:
Who needs what, and why?
Technical design later answers:
How will we provide it?
Why the “Why” Matters
Consider this shorter story:
As a Customer,
I want to view my Orders.
It is understandable.
But adding:
so that I can review my purchase history
makes the intent clearer.
Why does that matter?
Because the underlying need influences later design decisions.
If the Customer only needed to check the status of their latest Order, the required API behaviour might be different.
If they need complete purchase history, then concerns such as:
pagination
historical data
sorting
become more important.
User intent provides context for technical decisions.
User Stories Are Not Mandatory Everywhere
Real engineering teams use different terminology.
One team may use:
User Story
Another may use:
Feature
Another:
Product Requirement
And another may go directly to:
Engineering Ticket
We use User Stories in this course because they are useful for learning how to decompose requirements.
We are not treating the process itself as the goal.
The important principle is:
The user-facing purpose of the work should be clear.
Our First User Stories
We can derive several User Stories from the initial Product requirement.
Browse Products
As a Customer,
I want to browse available Products,
so that I can decide what to order.
Create an Order
As a Customer,
I want to place an Order containing one or more Products,
so that I can purchase available items.
View Order History
As a Customer,
I want to view my previous Orders,
so that I can review my purchase history.
Cancel an Order
As a Customer,
I want to cancel an eligible Order,
so that I can stop an Order I no longer want.
Pay for an Order
As a Customer,
I want to pay for an Order,
so that the Order can proceed after payment.
Manage Products
As an Administrator,
I want to manage Products,
so that Customers can access the current Product catalog.
Manage Inventory
As an Administrator,
I want to manage Inventory,
so that available stock remains accurate.
These stories are useful.
But they are still not implementation-ready.
Important details are missing.
That is where Acceptance Criteria become useful.
What Are Acceptance Criteria?
Acceptance Criteria describe the conditions that must be satisfied before a Story or feature can be considered correctly implemented.
A simple way to think about them is:
How will we know that the requested behaviour has been implemented correctly?
Consider the User Story:
As a Customer,
I want to place an Order,
so that I can purchase available Products.
Possible Acceptance Criteria:
- An Order must contain at least one item.
- Every item must reference an existing Product.
- Every requested quantity must be valid.
- Requested Inventory must be available.
- The backend calculates the Order total.
- A valid request creates an Order.
The expected behaviour is now much more concrete.
Acceptance Criteria Do Not Describe Implementation
Acceptance Criterion:
Requested Inventory must be available.
That is appropriate.
But:
Use SELECT ... FOR UPDATE on the Inventory row.
is not an Acceptance Criterion.
That is a technical design decision.
The same requirement could potentially be satisfied through:
pessimistic locking
or:
optimistic concurrency control
or:
an atomic conditional database update
The Acceptance Criterion should remain implementation-independent unless the implementation technique itself is a genuine constraint.
Good Acceptance Criteria Are Testable
Weak:
Order creation should work correctly.
What does correctly mean?
Better:
Given sufficient Inventory,
when a Customer submits a valid Order,
then the system creates the Order.
And:
Given insufficient Inventory,
when a Customer requests more units than are available,
then the system rejects the Order.
Now the behaviour can be verified.
Given / When / Then
One common format for Acceptance Criteria is:
Given <initial condition>
When <action>
Then <expected outcome>
For example:
Given a Product with 10 units available
When a Customer orders 2 units
Then the Order is accepted
Negative scenario:
Given a Product with 1 unit available
When a Customer orders 2 units
Then the Order is rejected
This format is common in Behaviour-Driven Development, or BDD.
It is useful because it makes the sequence explicit:
initial state
↓
action
↓
expected outcome
But not every Acceptance Criterion needs to use this format.
For simple rules, a direct statement may be clearer.
Avoid Ceremonial Given / When / Then
Weak example:
Given that the system exists
When the Customer wants to browse Products
Then Products should be browsable
The format is present.
The clarity is not.
The purpose of Given / When / Then is not ceremony.
It is useful when:
initial state
action
result
all matter.
For a simple validation rule:
Order quantity must be greater than zero.
is perfectly sufficient.
Let’s Refine the Create Order Story
One of the most important capabilities in the first version is:
Create Order
User Story:
As a Customer,
I want to place an Order containing one or more Products,
so that I can purchase available items.
From our previous requirement analysis, we know several behaviours are still ambiguous.
To move the course project forward, we now establish concrete first-release rules.
From this point onward, the following rules are treated as agreed Product behaviour for v1.
An Order Must Have at Least One Item
An empty Order has no business value.
Therefore:
An Order must contain at least one item.
Invalid:
{
"items": []
}
Quantity Must Be Positive
Each OrderItem quantity must satisfy:
quantity >= 1
Valid:
1
2
5
Invalid:
0
-1
-5
Fractional quantities are outside the scope of this system.
Products are treated as discrete units.
Referenced Product Must Exist
If the Customer references a Product that does not exist:
productId = unknown
the Order must not be created.
Criterion:
Every OrderItem must reference an existing Product.
Product Must Be Available for Ordering
For the initial version, an orderable Product must be active.
Later, Product browsing will refine availability further using Inventory.
But one rule is already clear:
Inactive Products cannot be ordered.
Product lifecycle will be modeled explicitly later.
Inventory Must Be Sufficient
Suppose:
Available Inventory = 5
Requested quantity = 3
The Order can proceed.
But:
Available Inventory = 5
Requested quantity = 6
must be rejected.
Important invariant:
Successful Order creation must not make
available Inventory negative.
We are not choosing the concurrency mechanism yet.
That belongs to technical design later.
The Backend Determines Price
The client is not the authoritative source of Product pricing.
Suppose a client sends:
{
"productId": "9ed4c9a9-8761-4e4f-9f50-aef83f14c13d",
"quantity": 2,
"unitPriceCents": 100
}
but the actual Product price is:
5000 cents
The backend must not use the client's:
100
The backend loads the authoritative current Product price.
Criterion:
The backend determines the price of each OrderItem
and calculates the Order total.
In our eventual implementation, monetary values will use:
long cents
throughout the backend.
Purchase-Time Price Must Be Preserved
This is an important business clarification.
Suppose the Product price when the Order is created is:
2000 cents
Later, the Product price changes to:
2500 cents
The historical Order must still represent:
2000 cents
The past Order must not be rewritten because the current catalog price changed.
Requirement:
The price used when an Order is created
must remain part of that historical Order.
The implementation will later determine how that value is persisted.
Duplicate Product Entries
Suppose the same Product appears multiple times in one request:
Product A × 2
Product A × 3
For the initial version, we will not allow duplicate Product lines in the same Order request.
The client should combine them:
Product A × 5
Criterion:
A Product may appear at most once
in a single Order request.
This keeps the first version simple and unambiguous.
What Happens If One Item Is Invalid?
Suppose the Order contains:
Product A × 2
Product B × 3
Product C × 1
and Product C does not have sufficient Inventory.
We do not create a partial Order.
The entire request fails.
Criterion:
Order creation is all-or-nothing.
Either:
the entire Order succeeds
or:
no Order is created
This requirement will later become important when we design database transactions.
Order Creation Acceptance Criteria
Our complete first-pass Acceptance Criteria are now:
AC-1
An Order must contain at least one item.
AC-2
Each OrderItem must reference an existing Product.
AC-3
Each Product may appear at most once in the request.
AC-4
Each quantity must be a positive whole number.
AC-5
Only Products available for ordering may be included.
AC-6
Requested quantity must not exceed available Inventory.
AC-7
The backend determines the price of each OrderItem.
AC-8
The backend calculates the Order total.
AC-9
The purchase-time Product price must remain
part of the historical Order.
AC-10
If any item is invalid,
the complete Order request fails.
AC-11
A successful Order belongs to
the requesting authenticated Customer.
The Story is now far more actionable.
Notice What We Still Have Not Decided
We still have not defined:
database tables
JPA entities
Handler classes
Repository interfaces
HTTP status codes
locking strategy
transaction implementation
Acceptance Criteria define behaviour precisely enough to work with.
They do not dictate the technical solution.
That is exactly what we want.
Product Browsing Story
User Story:
As a Customer,
I want to browse available Products,
so that I can decide what to order.
Initial Acceptance Criteria:
AC-1
Only Products available for ordering are returned.
AC-2
Each result includes the Product information
required to make an ordering decision.
AC-3
Product price is included.
AC-4
The result supports multiple Products
without requiring the entire Product catalog
to be returned in one response.
The last criterion suggests that we will probably need bounded list results.
The concrete pagination contract belongs to API design later.
Why Pagination Appears Early
Suppose there are:
20 Products
Returning all of them may be harmless.
But later there could be:
100,000 Products
Returning every row in a single response would be poor design.
That means the need for bounded list behaviour can appear during requirement analysis even before we decide the exact pagination API.
We still do not invent:
page size = 20
at this stage.
That decision comes during API design.
Order History Story
User Story:
As a Customer,
I want to view my previous Orders,
so that I can review my purchase history.
Acceptance Criteria:
AC-1
A Customer can access only their own Orders.
AC-2
Previous Orders contain enough information
to understand what was ordered.
AC-3
Historical item prices remain unchanged
when current Product prices change.
AC-4
Order history supports multiple Orders
without requiring the entire history
to be returned in one response.
Notice that security is part of the user-facing behaviour:
A Customer can access only their own Orders.
That is not something we should postpone as somebody else's problem.
Order Cancellation Story
User Story:
As a Customer,
I want to cancel an eligible Order,
so that I can stop an Order I no longer want.
Previously:
eligible
was ambiguous.
For the initial release, the agreed rule is:
Only UNPAID Orders may be cancelled.
Paid-Order cancellation and refunds remain outside v1 scope.
Acceptance Criteria:
AC-1
A Customer may cancel their own UNPAID Order.
AC-2
A Customer may not cancel another Customer's Order.
AC-3
A PAID Order cannot be cancelled in v1.
AC-4
An already-CANCELLED Order cannot be cancelled again.
AC-5
Cancelling an Order restores the Inventory
consumed by that Order.
AC-6
A successfully cancelled Order remains CANCELLED.
An important consequence is now explicit:
cancel Order
↓
restore consumed Inventory
This will later become transactional behaviour.
Payment Story
User Story:
As a Customer,
I want to pay for my Order,
so that the Order can proceed after payment.
Initial Acceptance Criteria:
AC-1
A Customer may pay only for their own Order.
AC-2
Only an UNPAID Order is eligible for payment.
AC-3
Payment is processed through
the configured external Payment provider.
AC-4
A successfully confirmed payment
marks the Order as PAID.
AC-5
A failed payment must not mark
the Order as PAID.
AC-6
The same successful payment outcome
must not be applied twice.
The external integration will later introduce concerns such as:
timeout
retry
idempotency
partial failure
But the Acceptance Criteria establish the business expectation first.
Product Management Story
User Story:
As an Administrator,
I want to manage Products,
so that Customers can access
the current Product catalog.
The word:
manage
is too broad by itself.
For the initial version, we narrow it to:
create Product
view Product
update Product
deactivate Product
Physical deletion is not required.
Historical Orders may still reference that Product.
Acceptance Criteria:
AC-1
An Administrator can create a Product.
AC-2
An Administrator can update
supported Product information.
AC-3
An Administrator can deactivate a Product.
AC-4
A deactivated Product cannot be ordered.
AC-5
Deactivating a Product must not remove
historical Order information.
AC-6
Regular Customers cannot perform
administrative Product operations.
Product deletion is deliberately outside the current scope.
Inventory Management Story
User Story:
As an Administrator,
I want to manage Inventory,
so that available stock remains accurate.
For the initial version:
An Administrator can view
and set current Inventory quantity.
Acceptance Criteria:
AC-1
An Administrator can view current Inventory.
AC-2
An Administrator can set
the current available Inventory quantity.
AC-3
Inventory quantity cannot be set below zero.
AC-4
Regular Customers cannot modify Inventory.
AC-5
Inventory changes affect future Product availability.
We do not introduce:
Inventory audit ledger
warehouse management
stock movement history
because those capabilities are not part of the initial requirement.
Acceptance Criteria Should Cover Permissions
Ignoring permissions when defining backend behaviour is dangerous.
Suppose the Story is:
Customer can view an Order.
Weak Acceptance Criterion:
Order details are returned.
Better:
The requesting Customer owns the Order.
and:
Another Customer cannot access it.
Security behaviour is part of the feature.
It should not be postponed until someone later remembers to “add security.”
The Happy Path Is Not Enough
Consider:
Create Order
Happy path:
authenticated Customer
+
valid items
+
sufficient Inventory
=
Order created
If this is the only behaviour we define, we may miss important cases:
empty items
unknown Product
inactive Product
quantity = 0
negative quantity
insufficient Inventory
duplicate Product entry
Strong Acceptance Criteria cover both:
meaningful success behaviour
and:
meaningful failure behaviour
But Do Not Turn Every Test Case Into an Acceptance Criterion
We still need balance.
Acceptance Criterion:
Quantity must be a positive whole number.
That is enough.
We do not need separate criteria saying:
quantity = 0 fails
quantity = -1 fails
quantity = -10 fails
quantity = -999 fails
Those are test cases.
The requirement defines the rule.
The test suite verifies representative cases.
Acceptance Criteria vs Test Cases
Acceptance Criterion:
Requested quantity must not exceed
available Inventory.
Potential test cases:
available = 10
requested = 1
→ success
available = 10
requested = 10
→ success
available = 10
requested = 11
→ failure
Acceptance Criteria describe the rule.
Test cases verify the rule using concrete examples.
They are related, but they are not the same thing.
Boundary Cases Matter
Backend bugs often appear at boundaries.
Requirement:
Requested quantity must not exceed
available Inventory.
Suppose:
available = 5
Important cases include:
requested = 4
requested = 5
requested = 6
The boundary:
requested == available
must be clear.
Our rule is:
requested <= available
So ordering the final available units is valid.
Acceptance Criteria Can Reveal Missing Requirements
Suppose we are writing the cancellation Story:
A Customer can cancel an eligible Order.
While writing a criterion, we say:
Cancelling an Order restores
the Inventory consumed by that Order.
That immediately raises another question:
When was Inventory consumed?
This tells us that the Inventory lifecycle itself must be defined.
Acceptance Criteria do not merely record requirements.
They can expose missing requirements.
User Stories Should Be Small Enough
Weak Story:
As a Customer,
I want to use the commerce platform,
so that I can shop online.
That describes nearly the entire Product.
It includes:
browse Products
create Order
pay
cancel
view history
Such a Story is too broad for implementation planning.
Better Stories represent independently understandable user capabilities.
But Do Not Split Stories Artificially
The opposite extreme is also unhelpful.
Bad:
As a Customer,
I want the Product ID field to exist.
Or:
As a Customer,
I want an OrderRepository.
The Customer does not care about Repository interfaces.
Those may be technical tasks.
They are not User Stories.
User Story vs Engineering Task
Story:
As a Customer,
I want to place an Order,
so that I can purchase available Products.
Later, engineering tasks may include:
Create Order domain model
Add Order persistence
Implement CreateOrderUseCase
Expose Order creation API
Add integration tests
The Story captures user value.
Engineering tasks break down the implementation work.
One Story Can Require Multiple Tickets
Suppose the Story is:
Customer can place an Order.
In a real codebase, this may require several engineering tickets.
For example:
BACKEND-121
Create Order domain model
BACKEND-122
Add Order persistence
BACKEND-123
Implement Inventory validation and consumption
BACKEND-124
Implement CreateOrderUseCase
BACKEND-125
Expose Create Order endpoint
BACKEND-126
Add Order creation integration tests
Later in Module 1, we will create the initial engineering backlog.
Definition of Done Is Different
Acceptance Criteria answer:
What behaviour must this feature satisfy?
Definition of Done answers:
What minimum quality bar must the team meet before work is considered complete?
For example:
Acceptance Criterion:
A Customer cannot create an Order
with insufficient Inventory.
Definition of Done may later include:
implementation complete
tests added
code reviewed
documentation updated where needed
CI passes
These are related, but they are not the same thing.
We will cover Definition of Done separately.
Avoid Mixing Team Process Into Product Behaviour
This does not belong in Acceptance Criteria:
PR must have two reviewers.
That is team process.
This does belong:
Order creation must reject
insufficient Inventory.
That is Product behaviour.
Keeping them separate makes documentation clearer.
A Practical Story Template
For this course, we can use a lightweight format:
# Story
## User Story
As a ...
I want ...
so that ...
## Context
Why is this capability needed?
## Acceptance Criteria
- ...
- ...
- ...
## Out of Scope
- ...
## Open Questions
- ...
Not every Story needs every section.
But Context, Out of Scope, and Open Questions can be useful for more complex capabilities.
Example: Create Order Story Document
# Create Order
## User Story
As a Customer,
I want to place an Order containing one or more Products,
so that I can purchase available items.
## Acceptance Criteria
- An Order must contain at least one item.
- Every item must reference an existing Product.
- Each Product may appear at most once.
- Quantity must be a positive whole number.
- Only Products available for ordering may be included.
- Requested quantity must not exceed available Inventory.
- The backend determines item prices.
- The backend calculates the Order total.
- Purchase-time prices remain part of the historical Order.
- If any item is invalid, the complete request fails.
- The created Order belongs to the requesting authenticated Customer.
## Out of Scope
- Discounts
- Coupons
- Shipping
- Tax calculation
- Multiple currencies
This provides much more useful engineering context than the original high-level Product sentence.
Avoid Over-Specifying Error Messages
Acceptance Criterion:
Invalid quantity must be rejected.
That is appropriate.
But writing this in an early Product Story:
Return HTTP 400 with code INVALID_ORDER_ITEM_QUANTITY
and exact message:
"Quantity must be greater than zero."
may be premature.
The API error contract should later be standardized as part of technical/API design.
An exception would be when exact public error behaviour is itself part of the agreed API contract.
At this stage, it is not.
Avoid Designing the Database Through Acceptance Criteria
Bad:
OrderItem must have product_id,
quantity, and unit_price_cents columns.
That is database design.
Better:
Historical OrderItem pricing must remain unchanged
when the current Product price changes.
Later, an engineer may decide to persist:
unit_price_cents
which is indeed the design we eventually use.
But the requirement should remain behaviour-first.
Out of Scope Is Part of Clarity
The Create Order Story includes:
basic Product ordering
Inventory validation
price calculation
Out of scope:
discounts
tax calculation
shipping
coupon codes
gift cards
This matters because it prevents accidental scope expansion.
An engineer should not think:
“This is a commerce Order system, so I should probably build a tax engine too.”
No.
We build what the current problem requires.
Do User Stories Need Estimates?
Many teams use Story Points or time estimates.
For example:
3 points
5 points
8 points
We will not go deeply into estimation methodology in this course.
Our focus is:
requirements
design
implementation
engineering workflow
We may discuss work size during planning.
But an artificial estimation framework is not one of the course goals.
Story Priority
Not every Story needs to be built at the same time.
A rough capability dependency is:
Products
↓
Inventory
↓
Orders
↓
Payments
Order history becomes meaningful after Orders exist.
Cancellation depends on the Order lifecycle.
Payment also depends on Orders.
These dependencies will influence backlog ordering.
Vertical Slice vs Technical Layer
An important planning question is whether we build:
all Domain classes
then all Repositories
then all UseCases
then all Handlers
or build a small capability end-to-end.
Real teams often prefer a vertical slice.
For example:
Create Product
HTTP/API
↓
Handler
↓
UseCase
↓
Repository
↓
Database
↓
Tests
Then move to the next capability.
This makes the system incrementally usable.
We will use this approach extensively during implementation.
But Some Foundation Work Comes First
Vertical slicing does not mean there is no shared foundation.
For example, we still need some setup such as:
Spring Boot bootstrap
database migration setup
API error-handling foundation
Some foundational work is created once.
After that, feature-by-feature vertical development becomes much more effective.
Acceptance Criteria and Code Review
Good Acceptance Criteria are useful during code review too.
A reviewer should not ask only:
Does this code look clean?
They should also ask:
Does this change satisfy
the intended behaviour?
Suppose the criterion says:
A Customer may not cancel
another Customer's Order.
The reviewer should look for:
ownership enforcement
and corresponding tests.
Requirement review and code review are connected.
Acceptance Criteria and Testing
Later, our test strategy will often follow:
Acceptance Criteria
↓
Test Scenarios
↓
Automated Tests
Criterion:
Each quantity must be a positive whole number.
Potential tests:
quantity = 1
→ valid
quantity = 0
→ rejected
quantity = -1
→ rejected
Another criterion:
A Customer may not access
another Customer's Order.
Possible integration scenario:
Customer A creates an Order.
Customer B requests that Order.
→ resource is unavailable according
to the API access contract.
The exact HTTP semantics will be defined during API/security design.
Product Manager and Engineer Collaboration
Suppose Product says:
Customers should be able to cancel Orders.
An engineer might respond:
For v1, I propose allowing cancellation
only before payment.
Cancellation will restore the Inventory
consumed by that Order.
Paid-Order cancellation and refunds
will remain out of scope.
Does that match the intended behaviour?
Product confirms.
Now the Acceptance Criteria can be recorded.
The engineer did not silently invent a business rule.
They:
identified ambiguity
proposed concrete behaviour
explained the consequence
received confirmation
That is healthy Product–Engineering collaboration.
Not Every Criterion Comes Directly From Product
Some criteria emerge from engineering correctness.
For example:
Order creation should be atomic.
A Product Manager may never use the phrase:
atomic transaction
But the Product expectation may be:
We should never create half an Order.
Engineering can translate that into:
Order creation must not leave partial state.
The technical solution may later be a database transaction.
A backend engineer's job includes deriving correctness requirements from business intent.
Don’t Hide Technical Risk Behind a Simple Story
A Story may sound simple:
Customer pays for Order.
But an engineer may know the external Payment provider can:
time out
fail
return an uncertain result
The Story's simplicity does not eliminate those risks.
Acceptance Criteria can capture the business expectation:
A failed Payment must not mark
the Order as PAID.
Technical design later handles:
timeout
retry
idempotency
provider success / local failure
Our Initial Story Set
For v1, our current Story set is:
STORY-1
Browse Available Products
STORY-2
Create an Order
STORY-3
View Order History
STORY-4
Cancel an Eligible Order
STORY-5
Pay for an Order
STORY-6
Manage Products
STORY-7
Manage Inventory
Authentication is a technical/security prerequisite for Customer and Administrator permissions.
It is not a separate local Customer-management capability.
Are These Engineering Tickets Yet?
No.
These are still Product-level Stories.
The next stages are:
Story
↓
Technical Design
↓
Engineering Breakdown
↓
Tickets
For example:
STORY-2
Create an Order
will later become several implementation tickets.
That separation is intentional.
A Simple Quality Check for User Stories
After reading a Story, we should ideally be able to answer:
Who benefits?
What capability do they need?
Why do they need it?
What behaviour makes it acceptable?
If these are unclear, the Story needs refinement.
A Simple Quality Check for Acceptance Criteria
For every criterion, ask:
Is it clear?
Can we verify it?
Is it actually required?
Is it behaviour rather than implementation?
Does it conflict with another criterion?
Does it reveal an unresolved question?
These checks catch many ambiguities early.
Engineering Principle
The core principle from this lesson is:
A requirement becomes useful engineering input when the expected behaviour is clear enough that different people can independently recognize whether it has been satisfied.
A User Story tells us:
who
what
why
Acceptance Criteria tell us:
what must be true
for the work to be accepted
Their purpose is not paperwork.
Their purpose is shared understanding.
Where We Are Now
Our project has progressed through:
Initial Product Requirement
↓
Requirement Analysis
↓
Functional / Non-Functional Requirements
↓
User Stories
↓
Acceptance Criteria
We now understand the expected behaviour of the major Customer and Administrator capabilities much more clearly.
But an important question remains:
What environment, constraints, dependencies, and existing engineering context are we building this system within?
A backend is rarely created in complete isolation.
The next lesson is:
Understanding the Existing Engineering Context
There, we will treat the project as something a new engineer has joined rather than as an isolated greenfield coding exercise.
We will examine:
existing technical constraints
organizational context
system boundaries
external dependencies
development environment
deployment assumptions
After that, we can move toward the Definition of Done and the initial engineering backlog.
