How Can Agile Teams Capture Non-Functional Requirements?
According to Ian Alexander and Richard Stevens in their book Writing Better Requirements, user requirements consist of capabilities (functional requirements) and constraints (non-functional requirements). Some constraints relate to individual capabilities and some relate to groups of capabilities (with the possibly that some constraints are solution-wide).
Constraints include quality criteria as well as anything else that constrains the solution.
Capabilities can be described using simple verb-noun phrases:
- Enter reservation
- Amend reservation
- Cancel reservation
- Add accommodation charge
- List guests
In the past, it was common to describe capabilities as use cases. It is now common to describe capabilities as user stories. User stories are popular with Agile teams who use the approach to populate a product backlog. The product owner creates a list of the capabilities required by a solution and describes them using user stories:
As a call centre operator, I want to be able to enter a new accommodation reservation so that the guest is guaranteed a room and the hotel can estimate its future occupancy rate.
When a constraint is relevant to a single user story, it can be described on the back of the story card as acceptance criteria:
Verify that the reservation can be created within 2 seconds, with 50 concurrent users
But there is a problem when constraints are solution-wide (i.e. they relate every user story in the product backlog). User stories must be “independent”, in other words the team’s understanding of a user story must not depend on understanding of any other user stories in the product backlog. This means that if I write a non-functional epic, which describes a solution-wide constraint, then all of the user stories in the product backlog will depend on that story.
As a platform support manager, I want to display all outputs at screen resolutions ranging from 480x320 to 1280x854 to comply with our standard operating environment (SOE)
The problems get worse. Product backlogs must be “prioritised” but how can I prioritise a solution-wide story on which all other user stories depend? Sprint backlogs should consist of the high-priority stories which the team has estimated they can deliver in a single sprint. Does that mean that a system story describing a solution-wide constraint should be included in every sprint?
Clearly the system story approach is flawed. So how can we ensure that an Agile team considers all of the relevant constraints in each sprint? If a constraint is solution-wide, then we could include it in the definition of done for a sprint. This would ensure that each product increment was evaluated against any constraints described in our definition of done.
But what if a constraint is not solution-wide but relates to a group of user stories (in other words, a subset of the product backlog)? In this case we should probably create a list of the constraints and somehow link them to the relevant user stories. Another possibility would be to include the constraint as an acceptance criteria for each user story that it was relevant to. But this would result in a lot of redundancy and as everyone knows, redundancy is the enemy of change.
In my mind, none of these approaches present a particularly elegant solution to the problem. Normally the definition of done is task focussed, serving as a check-list for sprint completion rather than a definition of product requirements. There is something rather ad-hoc about placing some constraints in the definition of done and others in a separate list and linking them to a subset of the product backlog.
My solution is to maintain a separate “constraint” backlog. The constraint backlog is reviewed during sprint planning for any constraints that are relevant to the user stories in the sprint backlog. These constraints are then added to the sprint backlog. The team can always choose to ignore a constraint if it is not relevant to the sprint objectives. For example, constraints related to things such as “hardening” or scalability could always be deferred to later sprints.
If a constraint has been fully satisfied at the end of a sprint, it is retired in the same way that user stories are retired when a capability has been fully delivered by a product increment. If a constraints remains relevant to one or more user stories in the product backlog, it is returned to the constraint backlog for inclusion in subsequent sprints.
Teams that use story cards can write a description of the constraint on the front of the card and use the back of the card to describe the risks associated with a failure to satisfy the constraint.
Given that the solution was developed in a desktop browser, there is a possibility that the user interface will not render correctly on mobile devices, resulting in an unsatisfactory user experience for mobile users.
It seems natural to prioritise the constraint backlog by risk. Risk Poker is derived from the popular planning poker approach to estimating. It can be used to assess the relative risk level of constraints. When risks are clearly identified and prioritised in this way, it becomes much easier to convince a product owner that a risk reduction sprint might be required to address a high risk constraint early in the product’s development. In this case, the sprint backlog would not include any user stories but would consist entirely of high risk constraints to be resolved during the sprint.
This approach to constraints, is similar to the way many teams handle bugs. Often the team maintains a separate defect backlog in a bug tracking system, rather than adding bugs to the product backlog. I am suggesting adding a third backlog describing constraints. The result is three independently managed backlogs - a capability backlog (product backlog); a defect backlog (bug tracking); and a constraint (risk) backlog.