TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

The Failures of "Intro to TDD"

169 点作者 davemo超过 11 年前

25 条评论

akeefer超过 11 年前
I think this is a great explanation of a lot of the obvious pitfalls with &quot;basic&quot; TDD, and why so many people end up putting in a lot of effort with TDD without getting much return.<p>I personally have kind of moved away from TDD over the years, because of some of these reasons: namely, that if the tests match the structure of the code too closely, changes to the organization of that code are incredibly painful because of the work to be done in fixing the tests. I think the author&#x27;s solution is a good one, though it still doesn&#x27;t really solve the problem around what you do if you realize you got something wrong and need to refactor things.<p>Over the years I personally have moved to writing some of the integration tests first, basically defining the API and the contracts that I feel like are the least likely to change, then breaking things down into the pieces that I think are necessary, but only really filling in unit tests once I&#x27;m pretty confident that the structure is basically correct and won&#x27;t require major refactorings in the near future (and often only for those pieces whose behavior is complicated enough that the integration tests are unlikely to catch all the potential bugs).<p>I think there sometimes needs to be a bit more honest discussion about things like: * When TDD isn&#x27;t a good idea (say, when prototyping things, or when you don&#x27;t yet know how you want to structure the system) * Which tests are the most valuable, and how to identify them * The different ways in which tests can provide value (in ensuring the system is designed for testability, in identifying bugs during early implementation, in providing a place to hang future regression tests, in enabling debugging of the system, in preventing regressions, etc.), what kinds of tests provide what value, and how to identify when they&#x27;re no longer providing enough value to justify their continued maintenance * What to do when you have to do a major refactoring that kills hundreds of tests (i.e. how much is it worth it to rewrite those unit tests?) * That investment in testing is an ROI equation (as with everything), and how to evaluate the true value the tests are giving you against the true costs of writing and maintaining them * All the different failure modes of TDD (e.g. the unit tests work but the system as a whole is broken, mock hell, expensive refactorings, too many tiny pieces that make it hard to follow anything) and how to avoid them or minimize their cost<p>Sometimes it seems like the high level goals, i.e. shipping high-quality software that solves a user&#x27;s problems, get lost in the dogma around how to meet those goals.
评论 #7134973 未加载
评论 #7133801 未加载
usea超过 11 年前
I have tried many times to do TDD. I find it extraordinarily hard to let tests drive the design, because I already see the design in my head before I start coding. All the details might not be filled in, and there are surely things I overlook from the high-up view, but for the most part I already envision the solution.<p>It&#x27;s difficult to ignore the solution that is staring my brain in the face and pretend to let it happen organically. I know that I will end up with a worse design too, because I&#x27;m a novice at TDD and it doesn&#x27;t come naturally to me. (I&#x27;d argue that I&#x27;m a novice at everything and always will be, but I&#x27;m even more green when it comes to TDD)<p>I have no problem writing unit tests, I love mocking dependencies, and I love designing small units of code with little or no internal state. But I cannot figure out how to let go of all that and try to get there via tests instead.<p>I don&#x27;t think that I&#x27;m a master craftsman, nor do I think my designs are perfect. I get excited at the idea of learning that the way I do everything is garbage and there&#x27;s a better way. If I ever learn that I&#x27;m a master at software development, I&#x27;ll probably get depressed. But I don&#x27;t think my inability to get to a better design via TDD is dunning-kruger, either.<p>I want to see the light.
评论 #7133969 未加载
评论 #7133257 未加载
评论 #7133219 未加载
richardjordan超过 11 年前
The comments section today looks like a support group for beginners&#x2F;intermediates who struggled with TDD and gave up, and so want to explain why it&#x27;s all bunk. I get this. I am not a great programmer. I&#x27;m self taught like a lot of you. I had tremendous difficulty grokking TDD and for the longest time I&#x27;d start, give up, build without it.<p>But, I&#x27;m here as a you-can-do-it-to. You might not think you want to but I&#x27;m so glad I DID manage to get there.<p>Feel free to ignore because I respect that everyone&#x27;s experience differs. But the real problem is that there are few good step by step tutorials that teach you from start to competent with TDD. Couple that with the fact that it takes real time to learn good TDD practices and the vast majority of TDDers in their early stage write too many tests, bad tests, and tightly couple tests.<p>Just as it&#x27;s taken you time to learn programming - I don&#x27;t mean hello world, but getting to the competent level with coding you&#x27;re at today, it&#x27;ll take a long time to get good with TDD. My case (ruby ymmv) involved googling every time I struggled; lots of Stack Overflow; plenty of Confreaks talks; Sandi Metz&#x27; POODR...<p>Like the OP says - at different stages in the learning cycles you take different approaches because you&#x27;re better, it&#x27;s more instinctive to you. I thought I understood the purpose of mocks&#x2F;doubles, until I actually understood the purpose of mocks&#x2F;doubles. When used right they&#x27;re fantastic.<p>The key insight that everyone attempting TDD has to grok, before all else, is that it&#x27;s about design not regression testing. If you&#x27;re struggling to write tests, and they&#x27;re hard to write, messy, take a lot of setup, are slow to run, too tightly coupled etc. you have a design problem. It&#x27;s exposed. Think through your abstractions. Refactor. Always refactor. Don&#x27;t do RED-GREEN-GOOD ENOUGH ... I did for a long time. It was frustrating.<p>This is a good post. Don&#x27;t dismiss TDD because you&#x27;re struggling. Try to find better learning tools and practice lots and listen to others who are successful with it.<p>It&#x27;s true that sometimes fads take hold and we can dismiss them as everyone doing something for no reason. But cynicism can take hold too and we can think that of everything and miss good tools and techniques. TDD will help you be a better coder - at least it has me. If your first response to this post was TDD is bullshit, give it another try.
评论 #7135171 未加载
评论 #7136472 未加载
hcarvalhoalves超过 11 年前
The approach outlined actually makes much more sense without OO. I guess the WTF comes from forcing yourself into a world of &quot;MoneyFinder&quot;, &quot;InvoiceFetcher&quot;, etc. Makes it look a lot more complicated and prone to error than it is, because you&#x27;re now supposed to mock objects that may have internal state. Otherwise it&#x27;s the usual top-down approach with stubs.
评论 #7132757 未加载
评论 #7132694 未加载
mattvanhorn超过 11 年前
I think that Red-Green-Refactor is as much about learning to habitually look for and recognize the refactoring opportunities as it is about being meticulous in reacting to those opportunities.<p>It&#x27;s true that nothing forces your to refactor - but I think wanting that is a symptom of treating TDD as a kind of recipe-based prescriptive approach. It is not a reflection of the nature of TDD as a practice or habit.<p>It&#x27;s a subtle difference, but important:<p>A recipe says &quot;do step 3 or your end result will be bad&quot;<p>A practice says &quot;do step 3 so you get better at doing step 3&quot;
danso超过 11 年前
The more I try to explain TDD, the more I realize that some of my favorite concepts, like the ability to mock functionality of an external process because the details of that process should be irrelevant...is just beyond the grasp of most beginners. That is, I thought&#x2F;hoped that TDD would necessarily force them into good orthogonal design, because it does so for me...but it seems like they have to have a good grasp of that <i>before</i> they can truly grok TDD.<p>Has anyone else solved this chicken and the egg dilemma?
评论 #7132508 未加载
评论 #7132053 未加载
评论 #7131883 未加载
Nimi超过 11 年前
I wonder about these workshops (even asked Uncle Bob Martin about them in a recent thread). I can&#x27;t shake the feeling they are the exact opposite of agility (obviously, he is better qualified than me to judge that). Their limited time schedules, which is essentially a bound over the amount of contact between the client and the supplier, seems analogous to the infamous &quot;requirements document&quot;. Also, there doesn&#x27;t appear to be a &quot;shippable&quot; product at the end - the developers apparently don&#x27;t end up practicing TDD.<p>I used to be an instructor for a living, and I kind-of equated lectures to waterfall and exercises to XP. There is even a semantically analogous term in teaching research, problem-based learning (each word corresponds to the respective word in test-driven development - cool, right?). Is there anyone else who sees these analogues, or am I completely crazy here?
评论 #7140441 未加载
mrisse超过 11 年前
Might one of the problems be that we place too much importance on the &quot;symmetrical&quot; unit test. In your example the child code is still covered when it is extracted from the parent.<p>As a developer that often prefers tests at the functional level, the primary benefit of tests for me is to get faster feedback while I am developing.
评论 #7132686 未加载
richardjordan超过 11 年前
Shout out for Sandi Metz book POODR, and her Railsconf talk The Magic Tricks of Testing, if you&#x27;re a rubyist (though the principles hold true for non-ruby OO programmers too).<p><a href="https://www.youtube.com/watch?v=URSWYvyc42M" rel="nofollow">https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=URSWYvyc42M</a>
评论 #7134632 未加载
评论 #7133217 未加载
mattvanhorn超过 11 年前
I agree with the general approach suggested in the article (in tests, write&#x2F;assume the code you wish you had).<p>But one detail ran counter to my personal practice.<p>I don&#x27;t believe that &quot;symmetrical&quot; unit tests are a worthy goal. I believe in testing units of behavior, whether or not they correspond to a method&#x2F;class. Symmetry leads to brittleness. I refactor as much as possible into private methods, but I leave my tests (mostly) alone. I generally try to have a decent set of acceptance tests, too.<p>Ideally, you specify a lot of behavior about your public API, but the details are handled in small private methods that are free to change without affecting your tests.
评论 #7132026 未加载
评论 #7132144 未加载
viggity超过 11 年前
Yes! I&#x27;ve always hated the common kata, because for every dev writing software for a bowling alley, there are 200,000 devs writing software the sends invoices or stores documents.<p>When I&#x27;m teaching TDD, the kata I have everyone go through is a simple order system.<p>The requirements are something like:<p>A user can order a case of soda<p>The user should have their credit card charged<p>The user should get an email when the card is charged<p>The user should get an email when their order ships<p>If the credit card is denied, they should see an error message<p>(etc....)<p>This way they can think about abstracting out dependencies, an IEmailService, a ICreditCardService, etc. There are no dependencies for a Roman Numeral converter.
GhotiFish超过 11 年前
I like the way he broke things up, but something bothers me about his technique.<p>All his classes ended in &quot;er&quot;.<p>he&#x27;s not writing object oriented software, he&#x27;s writing imperative software with objects.
评论 #7134518 未加载
ChristianMarks超过 11 年前
This is probably the first reasonably sophisticated attempt to describe a test-driven design&#x2F;development process I have read.<p>The observation that &quot;[s]ome teachers deal with this problem by exhorting developers to refactor rigorously with an appeal to virtues like discipline and professionalism&quot; reminds me of E. O. Wilson&#x27;s remark that &quot;Karl Marx was right, socialism works, it is just that he had the wrong species.&quot;<p>If test-driven design were the programming panacea its proponents sometimes seem to make of it, Knuth would have written about it in TAOCP. Instead Knuth advocates Literate Programming. TDD seems to attract a cult-like following, with a relatively high ratio of opinion to cited peer-reviewed literature among proponents.<p>TDD as this is commonly understood seems to me like the calculational approach to program design (c.f. Anne Kaldewaij, <i>Programming: the derivation of algorithms</i>), only without the calculation and without predicate transformers. Still it can be a useful technique.<p>There is no &quot;right&quot; way to program. This was evident from the beginning, when Turing proved the unsolvability of the halting problem. (Conventions are another matter.)
zwieback超过 11 年前
Sure, but if the end result is &quot;lots of little objects&#x2F;methods&#x2F;functions&quot; maybe there&#x27;s a simpler way of getting there, e.g. prescriptive design rules. After all, that&#x27;s what every design method, including stuff from the waterfall era attempted.<p>I&#x27;d like TDD to be more than just another way to relearn those old rules, especially if we arrive at the same conclusions on a circuitous path. Perhaps the old design rules, object patterns, etc. have to each be integrated with a testing strategy, e.g. if you&#x27;re using an observer you have to test it like this and if you refactor it like that you change your tests like so.<p>The general rules are easy to understand and your post makes perfect sense but once you formulate your new design approach you&#x27;ll have to find a way to teach it precisely enough to avoid whatever antipattern is certain to evolve among the half-educated user community, which usually includes myself and about 95% of everyone else.
searls超过 11 年前
Hey HN, I just wanted to thank you for the overall very positive, constructive comment thread. Thanks to you this post got roughly&#x2F;over ~22k page views and I didn&#x27;t receive a single vitriolic comment or bitter dissent. All I got was thoughtful, earnest, and honest replies. Made my day.
tieTYT超过 11 年前
OK but after you &quot;Fake It Until You Make It&quot; and you have to add a new feature to that class structure, aren&#x27;t you just going to start over with all the failures he brings up?<p>---------<p>I haven&#x27;t designed code the way he&#x27;s advocating, but I have attempted TDD by starting with the leaves first. Here are the downsides to that:<p>1) Sometimes you end testing and writing a leaf that you you don&#x27;t end up using&#x2F;needing.<p>2) You realize you need a parameter you didn&#x27;t anticipate. EG: &quot;Obviously this patient report needs the Patient object. Oh crap I forgot that there&#x27;s a requirement to print the user&#x27;s name on the report. Now I&#x27;ve got get that User object and pass it all the way through&quot;.<p>Maybe these experiences aren&#x27;t relevant. As I said, I haven&#x27;t tried to &quot;Fake It Until You Make It&quot;.
评论 #7139898 未加载
radicalbyte超过 11 年前
Excellent post, I&#x27;ve had exactly the same experience and come to exactly the same conclusion.<p>I still follow the old Code Complete method: think about the problem, sketch it out, then finally implement with unit tests. The results are the same, and it&#x27;s a lot less painful than greenhorn-TDD.
评论 #7133003 未加载
评论 #7133617 未加载
julie1超过 11 年前
TDD and agile have been an effort at breaking an old must have for code which was: ISO9001; the code should behave according to the plan, and if they don&#x27;t conform, plan must be revised if the tests failed. The Plan Do Check Act Mantra. Now, they find themselves facing the consequences of not respecting the expectation of the customers and they whine because &quot;it was not applied correctly, because no one cared&quot;.<p>So now, they reformalize exactly the so &quot;rigid&quot; ISO9001 they were trying to throw down.<p>What an irony.
ChuckMcM超过 11 年前
I suspect if they had called it <i>Architecture</i> Driven Development (ADD) rather than <i>Test</i> Driven Development (TDD) it might contextualize better. Basically what the author explains is that you can design an architecture top down from simple requirements, deriving more complex requirements, and then providing an implementation strategy that lets you reason about whether or not you are &quot;done.&quot;<p>But that &#x27;test&#x27; word really puts people in the wrong frame of mind at the outset.
评论 #7134430 未加载
searls超过 11 年前
Apologies for the downtime folks, this post is proving a little too popular for us. Would love to see some folks reaction to the post in the comments
Arnor超过 11 年前
&gt; ...TDD&#x27;s primary benefit is to improve the design of our code, they were caught entirely off guard. And when I told them that any regression safety gained by TDD is at best secondary and at worst illusory...<p>Thank you! Details of this post aside, this gave me an Aha! moment and I feel like I&#x27;m finally leaving the WTF mountain.
vegar超过 11 年前
Ian Cooper has a good talk that&#x27;s relevant to this blog post. It&#x27;s called &#x27;TDD, where did it all go wrong?&#x27; and a recording from NDC 2013 can be found here: <a href="http://vimeo.com/68375232" rel="nofollow">http:&#x2F;&#x2F;vimeo.com&#x2F;68375232</a>
tempodox超过 11 年前
Those guys must really hate their readers. That crappy web site is not zoomable! In the 21st century? In the era of “responsive web design”? Mega fail. Did they use TDD?
评论 #7143771 未加载
asfa124sfaf超过 11 年前
What about tools like Typemock? How does that fit in?
评论 #7143937 未加载
glittershark超过 11 年前
Hello there, Heroku error page
评论 #7133695 未加载