🎯 Chapter Insight
Requirements are rarely sitting there waiting to be collected.
They have to be discovered.
A stakeholder might ask for a new button. A user may request an additional field. A product ticket may describe a very specific change to an existing workflow.
At first glance, those requests look like requirements.
But often they are not.
They are proposed solutions.
The real requirement lives underneath them.
Why does the user need the button? What problem is the new field supposed to solve? What outcome is the workflow change trying to create?
Pragmatic developers do not stop at the surface of a request. They dig deeper.
They ask questions, challenge assumptions, and try to understand the need behind the proposed solution.
Because building exactly what was requested can still mean building the wrong thing.
💡 Developer Lens
In everyday engineering, it is incredibly easy to turn tickets directly into code.
A requirement says:
“Add an export button.”
So we add an export button.
A stakeholder asks:
“Can we add another status?”
So we extend the status field.
A user says:
“I need a search field here.”
So we build another search field.
The implementation may be technically perfect. The tests may pass. The feature may be delivered on time.
And yet the actual problem may remain unsolved.
Perhaps the user wanted an export because they cannot compare records inside the application.
Perhaps the additional status exists because the workflow no longer represents how the business operates.
Perhaps the search field was requested because the existing navigation makes important information difficult to find.
When we only implement the proposed solution, we miss the context that could lead to something better.
Understanding the underlying goal changes the conversation.
Instead of asking only:
“How should we build this?”
we begin asking:
“What are we actually trying to achieve?”
That question can completely reshape the solution.
Requirements Are Discovered Through Conversation
Requirements are not static objects that move perfectly from a stakeholder’s mind into a ticket.
People often do not know exactly what they need until they see something working.
They describe problems using the language and solutions available to them. Developers interpret those descriptions through their own technical perspective. Product managers add business context. Designers add interaction considerations.
Understanding emerges through conversation.
This is why requirements work is collaborative.
A developer who asks good questions can uncover information that was never written in the ticket.
Who is affected by this problem?
How often does it happen?
What do users currently do to work around it?
What would a successful outcome look like?
Are there cases where the requested behaviour should not happen?
What happens before and after this step?
These questions transform a vague request into shared understanding.
And that shared understanding is often more valuable than a perfectly written specification.
Ask Why Before Asking How
Developers naturally move toward implementation.
We hear a request and immediately start thinking about database changes, APIs, UI components, validation rules, and architecture.
That instinct is useful.
But it can also make us solve the technical problem before we understand the actual one.
A simple habit can slow that down:
Ask why before asking how.
Why is this needed?
Why does the current behaviour not work?
Why does the user need this information?
Why does this process need another step?
The goal is not to interrogate stakeholders or endlessly challenge every request.
The goal is to understand the purpose well enough to make better engineering decisions.
Sometimes the requested solution will still be the right one.
But now you will understand why.
Other times, the discussion reveals that a much simpler change would solve the real problem.
That is where discovery pays for itself.
Requirements Are About Outcomes
A requirement becomes much more useful when it describes an outcome rather than an implementation.
Compare:
“Add a button that exports the table to Excel.”
with:
“Users need to compare these records outside the application when preparing the monthly report.”
The first statement strongly suggests one implementation.
The second gives the team room to explore the problem.
Perhaps exporting is still the best solution.
Perhaps the comparison could happen directly inside the application.
Perhaps the existing reporting feature can already provide what users need with a small change.
Outcome-oriented requirements create options.
Solution-oriented requirements prematurely narrow them.
Pragmatic developers try to preserve those options long enough to understand which solution actually provides the most value.
Edge Cases Hide in the Why
Understanding the underlying need also helps reveal edge cases.
Suppose a ticket simply says:
“Allow users to delete documents.”
That sounds straightforward.
But once you ask why, more questions appear.
Why do users need to delete them?
Should documents disappear permanently?
What if the document is referenced elsewhere?
Who should be allowed to delete it?
Should deletion be reversible?
Does the organisation need an audit trail?
The original request describes an action.
The real requirement includes rules, constraints, risks, and expectations around that action.
Those details are often where the difficult engineering work lives.
Without understanding the goal, developers discover these questions late, sometimes only after the feature has already been released.
Requirements Change as Understanding Improves
There is another reason requirements cannot simply be collected once and considered complete.
Understanding changes.
Users see the first implementation and realise their workflow is different from what they described.
Developers discover technical constraints.
Designers uncover usability problems.
Business priorities shift.
New edge cases become visible.
This does not necessarily mean the original requirements process failed.
It means software development is a learning process.
Pragmatic teams expect requirements to evolve as they learn more about the problem.
Prototypes, incremental delivery, user feedback, and working software all provide information that documents alone cannot.
The objective is not to eliminate change.
It is to create feedback loops that help the team discover the right solution before too much is built around the wrong assumptions.
Developers Belong in Requirements Discussions
It can be tempting to think of requirements as something that happens before development.
Product people define what should be built. Developers then implement it.
But developers bring a unique perspective to discovery.
They understand the system’s existing capabilities, technical constraints, and hidden dependencies. They may recognise that a requested feature already exists elsewhere. They may see opportunities to solve the problem with a smaller change. They may identify edge cases that are easy to miss from a purely business perspective.
That does not mean developers should dictate product decisions.
It means technical understanding should be part of the conversation.
The earlier developers understand the problem, the more useful their technical judgement becomes.
Do Not Confuse Requirements With Specifications
A requirement describes the need.
A specification describes more precisely how the system should behave.
The distinction matters.
If we treat detailed implementation instructions as requirements, we may never question whether those instructions solve the right problem.
A stakeholder can be completely correct about the problem while being wrong about the best technical solution.
That is perfectly normal.
Users are experts in their problems.
Developers are experts in the system.
Good solutions emerge when those perspectives meet.
The goal is not to reject what users ask for.
It is to understand why they are asking.
🧭 Reflection
Think about the requirements you have implemented recently.
How often did you ask why before starting?
How many tickets described the desired solution without explaining the problem behind it?
Did you understand who was affected and what success looked like?
Have you ever delivered exactly what was requested only to discover that it did not actually solve the user’s problem?
The dangerous part is that this can still look like successful development.
The ticket closes.
The feature ships.
The acceptance criteria pass.
But if the original need remains, the work was not truly complete.
⚙️ Practical Tip
Pick one requirement this week and pause before touching the code.
Ask a few basic questions:
- What problem are we actually solving?
- Who experiences this problem?
- Why is the current behaviour insufficient?
- What outcome would make this successful?
- Is the requested solution the only way to achieve that outcome?
- What assumptions are hidden in the request?
You do not need hours of workshops for every ticket.
Sometimes a five-minute conversation is enough.
But those few minutes can reveal that the requested feature needs an important edge case, that a simpler solution already exists, or that the problem is entirely different from what the ticket suggests.
A little discovery before implementation can save a lot of development afterward.
Do not just collect requirements.
Dig for the real need.
🔢 #45 of 53 | The Pragmatic Programmer Series
This post is part of my 53-week series summarizing The Pragmatic Programmer, one timeless principle each week, translated into modern software practice and reflection.








