BDD and TDD - What are they for?

I’d like someone to give me very basic reasons for why I need Behavior
Driven Development (BDD, see RSpec) and/or Test Driven Development (TDD,
See Test::Unit).

I’m a fairly competent programmer. I think I use what they call an
“iterative” style of programming; I don’t rush out to build the entire
program at once. I do a very small framework, then attempt to run it and
see if it’s giving me the result I expect. If it’s not, then I figure
out what’s going wrong, and attempt to solve it before going on to the
next small part. You could say I do several iterations in an hour, to
give an idea of time.

It looks like TDD does exactly what I’m doing, but introduces far more
code to the equation. One of the biggest features of TDD is being able
to run a suite of tests to make sure new features don’t break old
features. Yet I have an eye for this while developing; I either fix the
upcoming problem because I know it’s going to happen, or I’m doing it
wrong in the first place. Sure, I occasionally miss, but who doesn’t? I
find the issue as quickly as I can and resolve it in a clean style.

BDD looks like a way to make it easy for non-programmers to do
programming, but not having people keep several functions in mind at any
one time. And it also does TDD? Am I close?

But everyone continually praises TDD and BDD, which leads me to believe
I’m missing something profound that could make me a better programmer.
So what’s the big deal?

Clinton Judy

Web D.

Glenn O. Hawbaker, Inc.

On Fri, Aug 15, 2008 at 4:10 PM, Clinton D. Judy [email protected]
wrote:

BDD looks like a way to make it easy for non-programmers to do
programming, but not having people keep several functions in mind at any
one time. And it also does TDD? Am I close?

BDD is simply an altered vocabulary for TDD. Vocabulary is important;
it effects how you think about a problem and how you decompose it.
For a lot of people, including myself, thinking about things in terms
of specifications of behavior rather than in terms of “how do I test
this method” leads to better-designed code.

What’s the deal? Like pair programming, BDD/TDD is one of those
things you have to try to get. If you can, find someone who is a pro
at it and do some TDD coding together. At some point it will “click”.

For me it was when I spent several weeks coding C++ by myself with
nothing but the spec for a communications protocol, and the very first
time we integrated my library into the main product it worked out of
the box. That kind of integration experience was unheard-of where I
used to work. I was hooked from then on, and I’ve never gone back.
Most of the TDDers I know have their own similar conversion story.

I find that when I’m writing code test/spec-first, I don’t have to
worry about debugging. The code is usually right the first time, and
when it isn’t the problem is obvious. It also forces me to write code
that is properly decoupled and obeys the single responsibility
principle, making changes much easier.

It sounds like you are doing most of your coding alone, on projects
that you can pretty much hold in your head at the one time, and on
which you can manually test without much trouble. When you start to
work on projects that haved tens or hundreds of thousands of lines of
code, have had many developers, some of whom are long gone, and which
could take days to manually test, the benefits of complete test/spec
coverage become impossible to ignore. And the only way to guarantee
complete coverage is to write the tests first.

But really, the only way to discover the joys of BDD/TDD is to do it
for a while.


Avdi

Home: http://avdi.org
Developer Blog: Avdi Grimm, Code Cleric
Twitter: http://twitter.com/avdi
Journal: http://avdi.livejournal.com

On Fri, Aug 15, 2008 at 4:10 PM, Clinton D. Judy [email protected]
wrote:

give an idea of time.
I pulled this link off the TDD page on our internal wiki here at work:

http://www.railsenvy.com/2007/10/4/how-i-learned-to-love-testing-presentation

I see your point. I’m struggling with TDD concepts myself. But I
think you answered your own question when you said:

Sure, I occasionally miss, but who doesn’t?

Test programs don’t. That thing they tested last week that you forgot
about? They remembered.

I agree that the overhead is extra development time. And I’m sure
test scripts are not infallible – for example, if you change
functionality in the program but not in the test.

Also, I’ve said this before here, but as a commercial programmer I’ve
spent years telling people that the code can’t tell you what the
program is supposed to do; only what it does. Test scripts tell
you what the code is supposed to do. That’s pretty cool.

On Fri, Aug 15, 2008 at 4:35 PM, Shadowfirebird
[email protected] wrote:

I agree that the overhead is extra development time.

