Echoes from the Stone Age
Posted by Uncle Bob on 10/06/2009
The echoes from Joel Spolsky’s Duct Tape blog continue to bounce off the blogosphere and twitterverse. Tim Bray and Peter Seibel have both written responses to Joel, me, and each other.
Here are some stray thoughts…
TDD
Anyone who continues to think that TDD slows you down is living in the stone age. Sorry, that’s just the truth. TDD does not slow you down, it speeds you up.
Look, TDD is not my religion, it is one of my disciplines. It’s like dual entry bookkeeping for accountants, or sterile procedure for surgeons. Professionals adopt such disciplines because they understand the theory behind them, and have directly experienced the benefits of using them.
I have experienced the tremendous benefit that TDD has had in my work, and I have observed it in others. I have seen and experienced the way that TDD helps programmers conceive their designs. I have seen and experienced the way it documents their decisions. I have seen and experienced the decouplings imposed by the tests, and I have seen and experienced the fearlessness with which TDDers can change and clean their code.
To be fair, I don’t think TDD is always appropriate. There are situations when I break the discipline and write code before tests. I’ll write about these situations in another blog. However, these situations are few and far between. In general, for me and many others, TDD is a way to go fast, well, and sure.
The upshot of all this is simple. TDD is a professional discipline. TDD works. TDD makes you faster. TDD is not going away. And anyone who has not really tried it, and yet claims that it would slow them down, is simply being willfully ignorant. I don’t care if your name is Don Knuth, Jamie Zawinski, Peter Seibel, or Peter Pan. Give it a real try, and then you have the right to comment.
Let me put this another way. And now I’m talking directly to those who make the claim that TDD would slow them down. Are you really such a good programmer that you don’t need to thoroughly check your work? Can you conceive of a better way to check your work than to express your intent in terms of an executable test? And can you think of a better way to ensure that you can write that test other than to write it first?
If you can, then I want to hear all about it. but I don’t want to hear that you write a few unit tests after the fact. I don’t want to hear that you manually check your code. I don’t want to hear that you do design and therefore don’t need to write tests. Those are all stone-age concepts. I know. I’ve been there.
So there. <grin>
The Design Pattern Religion
Tim Bray said:
My experience suggests that there are few surer ways to doom a big software project than via the Design Patterns religion.
He’s right of course. The Design Patterns religion is a foul bird that ravages teams and cuts down young projects in their prime. But let’s be clear about what that religion is. The Design Patterns religion is the ardent belief that the use of design patterns is good.
Here’s a clue. Design Patterns aren’t good. They also aren’t bad. They just are. Given a particular software design situation, there may be a pattern that fits and is beneficial. There may also be patterns that would be detrimental. It’s quite possible that none of the currently documented patterns are appropriate and that you should close the book and just solve the problem.
Here’s another clue. You don’t use patterns. You don’t apply patterns. Patterns just are. If a particular pattern is appropriate to solve a given problem, then it will be obvious. Indeed it is often so obvious that you don’t realize that the pattern is in place until you are done. You look back at your code and realize: “Oh, that’s a Decorator!”.
So am I saying that Design Patterns are useless?
NO! I want you to read the patterns books. I want you to know those patterns inside and out. If I point at you and say “Visitor” I want you at the board drawing all the different variants of the pattern without hesitation. I want you to get all the names and roles right. I want you to know patterns.
But I don’t want you to use patterns. I don’t want you to believe in patterns. I don’t want you to make patterns into a religion. Rather I want you to be able to recognize them when they appear, and to regularize them in your code so that others can recognize them too.
Design Patterns have a huge benefit. They have names. If you are reading code, and you see the word “Composite”, and if the author took care to regularize the code to the accepted names and roles of the “Composite” pattern, then you will know what that part of the code is doing instantly. And that is powerful!
Minimizing Concurrency.
In my first Duct Tape blog I made the statement:
I found myself annoyed at Joel’s notion that most programmers aren’t smart enough to use templates, design patterns, multi-threading, COM, etc. I don’t think that’s the case. I think that any programmer that’s not smart enough to use tools like that is probably not smart enough to be a programmer period.
Tim responds with:
...multi-threading is part of the problem, not part of the solution; that essentially no application programmer understands threads well enough to avoid deadlocks and races and horrible non-repeatable bugs. And that COM was one of the most colossal piles of crap my profession ever foisted on itself.
Is concurrency really part of the problem? Yes! Concurrency is a really big part of the problem. Indeed, the first rule of concurrency is: DON’T. The second rule is: REALLY, DON’T.
The problem is that some times you have no choice. And in those situations, where you absolutely must use concurrency, you should know it inside and out!
I completely and utterly reject the notion that ignorance is the best defense. I reject that lack of skill can ever be an advantage. So I want you to know concurrency. I want to shout “Dining Philosophers” and have you run to the board without hesitation and show me all the different solutions. If I holler “Deadlock”, I want you to quickly identify the causes and solutions.
Here’s a clue. If you want to avoid using something, know that something cold.
Sudoku
At the end of his blog, Peter jumps on the pile of bodies already crushing Ron Jeffries regarding the Sudoku problem from July of 2006.
I find the pile-up disturbing. Ron had the courage to fail in public. Indeed he announced up front that he might “crash and burn”. And yet he got lambasted for it by people who hid behind someone else’s work. The responses to Ron’s tutorial blogs were completely unfair because the authors of those blogs had everything worked out for them by Dr. Peter Norvig before they published their screeds. They were comparing apples to oranges because their responses were about the solution whereas Ron’s blogs were about the process.
Which one of us has not gone down a rat-hole when hunting for a solution to a complex problem? Let that person write the first blog. Everyone else ought to be a bit more humble.
Do the people on the pile think that Ron is unable to solve the Sudoku problem? (Some have said as much.) Then they don’t know Ron very well. Ron could code them all under the table with one hand tied behind his back.
Personal issues aside, I find the discussion fascinating in it’s own right. Ron had attempted to solve the Sudoku problem by gaining insight into that problem through the process of coding intermediate solutions. This is a common enough TDD approach. Indeed, the Bowling Game and the Prime Factors Kata are both examples where this approach can work reasonably well.
This approach follows the advice of no less than Grady Booch who (quoting Heinlein) said: “when faced with a problem you do not understand, do any part of it you do understand, then look at it again.“
Ron was attempting to use TDD to probe into the problem to see if he could gain any insight. This technique often bears fruit. Sometimes it does not.
Here is a classic example. Imagine you were going to write a sort algorithm test first:
Test 1: Sort an empty array. Solution: Return the input array.
Test 2: Sort an array with one element. Solution: Return the input array.
Test 3: Sort an array with two elements. Solution: Compare the two elements and swap if out of order. Return the result.
Test 4: Sort an array with three elements. Solution: Compare the first two and swap if out of order. Compare the second two and swap if out of order. Compare the first two again and swap if out of order. Return the result.
Test 5: Sort an array with four elements. Solution: Put the compare and swap operations into a nested loop. Return the result.
The end result is a bubble sort. The algorithm virtually self assembles. If you had never heard of a bubble sort before, this simple set of tests would have driven you to implement it naturally.
Problems like Bowling, Prime Factors, and Bubble Sort hold out the interesting promise that TDD may be a way to derive algorithmms from first principles!
On the other hand, what set of tests would drive you to implement a QuickSort? There are none that I know of. QuickSort and Sudoku may require a serious amount of introspection and concentrated thought before the solution is apparent. They may belong to a class of algorithms that do not self-assemble like Bowling, Prime Factors, and Bubble Sort.
This blog by Kurt Christensen provides all the links to the various Sudoku articles, and sums it up this way.
TDD may not be the best tool for inventing new algorithms, it may very well be the best tool for applying those algorithms to the problem at hand.
Actually I think TDD is a good way to find out if an algorithm will self-assemble or not. It usually doesn’t take a lot of time to figure out which it’s going to be.
Comments
Kjetil T. 32 minutes later:
So TDD causes programmers to implement Bubble Sort instead of Quicksort, and this is good thing? With methodologies like these, no wonder so much of today’s software is bloated and slow.
GBGames 37 minutes later:
I have no problem with thinking that TDD is faster in the long run, but what about in the short run? When you are starting out and have an entire code base that is legacy code? In the short run it feels slower, even if the work I am doing sets me up for faster coding agility in the future. When it comes to claiming that it is faster, “it just is” isn’t convincing anyone who isn’t already convinced. Is it possible that the project timeline is ever too short to gain the speed benefits of test-first design?
Peter Siebel’s article has a number of examples of people who aren’t convinced that it is always faster, and intuitively writing tests feels like writing code that no customer cares about and so slows you down. Perhaps the speed improvement argument isn’t well described? I’m looking up “fast” on this blog, and I found this:
* Indeed, as the application increases in complexity, the test code grows at a rate that is faster than the production code. Sometimes the production code actually shrinks as the test code grows because the programmers moved a load of functionality out of the code and into the data.
And there’s this quote from your talks and this post:http://blog.objectmentor.com/articles/2009/05/11/why-the-sea-is-boiling-hot
The only way to go fast, is to go well.
and
Once we, as professional developers, realize that the only way to go fast is to create clean and well designed code, then we will see the business’ need for speed as a demand for high quality code. *
Maybe there should be a greater emphasis on how slow the non-TDD engineers are without realizing it. They may think they are moving quickly, but spinning wheels working in a morass of ugly, dirty, hard-to-maintain code is slowing them down.
But there’s still that perception that TDD is slowing you down, especially when you are starting, and especially when you’re learning. How do you convince someone that they are moving faster when TDD feels like they have to stop doing what they have been doing for years (and feel that it is quicker to “just do it”) to do TDD?
Get someone over that hump, and the speed benefits of TDD will probably be much more apparent.
ATechieThought about 1 hour later:
I think the problem is most of avg. programmer wants to set the rules within the system;for them world is black or white.
Each technique and practice is double edged sword. It can save your life or kill you. so is the case, with TDD/Desgin patterns or any other notion of knowledge. With sword extremists faught wars and wise keeps peace.We want to be wise rather than extremist.
Second observation of mine is life is balancing act. Every problem and solution has its own context.We need to observe the context and wisely apply the solution fitting in the same (e.g. Sugar is good but it can be fatal for diabatic).
fogus about 1 hour later:
@Kjetil
No. TDD allows programmers to implement bubble sort first, testing against it’s interface completely. It then allows them to go back later and implement quick-sort and be extremely confident that they didn’t break the system by doing so.
Kjetil T. about 1 hour later:
What is gained by iteratively developing a Bubble Sort algorithm, when you have to replace it with a performant Quicksort anyway? Seems like a horrible waste of time, since by Uncle Bob’s own admission, Quicksort can not easily be implemented by applying TDD principles.
neil mosafi about 1 hour later:
I think the point is that once you’d written the tests for the simple algorithm (bubble sort) and you decided it was too slow, you could then try out any other algorithm (quick sort, kjetil sort, or whatever) and your tests would still be valid and would actually help you code the new algorithm much quicker
scott about 1 hour later:
@Kjetil
don’t do the geek thing and focus on one detail, missing the broader point.
razornl about 2 hours later:
TDD is one of the many ‘common practices’ available (I should really say required) for programmers. Patterns are another, and knowledge of common sorting (and other) algorithms is another.
As in every professional field, it’s the combined application of these well known tools and practices that makes a good practitioner.
A programmer who has diligently applied TDD as in the example above, to arrive at bubble sort is not ready. He or she is missing knowledge of algorithms. Quicksort (or better, I’m lacking here myself probably) should have been the answer here, for every single programmer (implemented TDD wise to make sure it is done properly).
Remember that the book is called ‘learning to program in 20 years’. There is a lot of this stuff and not all of it is part of the standard educational package for programmers.
Imagine a medical school that did not include hygiene in the basic drilling of their students. As if duct-tape surgeons were ok because they get the patient out the door quickly on both legs.
This is alas the current state of affairs in software land.
So keep pushing TDD until it’s unquestioned. And patterns and all the other stuff.
Angry Man about 2 hours later:
Uncleanbob, you’re not an idiot, so why do you write idiotic things? Why do your clean code fanaticism only apply to Java and not functional languages? Is it because of elitisim? Is clean code something for the unwashed java masses? Those who are turned away at the ivory tower gates?
What on earth drives you to believe that test driven development conjures up algorithms from the nothingness? Are you really so blind to the suppositions you freely insert?
The fact that you actually need to know something about factoring numbers before you get anything other than an if-else explosion from your prime factors-”kata” unless you actually know something about the end result and what you are trying to achieve? Indeed, you cannot even write a meaningful test without knowing something about what should happen with the input parameters!
Why muck about with toy examples creating primitive sorting algorithms no one in their right mind would use? Step 5 in your example is only natural to someone who actually know how to sort elements. Stop pretending it’s not. The proof? How do you know you are done at step 5? Because you know you are writing a sorting algorithm, and you know what it looks like. You know there is not a 6th test that will break the last algorithm exactly because you have all the prerequisite knowledge. Then why not stop pretending and just write the damn thing!
I use test driven development daily. Mainly because I find it useful to define usage of a class first, before I implement it. The tests are there to make sure things are still working as the system evolves. They are examples of approved behavior, the are not a specification for implementation. That would never result in anything other than a bunch of if-tests returning whatever passes the test code. Why do you pretend that it would?
EricSchaefer about 2 hours later:
Kjetil: The interface and behaviour of quicksort and bubblesort are equal. You can test drive bubble sort and replace is later by quicksort and still have the result thoroughly tested! Using quicksort right away would be premature optimization anyways…
Ben Rady about 2 hours later:
TDD slows you down if your goal is to be “done coding”. If your definition of done amounts to “It compiles, and nobody can prove that it doesn’t work” then writing a bunch of tests to prove whether or not it works makes your job harder, not easier. Sadly, in many organizations this is what “done” means, and so good developers wind up fighting against their environment, while the bad ones are encouraged to do more of the same.
If, on the other hand, your goal is to deliver a working system, then TDD makes you go faster. This is the only useful definition of “done” anyway, because that’s where you start making money.
Paul about 2 hours later:
I haven’t given TDD a fair shake, because it doesn’t seem accessible to me at all. I would like some feedback on how to overcome some of the inherent technical couplings that occur on every project I participate in.
I feel that I’m not blessed with the ability to do green field development at all. I have it in my head that if I were creating a new web application from scratch, or a new service, something simple, TDD would work easily.
As a consultant in the Microsoft space, every application I create is coupled with other technologies that can’t be uncoupled easily – SharePoint, SQL Server Reporting Services, CRM/xRM…
For example, how would one test a SharePoint Web Part that calls into the SharePoint API for rendering HTML? Or an application that generates a SQL Server report on a timer? I do very much feel like I’d be spinning my wheels pretending these other technologies are there for the purpose of testing.
I can wrap my head around testing basic library code. Does my service timer work in a variety of scenarios? Does the database layer return the right data?
But how do I translate this with complex requirements?
len smith about 2 hours later:
Awesome post. I think there’s a reality show in here with Uncle Bob screaming at developers and them sprinting to the the whiteboard to draw a design before being eliminated.
Cedric about 2 hours later:
“Are you really such a good programmer that you don’t need to thoroughly check your work?”
No, I write tests. I just write them last most of the time.
“Can you conceive of a better way to check your work than to express your intent in terms of an executable test?”
No, tests are the best way to check your work, but these tests don’t have to be written first to be effective.
“And can you think of a better way to ensure that you can write that test other than to write it first?”
I don’t see how writing them first makes my code better.
These three points just make a case about the importance of testing, and we are in agreement about that. But you’re not making a very convincing argument as to why writing these tests first is so important, and in my experience, doing so often slows you down since it encourages code churn (you spend a lot of time testing code that you will be replacing, see the Ron Jefferies example) and promotes micro design over macro design.
It’s also been my experience that TDD works great for easy problems such as bowling games or stacks but it scales very poorly in the real world or for problems where the input and output are very clearly defined. Good luck applying TDD for GUI’s or mobile devices. This is why TDD is not becoming mainstream, because people try it at their work and then realize it just doesn’t work.
noone@none.org about 2 hours later:
“Sorry, that’s just the truth”
Sure, your saying so makes it so.
“TDD is not my religion, it is one of my disciplines.”
It is your religious discipline. Like some cultist dancing around the fire baying at the moon exactly at midnight every single day. He is disciplined, sure. That doesn’t make his rituals effective.
“Then they don’t know Ron very well. Ron could code them all under the table with one hand tied behind his back.”
heh heh! Sure! We can see that from how he thrashes around for days on a simple problem. “Sudoku” was followed by “Shotgun blasts” (again incomplete), then “falling off rails” (because he couldn’t fix a deployment issue) and so on….and on …and on. Just read the man’s blog archives to see how he “codes everybody under the table” And now he is being some kind of Scrum Trainer, telling others how to do what he can’t do, and writing bad fictional accounts of “agile” success.
But then who cares about what actual code reveals? Your saying so makes Mr Jeffries a super coder. More “religious discipline” I am sure.
If any of you TDD fanatics think you are so much better than others at programming, show us code you wrote that is better than all the “stone age” programmers like Zawinski and Norvig and Knuth wrote or shipped. Go on, should be easy right?
Show us the brilliant code or products you shipped. THEN call other programmers “stone age” primitives. Right now you are “all hat and no cattle”.
As it is you sound like a lunatic insisting that his schizophrenic visions he sees are real and that people who don’t see the bugs on the walls are somehow deluded!
You call Peter Norvig and Don Knuth “Stone Age” programmers!
God, the arrogance.
Michael about 2 hours later:
As a commenter elsewhere put it, the “duct tape” types apparently really believe those of us who apply TDD were born with it and have yet to be shown the light of giving it up. It took me years of denying, then trying, then seeing both the quality and velocity of my work improve. shrug
Thing is, TDD is no guarantee of success. It merely improves the odds. That’s not sensationalist enough, so neither side focuses on that critical piece.
I can also accept that some people’s brains aren’t wired for TDD, and they do better work without. Some of these people have a far better ability to hold the whole system, quirks and all, in their brain at one time than I. If that’s how they create value, so be it.
I’d rather spend time getting things done than advocating for how I do them anyway. Within my teams, I lead by example. Or, as with TDD, sometimes I follow by example. :)
Again, shrug
Bastian Schenke about 2 hours later:
Not every problem you solve is researched like sorting algorithms. If it were all of us were unemployed. Not every part of a system is that mission-critical you need it to be perfect. If a feature is run once a day i give a shit on performance. If i figure out later that it is run a thousand times i will start all over and make it perfomant… without breaking the rest of the system.
Its not about perfect, super-performant software, its about shipping a product that works (even with bubblesort) and will still be working after a couple of changes and performance-tunings.
TDD is not a process that guarantees you a working system out of the box. You still have to about how to solve a problem.
Uncle Bob about 3 hours later:
noone@none.org about 2 hours later:
Good choice of name!
bq. You call Peter Norvig and Don Knuth “Stone Age” programmers!
God, the arrogance.
Actually, if you read carefully, you’ll see that I did not call either of them any names at all (other than to use Dr. Norvig’s proper salutation. Indeed, Dr. Norvig did not appear in the section about “Stone Age” that you refer to.
Dr. Knuth, and a few other’s did appear, but only because words were put in their mouths by another author; and I was refuting that author.
Peter about 4 hours later:
To me, automated tests are the only way to confidently improve existing code in a non-trivial system. The only economical alternative is write-once, test-once, debug-once, fix-once, deploy-once and then keep the code base the same as long as freaking possible. And in a world of constant streams of bug reports, change requests, system upgrades and what-not, the latter alternative is usually not very fast at all…
eejit about 5 hours later:
I devour this blog, but I struggle – how can I use TDD in my windows kernel driver development? Please share experience.
Kyle Szklenski about 5 hours later:
Sigh. The fundamental problem with people who are anti-TDD is that they seem to not understand that test-first is about the DESIGN of the class interfaces you’re using, not about the “proving your code works.” Proving your code works is just a nice side benefit, but I would argue that TDD doesn’t really satisfy that requirement completely, either. You need to go to functional/integration tests, then UAT to get to a point where you can be comfortable that the code “works”. Maybe I’m wrong about that, and certainly someone will correct me.
If you start writing your system and have no clue what your classes should look like and where your important abstractions need to be, then why not write a test that can tell you what functions/abstractions it probably needs, or makes sense to have?
I don’t see what the big deal is. I use TDD to tell me the technical specs for my class/interface design, and it has NEVER failed to simplify my systems. What is there to dislike about it?
Johannes about 7 hours later:
For those who don’t see TDD as making development faster: You’re not giving TDD a real try unless your current test run in less than 0.5 seconds (seriously).
Using TDD in “real world” situations, like driver development, systems with lots of interconnections etc. is harder, at least in the beginning. Trying out TDD on a toy problem is a good idea to understand the discipline. Then applying it in harder situations, or at least in subproblems in harder situations is not so hard.
Filipe about 7 hours later:
“Actually I think TDD is a good way to find out if an algorithm will self-assemble or not.”
And why is this important? The whole “self-assembling” code thing sounds rather religious to me. And it’s the reason Jeffries failed to finish his Sudoku solver. Testing is no substitute for thinking about the problem at hand.
James about 10 hours later:
“They were comparing apples to oranges because their responses were about the solution whereas Ron’s blogs were about the process.”
So what’s more important to the client, the process or the solution? At the end of the day, if all you are doing is gluing APIs to create your bloated CRUD app that has been done over and over and over again in different ways, then you might get away with TDD being a good approach.
However, if you are planning to do any serious problem solving that require a little deep thought process, jumping in and writing tests first is a complete stupid idea. It’s a lazy, hacking, and procrastinating idea. I guess in the age of instant gratification, TDD do strike a chord.
The sad thing with this blog post is that it doesn’t provide evidence to back it up, only childish name calling. In addition, I find it fascinating that you are commending an obvious failure, making excuses and yet fail to even notice Norvig’s success.
> Which one of us has not gone down a rat-hole when hunting for a solution to a complex problem? Let that person write the first blog.
Peter Norvig? He didn’t fail as well.
> Everyone else ought to be a bit more humble. Irony much?
Peter Seibel about 11 hours later:
Hey Uncle Bob, I’m not sure I like the implication in one of your comments above that I put words in anyone’s mouth. And as long as we’re being polite, it should probably be Professor Knuth; professors outrank mere PhDs.
-Peter
Uncle Bob about 12 hours later:
Peter,
Apologies. You are right, I overstated the issue. You didn’t actually put words in their mouths.
Bob.
Fredrik Bertilsson about 13 hours later:
If someone claims that a method (like TDD) saves time or improves quality, compared to some other method, I think that he has to provide some evidence supporting that claim. My question is: Do you have any references to studies made showing that TDD saves time or improves quality?
Monis Iqbal about 13 hours later:
Duct tape programming and TDD programming are two extremes. Neither is a winner and neither proves to be the silver bullet for their respective problems.
I think that as a programmer you need to learn all those tools/concepts that you mentioned in your post (design patterns, concurrency, algorithms) but everyone cannot be an expert and evolution is the process to go. Evolve with all these concepts, with TDD, with duct taping…
btw. @unclebob I think this post of yours was just an anger expression (and not only an answer to Joel), meant to provoke arguments. Joel’s post was also provoking but I don’t think it was intentional.
triple-dot about 17 hours later:
Where is the TDD equivalent of Netscape, Google Search, Fogbugz, Doom, World of Warcraft, Linux, Photoshop? Hmm?
Alexis about 17 hours later:
When I read all those blog entries, it seems that this one is just a way to put oil on the fire just because there was no clean winner when this debate was began.
Just a childish game to see who has the biggest toy? Well, it seems like the usual to me, when we’re talking about a consultant’s world…
noone@none.org about 17 hours later:
“Where is the TDD equivalent of Netscape, Google Search, Fogbugz, Doom, World of Warcraft, Linux, Photoshop? Hmm?”
but …but .. you mean the Chrysler Payroll project isn’t equivalent to these silly operating system kernels and games written by Stone Age programmers? ;-)
What does it matter that the team was kicked out and the project shut down? It still validates “cutting edge” programming practices like TDD. We TDD folks are very modern folks let me tell you . No “Stone Age” programming here, No Sir.
So there. Silly Fellow asking foolish questions.
Angry Man about 17 hours later:
I got no beef with TDD. At least not the flavor of TDD I was taught and gotten used to. Writing tests to define usage of interfaces is a good idea. Using tests to get rapid compile->test iterations, instead of build->deploy->test is a good idea, and certainly makes me faster. Having tests to provide safety when refactoring is also very useful.
However, trying to use fanatic TDD to convince yourself you are growing algorithms like bacteria in a petri dish, evolving them by providing evolutionary constraint in the form of test cases, that’s just crazy!
Ron Jeffries failed not because he is a bad programmer. He failed because he used an idiotic approach. You agree that extreme TDD is sometimes fruitless. In fact there are no fruits. It’s more like an easter egg hunt where you bring the eggs. Ron didn’t know how to write a sudoku solver (he brought no eggs). No one should be surprised that no eggs were found.
How do you expect TDD to coax out an algorithm for any non-trivial problem without tests for subsets of the problem that require knowledge about the resulting algorithm itself? You still have to think, then code. Either think as you write the test, or think as you write the algorithm. In the end it hardly matters, except that writing tests for absolutely everything is most likely a waste of time.
Uncle Sam about 21 hours later:
This blog sounds like a catholic priest teaching teenagers about sex.
The author is bragging about how something should be done without ever doing anything substantial and non-trivial himself.
Uncle Bob, when you write something like Tex, Vim or Linux or Samba or even a sudoku solver, you can have some substance to criticise Knuth or Zawinski methods of programming.
“Those who can do, those who can’t teach”
KevDog about 22 hours later:
@razornl
Really, quicksort should have been the answer to begin with? How big is the input? For small values of N, quicksort takes longer than bubble sort. In fact, many sorting algorithms switch to bubble sort when then partitions get below a certain value. Besides, you missed the larger point of
@Cedric TDD is becoming mainstream, you’re just not paying attention. Also, there is a vast difference between “trying” and “mastering”. And the comment that it doesn’t work where input and output are clearly defined, quite frankly, makes little sense. Having the I/O clearly defined makes the TDD process a breeze as you have concrete data to test against.
Honestly, you’re not going to change your mind, so I’m not really sure why I am bothering, but your dogmatic denial of the benefits of a practice betray a close-mindedness. Whenever someone says “In my experience, you’re wrong”, it means they have decided not to listen to data and are determined not to learn.
KevDog about 22 hours later:
My bad, didn’t finish a sentence. Should read “missed the larger point of there are algorithms that cannot be arrived at through this process”. And frankly, most programming doesn’t involve the creation of new algorithms.
Kyle Szklenski 1 day later:
Oh, another thing on the concurrency aspect. I came up with a good phrase for it:
Multi-threading is the first resort of the over-architect.
“Uncle” Sam – you said just about the stupidest thing I’ve ever heard. Sorry for the non sequitur here Uncle Bob – it’s just stuff like that that really pisses me off.
Rick T 1 day later:
http://www.yafla.com/dforbes/The_Underappreciated_Art_of_Duct_Tape_Programming/
Appropriate read. Moderation is key.
najcik 1 day later:
As of a poor developer point of view: I see TDD as a very structured and sensible approach to write code. It’s better to write them first because this way you describe what need to be done and what you expect from the code you are about to write. Any test written before code manifests your understanding of the code being written. And it’s really so much easier to write them first. After writing code any test is not specifying requirements – it’s more like documenting without giving possibility for the tests to aid the designing process. Documenting also means I have to look at the code and put comments in it and construct documents which sooner or later begin to lag.
But I would not call anybody who write their code without writing tests unprofessional because that’s simply too risky – there are very brilliant guys who don’t use this discipline but surely they use other – like convensions to organize the code wisely. But if you don’t have an automated suite of tests it will be difficult for someone to take the project over. However I would be afraid to become in charge of such codebase. For me maintainability is a matter of concern and I think for UncleBob is that too because maintaining code is where real costs and the really tidious work hide.
But one more thing to say – test driven development is not as easy in real world scenario and real problems arise because you need good isolation frameworks and knowledge to be able to stub your dependencies. Sure everybody can instantiate an object in a test, call a method or two and than assert on something. Well that’s an ideal scenario which happens to be more likely to occure if you TDD, but if you write tests aftewards or write tests for a piece of legacy code chances are there are already so much coupling problems that creating even a simple test is really tidious. These skills take time to develop, books to read and sometimes in existing system you have to write one single line to alter the behavior but constructing a test for it with all the isolation you have to apply can take many, many LOC of so.
Esko Luontola 1 day later:
Uncle Sam: “Those who can do, those who can’t teach”
That saying should be expanded with “those who can better than everyone else, also teach.” A true master is one who can teach others to become as good as himself.
For example, you mentioned Donald Knuth and he teaches. He has even written some pretty deep books. So your argument is conflicting itself.
Philip Schwarz 1 day later:
In Uncle Bob’s previous post, you expressed concern at the blurring of the line between “having unit tests to do regression testing” and “developed test first and designed with TDD ” when arguing for TDD.
In this post, you said: If any of you TDD fanatics think you are so much better than others at programming, show us code you wrote that is better than all the “stone age” programmers like … Knuth wrote or shipped.
Interviewer: ...today’s developers frequently build programs writing small code increments followed by immediate compilation and the creation and running of unit tests. What are your thoughts on this approach to software development?
Knuth: ... the idea of immediate compilation and “unit tests” appeals to me only rarely, when I’m feeling my way in a totally unknown environment and need feedback about what works and what doesn’t. Otherwise, lots of time is wasted on activities that I simply never need to perform or even think about. Nothing needs to be “mocked up.”
So it seems that you are blurring the line between “having unit tests to do regression testing”, and “rarely having unit tests”: the question you should be asking is “If any of you automated unit-test fanatics think you are so much better than others at programming, show us code you wrote that is better than ….etc”.
As Keith Braithwaite says in this post:
And thus is the working life of the research computer scientist different from the working life of the commercial software engineer. I’m tempted to say (and so I will) that the jobbing industrial programmer spends more time in an unknown environment and needs more feedback (and, right now!) about what works and what doesn’t more often than a researcher does.
and also:
...anyone who reads that interview and thinks to themselves “ha! See! Knuth doesn’t unit test, so I don’t need to either” needs to consider a couple of things:
1. you aren’t Don Knuth
2. are you really prepared to do all the other stuff that Knuth does so that his programs still work without unit testing?
3. if so, whom do you imagine is going to pay for you to?
42 1 day later:
Reading all these comments, it reminds me of an evolutionist trying to explain the concepts of Darwin to creationists. TDD is there to protect us! If you are lucky enough to have a decent spec, that will NEVER change, code without it! But the rest of us have to deal with horrible, ever changing specs. Agile and tdd is a worm digging through the path of least resistance (see YAGNI). Non-TDD coders use a bulldozer, leaves gaping holes everywhere and someone else ends up rewriting it all.
Paul Thor 2 days later:
its to easy to be negative! When someone is trying to do something positive.
Stone Age Programmer 3 days later:
Re 42’s comments: Yes, this sounds like a discussion between evolutionists and the creationist, with the difference that the TDD programmers are playing the role of crearionists – asking everybody to “faithfully” accept their claims that TDD is indeed better. Evolutionists (stone age programmers) want to see evidence.
If you knew Uncle Bob's political and religious views, it would be clear to you that he falls solidly on the side of the conservatives.
James Carr 3 days later:
Good response Uncle Bob. How people can continue to think that TDD is some silly fad continues to amaze me. Anyone with an ounce of experience would know that TDD helps produce clean, professional code that has been proven that it needs to exist thanks to well defined examples.
It isn’t just silly, but unprofessional imho not to do TDD. Deal with tons of legacy code packed with 2000 line classes and no tests around it and please someone try to tell me that TDD is a bad thing.
Cedric 3 days later:
James: thousands of companies are producing very good software every day without using TDD (and sometimes without even using automated testing).
Calling them unprofessional is not just disrespectful, it makes you sound like a zealot…
And I understand that you and Rob live off the TDD industry, and as such, you are surrounded with companies that do use TDD, but hopefully you realize that you are seeing the inside of a bubble.
TDD is still far from being mainstream and so far, remains confined to conferences, books and a very small subset of companies.
James Carr 3 days later:
Cedric: What!? How can you prove to me your code is even needed if you haven’t proved the need for it to exist with a well defined example? How can you refactor without having to worry about breaking some unapparent piece of functionality that will cost a company millions of dollars?
I work both on new projects and legacy projects all the time, some done with TDD and some that were built by hacking away with no tests. I find the latter to be a lot more difficult to work with.
Maybe you just don’t have the industry experience that has taught me that code written test first is always a lot more cleaner and easier to work with than code that is not.
Or maybe I should just listen to you and see the beautiful light of cowboy coding? :)
James Carr 3 days later:
I might have came off in kind of a condescending tone. My point is “my” experience has taught me to value TDD over DDT. Maybe this is the opposite for you, but I know that it works well for me and the code I have written without doing TDD is always a bit of a mess.
Cedric 3 days later:
James, you seem to assume that there are only two states for code: “written with TDD” and “with no tests”.
There is a third state, “written with tests last”, and my claim is simply that millions of lines of code were written this way and that this code is working just fine.
Mocking developers and companies that write code this way and calling them “unprofessional” is precisely what makes people think that there is a disconnect between the TDD crowd and the rest of the world.
Cedric 3 days later:
By the way, thanks for rectifying the tone in your second post.
The constant use of deprecating adjectives for people who don’t use TDD (unprofessional, cowboy coding, etc…) doesn’t really help when you are trying to convince.
Cedric 3 days later:
James, you seem to assume that there are only two states for code: “written with TDD” and “with no tests”.
There is a third state, “written with tests last”, and my claim is simply that millions of lines of code were written this way and that this code is working just fine.
Mocking developers and companies that write code this way and calling them “unprofessional” is precisely what makes people think that there is a disconnect between the TDD crowd and the rest of the world.
Jake 3 days later:
“I think that any programmer that’s not smart enough to use tools like that is probably not smart enough to be a programmer period.”
I totally agree with you on that. However, we can’t ignore reality. How many programmers are out there? and how many of them are really good at those tools? So if we kick them out of the industry just because they aren’t smart enough to be a prammer, this industry will collapse…
Christopher Svec 5 days later:
How do you respond to this Microsoft study saying that TDD results in fewer bugs, but longer development time:
http://research.microsoft.com/en-us/projects/esm/nagappan_tdd.pdf
They say they saw 40-90% lower defect density with TDD, but 15-35% increase in initial development time.
(though the development time number was merely an estimate, as opposed to a measured number)
Antony G 8 days later:
Wow – feel the love in these comments.
The simplest thing I could suggest to people detracting the effectiveness of TDD is to simply try it. Then try to live without it.
I can only speak out of personal experience, but to me this is the clincher.
Norbert 23 days later:
I read Spolkys article and thought, well, he has some points. I’d never thought what kind of blogstorm he’d raise with this.
Folks, please, do not be religious about this. If TDD helps you, great! Keep it up. Personally, I try to work like Peter Norvig and Knuth—though I know I’ll never play at their level. To me, TDD (yes, I tried) seems kinda cool if your code can be handled like a black box with nice interfaces that are not crossing system boundaries or user interfaces and if you are not trying develop an algorithm. You can only solve problems that you really do understand.
For all those TDD evangelists out there who cannot stop saving the poor sheep out there (like myself), why don’t you guys gather the evidence that TDD is really, truly producing more stable and better code? Your claims should be measurable. Repeating them does not help. You should have some statistics that count applications crashes and whatnot in order to solidify your claims. Remember: People like me do not try to convince you that TDD is bad, but that we simply do not buy into this as religiously as you do. And we do not call you names, ok?
Until then, pretty please, stop preaching and state the facts and your conclusions. You never know, you actually might win me over, but, sorry to say, the tone in these discussions is revolting.
maddin 23 days later:
if you compare TDD with the hygiene practices a surgeon does, i think its not entirely fair. If a surgeon does not wash his hands before a surgery, the chance is almost 100% the patient will suffer. However, i have written lots of code and it works till today and i did not do TDD as it did not exist in its current form. So, absence of TDD is not life threatening, you can succeed without it.
Bottom Line: TDD is a tool that i use when appropriate. There are cases when its not appropriate. I expect an real professional to look at the problem and pick the right tools to solve the problem most effectively. And i don’t agree that TDD makes you a better programmer. Its the other way round, if you are a good programmer you adopt techniques like TDD. If you are a lame coder no tool nor technique will save you.
just my 2 cent.
Mohammad Azam 29 days later:
TDD is awesome and there is no doubt about it. It gives you confidence to make changes and in the long run it proves to be very useful.
But then there are some straight forward projects like “Building Discussion Boards”, “Building Knowledge based WebSite” to host articles and stuff that does not require TDD approach.
The reason that they don’t require TDD is that there is no complexity in the code. Everything is so straight forward.
Bottom line is that the domain will dictate if TDD is required or not. For complex domain TDD should be mandatory but for simple projects it MIGHT be an overkill.
Thanks, Azam
Adrian 30 days later:
I don;t understand why we speak about developing speed when we speak about TDD.
In my opinion, the main goal of TDD is not “increase productivity”. I never think at TDD as a productivity booster. For me TDD is a guarantee offered to myself and to the client that my work is well done. Is a way to protect my reputation.
So, in my opinion, speeding or slowing the development process when we speak about TDD is meaningless.
Adrian 30 days later:
My remarks regarding:
“How do you respond to this Microsoft study saying that TDD results in fewer bugs, but longer development time”
TDD = longer development time (~40%) = fewer defects = less time for bug fixing = The total time spent in developing an US is smaller because what we lose in development we gain by spending less time in bug fixing.
And think about your reputation when the client sees an “null reference set to an instance of an object” exception.