In software development, the requirement word gets thrown around like confetti 🎉🎉🎉:
“Is this a requirement or not?”
“We’re unable to estimate, because the requirements are unclear."
“We still have to talk to stakeholders to figure out the requirements.”
Despite requirements being frequently and casually dropped in conversation like it’s incredibly clear what we’re talking about, I’m going to argue the opposite is the case: Requirements don’t mean what you think they mean, and someone saying it’s a requirement doesn’t mean it’s necessarily required.
Confused yet?
Let’s fix that by going down the requirement rabbit hole together!
The Roots of the R-word
The word requirement comes from Latin requirere, meaning to ask again. In the English language around the 16th century, this evolved into the noun requirement, meaning “A thing that is asked or demanded”. Today the word requirement means something that is necessary or essential.
So whenever we label something as a requirement, people may conclude it’s necessary or essential, but is that really the best way of looking at requirements?
Let’s take a look at a more modern and multi-faceted definition of software requirement from the International Requirements Engineering Board (IREB):
A need perceived by a stakeholder.
A capability or property that a system shall have.
A documented representation of a need, capability or property.
O boy, here’s where things get tricky.
A software requirement can basically mean three wholly different things. This is where the trouble starts, as they are all related but distinctly different.
The Penta-Layered Nature of Requirements
Let’s expand upon the above definition by showing how these different types of requirements are related to each other, plus what else affects how a requirement is ultimately realized:
The need we're trying to address shapes how the system is supposed to work.
How the system is supposed to work shapes how we attempt to document our system.
How we create, collaborate, and describe our documentation shapes how it’s interpreted and understood.
How it’s understood and interpreted shapes how we ultimately realize the functionality.
All these things together shape whether we’ve actually addressed the requirement adequately or not.
You could visualize this chain of interactions as follows:
All of these puzzle pieces should gently slide into each other. Unfortunately, that is rarely the case. Every step along the way, we face many sources of noise, just like these colorful puzzle pieces will never fit together because of the noise my terrible drawing skills introduced.
Needs are noisy because:
Stated needs may not be the actual needs. People are unreliable narrators. “People don’t think what they feel, don’t say what they think, and they don’t do what they say”, as David Ogilvy famously has said.
When we talk about their needs, we talk about interpreted needs. The interpreted need may or may not be what they actually need. Almost everybody says their health is important, but when you ask what someone does for their health, you will get much more reliable information. Revealed preferences are much more reliable than declared preferences.
To make matters worse, needs are often communicated by proxy. Sales tells us the customer wants a Drupal integration. We don’t go to the source of the needs but often talk to a proxy who tells us what they believe the customer needs. Don’t do this. We’ve got enough noise going around without any proxy silliness involved.
In short, there are many places in the first step of the chain where things can go terribly wrong. Let’s say we know the need, and then we think about how the system should behave to address that need.
System properties are noisy because:
Even with a clear understanding of the need, there are multiple ways of addressing it. Let’s say a customer wants to receive an invoice they can submit for tax purposes. You could e-mail the customer, list all the invoices in my account, or send the invoice directly to their bookkeeping program. You could do all of those things or even do something else entirely. There are many options we can explore in the solution space.
The way the system already works technically limits options and affects the feasibility of solutions. Maybe sending emails is a part of a legacy system you’re scared of touching. Suddenly, it becomes much less likely you’ll choose that option even if it would be the best solution for the customer.
The way the system already works affects our thinking about possible solutions, as there is a natural tendency for us to want it to blend in with the existing system.
The documented version of the requirements is noisy because:
Writing things down perfectly is impossible, and we will always leave room for misunderstandings.
We tend to over-complicate documentation, which means the signal gets lost in the noise. It’s hard to be concise and brief. While you’re still clear, it’s much easier to ramble and provide the illusion of clarity.
The more uncertain we are, the more we will try to project certainty in our requirements, which results in over-fitting our requirements and injecting them with noise.
The understood version of the requirements is noisy because:
Every person has their own lens through which they view the world: their worldview, history, values, culture, and experiences shape how they interpret what they are reading. What you write down, isn’t what they will get out of it.
Whatever we write down, isn’t what people understand. In the end, shared understanding is more important than perfect documentation, but we often fuss far more about the textual representation over what is understood.
Some people love reading, others hate reading. The fact that we write it down doesn’t mean people will read it entirely and get it. They may scan things and infer meaning from the little bits and pieces they care to read.
And then, when we ultimately deliver functionality, we may still run into problems because:
Requirements are not linear. We should move back and forth between the different representations to find the best solution, but this doesn’t always happen because the chain of requirements is lost in translation.
People (like AI) can hallucinate in all the different steps, believing something is necessary while it isn’t. In my personal experience, this is one of the biggest problems in software development.
The link from need, to system capability, to documented version, to what we’ve ultimately built is missing. It’s delivered, but we’ve forgotten why because got sucked in delivering the documented solution we ultimately agreed upon.
We can conclude there are many places where requirements can go wrong, how do we prevent this from happening?
Floating Requirements Vs. Anchored Requirements
We should document the reason behind the requirements. Requirements aren’t required; what those requirements make possible is what might be required. For example, let’s say you have a requirement in your product because of GDPR legislation in Europe. The GDPR legislation determines the requirement, not the requirement itself. Requirements can be wrong, and I’m 100% sure about this because I’ve worked at different companies where the same GDPR requirements were interpreted wholly differently.
If we’re building something to address a need, we must make sure that there’s a clear link to this need throughout the chain of requirements - we call this an anchored requirement. This ensures our requirements are anchored in the reality of what we’re trying to achieve. We should ensure we have anchored requirements, because these can be challenged and reshaped to resolve the initial need.
But what often happens is that we end up with floating requirements. They are a requirement, but we don’t really know why they are a requirement beyond someone stating that they are required. We may not even remember who stated them or where they came from. Floating requirements are extremely dangerous and can cause massive problems for your product as you may deliver something that may or may not make your product better.
Formulating and describing requirements has a tendency to result in Requirement Tunnel Vision. We tend to get sucked in how the system should work, not whether how the system works to enables the work it’s supposed to enable. This happens because building software is complex, and it’s easy to get sucked in how it works because that’s challenging enough. We should always have what we’re trying to achieve in the back of our mind.
How to Prevent Being Fooled by Requirements?
In short, when we talk about requirements, always think about:
Why is this a requirement? And is it really a requirement? Just because someone says it’s required, doesn’t mean that’s the case. Where does the requirement come from? Is it rooted in the reality of the user? Is it a guess about what the system itself needs? Where does the requirement come from?
What’s the requirement ultimately rooted in, and are we sure it’s true? If we have some doubt, how can we reduce uncertainty?
Requirements are noisy and multi-faceted, which means there is a lot of room to create confusion and drag your product down. You must keep your requirements rooted in reality, and you don’t do that by simply stating that something is required, but knowing the reason behind why it’s required.
What people ask for is not what they need, what they need is not what they want, and what they want is not necessarily what they need. This is actually the biggest problem you’ll face when you work as a consultant.
Requirements must be challenged. Floating requirements that have been written down, but nobody knows why they matter can’t be questioned. There should be a clear link to the actual problem or challenge we’re trying to solve, so we can reframe the problem or adjust the solution as necessary.
And if a requirement can’t be questioned, that means you’ve lost something important along the way,. you’re probably better off discarding the requirement to see if it’s really needed.
We often spend a lot of our time worrying if the system behaves as expected, but our primary concern we’ve built the right thing that solves that actual problem we’ve intended it to solve.
It’s easy to get sucked into requirement discussions that merely focus on how the system should behaves, instead of what’s the system is supposed to make possible with that behavior.
The first results in requirement tunnel vision and suboptimal products, the second grants you the freedom to shape the requirements as necessary to solve the right problems and arrive at the best solution.
Requirements are never required, it’s what the requirement makes possible that might be required.
If we don’t know what the requirement is supposed to help make possible, then we can’t tell if it’s true, and all we can do is ship and forget.
I'm a big fan of Sutherland's "Enabling Specifications", even if they didn't make it into the Scrum Guide. I've written about them here: https://bettersoftware.uk/2024/08/26/improve-your-offshore-software-development-with-enabling-specifications/ and I wondered @Maarten, if you had an opinion on their use, good/bad/indifferent, particularly since the prescriptive nature of them seem to fly in the face of the current agile movement.
I follow a very simple and straightforward rule:
A valid requirement must be translated into understandable and measurable acceptance criteria.
This approach reduces clutter, ambiguity and misunderstandings.