After doing TDD/BDD for, oh, five years or so, I’m convinced that the
“it takes longer” argument is a red herring. It may be true when
you’re first learning TDD and it takes you awhile to work out how to
properly test something. But I’ve found that once I internalized
testing my coding velocity actually increased. And more
importantly, it became much steadier. Non-TDD projects are often
marked by a very fast initial ramp-up, then velocity starts to
decline, and then eventually they hit a wall where every change seems
to take 2-5 times as long as it should because of all the unintended
consequences. TDD projects, by contrast, retain about the same speed
from start to finish. Write test; watch test fail; make test pass;
refactor; repeat - it’s a rhythm that stays constant no matter how
large the codebase.

I’ve also found that for me, personally, TDD reduces my initial
startup time. In the past I used to spend a lot of time trying to
dream up the “right” object model to fit the project, and I’d have a
hard time actually figuring out where to dig in and start coding. And
then when I did dig in for awhile, it would suddenly occur to me that
I’d failed to account for something basic and I’d realize I needed to
re-tool my design. And of course the subsequent refactoring would be
prone to breakage because I had no regression tests.

When I’m doing TDD, all I have to think about to get started is the
simplest possible unit of concrete, testable functionality. I make
that work the simplest possible way, and then move on to the next
simplest case. As soon as I find myself duplicating code I refactor.
Out of this rhythm the “right” design emerges, a piece at a time - as
it is needed. And there’s no wasted time at the beginning trying to
figure out how to architect for the future.

Which is all to say why I find any project over, say, a hundred lines
of code actually goes slower without TDD/BDD.


Avdi

Home: http://avdi.org
Developer Blog: Avdi Grimm, Code Cleric
Twitter: http://twitter.com/avdi
Journal: http://avdi.livejournal.com

On Friday 15 August 2008 15:10:26 Clinton D. Judy wrote:

I’d like someone to give me very basic reasons for why I need Behavior
Driven Development (BDD, see RSpec) and/or Test Driven Development (TDD,
See Test::Unit).

BDD is a philosophy and a vocabulary for talking about TDD. They are not
mechanically different – a good TDD suite should support BDD, and vice
versa. But they do introduce a few new ways of thinking about the
problem.

I do a very small framework, then attempt to run it and
see if it’s giving me the result I expect. If it’s not, then I figure
out what’s going wrong, and attempt to solve it before going on to the
next small part.

That’s good. Question: How do you know when it’s giving you the result
you
expect?

BDD adds an extra step: You write down the result you expect, in code
form, as
tests. You then write your framework, pretty much as you’ve described,
until
the test passes.

There are two direct benefits to this approach: First, you know when
you’re
done. If it passes a test and you don’t think it’s done, write down
why you
don’t think it’s done – again, as a test.

In other words, it prevents you from writing a ton of unnecessary code.

The second benefit is that, coding this way, you accumulate some small
measure
of documentation: By reading your tests (which BDD calls “specs”), it’s
possible for someone to get an idea of what your code is supposed to do.

It looks like TDD does exactly what I’m doing, but introduces far more
code to the equation.

Correct. I won’t sugarcoat it – when I’m doing proper BDD/TDD, I will
sometimes have twice as much code in tests as I do in the actual
program.

One of the biggest features of TDD is being able
to run a suite of tests to make sure new features don’t break old
features.

Not just new features, but any code change. It means that you can do a
massive
internal refactoring, or even replace one library (or program) with
another,
and have some assurance that things still work exactly the way they’re
supposed to.

A simple example: Web browsers. Having the spec, in written form, wasn’t
good
enough. That’s why we have the Acid2 and Acid3 tests – now we can know
which
browsers have properly implemented the specs, and to what extent. It
also
provides something for browser developers to work towards.

Yet I have an eye for this while developing; I either fix the
upcoming problem because I know it’s going to happen, or I’m doing it
wrong in the first place.

The problem is, you know your own code very, very well right now.

Will you know this code that well in five years? Will you be able to
change
any part of it without fear that you will break something?

And, perhaps more importantly, will a total stranger be able to sit down
and
do the same?

Sure, I occasionally miss, but who doesn’t?

Your test suite.

BDD looks like a way to make it easy for non-programmers to do
programming, but not having people keep several functions in mind at any
one time.

It’s not about keeping several functions in your mind.

It’s about keeping the entire program in your mind at once.

