TS-1: Software Requirements Specification
This technical standard covers best practices for defining and managing software requirements.
A software requirements specification (SRS), also known as a system requirements specification, defines the acceptance criteria (ACs) for a software system. It is the basis for the software’s design, implementation, and verification.
Without requirements or design, programming is the art of adding bugs to an empty text file.
– Louis Srygley
This technical standard covers two aspects of requirements specification.
- What a good requirements specification looks like.
- How a specification is managed over time so it stays an accurate, trusted description of the system as it actually is in production.
Note
A reference implementation of everything described here is maintained separately at github.com/kieranpotts/specs.
Scope
A software requirements specification is two things.
- It is a living description of what a production system does today.
- It is a chronological record of the product decisions that shaped the current system.
Thus, in a software requirements specification, the current specification is justified by the reasoning that produced it.
Living specification
The first part of a software requirements specification is a living document that answers the question: "What does the system do right now?"
The living specification MUST be kept synchronized with the evolving software system itself. Changes to specification artifacts MUST be implemented at the same time as the corresponding changes in code and configuration.
When a requirement changes, the specification is overwritten. It is RECOMMENDED to use a version control system to record changes made to the specification over time. But the specification itself SHOULD NOT hold any history of its own. A clean specification describes a system as it exists at a point in time.
Product decision log
A specification alone tells you what a system does, but not why. It is RECOMMENDED to keep a second artifact alongside the specification — a product decision log.
Every significant proposed change to the specification — whether ultimately implemented or rejected — SHOULD be preserved in the product decision log as a record of the final decision and the rationale for it.
The product decision log is the institutional memory of the product. When someone asks "why doesn’t the catalog support multiple currencies?" or "why did we reject open, unauthenticated access?", the answer is on record.
Implementation agnostic
A software requirements specification SHOULD be agnostic of implementation. It SHOULD record what the system does and why, in the language of the business, but not how it is built, beyond what is strictly necessary to understand the system’s functional and non-functional requirements.
Technical decisions — about the technologies, tools, and architectural patterns used to construct, verify, and host the solution — SHOULD live separately. A request for comments (RFC) repository to capture technical decision-making is a useful companion to the SRS that serves this purpose — see TS-3.
Keeping apart requirements and implementation means the specification artifacts will survive replatforming. Rebuild the system on an entirely different stack and its SRS need not change.
Also, free of technical detail, the specification will be more valuable to its primary audience — not, in fact, the technical teams, but the business people and other non-technical stakeholders.
Product requirements document
This technical standard distinguishes a software requirements specification (SRS) from a product requirements document (PRD). Both describe a system from the user’s perspective, and both stay light on implementation detail. What separates them is formality and completeness.
A PRD is an upstream artifact, owned by product management, that defines the problem in an informal format, the key stakeholders and decision-makers, plus desired outcomes, success metrics, and timelines for delivery. Much of this will also be covered in the SRS. The difference is depth and obligation. A PRD raises this information in only as much detail as required to align stakeholders on broad goals and scope. The SRS makes the requirements precise and testable.
The SRS is a PRD’s successor. The SRS turns the product vision, defined in a PRD, into a verifiable, testable specification. The SRS is more refined and concrete than a PRD. It reads less like a mission statement and more like a contract between the business and the technical teams.
Both artifacts SHOULD be implementation-neutral, but the SRS MAY lean slightly closer to it. A good SRS models the domain, and that domain model becomes the foundation for the software architecture. The SRS may also, where strictly necessary to state an acceptance criterion, touch on interfaces such as APIs. It SHOULD be possible to drive design docs and test cases directly from the SRS, and inevitably this will require some implementation details leaking into it.
While PRDs are owned and maintained by product managers, the SRS is owned by technical stakeholders and maintained by them in collaboration with product managers. The SRS endures for as long as the system it specifies does. The SRS SHOULD be kept as close to the code as possible, ideally on the same version control server as used for the reference code repositories. A PRD may be more ephemeral — it need not be persisted once it has been translated into an SRS. Over the lifetime of a system, there MAY be multiple PRDs, one for each discrete initiative, but there SHOULD only be one living SRS.
- | PRD | SRS |
|---|---|---|
Question answered | What should the product do, and why? | How is the product verified? |
Primary audience | Business stakeholders | Engineers and testers |
Author | Product managers | Software architects and technical leads |
Formality | Just enough to align on goals, scope, and priorities | Detailed and testable |
Lifespan | Short-lived | Long-lived |
Typical contents | Problem statement, resource constraints, prioritization, roadmap, user personas, success metrics and KPIs | Domain model, actors, functional requirements as testable scenarios, non-functional requirements as measurable thresholds |
Executable tests
Executable tests complement requirements specifications, but they are not the same thing.
Executable tests can help to confirm that a system does what it is specified to do, but they don’t capture motivation, scope, or the alternative behaviors that were considered but ultimately left out-of-scope or subsequently deprecated.
Ideally, executable specifications would live directly in the SRS. Acceptance criteria would be written in a form that can also run as tests, eg. Gherkin scenarios backed by step definitions. If the specification and the verification are the same artifact, they cannot drift apart.
In practice, this isn’t always possible. Some acceptance criteria don’t map cleanly onto a test-runner format. Or the SRS may be maintained in a document system that can’t execute code. In these cases, the requirements specification SHOULD remain the source of truth for intent, and each requirement SHOULD be cross-referenced to its verification.
Persistence
Requirements documents have a tendency to rot over time. Written once at the start of a project, they are abandoned as the system evolves past them. Eventually they describe a system that no longer exists, and stakeholder trust in the specification deteriorates.
A specification can avoid that fate by binding itself to production.
To achieve this, a change to the specification artifacts MUST be merged in the same changeset as the corresponding changes to code and configuration. The specification and the system it describes change in lockstep.
This requires for specification artifacts to be kept close to the code, and for the maintenance of those artifacts to be deeply integrated into normal software development methods and tools.
For this reason, this technical standard RECOMMENDS that software specifications be persisted under the same version control system as used to manage change in the software’s code and configuration.
The payoff is a single, trustworthy answer to the question: "What does the system do right now?" New team members, support staff, auditors, and other stakeholders can read the software specification and have confidence that it is correct.
Wikis and issue trackers are commonly used to manage software requirements, but these keep the specification artifacts isolated from the source code and configuration, and subsequently the specification tends to drift from reality in time. Issue trackers are good for managing in-flight work but are poor as durable, structured records.
Using version control to manage specifications has other advantages, too.
- Branching and review. A proposed change can be drafted and negotiated in isolation before it touches the specification on the main line.
- An immutable history. A merged commit is a permanent, tamper-evident record, and past snapshots of the specification can be recovered.
- Built-in diffing. A reviewer can easily see precisely what a change does to the specification.
- Blame and log. Any line of the specification can be traced back to the change and commit that introduced it. The specification’s changelog is built in to the version control substrate.
Minimal friction is added to the software development lifecycle, because the specifications live where the work already happens. And the SRS can be integrated into existing automation tools and delivery pipelines, further improving productivity and outcomes.
Best practice is to persist software requirements artifacts under the same code repositories as the software itself. Several placements are possible.
- Colocated inside the service or module (eg.
src/specification/). The specification is versioned with the code. One revision or merge updates both behavior and specification atomically. This is RECOMMENDED for a single service or a small monorepo. - A dedicated top-level folder in a monorepo (eg.
/specification/at the root of a repo that covers several software components). This is appropriate when multiple components or services share a single product-level specification. - A separate repository. This becomes necessary when a codebase spans multiple repositories. It is also necessary where non-technical stakeholders need read access to the specification but should not also have write access to the code. This separation adds costs to coordinate code and specification changes, so it is not recommended until the separation becomes necessary.
my-service/ ├── src/ ← Production code. ├── specification/ ← Specification artifacts. │ ├── context/ │ └── requirements/ ├── proposals/ ← Product proposals archive. └── README.md
Generated views
One of the trade-offs of persisting software requirements under version control is that they become less accessible to non-technical stakeholders.
Where product owners, auditors, or external partners need a readable view of the specification, but should not be able to edit it directly, you SHOULD publish a generated, read-only rendering (eg. a website), ideally as part of an automated build step.
The ./specification/ tree remains the single source of truth, and from it different views are generated as derived
artifacts for different audiences.
Responsibility
A requirements specification MUST be written and maintained collaboratively, between the customer — or a representative of them, such as a product owner — and the software development team. Ownership, however, lies with the technical teams. They are responsible for maintaining the specification and keeping it synchronized with production.
The collaboration is necessary because the line between business requirement and technical design is blurry. For example, "passwords must be strong" is a business requirement, but to realize it requires technical decisions on business rules.
- Minimum 12 characters. - Checked against a configurable list of common and breached passwords. - No mandatory composition rules (eg. one uppercase letter, one number, one special character). - No forced expiry time.
Business stakeholders may expect composition rules and password expiry times to strengthen passwords, but current guidance holds that both weaken security in practice, because these constraints push users toward predictable substitutions and incremental variations. Technical stakeholders understand these trade-offs.
This simple example demonstrates why it is necessary for requirements to be specified through collaboration between product and technical stakeholders. The work of requirements engineering sometimes involves having difficult conversations, such as telling a customer that a requested change cannot be made within the allocated time and budget. Successful software delivery in dependent upon development teams being able to represent their rationale viewpoint so the customer can make better, more informed decisions.
Good engineers build to requirements. Great engineers push back on requirements.
– Jeff Bezos
Acceptance criteria
Requirements SHOULD be written as acceptance criteria (ACs).
Acceptance criteria — which are also known as conditions of satisfaction — are the set of conditions a software system must satisfy to be accepted by the customer.
A requirement is an underlying need. An acceptance criterion is the testable form that requirement takes once refined for the specification.
Acceptance criteria MUST be objectively verifiable. Each AC SHOULD resolve to a clear pass/fail condition, not a subjective judgment such as "user-friendly" or "reasonably fast". Each criterion SHOULD, if practical, be expressed in an executable form such that its verification can be automated.
Acceptance criteria SHOULD be written from the perspective of end users. They SHOULD specify user needs and wants, and SHOULD NOT prescribe solutions. This means ACs SHOULD NOT include technical implementation details, or even make reference to software, as much as reasonably practical.
Acceptance criteria MUST NOT be presented as a list of instructions for things the business would like implemented in software. The place for unrefined, business-facing statements like this is a product requirements document.
Acceptance criteria SHOULD be written in a consistent style and set of conventions, and MUST be written in the language of the business domain. Critically, acceptance criteria MUST be understandable to business stakeholders.
Acceptance criteria MUST cover both functional (behavior) and non-functional (quality) requirements. What the software does (specified via functional requirements), combined with the constraints within which it must operate (specified via non-functional requirements), is the whole of what the system is obliged to deliver. A solution is said to be functionally complete if it meets both its functional and non-functional acceptance criteria.
Structure
A specification SHOULD be organized so that every category of requirement has a single, unambiguous home. The objective is for no requirements to be left undocumented.
This technical standard offers an opinionated taxonomy for filing software requirements. This is the RECOMMENDED minimal baseline structure for the specification of greenfield projects.
Note
A template SRS repository that follows this structure, and which can be forked for new projects, is maintained at github.com/kieranpotts/specs.
specification/ │ ├── context/ ← The problem space (descriptive). │ │ │ ├── overview/ ← Mission, problem, and scope. │ ├── constraints/ ← Regulatory, legal, and business constraints, plus assumptions. │ ├── model/ ← Domain entities and their relationships. │ ├── actors/ ← Participants and their hierarchy. │ └── glossary/ ← Ubiquitous language. │ ├── requirements/ ← The delivery contract (prescriptive). │ │ │ ├── behaviors/ ← Functional requirements. │ │ ├── features/ ← Scenarios. │ │ ├── rules/ ← Invariants, policies, and lifecycle transitions. │ │ ├── access/ ← Permissions (maps actors to capabilities). │ │ ├── interfaces/ ← External contract: operations, resources, events, etc. │ │ └── journeys/ ← Wireframes or call-sequences. │ │ │ └── qualities/ ← Non-functional requirements. │ └── proposals/ ← Immutable archive of every proposed change.
The proposals/ tree is a sibling of specification/. The specification describes the system as it is now. The proposal
archive records how it got to that state.
In the specification section, the top-level split is between context and requirements. Context is descriptive. It says what is. This part of the specification covers the domain, its vocabulary, its participants, and the conditions the system operates within. None of it is a requirement in its own right. Rather, the context is the shared frame of reference from which requirements are derived. Requirements are prescriptive. They say what should be. Every statement is an obligation that can, in principle, be verified against the running system.
Keeping the two apart means a reader always knows whether they are reading background or a binding commitment. The separation prevents descriptive material from quietly accreting the force of a requirement.
Context
The context part of a specification is descriptive. It establishes the problem space the system operates in, and the domain the system is built around. None of it is a requirement in its own right. Rather, context is the shared frame of reference from which the requirements are derived.
This technical standard RECOMMENDS that the context of a system be documented across the following sub-sections.
- Overview. Mission statement, problem space, and scope.
- Constraints. Regulatory, legal, and business constraints, plus any assumptions made in those.
- Model. Domain entities and their relationships.
- Actors. Participants in the system, and their hierarchy.
- Glossary. Defines the system’s ubiquitous language, derived from the business domain.
specification/ │ ├── context/ ← The problem space (descriptive). │ │ │ ├── overview/ ← Mission, problem, scope. │ ├── constraints/ ← Regulatory, legal, and business constraints, plus assumptions. │ ├── model/ ← Domain entities, relationships, ERD. │ ├── actors/ ← Participants and their hierarchy. │ └── glossary/ ← Ubiquitous language. │ └── requirements/ ← The delivery contract (prescriptive).
Overview
Start with a high-level description of the system, written in prose. This should cover the following topics.
- The mission statement — the value the system delivers, and to whom.
- The problem(s) the system solves.
- The scope — what is in and, just as importantly, what is explicitly out.
The scope statement is particularly important. It’s what stops the specification quietly expanding to describe responsibilities that belong in other systems.
Constraints
Constraints describe the conditions imposed on the system from the outside. The conditions are the "givens" the system must work within, rather than behaviors the system is expected to exhibit (the "thens").
Conditions include the following.
- Regulatory and legal constraints, such as applicable laws and standards (eg. data-protection law).
- Business constraints, such as contractual terms and commercial boundaries.
- Assumptions the specification makes. (If an assumption proves false, the affected requirements will need to be revisited.)
- Dependencies — external systems and services the system relies on.
Constraints are descriptive. A regulatory or contractual constraint may read like a requirement, but it is actually a boundary set by the world — a law, a contract, a dependency, a standing assumption — not a behavior that the product owners have chosen for the product to exhibit.
Where a constraint implies a testable obligation on the system, it is RECOMMENDED to state that obligation as a rule or quality, and cross-reference it from the constraint, so the constraint itself remains purely a statement of the boundary.
Domain model
The domain model documents the system’s entities, which individually encapsulate a discrete category of information and, optionally, behavior.
The domain model should capture the key attributes of each key entity type, plus the relationships between entities. Entity-relationship diagrams may be useful to represent the domain model visually.
The domain model SHOULD declare the states that an entity can hold (eg. a status of available, reserved,
or sold) but SHOULD NOT specify the business rules that determine the allowed transitions between those states.
Those belong in Requirements → Behaviors → Rules.
The domain model is one of the most important parts of a software requirements specification. It anchors the project’s shared vocabulary and is the foundation from which the system’s actors and behaviors are derived. The domain model is also the closest that the SRS comes to the software architecture. Indeed, there may be a lot of necessary overlap between this part of the requirements specification and the system’s design docs.
For modeling techniques, see TS-4.
Actors
Actors are the participants in the domain — the people, organizations, and external systems that have goals the system must serve. The actors are derived from the domain model.
Actors are typically arranged as a hierarchy, ordered by privilege. Privileges are inherited down the hierarchy. An actor holds every capability of the actors below it in the hierarchy, plus whatever is granted to it directly.
Although the hierarchy of actors should be defined as part of the background context, this is not the right place to specify the particular privileges that are afforded to each actor. Permissions — the behaviors that each actor is allowed to access — SHOULD be specified separately, under Requirements → Behaviors → Access.
Glossary
It is RECOMMENDED to include a glossary of terms that define the project’s ubiquitous language. Capture every domain term, each with a single agreed meaning that’s used consistently throughout the specification — and also throughout the design docs, the code and tests, and every other artifact in a project’s workspace.
The glossary may be a superset of the terms defined in the domain model. The model defines entities, but not every domain term is an entity. For example, reservation, credential, and currency are domain vocabulary with no structural definition. The glossary is the flat index of all domain vocabulary, including but not limited to domain entities and their properties.
Consistent vocabulary is key to keeping requirement specifications coherent. Using the same term to mean the same thing throughout a whole specification is one of the highest-leverage things to get right.
Behaviors
Functional requirements ("behaviors") MUST be defined distinctly from non-functional requirements ("qualities").
The functional requirements of a software system are what it does from the perspective of the users who interact with it. The non-functional requirements define the operational constraints within which the software system is expected to work.
This technical standard RECOMMENDS that the behaviors of a system be documented across five complementary sections.
- Features. Concrete, scenario-level behaviors.
- Rules. Covers policies, invariants, and entity lifecycle transitions that hold across many features.
- Access. Maps actors to the functional capabilities they are permitted to access.
- Interfaces. Defines the system’s external contract — the operations, resources, and events the system exposes.
- Journeys. How features combine into end-to-end flows, from the perspective of different actors.
specification/
│
├── context/ ← The problem space (descriptive).
│
└── requirements/ ← The delivery contract (prescriptive).
│
├── behaviors/ ← Functional requirements.
│ ├── features/ ← Scenarios.
│ ├── rules/ ← Invariants, policies, and lifecycle transitions.
│ ├── access/ ← Permissions (maps actors to capabilities).
│ ├── interfaces/ ← External contract: operations, resources, events, etc.
│ └── journeys/ ← Wireframes or call-sequences.
│
└── qualities/ ← Non-functional requirements.Features
Features document the concrete, scenario-level behaviors of a system.
A scenario is a single, concrete example of a feature in use. Each scenario captures a specific starting condition, a specific action taken by an actor, and the specific outcome that follows. A feature is typically composed of multiple scenarios. The feature names the capability, while the scenarios frame the capability as test cases. Each scenario is a condition of satisfaction that either holds true or false.
Acceptance criteria for functional requirements may be captured in a variety of ways. A basic, unstructured list is a good starting point. For example, "As a newcomer I can register for an account by creating a login and providing my contact information" might be translated into the following technical condition of satisfaction.
- A username must be provided. - It must be between 4 and 20 characters long. - It must be unique. - The username is case sensitive. - A password must be provided. - It must be between 8 and 20 characters long. - It may contain numbers, letters, and special characters. - It must contain at least one letter and one number. - An email must be provided. - The email must be provided in a valid format. - The email must be confirmed by double entry. - The email must not already exist in the system.
But this informal notation is insufficient for complex systems, which need a more structured approach. In this situation, this technical standard RECOMMENDS the Gherkin language to specify features. The language itself is covered in depth in the section on executable specifications.
Whichever format is used, the following practices keep scenarios useful as specification.
- A scenario SHOULD define one discrete behavior. If a scenario has two unrelated outcomes, it is probably better expressed as two scenarios.
- Outcomes SHOULD be as concrete as reasonably practical. Prefer "then the response contains at most 10 records" over "then one or more records are returned."
- The project’s ubiquitous language SHOULD be used throughout all features and their scenarios.
- Unhappy paths SHOULD be covered too — empty results, not found, unauthorized, etc.
- Edge cases SHOULD be covered as much as reasonably practical. These are where requirements are most often ambiguous, which is all the more reason to make them explicit.
- Cross-cutting invariants SHOULD be lifted out of scenarios and moved into rules.
It may be desirable to organize features by actor. Because privileges are inherited down the actor hierarchy, each feature can be specified once against the lowest-privileged actor that can exercise it.
Rules
Validation constraints and policies like "a pet can’t be reserved and sold at the same time" are cross-cutting concerns that tend to span multiple features. Specifying them at the level of features would duplicate them across every feature they touch, leading inevitably to drift.
The solution is to state policies and validation constraints as business rules in one central place. Each rule gets a single authoritative statement with a stable identifier, so they can be cross-referenced from feature scenarios and elsewhere as necessary.
Similarly, entity lifecycle rules live under business rules, not in the domain model. The states that an entity can hold are part of its structure, so the domain model declares that they exist. But which state transitions are allowed, and which actors have permissions to mutate them, is a prescriptive constraint — a rule. Thus, the model defines the vocabulary of states, but business rules define the conditions under which those states may transition from one to another.
State each rule so that it is unambiguous and, where possible, testable. Give each a stable identifier so it can be cross-referenced from other specification artifacts.
A state-transition diagram is a good way to express an entity lifecycle.
Access
This section defines which actors have permissions to access features of the system. It is RECOMMENDED to be defined as a simple actor-feature map.
Since permissions are inherited down the actor hierarchy, a capability available to a lower-privileged actor can be assumed to be available to all higher-privileged actors. Therefore, it is sufficient to state each capability once, against the lowest-privileged actor that holds it.
Capability | Minimum actor |
|---|---|
List and filter the catalog | Authenticated User |
Search the catalog | Authenticated User |
Retrieve a single record by ID | Authenticated User |
Reserve a record | Authenticated User |
Withdraw a record from the catalog | Administrator |
Access rules are defined separately to the actors to which they apply. That’s because, while actors are derived from the domain model, access rules are requirements that the system must enforce.
Rules may be used to govern finer-grained conditions that may otherwise introduce unwanted complexity if defined in the actor-feature map.
Interfaces
Interfaces describe the system’s external contract — the operations it exposes, the resources they act on, and any events it emits.
This SHOULD be a behavioral contract only. Protocol, transport, payload formats, and endpoint naming are technical design decisions, not requirements.
State here only what a user can rely on: the operations available, their inputs and outputs (specified in domain terms), and the actors permitted to invoke them.
Journeys
While interfaces define the external contract of the system, journeys define the user experience.
The relative weight of journeys and interfaces depends on the system. For a user-facing product, interfaces may be thin and journeys rich. For a headless system, the reverse.
Wireframes MAY be used to specify the journeys through a UI system, while annotated call sequences will be more appropriate for headless systems. Either way, these SHOULD be at the level of structure and flow. Pixel-perfect visual designs, for example, are downstream concerns that do not belong in a requirements specification.
Whatever the format, the journeys should show how the system’s features combine into coherent end-to-end flows — the paths a user follows to accomplish their goals. Whereas features specify what the system does, journeys show how those functions come together in the user experience.
Journeys apply only where there is a multi-step flow worth documenting. A feature that is made available through a single atomic operation has no journey to be documented.
Qualities
The qualities of a system are its non-functional requirements (NFRs) — also known as quality requirements (QRs) or cross-functional requirements (CFRs). They define the operational constraints within which a software system is expected to work. They include, but are not limited to, security, performance (throughput, latency, responsiveness), scalability, availability, portability, and data retention requirements.
Many NFRs are architecturally significant, heavily influencing fundamental design choices such as technology stacks and databases. For example, scalability and durability require big up-front decisions on both the software architecture and the production infrastructure, eg. planning for redundancy in additional hardware, network, or bandwidth capacity. For these reasons, non-functional requirements can be much harder to change than functional requirements (FRs) later in a project. Some NFRs, such as uptime guarantees, will also be reflected in service level agreements (SLAs) and are therefore significant to business stakeholders and customers.
For these reasons, quality requirements MUST be comprehensively specified before major design and construction work begins on a new system. In general, the same is not true of functional requirements, for which there is usually more scope to specify incrementally.
Nevertheless, it is RECOMMENDED to restrict the scope of the specified quality requirements to the system’s dynamic quality attributes. These are the qualities that emerge at runtime and are observable externally in the way the system behaves for real users in production. They are distinct from a system’s static quality attributes, which are internal qualities of the code and design (readability, modularity, naming, structure) that emerge at or before compile time and that matter to developers rather than users.
Static qualities are not requirements the business specifies, though they are influenced by them. Rather, static qualities are design concerns, addressed through architectural design and refactoring work. For this reason, it is RECOMMENDED to keep static qualities out-of-scope for the requirements specification.
Organizing qualities
Qualities SHOULD be grouped by quality characteristic, using the product quality model of ISO/IEC 25010 as the RECOMMENDED taxonomy.
- Functional suitability. Covers functional completeness, correctness, and appropriateness — see TS-2.
- Performance efficiency. Time behavior, resource utilization, capacity.
- Compatibility. Co-existence, interoperability.
- Interaction capability. Usability, accessibility, learnability.
- Reliability. Availability, fault tolerance, recoverability.
- Security. Confidentiality, integrity, authenticity, accountability.
- Flexibility. Adaptability, scalability, installability.
- Safety. Operational constraint, fail-safe, hazard warning.
This technical standard excludes the ISO/IEC 25010 category of maintainability (modularity, reusability, testability) from the taxonomy. These are primarily static qualities — design concerns addressed through code design and refactoring, not requirements the business specifies. Where a maintenance concern is genuinely observable at runtime, such as the time taken to restore service after a fault, it belongs under reliability as a recoverability requirement.
Acceptance criteria
Like functional requirements, non-functional requirements SHOULD be specified as acceptance criteria with measurable, testable benchmarks. For example, "the system handles 1,000 concurrent users" can be tested by simulating that load and measuring performance under it.
A quality requirement that cannot be measured against a benchmark cannot be verified. So, wherever a quality is objectively measurable, it MUST be stated as a concrete threshold. Some examples follow.
- Availability: 99.9% uptime during business hours.
- Responsiveness: Page loads under 2 seconds for 95% of requests.
- Maintainability: New features are implemented and shipped in under 5 days on average.
- Defect escape rate: Less than 1 critical bug per 1,000 line of new code.
Prefer to use specific metrics such as Mean Time Between Failures (MTBF) and Mean Time to Recover/Repair (MTTR). It is RECOMMENDED to track the core DORA metrics as a minimum. These metrics, analyzed in aggregate, measure how effectively a team delivers software changes by balancing speed of value delivery against the stability of the evolving software.
- Delivery metrics:
- Deployment frequency. How often you successfully release to production. High frequency usually means small, low-risk changes and fast feedback.
- Lead time for changes. How long it takes a commit to reach production. This reflects the efficiency of your CI/CD pipeline.
- Stability metrics:
- Change failure rate. The percentage of deployments that cause a production issue requiring rollback, hotfix, or patch. It makes breakage visible.
- Time to restore service. How long it takes to recover from a failure. Also known as MTTR. Fast recovery is a hallmark of resilient systems.
More indirect measurements such as the open/close rates of incidents, and user analytics such as shopping cart abandonment rate, may also be useful.
Alternatively, it may be possible to define acceptance criteria in terms of conformance to published standards, such as AES-256 (for encrypting sensitive data at rest), TLS 1.3 (for data in transit), the Web Content Accessibility Guidelines (for accessibility), and the EU General Data Protection Regulation (for the handling of personally-identifiable data). Cite a specific version, and state the conformance level where the standard defines one, eg. "WCAG 2.2 Level AA".
Where an objective quality requirement is verified by an automated check — eg. a load test, a security scan, an accessibility audit — the requirement SHOULD cross-reference that check, and the check SHOULD back-reference the requirement, via their respective unique identifiers.
Some quality attributes, such as aspects of security, authentication, and authorization, naturally lend themselves to verification using conventional functional testing techniques. These are best specified as user stories and included as part of the functional requirements. Authorization requirements, for example, can mostly be dealt with by specifying personas or roles and the permissions associated with each.
As an administrator I want to change the email server settings via a UI so that I don't need to raise IT change requests to do this
Avoid vanity metrics. Metrics like test coverage and ticket churn are still worth tracking for other reasons, but they
don’t make good quality benchmarks. High test coverage does not tell you anything about the quality of your tests.
The velocity of tickets closed does not tell you anything about the value delivered to users. At their worst, when
metrics are treated as targets they can distort people’s behavior in a way that leads to worse outcomes, not better
ones, eg. writing meaningless tests, over-fragmenting work tasks, or creating lots of noise in git log.
Choosing thresholds
"Availability of 99.99%" is a quality requirement with a concrete, testable threshold. But that threshold is an entirely arbitrary one unless the value of meeting it exceeds the cost. Thresholds should be set at levels where they offer the optimum cost-benefit trade-off, given the domain and the business’s appetite for risk, etc.
The general rule is to choose thresholds that can be justified by what failing to meet it would cost the business. For example, a manufacturer whose process-control system has to run continuously, with no downtime acceptable at all, will require one or more redundant systems to maintain availability during downtime of one instance. Redundancy is expensive, but it could be justified if the cost of operating redundant systems is cheaper than halting production every time the control system goes down.
Quality requirements SHOULD include the business justification for the thresholds set.
Subjective quality requirements
Some NFRs are more nebulous and subjective. User experience is a case in point. UX is an entirely subjective quality, difficult to specify and measure in quantifiable terms. It must instead be satisfied through the development process via user research, continuous testing via A/B strategies, and/or user satisfaction surveys.
In some cases, qualities can be translated into quantifiable metrics. Net Promoter Score (NPS) is one such metric. It is a methodology for tracking user sentiment. It’s based on a single core survey question: "How likely are you to recommend our product/service/company to a friend or colleague?" Respondents rate their likelihood on a scale from zero (not likely) to 10 (extremely likely). Based on the responses, customers are categorized into three groups: promoters (score 9-01), loyal customers who are likely to help fuel growth; passives (7-8), satisfied but unenthusiastic customers who are vulnerable to competitive offerings; and detractors (0-6), unhappy customers who can damage your brand and impede growth through negative word-of-mouth, ie. actively discourage others from engaging. An overall NPS score is calculated by deducting the percentage of users who are detractors from the percentage of promoters. This is a hard number that can be tracked over time, and targets specified.
Wherever practical, subjective qualities should be captured in more objective metrics through measurement. Where this is not possible, the requirements SHOULD still be specified but be clearly marked as non-concrete.
Prioritizing qualities
Qualities SHOULD be prioritized relative to one another.
Prioritization is necessary because qualities compete. Raising one often lowers another. Multi-factor authentication raises security but lowers usability. Caching a derived value raises performance but puts correctness at risk. Tuning a system for a particular runtime environment raises its performance but lowers the portability of the system into other environments.
The priority order MUST be treated as a general guideline rather than a rule to be applied consistently in every case. A lower-priority quality MAY still take precedence in a specific context where it is clearly justified and documented. The ranking is an input to design, not an output of it.
The purpose of defining a priority order for quality attributes in the requirements specification is that it puts the choice in the hands of business stakeholders. Engineers are well placed to say how two qualities trade off against each other in a given design, but they are less well placed to say which qualities the business values more than others.
Executable specifications
Wherever practical, it is RECOMMENDED to specify requirements — both functional and non-functional — in a format that allows automated verification without requiring tests to be maintained separately. This means the specifications themselves MUST be presented in a format that, as well as being accessible to humans, can also be parsed by machines and translated directly into generated, executable tests.
This technical standard RECOMMENDS the Gherkin format for this purpose. Gherkin is a testable specification format that can be parsed by machines and used as the basis for automated acceptance testing.
The Gherkin language was originally developed as part of the Cucumber testing framework, but it has since been adopted by other testing frameworks including SpecFlow, Behat, JBehave, and Lettuce. It is widely supported.
Gherkin is a business-readable domain-specific language. It specifies a software system on a feature-by-feature basis from the point of view of different groups of users. One of the objectives of the language’s design is to provide a unified specification that can be written and understood by both technical and non-technical stakeholders. Gherkin provides a common standard for product managers and developers to collaborate on the core business requirements.
Gherkin SHOULD be used as much as reasonably practical to specify behavioral scenarios. It MAY also be used to specify some non-functional requirements, too, where those requirements can be reduced to an automate-able test.
The following documentation covers the basic features of the Gherkin language that are well supported by most BDD-style testing frameworks. This is the RECOMMENDED baseline syntax. Various test frameworks support additional extended syntax, which you MAY opt in to.
Note
The canonical Gherkin specification lives at https://cucumber.io/docs/gherkin/reference/.
Basic structure
Gherkin is line-oriented — one statement per line, and line endings terminate statements or open new blocks.
Structure is determined by keywords — Feature, Background, Scenario, Given, When, Then — not by indentation.
Parsers ignore leading whitespace outside doc strings, so indentation is purely a readability convention. Nesting steps
two spaces under their scenario, and scenarios two spaces under their feature, is the conventional layout and SHOULD be
followed.
Business rules are structured by features, scenarios, and steps. A single feature is described in a plain text file
with the .feature extension. Each feature file MUST contain at most one Feature block. A feature may have multiple
scenarios, and a scenario may play out over multiple steps.
Feature: <title>
In order to <realize some business value>
As a <user type>
I want to <achieve some goal>
Background:
Given <state>
(And <expectation>)
Scenario: <title>
(<optional description>)
Given <state or precondition>
(And <state or precondition>)
When <event or action>
(And <event or action>)
Then <expected outcome>
(And <expected outcome>)
(further scenarios)Feature: Refund item
In order to be confident in my purchases
As a customer
I want to receive refunds for faulty goods
Scenario: A customer returns a faulty microwave
Given a customer has bought a microwave for $100
And the customer has a valid receipt
When the customer returns the microwave
Then the customer should be refunded $100Feature files
Feature files (*.feature) are the concrete, scenario-level functional requirements.
How much behavior belongs in one file is a matter of judgment. A file SHOULD be scoped to a single feature. But where a feature is large, it is better split it across several files, each covering one coherent aspect of it, than allowed to grow into a scenario dump. The test is whether a reader can hold the file’s contents in their head.
The opening lines of each feature file MUST have the following structure.
Feature: <short description of feature> In order to <realize some business value> As a <user type> I want to <achieve some goal>
This describes the business value the feature delivers, in the format of an acceptance test — a twist on the classic user story formula, which traditionally has the following structure.
As a <user type>, I want to <some goal> so that <some reason>
A user story tells us who the feature is for, what the user wants to achieve, and why. Gherkin flips this format around, putting the business value at the start of the acceptance criteria.
In order to <realize some business value> As a <user type> I want to <achieve some goal>
This top section is for the benefit of humans. It is not used by machines in the execution of behavior-driven tests.
Scenarios
At the level of the feature, both user stories and Gherkin describe the problem, not the solution. Gherkin goes further by describing how the problem will be solved in the software. This is done via one or more scenarios.
A scenario is a concrete example that illustrates a business rule, expressed as a sequence of steps. Scenarios MUST follow the below pattern.
- Describe an initial context.
- Describe an event.
- Describe an expected outcome.
Scenario: <some determinable business situation> (<optional description>) Given <state or precondition> (And <state or precondition>) When <event or action> (And <event or action>) Then <expected outcome> (And <expected outcome>)
Scenarios are also tests. Each scenario is an executable specification of the system.
Scenario: A user posts to their blog Given a user is logged in When the user publishes a new blog post Then the user receives confirmation that the post was published And the post is published immediately Scenario: A user schedules a post to be published in the future Given a user is logged in And the user has drafted a new blog post When the user schedules the post for a future date Then the user receives confirmation of the scheduled publication date And the post is not immediately published
A scenario SHOULD NOT restate a business rule that is stated in the Requirements → Behaviors → Rules section. Nevertheless, those rules will be codified in the steps of some scenarios. Where so, the scenario should cross-reference the related business rules using their identifiers.
Steps
Scenarios are composed of multiple steps. The number of steps per scenario is unlimited, but scenarios SHOULD aim for five or fewer steps. Any longer, and scenarios lose their expressive power as specification and documentation.
Each step MUST start with one of the following keywords.
GivenWhenThenAndBut
An asterisk (*) MAY be used in place of any of these. It carries no meaning of its own, instead taking the meaning of
the preceding step’s keyword. It is useful where a list of preconditions reads awkwardly as a chain of And steps.
Steps are also known as "givens", "whens", and "thens".
Givens are preconditions that put the system in a known state before a user or some external system starts interacting with it. Things that "happened earlier" are also okay.
Given no users are logged in Given the customer is logged in as an administrator Given a $100 microwave was sold on 2020-11-03
Behavioral test frameworks will use the Given information to configure the system-under-test to an initial state. This
may involve creating mock objects or adding records to a database, for example.
Whens are used to describe a system event or user action. This can be a person interacting with the system, or it can be an event triggered by another part of the system, or a combination of both. Whatever happens, it causes a transition in state.
When the customer submits their credentials When the customer returns the microwave When the overnight settlement run completes
A When step SHOULD name the action in business terms, not the mechanics of performing it. "When the customer submits
their credentials" survives a redesign of the login screen. "When the customer fills the username field and presses the
login button" does not. It binds the specification to a particular user interface, which is a design and implementation
choice, not a requirement.
A scenario SHOULD have no more than one or two When steps. Any more, and the scenario SHOULD be split into multiple
smaller ones.
Thens are assertions — actual outcomes (what the system actually does) compared against expected outcomes (what it
is supposed to do). Each Then step MUST describe a specific, verifiable (ie. testable) result, output, or expected new
state.
Thens SHOULD observe outcomes related to the business value in the feature description — a report, user interface repaint, message, command output, etc. — rather than something deeply buried in the system, such as a database change. Assertions SHOULD NOT be made about the system’s internal state or implementation details — though, in practice, this is hard to avoid.
A scenario MAY have multiple Given, multiple When, and multiple Then steps, but they MUST always be grouped in that
order. For better readability, subsequent Given, When, and Then keywords MAY be swapped for And or But.
Steps are the basis for automated behavior-driven testing. Test automation systems will take the trailing portion of
each step — the text after the keywords Given, When, Then, And and But — and map it to a callback function,
which is executed. Typically, the callbacks for each Then step will inspect some aspect of the system to verify the
assertion made in the step.
Step arguments
A step whose subject does not fit comfortably on one line MAY carry an argument on the lines beneath it. Two forms are available, and both are passed to the step definition as a final parameter.
A doc string carries a block of text, delimited by triple quotes. It is used where the value is prose, a payload, or anything else whose internal line breaks matter.
Given a customer has submitted the following complaint: """ The microwave arrived with a cracked door. I would like a refund rather than a replacement. """
A data table carries rows of structured values, delimited by pipes.
Given the catalog contains the following products: | name | status | price | | Microwave | available | 100 | | Toaster | reserved | 40 |
A data table attached to a step is not the same construct as the Examples table of a scenario outline, though they
look alike. A data table is a single argument to one step within a single scenario. An Examples table generates
several scenarios from a template.
A step argument that runs to dozens of rows is usually test fixture data that has escaped into the specification, in which case the scenario has probably stopped illustrating the underlying business rule effectively.
Backgrounds
The same Given steps can end up repeated across all scenarios in a feature file. Repeated preparation steps are
usually incidental detail, not essential to describing individual scenarios. Such details SHOULD be moved to the
background — literally, a single Background section, placed near the top of a feature file between the Feature block and the
first Scenario, written just like a scenario except with no title.
Background: Given a $100 microwave was sold on 2020-11-03 And today is 2020-11-18
Background sections provide context to all subsequent scenarios. Test automation systems will run the background script immediately before testing each scenario, thus putting the system-under-test into the same preset state for every test.
Rule blocks
A Rule block groups the scenarios that together illustrate one business rule. It sits between the Feature block and
the scenarios it owns.
Feature: Reserve a product
Rule: A product can only be reserved while it is available
Scenario: Reserve an available product
Given a product with status "available"
When a Partner reserves the product
Then the reservation is confirmed
Scenario: Cannot reserve a sold product
Given a product with status "sold"
When a Partner reserves the product
Then the response indicates the product is not availableThis is the Gherkin counterpart of the business rules described under Requirements → Behaviors → Rules. Where the
specification states a rule centrally with a stable identifier, the Rule block SHOULD name that identifier, so the
scenarios that verify a rule can be traced to the rule they verify.
Rule: R3 — Reservation requires an available product
Rule is supported by current versions of all the major BDD frameworks, but it is a later addition to the language than
the rest of the syntax described here. Confirm support before adopting it.
Scenario outlines
A complex business rule with several variable inputs or outputs can end up producing several scenarios that only differ by their values.
Copying-and-pasting scenarios to test different values creates duplication. A scenario outline SHOULD be used instead.
It is an alternative to a scenario that allows the expression of a scenario using a template with <placeholders> and a
table of replacement values.
Scenario Outline: Eating
Given there are <start> cucumbers
When I eat <eat> cucumbers
Then I should have <left> cucumbers
Examples:
| start | eat | left |
| 12 | 5 | 7 |
| 20 | 5 | 15 |In this case, two scenarios are generated from this scenario outline — one per row of the Examples table. It is the
equivalent of writing the following ordinary scenarios:
Scenario: Eating Given there are 12 cucumbers When I eat 5 cucumbers Then I should have 7 cucumbers Scenario: Eating Given there are 20 cucumbers When I eat 5 cucumbers Then I should have 15 cucumbers
Variables in the scenario outline steps are marked up with < and >.
A scenario outline section MUST be followed by one or more Examples sections. Examples are tabular data used to
populate the scenario outline’s variables. The table MUST have a header row with column names corresponding to the
variables encoded in the scenario outline steps. Each table row produces a new scenario, with the variables filled in
with its values.
Tags
A tag is a label attached to a feature, rule, scenario, or examples table, written as an @-prefixed word on the line
above.
@checkout @slow Scenario: Checkout with a saved payment method
Tags are metadata for the test runner, not part of the specification’s meaning. Their main use is selection — running or excluding a subset of scenarios, such as a smoke-test set, or those known to be slow or fragile.
Tags MAY also be used to cross-reference requirement identifiers, giving a machine-readable binding between a scenario
and the rule or quality it verifies — @R3, or @Q1.4. This is a convenience for tooling, and does not replace stating
the rule centrally.
Tags SHOULD be few and their meanings documented.
Implementation
A .feature file is not by itself executable. Each step MUST be wired up to a callback function — often called a
step definition or glue code — that the test framework executes when the step runs. The step text is matched against
the step definitions by a pattern (a regular expression or similar), and any placeholders in the step text are passed to
the callback as arguments.
Step definitions SHOULD be kept thin. A step definition’s job is to translate business language into a call against the system-under-test, not to contain business logic itself. Where several steps across different features share the same wording, their step definitions SHOULD be reused rather than duplicated.
Step definitions SHOULD communicate directly with the business rule implementation, going through as few layers as possible. Scenario outlines in particular SHOULD NOT be automated using UI automation such as Selenium WebDriver. Scenario outlines SHOULD only be used to validate the implementation of a business rule that behaves differently based on variable input parameters. Validating a business rule through a UI is slow, and when there is a failure it is difficult to pinpoint where the error is. Testing close to the business rule, by contrast, is fast, and errors become easy to diagnose and fix.
Identifiers
Except for small-scale systems, every requirement MUST have a unique, unambiguous, durable identifier. This allows for each requirement to be referenced consistently from proposals, tickets, tests, and code.
This technical standard RECOMMENDS the following identifier scheme for software requirements. The first part of the identifier is a single letter that maps to a requirements category.
- F = Features
- R = Rules
- A = Access
- I = Interfaces
- J = Journeys
- Q = Qualities
The second part of the identifier is a incrementing whole number: 1, 2, 3 … 10, 11, 12 …
Where a single requirement holds several independently-verifiable scenarios, each scenarios is given a point number:
.1, .2, .3 … .10, .11, .12 …
F3 One discrete feature, eg. "reserve a product". F3.2 The second scenario defined within this requirement. R5 A single business rule. R5.3 A variation or example. Q1 On discrete quality attribute, eg. "latency". Q1.4 The fourth stated latency threshold.
Identifiers, once assigned, are permanent. An identifier MUST NOT be reused for a different requirement, even after the original is deprecated and removed. Gaps in a sequence are okay — they represent requirements that once existed but are no longer relevant to the current system.
As a rule of thumb, each unique identifier SHOULD represent a requirement that can be verified by a single discrete test. For example, in quality requirements each stated threshold should have a unique identifier of its own. Even a single quality such as latency may state different budgets for different operations and load conditions, and each is a separate pass or fail — and therefore each should have its own unique identifier.
Identifiers are more stable than the requirements they reference. Requirements may be recategorized, renamed, reworded — but their identifier will remain stable throughout.
Throughout a specification, related requirements SHOULD cross-reference each other using their identifiers. For example, interfaces and journeys should cross-reference the features they expose, and vice versa.
Deprecation
A requirement whose withdrawal has been agreed, but whose behavior is still in production, MUST be marked as deprecated in the specification. Only when the behaviors are fully removed from the production system should the corresponding requirements be fully deleted from the specification.
Deprecation markers SHOULD appear at the head of the artifacts they apply to. Where a deprecation applies to a single behavior scenario or a quality threshold, rather than a whole requirement artifact, the marker SHOULD be applied at the scenario level.
A machine-readable marker is RECOMMENDED where the format allows one. For example, Gherkin supports the @deprecated
tag on both features and scenarios.
Proposals
A complete requirements management practice requires two types of artifact.
- The specification. Mutable and always describing the as-is production system.
- The proposal archive. An immutable, append-only log of every significant proposed change to the specification.
The specification answers "what does the system do?" The proposal archive answers "why is it that way?"
The two artifacts SHOULD be colocated, so as to prevent drift between the description of the system and the record of the reasoning behind it. A version control system is RECOMMENDED as the home for both artifacts.
Proposal lifecycle states
Changes to specifications SHOULD always be introduced through proposals. Each proposal is drafted, reviewed, decided, and — if accepted — moved to the archive at the same time that the corresponding changes to the specification artifacts are made.
Each proposal SHOULD move through a defined state machine, reflecting the process of drafting, discussing, and ultimately accepting or rejecting a proposed change to the system specification.
The following lifecycle states are RECOMMENDED for a baseline implementation.
stateDiagram-v2 [*] --> Draft Draft --> Proposed Proposed --> Accepted Accepted --> Released Released --> Superseded Proposed --> Rejected Rejected --> [*] Released --> [*] Superseded --> [*]
The states have the following meanings.
- Draft. The proposal is being written. It is not yet ready for peer review. Early feedback MAY be solicited, but no decision is being sought yet.
- Proposed. The proposal is complete and open for a decision. It is now formally reviewed and negotiated with the relevant stakeholders.
- Accepted. The proposal is approved by the product managers. Implementation is being tracked via the normal product backlog system. Its specification edits are not yet on the main line, and MAY continue to evolve during implementation.
- Rejected. The proposal will not be taken forward.
- Released. The change has been built, its specification edits are merged alongside the implementing code, and the changeset has been deployed to production.
- Superseded. A previously released change is no longer in effect. A later proposal replaced or removed the feature.
When under version control, proposals should be introduced via side branches and merged to the main trunk when they reach either the rejected or released state. When released, the proposal SHOULD be merged alongside the corresponding changes to the specification artifacts. This way, specifications and proposals stay in lockstep with the current state of production.
Removing behavior from a system is a specification change like any other, and so proposals to withdraw requirements SHOULD follow the normal lifecycle.
Prioritizing proposals
Accepted proposals form a backlog of changes awaiting implementation. It is RECOMMENDED these be prioritized using a scheme such as MoSCoW.
- Must. Non-negotiable for the mapped release.
- Should. Important but not release-blocking.
- Could. Worth having if time and budget allow.
- Won’t. Agreed to be out-of-scope for the mapped release.
Alternatively, proposals can also be mapped to milestones or releases.
Best practices
- Give each proposal a unique reference number. The number SHOULD be treated as immutable once assigned. This helps to keep stable cross-references.
- Scope each proposal atomically. One feature or one quality requirement that can be reviewed, decided, and shipped independently of any other change.
- Review cross-functionally. The product teams SHOULD read a proposal for scope and business intent, QA SHOULD read it for missing or ambiguous acceptance criteria, and engineering SHOULD review and approve it for feasibility.
- Keep description and reasoning in their proper homes. The specification says what the system does, while the proposals say why changes were made over time. Rationale SHOULD NOT be smuggled into the specification, and a proposal SHOULD NOT restate the specification — it SHOULD instead link to the artifacts it edits.
- Leave out implementation details. How the change is rolled out — migration steps, sequencing, feature flags — is an implementation concern and SHOULD NOT appear in neither specifications nor proposals.
- Keep feedback out of the record. Open-ended debate and negotiation SHOULD happen in a discussion thread attached to the proposal, separate from the document and its revision history. The proposal document’s history then stays a clean record of how the proposal evolved.
- Treat merged proposals as immutable. A merged proposal MUST NOT be edited or deleted. To revisit a decision, open a new proposal that supersedes the original, cross-referencing the two.
- Keep a record of rejected proposals. It is worth recording the rationale for proposals being rejected as much as it is for them being accepted.
- Trace requirements to their implementation. Where the tooling allows, each requirement SHOULD be linked to its implementing component, its test suite, and any tracking ticket for outstanding work.
Definition of Ready
It is RECOMMENDED that software projects have a Definition of Ready (DoR). This a documentation artifact that defines a set of criteria that MUST be met before a proposal for a behavioral or quality change is considered "ready" to be worked on.
The DoR SHOULD be formatted as a simple, short checklist. The purpose is to provide a quick point of reference for teams to check they’ve got everything they need to successfully complete a development task, before proceeding with it.
The checklist SHOULD be generic enough to be applicable to all kinds of development tasks, and emphasis should be on requirements readiness. A development task is ready when its acceptance criteria are unambiguous, testable, and small enough to build.
- Are the requirements clear and (sufficiently) unambiguous? - Are the acceptance criteria defined in a testable format, and can the tests be automated? - Is it clear who the stakeholders are? - Does the team have the knowledge and resources required to complete the task? - Can the work be done independently of other tasks running in parallel? - Can the work be implemented in small increments? - Can the design be iterated based on feedback?
References
- Adzic, G. Impact Mapping.
- Brandolini, A (2013). Introducing EventStorming.
- Cohn, M (2004). User Stories Applied: For Agile Software Development.
- Jacobson, I (1992). Object-Oriented Software Engineering: A Use Case Driven Approach.
- Patton, J. Story Mapping.
- Srivastava, PJ. A Short Guide to Writing Software Requirements.
- Wiegers, K (2021). Software Development Pearls.
- Wynne, M (2015). Introducing Example Mapping.