What to put around a requirement so developers are not blocked, including background, acceptance criteria and business rules, and when to reach for user stories, use cases or a user-interface specification.
The context problem
Expecting developers to magic something from a vague idea or a one-sentence user story isn’t a particularly helpful approach. Technical staff are great at solving relatively well-bounded technical problems but dire at stepping into the customer’s shoes.
Unfortunately, many software requirements are just too vague and open to interpretation. Select a few requirements from your team to inspect. Most teams find the same things: requirements that describe what the developer should build, with almost nothing about why, for whom, or what ‘done’ looks like.
The context around a requirement
What’s usually missing is all the context. The role of a requirement isn’t to instruct the developer line-by-line. It’s to surround the work with enough information that the developer can make confident decisions without becoming blocked. Three groupings are helpful, mindful not to slip into ‘solution mode’ when doing so.
The problem and the users. Background information, research data and user feedback, related product features. Why is this being built, for whom, and how does it fit alongside what already exists? Get this wrong and the rest is wasted effort. You’ll see a team spend three sprints on a sophisticated reporting dashboard because a story said users needed to see data trends. Nobody mentioned that the actual users were field technicians who simply wanted a yes/no equipment-status indicator on their phones. The dashboard was technically brilliant and completely useless. A sentence of background would have prevented it: field technicians currently phone the office to check equipment status, wasting around 15 minutes per check, and this feature lets them see status instantly on site.
What good looks like. Acceptance criteria, alternative scenarios, business rules, error handling. What must the implementation handle, including the unhappy paths and the rules that aren’t obvious? Acceptance criteria are where ‘done’ stops being an aspiration and becomes something testable. ‘User can log in securely’ is wishful thinking; it means something different to everyone who reads it. Compare: ‘User logs in with email and password. Valid credentials grant access within 2 seconds. Invalid credentials display “Incorrect email or password” — don’t specify which is wrong, as that’s a security risk. After 3 failed attempts the account locks for 15 minutes and the user receives an email notification.’ Now the developer knows what to build, the tester knows what to verify, and there’s no ‘well, yes, but…’ moment at the demo.
In my experience, the business rules nobody writes down are where the most expensive mistakes begin. ‘Process the refund’ sounds straightforward until you discover that refunds are only allowed within 30 days, except for faulty products (90 days), unless the item was purchased on sale (no refunds), unless the sale item was itself faulty (30 days), and refunds over £500 require manager approval, except for corporate accounts who have pre-approved authority up to £5,000. None of it is obvious; all of it is critical. Miss one rule and you have either opened a way to exploit the system or blocked a legitimate refund. Write down every ‘except’, ‘unless’ and ‘but’ you hear in stakeholder conversations — these are business rules hiding in plain sight.
Boundaries and guidance. Illustrations, UI mockups and designs, assumptions, constraints, and any technical approaches that are acceptable or off-limits. What’s already decided, and what space is the developer free to operate within? Here the line to hold is what rather than how. ‘Add a dropdown menu 150 pixels from the left edge, 200 pixels wide, in Arial 12pt, options Red, Blue and Green listed alphabetically, default Blue, background #F5F5F5’ dictates every decision — and a developer who follows it faithfully on a screen whose design system uses different fonts and colours produces something that looks jarringly wrong, yet meets the requirement perfectly. ‘User needs to select a colour preference. Use the standard dropdown component from the design system. Options: Red, Blue, Green. Default to Blue’ provides the guardrails and lets the developer apply their expertise. The distinction worth holding is between ‘must use existing system X’, a necessary constraint, and ‘must implement using pattern Y’, an unnecessary restriction.
Performance attributes and non-functional requirements (eg. accessibility, interoperability, redundancy) should also be defined. Technical details such as API endpoints and message schemas should only be included if they are significant or enhance readability.
How much context to provide varies by team and situation. Experienced developers in small co-located teams need less. Junior developers in remote teams building enterprise software need more, and this is especially true for offshore teams working across time zones and language barriers. The universal test is whether the developer can proceed without interrupting their work to seek clarification. Just-enough detail is the goal, not exhaustive detail, and where that balance sits depends on how the team works.
Functional and non-functional requirements
Functional requirements describe what the software should do; non-functional requirements, often abbreviated to NFRs, describe how it should do it. Non-functional requirements are also known as ‘quality attributes’ because they relate to the standard of service a user should expect from the software.
‘I want to make a payment by credit card’ is a functional requirement; it describes a user action that is part of achieving a bigger goal. ‘The payment should be secure’ is a quality attribute that explains how the payment should be performed ie. securely. Further elaboration is possible by specifying implementation-specific details, eg. ‘256-bit encryption for card details’ and ‘compliance to PCI-DSS’, an industry standard for card payments.
Non-functional requirements often apply to entire software products or whole sub-systems, unlike functional requirements that describe individual functionality. ‘I want to make a payment by PayPal’ is a second payment requirement, but the expectation of doing it securely still applies. For this reason, NFRs are often specified at the product level and then referenced within individual software requirements or inferred as generally applicable. ‘Cross-cutting concern’ is a commonly used term to describe this.
Read more: functional and non-functional, compared
User stories
User stories describe an action a user wishes to perform in order to achieve a goal. They are single sentences written in a prescribed format, usually ‘As a [user] I want to [action] so that [outcome]’. They are usually accompanied by acceptance criteria that clearly outline what must happen.
User stories are a type of software requirement, but often mistakenly written to be ‘mini-specifications’. Instead, they should remain high-level statements so developers are encouraged to discuss the lower-level details. Collaboration throughout development is the goal. User stories are the primary way to capture requirements in agile teams and they originated in Extreme Programming.
Read more: Painless Functional Specifications
Use cases
A user story keeps things deliberately light and trusts conversation to fill in the detail. Sometimes that isn’t enough: the workflow is intricate, the team can’t talk things through in real time, or someone needs a complete record of exactly how the system behaves. When that’s the situation, a use case is the better tool, and it’s worth understanding how the two differ.
A use case provides a detailed, step-by-step description of how a user interacts with the system to achieve a specific goal, documenting the main flow, the alternative flows and the error handling comprehensively. The structure is conventional: the actors who use the system, the preconditions that must be true before starting, the main flow of the normal path step by step, the alternative flows for when things go differently, and the postconditions that hold once it completes.
Take transferring money between accounts. The actors are the account holder and the banking system. The preconditions are that the user is logged in, holds multiple accounts, and has sufficient balance in the source account. The main flow runs from selecting ‘Transfer Money’, through choosing source and destination accounts and entering an amount, to the system validating funds, showing a confirmation screen, processing the transfer and displaying updated balances. The alternative flows are where the value lies: insufficient funds returns the user to the amount step with a clear message; cancelling at confirmation processes nothing; a system error during processing rolls the transaction back and notifies the user that no funds moved. The postconditions record what is now true — funds transferred, both account histories updated, confirmation sent.
The distinction is best put plainly. A user story is what the user wants to achieve; a use case is how the system makes that happen. Stories are user-focused, outcome-driven conversation starters, small enough to complete in a week or two, and they work best when teams collaborate daily and refine details through discussion. Use cases are system-focused and comprehensive, larger in scope, and a single use case may span several stories. They earn their cost when system behaviour is complex, when the work has to be signed off through a formal approval process, when developers are remote or offshore and can’t ask a quick question, and when replacing a legacy system whose current behaviour must be captured in detail, edge cases included.
You don’t have to choose one or the other, and often you shouldn’t. Many teams use user stories for agile planning and maintain use cases for the genuinely complex workflows — lightweight stories on the backlog, detailed use cases attached to the few features that warrant them, with the story’s acceptance criteria referencing the use case. A trading desk might carry the story ‘As a trader, I want to execute a foreign exchange trade so that I can fulfil client orders’, with acceptance criteria stating only that it must support every scenario documented in use case UC-042, FX Trade Execution — itself a detailed document covering fifteen trade types, forty error scenarios, regulatory validations and audit-trail requirements. That gives you agile flexibility for the backlog and comprehensive documentation exactly where it matters. The question is never ‘which is better?’ but ‘which serves the team’s needs right now?’
Requirements for user interfaces
Not all software has a user interface, but those that do require special consideration as to who designs it, when it’s designed, and to what level of detail. Choosing the right approach matters all the more given that many products span desktop, mobile and tablet, each with different layouts and interaction patterns. There are two broad approaches, and each changes the requirements developers actually work from.
Developer-produced interfaces
Developers are solely responsible for designing and implementing the interface, either because they are experts in UI development, the product isn’t complex, or the team isn’t large enough to support specialised UI developers. The backlog is populated with user stories and developers build them as best they can, including any necessary interface. Wireframes and sketches may accompany each story, more as a guide than anything else, and alternative flows and unhappy paths are usually not considered in advance. Developers collaborate directly with the story author — product owner, business analyst, onsite customer — as the software takes shape, making sure the acceptance criteria are met and the interface performs acceptably. Sometimes an actual user is dropped into the team, being the person best placed to explain the features and collaborate as the design takes shape. Standard component libraries and frameworks accelerate frontend development and keep the look and feel consistent, and over time a library of standard layouts and product-specific interaction patterns develops. If you do attach a mockup, annotate it — explain what happens when users click, show the error states, illustrate the mobile version, demonstrate the empty state before any data exists.
Read more: The Customer is Always Available
UX-designer-produced interfaces.
UX designers, sometimes called product designers, become the ‘voice of the customer’ and are responsible for designing entire, end-to-end user experiences. Gone are the grey screens, comboboxes and modal popups some developers typically favour. User research and focus-group sessions, conducted periodically, inform the product roadmap and which features to design next. Wireframes and high-fidelity UX collateral become the defacto requirements developers work from, and your typical ‘as a, I want, so that’ user story no longer appears in the development backlog. Developers build entire end-to-end journeys, and the technical team is included in the design process, at least at key points, to assess the feasibility of each design including the required backend capabilities. Finished journeys are ‘cut up’ into frontend and backend stories and added to the backlog for developers to refine and build, with close coordination ensuring backend systems are ready for integration with frontend screens at the right time. Direct user feedback follows each new launch, often infrequently every three to six months.
The two approaches change what ‘a requirement’ even looks like on this team. Under the first, the user story plus its acceptance criteria remains the unit developers work from. Under the second, the design collateral is the requirement and the story recedes. Neither is correct in the abstract; the right choice follows from the product’s complexity, the team’s makeup and how much the interface carries the product.
Once written, software requirements are not finished. They are reviewed and clarified as a team, which is the subject of Reviewing Requirements.