But the mention of non-programmers does bring to mind another benefit,
and one
which I rarely see implemented: Stories. A story is a way to express, in
plain text, how a program should behave, from the user’s point of view.
Ideally, a customer could write stories by themselves.

Realistically, you would probably write the stories with the customer –
they
do read like plain English, so the customer can understand them, but
they
need to be somewhat stricter, so that you can more easily use them to
write
tests later.

Given a story, and a bit of translation, you can define your eventual
target
behavior, exactly the way the customer (or your boss) wants. Converted
to
integration tests, you have feedback as to when you’re done – when it
does
exactly what the customer wants.

I’m still not fluent enough at writing tests that I can actually start
with a
clean project and test first. I still usually end up doing an evening or
a
weekend worth of code before I have enough of a program in place that I
can
properly reason about what my tests would look like – what I actually
expect
from this program.

But I’m not sure yet whether this is a deficiency in BDD or in my own
line of
thought. And I do find that after a week or so of development, the
program
has gotten to a point where I need tests – or at least, where I’m doing
so
much testing manually that it’s a pain.

Simple example: I’m writing a program which spiders a certain website,
scrapes
some useful information out of the HTML, and dumps it into a database.
I’ve
been building it incrementally, as you’ve described, but every time I
want to
make sure something works, I have to start with a fresh database, open
up an
irb console, and have it download the same page. I then have to browse
through the database records, making sure they match what I’m expecting.

I’m about to convert this process to a test suite – some pre-downloaded
HTML,
so I’m not hitting the site every time, and a test to cover this
behavior, so
that I don’t have to keep browsing through records.

David M. wrote:

BDD is a philosophy and a vocabulary for talking about TDD. They are not
mechanically different – a good TDD suite should support BDD, and vice
versa. But they do introduce a few new ways of thinking about the problem.

BDD is “customer facing”. It’s supposed to be about writing the tests
in terms
a civilian client could understand and agree on.

It’s not about keeping several functions in your mind.

It’s about keeping the entire program in your mind at once.

And it’s about keeping the entire program out of your mind all at once.
It’s
about making changes while looking at a huge application like a map thru
a soda
straw. I want to make one little change, in one corner, without worrying
that I
will derail some other far-flung part of the app. Its tests will defend
it.

Good stuff snipped!

Clinton D. Judy wrote:

I’d like someone to give me very basic reasons for why I need Behavior
Driven Development (BDD, see RSpec) and/or Test Driven Development (TDD,
See Test::Unit).

Shine the “Phlip” symbol on the underside of the nearest cloud deck!

I’m a fairly competent programmer. I think I use what they call an
“iterative” style of programming; I don’t rush out to build the entire
program at once. I do a very small framework, then attempt to run it and
see if it’s giving me the result I expect. If it’s not, then I figure
out what’s going wrong, and attempt to solve it before going on to the
next small part. You could say I do several iterations in an hour, to
give an idea of time.

When you say “attempt to run it”, you should be mixing manual testing
with
running unit tests. They give a second opinion.

However, they are permanent. Imagine if you put a “mini-me” in a bottle,
who
came out and manually tested, instantly, each time you changed the code.
Imagine
if it would warn if nearly any behavior changed since the last run.

You could go faster - making bigger changes - with less manual testing.

It looks like TDD does exactly what I’m doing, but introduces far more
code to the equation.

Yet that code should be super-easy to write. A TDD test should obey the
Assemble
Activate Assert pattern:

def test_case
foo = assemble_foo()
result = foo.activate()
assert{ result == 42 }
end

Compared to production code, that test code looks super-easy to write.
Tip: The
easier a test is to write, the cleaner and more decoupled your code is.
So,
counter-intuitively, the more lazy you get writing tests, the more
pressure
forces your code to decouple.

To do TDD, you write the test case first, then write code to pass the
test. You
only write new code if you have a failing test case. So your code is
decoupled
before it is even written.

One of the biggest features of TDD is being able
to run a suite of tests to make sure new features don’t break old
features. Yet I have an eye for this while developing; I either fix the
upcoming problem because I know it’s going to happen, or I’m doing it
wrong in the first place. Sure, I occasionally miss, but who doesn’t? I
find the issue as quickly as I can and resolve it in a clean style.

You should run a TDD test suite after the fewest possible edits: 10 at
the most,
and hopefully just 1. A coding session should go type-type Test,
type-type Test,
type-type Test, in tiny cycles.

