
Giving Up on TDD - mxhold
http://blog.cleancoder.com/uncle-bob/2016/03/19/GivingUpOnTDD.html
======
jblow
For many paragraphs, I thought this was a parody of TDD defense, but then it
turns out it wasn't.

His 'defense' of the point is basically: Look, when you do TDD you have to put
a lot more work into the tests than you thought! It is not just a simple
thing!

Okay, fine, but ... Before embarking on TDD, the programmer had a picture in
his head of what the costs+benefits of this change would be. Now you are
telling him the costs are WAY higher. So a successful defense would have to
then make the case that the benefits are also WAY higher.

But he doesn't. Because the benefits aren't higher, in fact they are lower (as
is the case with every well-intended scheme in the history of anything.)

As usual my advice on this is: look at the people who build things you find
highly impressive, and study how they did it. This is much more fruitful than
reading the output of people who want to spend all day telling you how to
program (which leaves very little time for them to build software that is
impressive, i.e. they never even test their own ideas!)

~~~
c0achmcguirk
> As usual my advice on this is: look at the people who build things you find
> highly impressive, and study how they did it. This is much more fruitful
> than reading the output of people who want to spend all day telling you how
> to program (which leaves very little time for them to build software that is
> impressive, i.e. they never even test their own ideas!)

"Uncle Bob" Martin has built a lot of impressive things. Most notably FitNesse
[1] the service level test framework. He tests his ideas out and is a great
teacher.

I've been doing TDD for years thanks to Uncle Bob, Martin Fowler, and Roy
Osherove (who have all built impressive things) and I've leveled up as a
result. In fact my entire team has leveled up with this simple discipline.

I've yet to meet an anti-TDD zealot who has actually spent a month developing
the art of TDD. The detractors tend to be people who write really brittle
tests that are a pain to maintain.

