The crux of Test Driven Development is that you use tests to drive the creation of your code, and in that loose sense, the guidelines pass muster, but there's more to it than that, really.
The key advantage that TDD gives you is feedback. You write a failing test case, make it pass, and then you formulate the next test case. The wonderful thing is that when you get to that next test case, you have the feedback from getting the first one to pass to draw upon. Often that feedback will lead you to formulate the next test case in a different way. It could even lead you to produce a different interface for the class you were writing.
Now, what I've described might sound bad. It might sound like, well, maybe the decisions that you make during development will drift a bit. Drifting might not sound very good but the fact is it is good in this case. It's good because we control it. We are able to incorporate the things that we learn immediately when we learn them. The alternative is to ignore things that we learn or not learn them at all, and that's not a very clever strategy.
The style of TDD described in the guidelines would have us jump ahead and write five, ten, maybe twenty test cases before getting the first one to pass. You can do that, but it's like putting on a set of blinders. When you don't have to formulate the next test case right after passing the last one, there isn't much chance to think about improvements. Worse, there is a disincentive to thinking about them: if you find any, you have to delete all of the speculation you've hardcoded in the tests and interfaces you created in advance.
Just for the record, I'm not a Microsoft-basher. I've met quite a few people who work there and they are very smart, people I have a lot of respect for, but there is something mysterious that happens in nearly all large organizations. Ideas get passed from person to person through a grapevine, and the form that they end up in is rarely the form they start in. It's a lot like politics, really. Politicians can't send nuanced messages because they know that only the most simplified version of what they say will propagate, and they have to be very careful that the simplified version of what they say isn't counter to their intentions. But, that's probably a topic for another blog.
Right now, I hope that MS revisits their guidelines. Yes, they have a tool that generates test stubs, but using it for TDD looks counter-productive. Adding stubs to legacy code? That would be great, but getting in the way of the feedback cycle? Bad. Bad. Bad.
The thing that really gets my goat about this is that TDD is unambiguously about tests driving development. Not about development generating tests. Recognising this, but calling it "traditional" TDD smacks of trying to redefine the term.
I like the idea, but not for developing new code, rather as a safety net for existing code.
I agree - creating large numbers tests in advance seems like just another of writing a detailed formal specification in advance, with the same disadvantages.
Things will inevitably change in the course of development, making the specification (tests created in advance) obsolete. Also, as you point out, the things learned from implementing one test will affect how subsequent tests are implemented.
>> ...there is something mysterious that happens in nearly all large organizations
Not really a mystery in this case - it's called "marketing". The principles of agile development: "individuals and interactions over processes and tools" pose a bit of a dilemma to those trying to sell processes and tools. Microsoft wants to jump on anything that's popular with developers - but how do you sell fancy new tools for an approach that values simplicity? Well, you just start redefining the approach to include your tools and processes: new, improved Microsoft TDD, better than traditional TDD.
It's a little sad, really. I look at all the wizards and "team tools" and everything else that's new in Visual Studio 2005 - it all seems to have been designed for flashy demos, and I don't see a single thing that I can imagine using in my day-to-day development.
Definitely a case of the 'T' in TDD being hijacked to stand for "Tools". Typical of vendor marketing materials, to take a simple idea and try to stuff if full of as many of the "features" of their tools as they can.
In the Microsoft article, the explanation for creating classes before tests is "...so that, while creating tests, you can take advantage of [...] features in Visual Studio 2005 Team System...".
The sad thing is, that the right tools could help with so-called traditional TDD.
For example after writing a test which references a non-existent class and/or method, the tool could offer to create stubs for these automatically, deducing names, argument types and return types from the usage:
If the programmer writes this:
IntegerStack stack = new IntegerStack(); int value = 5; stack.Push(value); Assert.AreEqual(5, stack.Pop());
The tool could generate this:
class IntegerStack { public void Push(int value) { throw new NotImplementedException(); } public int Pop() { throw new NotImplementedException(); } }
As is happens, the Resharper third party add-in for Visual studio does basically this today, along with many other useful things - which demonstrates that it can be done. So it seems we have a case of modifying a process to fit the tools, rather than building tools to support a process.
there is something mysterious that happens in nearly all large organizations. Ideas get passed from person to person through a grapevine, and the form that they end up in is rarely the form they start in
Steve Jobs covered this in a Time interview, he calls it the Parable of the Concept Car whereby someone designs a great car and then the engineers and accountants get hold of it and it ends up looking like, well, crap.
Someone in Microsoft probably wrote a little paper that showed how VS could be used to support TDD and showed it to his manager and by the time it got through more layers and management we get to see it on the web site.
Where it got slated. So much for embrace and extend.
TDD seems flawed for me because....I don't think, solve problems, or code this way. I don't approach a problem looking at corner cases, or ways that will not solve the problem.
Using OO, I try figure out/understand the model and interactions (through rapid/iterative prototyping) before I'd know how to write a good test for it.
I prefer a more "creative" approach to thinking, coding, solving problems rather than the TDD's more "scientific" approach, and maybe each methodology has it's place depending on the nature of the problem you are trying to solve.
Doing TDD, you are also thinking about which classes etc your problem requires. Only now, you start using them instantly rather than waiting until your "design" is ready. I don't consider this to be a more scientific and less creative approach - on the contrary. The extra bonus, of course, is that the final design ends up being testable which something that doesn't easily apply to a design thought out the "conventional" way.
I think the approach you should use would depend on how well you understand the task you're faced with and how sure you are about the approach to take to solve it.
If you don't understand the requirements of the project at all, you need to have a way to get these under control first. Writing tests in advance is a good way to think about the requirements of the problem and establish the questions you need to ask others.
If you really understand a problem well and are sure exactly how you are going to do it (if it's well specified and something you've done lots of times before), a process with a lot of control such as TDD makes the development more reliable.
If it's something in between, then it might be worth developing throwaway prototypes in parallel with the tests, to investigate what can be done and whether it is testable at the same time.
TDD was invented/popularized through eXtreme Programming/Agile methods, but can definately be used outside such methodologies. That said it might also be misused or applied in such a way that it is counterproductive, especially when used in a waterfall-like process where lot of tests are written long before the code is implemented. I think Microsoft is trying to satisfy the waterfall-people, so that it doesnt <i>sound</i> Agile anymore. Here is how I think this happened: There are lot of smart people inside Microsoft, and I think a lot of them don't use Visual Studio. I know a lot of developers in Microsoft was upset when they where not allowed to use plain C++ anymore for developing Visual Studio, Windows , SQL Server etc. The latest version of Visual Studio is really bloated, it's a whole DVD. What on earth have they put in there? I think the marketing people in Microsoft have had too much influence on the development tools. Good development tools have never been crafted by these guys, developers creates their own tools when and where they are needed. That's why so many open source developemt tools and libraries is used in almost every project these days. The (socalled) arcitects behind Visual Studio can't be familiar with the principals that was invented/became popular together with TDD. One of the principles that came with it was (yell it out!) YAGNI: You aren't gonna need it. TDD and associated practices and principles is described at Wikipedia http://en.wikipedia.org/wiki/Test-driven_development, and should be read by all people even thinking about making development tools supporting TDD or any other agile practice/principle.
Erich Gamma seems to agree with "Test-First" methodology when developing eclipse (based on discussions I've seen on artima...)
...However I write better more flexible OO code with rapid iterative throw away prototypes... Thinking about the problem by writing tests first may make sense for some people, I just dont think that way.
What I take from the premise of the original article was that "If you can write your tests first, but then your are on the slippery slope to solving the problem a certain way." That's why I view it as "less creative, and more methodical/scientific".
TDD seems to assume you have specific solution in mind (i.e. hypothesis) and you want to somewhat "scientifically prove" it works by finding all of the ways that it will break (In logic I belive this is the process of proof by contradiction)... The problem/inflexibility for me is it assumes "You have a solution/hypothesis in mind"... What if my original hypothesis was incorrect or needs to be tweaked... (this causes you to technically redo all of the work done to validate your original hypothesis)
(I'm not bashing, I think everyone's entitled to their own opinion on what works best for them...)
> TDD seems to assume you have specific solution in mind > (i.e. hypothesis) and you want to somewhat "scientifically > prove" it works by finding all of the ways that it will > break (In logic I belive this is the process of proof by > contradiction)... The problem/inflexibility for me is it > assumes "You have a solution/hypothesis in mind"... What > if my original hypothesis was incorrect or needs to be > tweaked... (this causes you to technically redo all of the > work done to validate your original hypothesis)
I think that the way you are thinking about TDD is not how most people practice TDD. I don't think most people start by testing the edge cases. I think the earliest tests (or the earliest iterations of the earliest tests) need to be very broad and general.
The point of TDD is feedback. So you don't want to get too far ahead of yourself in designing new tests because you expect to learn something and make changes. And if it comes down to it, the tests are expendable. You don't stick with a bad solution just because you have unit tests for it.
> TDD seems flawed for me because....I don't > think, solve problems, or code this way. I don't > approach a problem looking at corner cases, or ways that > will not solve the problem.
Very few people naturally think TDD but then even OO has to be taught and this talk of corner cases does not even sound like you understand TDD at all. If you were doing TDD you would start off with the general case, get that to work and then add more cases as they occurred or were needed. It is not a matter of exhaustively finding all the possible test cases for the first method you think of before you can move on.
> Using OO, I try figure out/understand the model and > interactions (through rapid/iterative prototyping) before > I'd know how to write a good test for it.
If is a very strange class that you cannot state at least something about the sort of interactions you will have without creating the whole. From what you have said above as you come up with a prototype then you could also be creating the tests.
> I prefer a more "creative" approach to thinking, coding, > solving problems rather than the TDD's more "scientific" > approach,
Never heard TDD being called "scientific" before. Where did you come up with that from?
> and maybe each methodology has it's place > depending on the nature of the problem you are trying > to solve.
The only thing you seem to have got right so far. But before you dismiss TDD because you think you are too "creative" for such a "scientific" methodology you should perhaps learn more about it.
I tried to stress the fact that TDD was not my preferred method of development. I'm sorry if people took offense, I'm not trying to dismiss it, I'm just giving a personal opinion. (after all that's what a discussion forum is for isn't it?) (And no... I don't think I'm too creative for TDD... but I am happy to amuse :-)
A few years ago, I consulted on a project and we tried TFD, and the team had a hard time being very productive with it. Personally, I decompose problems by coding prototypes, not refactoring test cases... that's all I'm saying...
I've read the http://www.agiledata.org/essays/tdd.html intro to TDD and I like what it has to say about the benefits of TDD.... In reality, I've never seen nor heard of any first hand accounts of Pair Programming, or TFD/TDD existing in a company for more than a few weeks before it is abandoned. (generally because it requires too much discipline... "they refuse to add even a single line of code until a test exists for it." (hmm maybe that's where I got methodical/scientific)
According to TDD this would mean that a project would have 100% code coverage (every line of code is tested)... and I have yet to see a project achieve this lofty goal.
I think there are plenty of good things to take away from the XP and Agile movements, but all this stuff is relatively new in the scheme of things, so maybe some things work for you and not me...
"Let he who has not written functional code before a unit tests cast the first stone":}
Flat View: This topic has 25 replies
on 2 pages
[
12
|
»
]