If you delay to run the test, the more risk you absorb with your edits.

This helps sustain projects as they get huge; the code stays just as
easy to
work with as a tiny project. Nobody can cross-check everything in a huge
program.

BDD looks like a way to make it easy for non-programmers to do
programming, but not having people keep several functions in mind at any
one time. And it also does TDD? Am I close?

Yes - BDD is TDD with an added layer: A “literate programming” framework
that
forces you to think in clear English* statements that your client could
understand.

*or whatever your client speaks!

That anyone can do TDD with BDD (and they do) speaks volumes about
Ruby’s
ability to support easy and flexible DSLs.

But everyone continually praises TDD and BDD, which leads me to believe
I’m missing something profound that could make me a better programmer.
So what’s the big deal?

The big deals are: Almost no debugging, a super-high velocity, the
ability to
deploy any integration, the ability to rapidly share code with
colleagues, code
that strongly resists new bugs, and the ability to allow your client to
“steer”
your project, feature-by-feature, in real-time.

If your tests fail unexpectedly, the fault must lie in your last edit.
You can
undo or revert it. If your tests gate your Subversion or Gitorious
version
controller, then you know that you can always revert your code to get
rid of a
test failure. Working in tiny cycles, and constantly integrating your
code,
allows you to take bigger steps with more confidence.

Debugging is the greatest time-waster in all programming. Grizzled
senior
programmers (like some of my friends!) can all remember working on
projects with
bugs so big, you could spend the first week just isolating which module
contained the bug. With debugging out of the way, you spend your
remaining time
understanding requirements, implementing them, integrating them, and
deploying
them. Your project goes very fast as your client learns to request very
small
features, each an increment over the existing features. Very few
features go to
waste. And a project with a complete test rig cannot lose its value over
time.
New code is often easier to write than old code, even despite projects
with
thousands of features. This metric is unheard of in software
engineering, where
new features are typically harder to write than the first ones.

If your tests gate your integrations, than you could deploy any
integration. It
might have unfinished features (and you might make their View buttons
invisible!), but the tests will tell you it has no bugs. This metric is
also
unheard-of in classical programming, where a project typically must
endure a
“polish phase”, as much as 25% of development time, to get it “ready to
ship”.

Next, if I need my colleagues to be able to mess with code I wrote (and
vice
versa), then I don’t need them breaking it because they didn’t
understand it
(what are the odds?:). If they run my tests (and they do!), then there’s
a
little bit of me in them, working with them, keeping my features stable
while
they add theirs.

The TDD cycle has three steps: Write a test that fails for the correct
reason,
write simple code that passes the test, and refactor your code to make
it clean
and dry. Notice you don’t refactor until the code passes its test.
Refactoring
means merging the new code with the preexisting code. And you don’t
refactor
until your tests say the new code works. This implies only good code
with valid
features gets merged together. TDD’s influence on design cannot be
understated:
It produces rock-solid code that strongly resists bugs.

Under classic software development, you would ask your client for a long
list of
features, then ask to be left alone for a while! Under TDD, your new
features
can be reviewed as they emerge. Your client has better odds of getting
the
features they want if they practice “just in time requirements”. They
only
require features in small increments from those installed features which
they
like. TDD allows a business cycle as short as a week to add features,
review the
code, and request for features. This improves the odds your client gets
the
features they need - not just some of the features they ask for. Your
client no
longer has the burden of predicting the future and planning every
feature they
might need.

The Ruby on Rails project has copious unit tests; its success is an
example of
these forces at work…

Hi –

On Sat, 16 Aug 2008, Phlip wrote:

Clinton D. Judy wrote:

BDD looks like a way to make it easy for non-programmers to do
programming, but not having people keep several functions in mind at any
one time. And it also does TDD? Am I close?

Yes - BDD is TDD with an added layer: A “literate programming” framework that
forces you to think in clear English* statements that your client could
understand.

I wouldn’t call it literate programming in the Knuthian sense, though.
Knuth says: “The practitioner of literate programming can be regarded
as an essayist, whose main concern is with exposition and excellence
of style.”[1] It’s a different undertaking from writing BDD
specifications (even though of course it’s nice if BDD specifications
are reasonably well-written).

David

[1] http://www.literateprogramming.com/

Hi –

On Sat, 16 Aug 2008, Clinton D. Judy wrote:

BDD looks like a way to make it easy for non-programmers to do
programming, but not having people keep several functions in mind at any
one time. And it also does TDD? Am I close?

I wouldn’t say that it makes it easy for non-programmers to program.
At its best, it can provide output and summaries that non-programmers
can easily read, understand, and amend. But the programming part of
BDD is truly programming.

This is actually at the root of why a lot of people, including me,
find it hard to bond with RSpec. In some respects, the syntax tries to
look and read like English, but it’s still 100% programming and there
are serious impedance mismatches between English and Ruby. But RSpec
generates summaries that are purely in English, and that describe the
program’s requirements in such a way that any stakeholder in the
project, programmer or not, can read them. I would not expect a
non-programmer to be able to read RSpec code.

You should, however, check out RSpec if you’re interested in BDD. It
represents a fantastic achievement (my problems with it are at the
level of my own stylistic preferences), and has a huge following.

But everyone continually praises TDD and BDD, which leads me to believe
I’m missing something profound that could make me a better programmer.
So what’s the big deal?

It scales. If you’re doing something small, you can run it and eyeball
the results and that’s fine (and that is, in fact, a test). Like
everything else in programming, though – calculations, data munging,
administrative tasks – testing your code benefits from being
automated when you have to do more than a miniscule amount of it. It’s
really that simple, and everything else proceeds from that.

David

Hi –

On Sat, 16 Aug 2008, Eleanor McHugh wrote:

could understand.
are only as good as the analysis which goes into them and can very quickly
become redundant when working on greenfield projects with very loose
requirements. They’re also as prone to error as any other code so beyond a
certain level of complexity it’s not entirely obvious that they improve code
quality rather than hindering it.

The essay-writing point, though, isn’t at odds with writing tests;
it’s more about documentation. I agree entirely with your point about
complexity – and also simplicity, as a test like this:

assert_equal(my_method(x), 10)

can pass based on:

def my_method(x)
10
end

even if my_method is really supposed to be doing calculations. It’s
not hard not to do that kind of cheat, of course, but it’s a good
reminder that there’s nothing magical about tests.

David

David A. Black wrote:

Yes - BDD is TDD with an added layer: A “literate programming” framework that
forces you to think in clear English* statements that your client could
understand.

I wouldn’t call it literate programming in the Knuthian sense

A> hence the “scare quotes”, and

B> hence Knuthian literate programming is less than useful for us
mortals.

If Knuth only intended to invent markup languages in his spare time, and
did not
intend to split the difference between developer-facing and
customer-facing
verbiage, then we are beyond literate programming.

Here’s an example of a test case written in programmer-speak:

test_strobe_count_down_fields_in_pre_fight_states

Now reverbiage it:

specify ‘the audience sees an animated countdown before the fight’ do

Figuring out how to say an internal detail in terms a client can
understand is
often brain-wrenching. As developers, our brains are prepped with
developer
terms. The B in BDD stands for “Behavior the client has requested”…

On 16 Aug 2008, at 12:51, David A. Black wrote:

that your client could understand.

I wouldn’t call it literate programming in the Knuthian sense, though.
Knuth says: “The practitioner of literate programming can be regarded
as an essayist, whose main concern is with exposition and excellence
of style.”[1] It’s a different undertaking from writing BDD
specifications (even though of course it’s nice if BDD specifications
are reasonably well-written).

Many programmers believe they’re bad at writing essays, and rather
seeing an opportunity to improve their skills they would rather write
tests. But tests are only as good as the analysis which goes into them
and can very quickly become redundant when working on greenfield
projects with very loose requirements. They’re also as prone to error
as any other code so beyond a certain level of complexity it’s not
entirely obvious that they improve code quality rather than hindering
it.

That said, everyone seems to love them so they must have some value.

Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net

raise ArgumentError unless @reality.responds_to? :reason

On 16 Aug 2008, at 15:33, Phlip wrote:

prepped with developer terms. The B in BDD stands for “Behavior the
client has requested”…

Which of course presupposes there is a clear and direct transformation
between what the client believes they want, what they actually want,
what they should actually get (which is not always the same thing) and
how these can be represented in software given whatever other
arbitrary requirements apply. I’m too much of a cynic (i.e. have
worked on too many complex projects with multiple stake-holders) to be
convinced of this fact, but I definitely wouldn’t discourage anyone
else from giving it a go as different tools work for different people :slight_smile:

Ellie

Eleanor McHugh
Games With Brains
http://slides.games-with-brains.net

raise ArgumentError unless @reality.responds_to? :reason

Eleanor McHugh wrote:

worked on too many complex projects with multiple stake-holders) to be
convinced of this fact, but I definitely wouldn’t discourage anyone
else from giving it a go as different tools work for different people :slight_smile:

That’s why you don’t T- or BDD in a vacuum. Your “goal donor” should
review your
features, and their tests, in tiny little increments, every couple of
days, with
a new release and a new requirements list each week.

The “goal donor” writes a user story saying “if you fail to log in six
times,
put the user’s IP in a killfile for one hour”, then you should have a
spec that
says the same thing. Doing exactly what the client says would be
“malicious
compliance”, if letting them follow up weren’t so easy.

Hi –

On Sat, 16 Aug 2008, Phlip wrote:

B> hence Knuthian literate programming is less than useful for us mortals.
If you want to do what Knuth created it for, it is, or can be, very
useful. As far as I know it has nothing to do with testing.

specify ‘the audience sees an animated countdown before the fight’ do

Figuring out how to say an internal detail in terms a client can understand
is often brain-wrenching. As developers, our brains are prepped with
developer terms. The B in BDD stands for “Behavior the client has
requested”…

My point is simply that “literate programming” is already a known term
that refers to something other than creating clear phrases to describe
tests. I’m not suggesting any kind of fight-to-the-death (or "it
‘fights to the death’ do :slight_smile: between them.

David

On Saturday 16 August 2008 06:51:23 David A. Black wrote:

I wouldn’t call it literate programming in the Knuthian sense, though.

Well, TDD and BDD seem very much against the Knuth style. After all…

“Beware of bugs in the following code. I have only proven it correct,
not
tested it.”

Hi –

On Sun, 17 Aug 2008, David M. wrote:

On Saturday 16 August 2008 06:51:23 David A. Black wrote:

I wouldn’t call it literate programming in the Knuthian sense, though.

Well, TDD and BDD seem very much against the Knuth style. After all…

“Beware of bugs in the following code. I have only proven it correct, not
tested it.”

It was: “Beware of bugs in the above code; I have only proved it
correct, not tried it.” And it was, after all, a warning, not a
best-practices recommendation :slight_smile:

David

On Saturday 16 August 2008 08:54:28 Eleanor McHugh wrote:

But tests are only as good as the analysis which goes into them
and can very quickly become redundant when working on greenfield
projects with very loose requirements.

I would say that such a project is very much in need of some
requirements,
even informal ones.

They’re also as prone to error
as any other code so beyond a certain level of complexity it’s not
entirely obvious that they improve code quality rather than hindering
it.

Well, I don’t really see how they could hinder it…

And you’re right – they are prone to error. But the point of a test is
to
make error noisy – generally, when you have a bug in your test, you’ll
know
about it very quickly.

In fact, TDD suggests that you write the failing test first. That
implies that
your test has to be at least half-right, when written – it has to fail.
It
also implies that by the time a test and its corresponding code has been
accepted, the test has failed on at least one case where there was a
problem
with the code, and succeeded on at least one case where the code is
believed
to be correct.

It’s not infallible, no, but it is much better than nothing.

And as I said in my other post, certainly by the time you get to
integration
testing, either you’re going to be doing it by hand, or you’re going to
have
it automated. Which would you prefer?

That said, everyone seems to love them so they must have some value.

Wrong attitude, and, frankly, Godwinbait.
(Everyone seemed to love the Nazis! Did they have some value?)

Certainly, if everyone loves them, you should take a second look. But if
you
really can’t find any value in them, it might not be you. It might be
that
there really is no value in them.

I think tests are good and useful, but I don’t want you or anyone to be
so
easily led. The truth is what it is, no matter what other people
believe.

On Aug 16, 11:27 am, Eleanor McHugh [email protected]
wrote:

Which of course presupposes there is a clear and direct transformation
between what the client believes they want, what they actually want,
what they should actually get (which is not always the same thing) and
how these can be represented in software given whatever other
arbitrary requirements apply.

The whole “requirements in front” idea is perfectly simple and
logical; also, typically impossible or wrong.
“If I’d asked people what they wanted, they would have asked for a
faster horse.” – attributed to Henry Ford.

Ron