[1] - [http://FitNesse.org](http://FitNesse.org)

~~~
khushia
I've been using FitNesse heavily at work for the past few years, and I've been
surprised by how buggy we've found it.

We have over 30,000 tests and we've had to rewrite part of it because it
memory-leaked so badly. Unfortunately the company has strict rules against
contributing back to Open Source projects.

~~~
kolanos
Relevant:
[https://www.youtube.com/watch?v=IRTfhkiAqPw](https://www.youtube.com/watch?v=IRTfhkiAqPw)

Specifically the Uncle Bob example of OOP run amok.

------
ryanbrunner
There's definitely some good points here, but I have a huge issue with this
point:

> Something that is hard to test is badly designed.

In my experience, TDD has a natural tendency to favour decoupling at all
costs, and TDD zealots will push de-coupling units as an unqualified positive.
And if your metric is "good design = easily testable and low coupling" it
certainly looks that way.

This mindset fails to take into consideration the fact that tightly coupled
things are often simpler to understand and reason about. They're more closed
to extension, sure, and harder to test in isolation, but a straightforward
process that acts like a "black box" and performs a job simply in a few lines
of code is often better than the class explosion that rigid TDD often
encourages. And what's the value of keeping things open to extension if the
only thing that is going to reasonably extend them are tests?

A good illustration made by DHH as part of one of his anti-TDD tirades is
here:
[https://gist.github.com/dhh/4849a20d2ba89b34b201](https://gist.github.com/dhh/4849a20d2ba89b34b201)

Anyone who can honestly say the latter example has a better design has a very
different opinion on "good design" than I do.

~~~
ktRolster
His point, as phrased, is correct though, _something that is hard to test is
badly designed._ You need to be able to test your software in some way or
another. Even if you've proven its correctness, you still want to put it
through some basic sanity tests (as Donald Knuth pointed out).

~~~
sago
Yes, but it misses the point of the criticism.

The issue isn't whether the final product is difficult to test. It should be
roughly as easy to test the final product no matter the implementation
strategy.

The problem is that TDD requires a royal-road of testing. No code can be
written without tests for that specific piece of code. So you can only build
the whole out of components that are testable in isolation. The claim is that
this excludes architectures that don't provide such a step-by-step path of
testing.

This interacts badly with the 'make everything an API' idea. You end up with
these functionally small units with over-engineered APIs rather than something
more complex, more efficient, and easier to refactor as a whole.

------
EdSharkey
Forcing yourself to not write a line of production code without having a test
in place to test it first produces a very high level of coverage over all your
control paths. You wind up with the tests being an ad hoc specification for
the production code. Not really a design as much as documenting the code.

This is a really irksome way for me to work, and I find that level of
diligence difficult to muster. Often I will find myself writing the production
code first and writing tests to cover after the fact. My coverage is probably
not as high as it is when I TDD the code.

The cadence of TDD'd projects I've worked on professionally is painfully slow
and predictable. If you're at a workplace that is giving you the time and
resources to do it, then you're likely also pairing, which helps impatient
souls like me stick to the program. My team has been blessed to have a devops
guy who has a scientific mind and acts as informal agile coach while pairing -
and he's probably the reason we do a good job on the TDD because he makes us
all better at it.

If you're at a workplace that is encouraging TDD and pairing, you should be
thankful and honestly try to do a great job at it. Your work weeks will be
relaxed and you probably won't need to work much overtime. I wind up with lots
of left over energy to burn on my home projects, which I appreciate.

~~~
davidjnelson
Jobs like that are indeed amazing. Anyone have an effective strategy for
evaluating if a job is like that while interviewing? Or perhaps a list of
companies that operate this way? I'll start the list with Autodesk, although
all projects and teams are different of course.

------
barrkel
This is an argument against a straw man, IMO; people who have a problem with
TDD don't (or shouldn't) have a problem with testing, or creating a design
that is testable.

What TDD is specifically poor at is design. Test Driven Design literally means
your tests drive the design of the system, rather than any other
consideration, like reducing API scope, reducing complexity, reducing
configurability (yes, excess configurability is a bad thing, and TDD tends to
encourage it). TDD in particular won't drive insightful designs, because
insight is a product of a fertile and well stocked mind meeting a problem
domain - it does not emerge organically out of tests.

------
robert_tweed
Title is slightly misleading, so for anyone reading the comments first, this
is Uncle Bob's rebuttal of yesterday's "Giving up on test-first development",
in the form of a Q&A.

Original discussion here:
[https://news.ycombinator.com/item?id=11310711](https://news.ycombinator.com/item?id=11310711)

------
legulere
> but he said he was just using it for some home projects

I think here lies the biggest problem. For small/hackish projects you barely
get any benefits from test driven development but still have the higher costs.
Test-driven development means that you will spend more effort while
developing, but will have to spend less on maintaining in the long run.

The fun part about home projects is that you don't really have to think about
maintenance at all and you can just hack things away until they work for you.

PS: you should write out acronyms once in the beginning of an article

~~~
EdSharkey
My home projects become tragic when they get past the trival size and I
haven't been TDD'ing and designing all the way through.

I think part of my problem is that I cannot devote a consistent level of
effort every week to my current home project. Sometimes I'll leave and when I
come back to it, I'm lost without a test suite and wind up rewriting huge
swaths of it.

Really good tests also serve as up-to-date documentation of your design. If
you code in Java or Groovy, check out the Spock Framework. Spock tests read
like a story. I wish there was a Spock-like DSL for JavaScript development.

~~~
vorg
Spock hacks into Groovy's AST to make labelled expressions have special
meanings:

    
    
      def "adder-test"() {
        given: "a new Adder class is created"
        def adder = new Adder();
    
        expect: "Adding two numbers to return the sum"
        adder.add(3, 4) == 7
      }
    

It could all easily break if the Groovy parser or AST is updated. And very
clunky, which says something about Groovy's design post v 1.5.

------
overgard
Regardless of if TDD works, we see this argument pattern all the time, some
magical claim for effectiveness is asserted via a methodology (always
anecdotally), someone says "didn't work for me" and the response is ALWAYS
"well you didn't do it long enough to get it!"

It's all just noise. Theres nothing wrong with having your pet theory, I just
wish entire industries wouldn't carelessly hop on board every time some
consultant comes up with an acronym and some promises.

------
jdking
For a new project I like to start by writing code that sketches out ideas of
how the software should hang together.

TDD at this point is kind of wasteful because if you decide to backtrack or
rework aspects of the design then you have to also rework all of the tests. I
find that once the design begins to crystalize, adding unit tests at this
point is valuable, but not necessarily in a 'test-driven' way.

TDD by itself, per se will not automatically produce a good design, and can
often produce bad designs with huge proliferation of classes / interfaces that
makes a codebase more complex and difficult to understand.

TDD is not the be all and end all that some commentators seem to believe.

------
sago
To me, TDD means:

1\. No functionality is coded without a failing test.

2\. Only code the minimum functionality to make the test pass.

It does not mean 'test more' or 'write tests'.

So I'm not sure more than 10% of this 'defence' bolsters the method at all.
Seems like the normal rhetorical bait and switch - you pretend that your
opponent is criticising testing and respond by defending some more or less
vague notion of tests, with no substantive defence of TDD beyond "you didn't
try hard enough." The example of the pacemaker, for example, has no relevance
to TDD whatsoever.

~~~
davidjnelson
Don't forget 3. Easily and safely refactor both your production and test code.

------
100k
I found it strange that Martin suggests that the gaps in TDD-style tests with
regard to dealing with bad input should be filled by integration tests, which
due to their complexity seem more likely to cover the happy path, rather than
fuzz testing or quickcheck
([https://en.wikipedia.org/wiki/QuickCheck](https://en.wikipedia.org/wiki/QuickCheck))
style tests.

~~~
davidjnelson
Right, those two tools seem like a natural fit for bad data input testing, and
do seem to make more sense at the unit level.

------
vmorgulis
An interesting and simple way to overcome the testing interface design problem
with "tracing tests":

[http://akkartik.name/post/tracing-tests](http://akkartik.name/post/tracing-
tests)

------
facepalm
And communism would work if only people would do it properly. It seems to me
that kind of argument could be made about anything. "It only didn't work
because you didn't do it properly".

Doesn't it work for Homeopathy, too? "It would have worked if you hadn't
passed it through the x-ray scanner at the airport" or "it would have worked
if you had taken the medicine while doing a handstand".

In the end doing it right becomes so complicated that you need to hire an
expert to do it for you. Wonder if that was the point all along - basically
marketing.

~~~
Ace17
Some disciplines are hard to do properly, and easy to do wrong. It's a mistake
to dismiss them just because the return on investment isn't immediate. We're
mostly programmers here, we're not supposed to be afraid of steep learning
curves!

~~~
facepalm
Sure, although my heuristic for trying new Software methodology tends to be
"does it make things simpler?". That article made my head hurt...

------
sargas
Moral of the story. Choose simple design, and test your code. Am I missing
something?

Btw, this website is great! I really enjoy the writing approach.

------
projectileboy
TDD is just a tool, not a religion. If the tool works for you, use it. If not,
don't. I would encourage people to give it an honest try and see if they find
it valuable.

------
me_again
Q: Are you sick of the Socratic method?

A: Oh God yes.

Q: What's wrong with it?

A: It's overly verbose, condescending, and allows you to give the appearance
of resolving a debate when all you've actually done is talk down to a sock
puppet.

~~~
greenyoda
_" It's overly verbose, condescending, and allows you to give the appearance
of resolving a debate when all you've actually done is talk down to a sock
puppet."_

I agree with your criticism of the article's style. But to be fair, if you're
arguing with yourself (as the author is), it's not really the Socratic Method,
which is a dialog with another person. If you don't get to control what
questions the other person asks, it makes for much a more interesting
conversation.

~~~
me_again
Agreed- if there are 2 real people debating, it's much more bearable.
Ironically some of the canonical Socratic dialogs
([http://www.gutenberg.org/files/1643/1643-h/1643-h.htm](http://www.gutenberg.org/files/1643/1643-h/1643-h.htm))
have the same problem - Meno's slave is too obviously Plato's mouthpiece IMHO.

------
inaprovaline
Every single time a developer releases a piece of code not covered by tests,
he/she is basically taking a bet, hoping that things will work. And very often
that is simply not the case.

Releasing not tested code is simply unprofessional and wrong in so many
different ways.

I honestly don't see any valid argument to not write tests.

~~~
jqm
Agreed, but writing tests isn't necessarily the same as TDD.

------
exabrial
Tdd is actual engineering: requirements first, set expectations, plan,
estimate, build. Silicon Valley (generalization) has extreme shortsghtedness
when it comes to building software, there are a lot of prima donnas, hipsters
using whatever is cool,tech decisions made on opinion rather than measurement,
and NIH.

Have a spine and push for tdd. The prima donnas will attack you ad hominum and
call you slow. But it feels pretty damned good to be right.

~~~
usrusr
That's why conservative engineering traditions mandate that whenever one sets
out to design a bridge, the very first thing to do is to build a really heavy
car.

~~~
overgard
You also want to make sure your heavy car falls off the leading edge of the
bridge before you raise the support structure for that part. So you're sure
you're not building unnecessary bridge parts.

