Hacker News new | past | comments | ask | show | jobs | submit login
TDD isn't dead just because DHH can't do it (rubylove.io)
39 points by prajjwal on April 25, 2014 | hide | past | favorite | 38 comments



So, was this meant to be a counter point to DHH's article in any way? I really just got that you're mighty pissed that RR Parley banned some of your posts.

Dually, DHH didn't say TDD was dead, he specifically said "TDD is dead /to him/".

Really, I think the most important take away even for people who disagree, is this: > I don't think that's healthy. Test-first units leads to an overly complex web of intermediary objects and indirection in order to avoid doing anything that's "slow". Like hitting the database. Or file IO. Or going through the browser to test the whole system. It's given birth to some truly horrendous monstrosities of architecture. A dense jungle of service objects, command patterns, and worse.

I'd like to see someone form a well constructed argument for why that statement is inaccurate, over-stated, or otherwise unfair instead of just ranting about how trying to disagree with what DHH posts ends up putting you on the receiving end of a bunch of zealous admins.


> I'd like to see someone form a well constructed argument for why that statement is inaccurate, over-stated, or otherwise unfair

Here's his statement again, rewritten without the Fox News-style editorialization:

"Test-first units lead to a graph of intermediary objects in order to avoid doing things that are outside the scope of your test. This practice isolates the piece of code you are testing, but as a side-effect means that you don't do unnecessarily slow work like hitting a database, filesystem or web browser. It has given rise to new patterns of application architecture such as a service and command layers."

Oops, I wrote all the same facts but stated them neutrally, and now it doesn't sound like a horror movie! How am I supposed to bully Rails devs into following my style?


> Here's his statement again, rewritten without the Fox News-style editorialization

And here's me applying your own technique to that sentence: "Here's an editorial rewritten without the editorialising". You then feign surprise that that doesn't leave much.

DHH's point was that the resulting graph of intermediary objects is (in his experience) overly complex - the implication being that, where possible, simple is better than complex (which, yes, is a value judgement).


DHH does have a point, but he makes it in a manner that is hyperbolic, accusatory, narrow-minded, stubborn and often rude. I find him to be a negative voice in the community and a dangerous leader. I am happy to fight fire with fire where necessary, and agree with the tone of the article linked by the OP.


This is the DHH everyone has come to expect, and enjoys reading. The entire premise of rails is based on putting negative light on configuration, this is sort of David's M.O.

The rails community has come to terms with the lack of pedantically focused programming practices that DHH embodies, however, his whole aura is one of an individual who has experienced extreme success, and therefore he's still an important community asset. He's a thought leader because he has created immense value from his opinions, and his vitriolic opinion of software architecture and abstraction has always existed. You can literally trace this back to RSpec.

I still argue OP isn't doing anything to support an opposite opinion, and is simply feeding the perspective that DHH was trying to be inflammatory instead of opinionated.


> hyperbolic, accusatory, narrow-minded, stubborn and often rude

Plus:

> fight fire with fire

Seriosly.


Sure, why not? See the "asshole vacuum" scene in HBO's Silicon Valley S01E02.


I don't agree with DHH on most of it's design decisions (but who am I, I don't have the same 'track record') but I do agree wholehartedly with his opinion voiced in his rant/"article". Sure, the title is a flamebait pur-sang for TDD zealots.

Like Slackwise said below; TDD isn't dead but everyone considering it as a silver bullet should scratch their heads... twice, and rinse and repeat.

> YOUR code is hard to test BECAUSE you don't TDD.

<downvote mode on> YOUR code is hard to understand due to high levels of decoupling; overuse of abstractions and refactorings for the sake of code beautification. But at least it's tested! <downvote mode off>


This post has nothing to do with the title. The content of the post clearly shows that the writer is upset that the way he is expressing himself isn't acceptable in somewhere like the Ruby Rogues Parley.

I'm a member of the Ruby Rogues Parley and I saw your posts. The combination of you swearing a few times and calling people out for "TDD challenges" is what made people flag your post, not because of your ideals. People on the parley respectfully disagree with each other all of the time.


Every once in a while I'm reminded of the negative side of the ruby community that people always talk about. I'm not entirely sure why there seem to be a ton of highly negative and highly vocal people giving it a bad name, or if it's even anything other than my selective bias, but it is really unfortunate. For every Matz and Jim Weirich there seem to be ten Ruby rockstars who think the best way to make a name for themselves, or have their argument known is by being the biggest bully.

Are other communities like this or is it more pronounced in the ruby community?


It honestly seems like it's more prominent in the ruby community, and I'm not entirely sure why. Part of it may be that ruby is so expressive and nice to work in that it ignites people passions, which can be good or bad... I can say, however, that years back when I was trying to get into ruby from PHP, people like this gave me a very negative view of the ruby 'community' and were the biggest obstacle I had to embracing ruby.


Thanks for this insight. I got the same feeling while reading it and suspected it was the manner of delivery more than the disagreement.


I strongly believe software needs to be tested, and that tests need to be written to avoid repeating yourself (or screwing yourself over) later on, but trying to write such tests using a TDD approach absolutely destroys my ability to think laterally and creatively and come up with new effective approaches to problems.

If I'm working on something that I've already done, then TDD may work alright, but if I'm doing that rather than searching for some library or code I've already written, then I'm failing already. If it's something simple, then TDD is also not a problem, but at that point I'm really wasting my time.

TDD stunts design, thinking, and refinement ability, and only works when there is nothing left but execution. In my mind, as long as the tests get written (and obviously makes sense to write them at around the time the function/method/class is written), then I'm alright. Also, I usually don't know what a class will look like until I've written it, used it for a little bit, tested it manually, etc. If I were to write a test for it prior to this, then I'd be wasting time. I don't know how people are able to write these tests, and separate everything out beforehand. I'm not comfortable or satisfied with what I've written, until I see it, play with it, test it manually, then use that data to go back and smooth out and refine what needs to be.

I'm wondering if this is an MBTI judger/perceiver issue, with judgers being more able to wire their minds into that of a TDD'er, while perceivers see it as fundamentally problematic.


To quote The Big Lebowski:

"You're not wrong, Walter. You're just an asshole"

The author gets all riled up about being banned for his 'challenge of DHH', when (if this post is any indication) its likely his attitude that got him in hot water.


> YOUR code is hard to test BECAUSE you don’t TDD.

TDD isn't dead, but it also isn't a silver bullet.


Exactly. What all this foaming at the mouth ignores is that it is very possible to do "TDD" and still accomplish nothing useful.

I've seen tests that for all intents and purposes will never fail because they are testing the wrong thing. Write a huge method that has numerous side effects, but only test the return value? Essentially useless!


Indeed. There are plenty of things that are hard to usefully test.

Multithreading code? Enjoy using TDD to ensure it has no livelocks, deadlocks, or missing memory barriers leading to reordered operations. Especially if it's inlined in multiple contexts...

Graphics code? Needs to look similar (but not necessarily exactly the same) across a wide range of OSes, underlying APIs, GPUs, and driver versions - plus many of the same concerns as multithreading code.

Cryptographic code? Well, perhaps heartbleed could've been caught ;). But all the well intentioned MD5 unit tests in the world won't make it useful (in-context)...


I'm not a TDD adherent in any way, but depending on the language you can get some interesting results with automated tests and concurrency. Erlang has a number of applications which automatically reorder the scheduling of the various processes running in order to (hopefully) ensure the code doesn't die when run concurrently. This is much easier to do in certain languages (ruby obviously not being one of them).

Then again, traditional livelocks, deadlocks and improper use of memory barriers aren't really the problems that you would face at the level of abstraction that Erlang provides.


There's also tools like CHESS to do that kind of thing in Microsoft's ecosystems: http://research.microsoft.com/en-us/projects/chess/


TDD rocks if you do it well. You know what? NoTDD rocks if you do it well, too. There is no 'one true method' for development life - conditions change, and you have to be prepared to apply the right process according to the nature of the task.

If you're building something that has to be safe, say .. a life-critical system - you better be damn sure you are testing absolutely every single thing. Everything.

If all you're doing is setting up another hipstersite on the interwebs and hope to have a few million groupies soon, well .. maybe you can avoid the tests, and just wait for the support mails. That's also a valid way to get things done - if it works for you.


>DHH does not need to be held up like a treasure or someone to emulate unless you want to be a handsome with a big attitude and a nice car and loads of money.

BS ad-hominen's like these probably exlain why his comments were hidden and he was banned after 6 posts.

And that's the peak -- the rest goes downhill:

>Personally, I want to write craftsman quality code. I want to explore using academic practices like functional programming to make my code cleaner still.

I mean, seriously? It's 2014, nothing academic about functional programming practices. This kind of talk doesn't grow confidence in the poster's vast knowledge of the field, and deep experience.


In my experience, TDD and unit testing is awkward and uncomfortable when working with application code, since you often find yourself simply testing dependency wrappers, which has limited value. On the other side, integration tests are kludgy and uncomfortable when working with library code. "Round peg, square hole" and all that. I often see two sides arguing for a universal testing strategy, when the use cases are very different.

I try to treat tests as nothing more than repeatable artifacts of whatever I was trying to do to verify the code I was writing was working. So if the code was primarily aimed at hitting a bunch of web services and making DB calls, then the tests will end up as integration tests naturally. If the code is doing a bunch of isolated calculations, then it will probably be unit tests.

This is a classic case of developers talking past one another and trying to force their use case on others in my opinion.


"nothing more than repeatable artifacts of whatever I was trying to do to verify the code I was writing was working" I really like this way of looking at things, and think I might adopt it myself. It's kind of a nice way of saying "test the interface", but more like "test the interface of the code exercised by the primary consumer of the interface".


Synopsis:

Pay to play discussion bans person for trollish posts following requests for better behavior from moderators in reaction to previous trollish posts. By logical inference this banning proves that intelligent discussion which admits the possibility that TDD has shortcomings is nothing but cargo cult hero worship of a technically inept has been and that TDD is the sole true religion.

Commentary:

In my opinion, this is why hell banning may be better for cases where there is not a shared set of standards between moderators and posters. The loss of audience is not so apparent immediately and the lag time means there is less likelihood of immediate escalating reaction while the poor behavior is still spotlighted. Hell banning also offers the possibility of readmission should behavior change with the retention of identity.


The best way to convince people to write tests is to remind them that they are already writing tests, but they're throwing them away. If you're writing a method, you are almost certainly testing it with a bit of code to verify the output. You're probably writing one of these little tests every 5 minutes. Save them in a folder called "unit tests". Are you writing code to make sure one part of the API works with another? Save it in a folder called "integration tests". Opening up a browser to make sure the right stuff is appearing on the right part of the page? Save it in a folder called "functional tests". Put in a code coverage tool to make sure you're calling all the code you've written in a test - personally this usually happens when I "got rid" of code without actually getting rid of it (rot).

I mainly work in Ruby and Rails these days, and I'll concede that it all gets a little blurred (and I did plenty of handwaving in that previous paragraph, but you couldn't see it because I was typing). But as long as you're doing something like that, I really do think you'll end up with a well tested app with full coverage.

TDD? Well, sure, I've done it, but I'm not going to insist on it, for myself or anyone else. You could write that integration test first, or you could write it iteratively. You could write a functional test that makes sure a bit of text is present on a web page, and then write the the code that generates that bit of text, or the other way around. I don't see it making a big difference - other than that forcing people to write the test first can be a mental intrusion that badly disrupts their thinking process on certain types of tasks.

In spite of all that, I (like a lot of people on HN, regardless of where they stand on TDD) would welcome a compelling rebuttal of DHH's recent blog post.


Your code is not hard to test because you don't do TDD. There is a different rule:

python -c 'from subprocess import *; print Popen(["python", "-c", "import this"], stdout=PIPE).communicate()[0].splitlines()[-3].replace("explain", "test")'

Yeah I know it's ruby thread :)


I think TDD is good when writing something you've done a few times before ("I know exactly how to write this app"). I tend to get projects that require exploration. I refuse to write a bunch of test code for each new class knowing that I might delete the class later.


Ad hominems seldomly make for a constructive argument.


'I possess the only truth and you need to prove me wrong not the other way around'.

I witness this so often I'm starting to believe it's the motto of the software industry.

The drift to fundamentalism about TDD over the last years is just another example. TDD is a good methodology that can save time and improve code quality, but only if understood and performed correctly.

That means more unit tests does not equal a better design and easier to maintain code base produced in less time. Better unit tests, testing non trivialities and accepting the limitations of unit testing does.

You cannot possibly test all states on a sufficiently complex, non trivial program constantly evolving to better fit its users' needs as they are discovered and redefined. And that's not the basis of TDD: Outlining your design by identifying its fundamental parts and writing tests for them before implementing them is.

Back to the main topic, I have seen people rant about version control systems, integrated developing environments and all kinds of tools and procedures involved in the software development process: They all take a few good arguments and stretch them to irrationality.

For example: how can somebody like git and HATE mercurial, bazaar... Maybe you prefer one or the other and you have your reasons, that's alright: Different tools for different people. But am I a dumb person for having different preferences? And if I'm not, does that mean you are dumb? I've seen pretty dumb things done by developers using every tool/methodology, including myself. Usually the reason is their lack of experience and understanding, much more often than using the wrong tool/methodology.

TDD or whatever, once you learn you'll do fine. But don't be an asshole and blindly criticize people who prefer doing it differently, even if you are the smarter one. Specially if you are the smarter one. And just because you don't understand a tool or methodology (yet, or ever) it doesn't mean people using it are dumb, that's all I'm saying.

TDD has been proven effective. TDD hasn't disprove all other effective approaches out there. Specially the ones yet to be discovered by less arrogant people.


Well he said "TDD is dead long live testing" didn't he? I don't even agree with David on some parts but but you can't write a rebuttal based on half a title.


Ruby and Rails are far bigger than any one person, and the types of apps many of us build today can be far more complex than Basecamp.

Saying that though, digging into what DHH said, he was really just arguing for pragmatism and the testing pyramid. He just used the wrong words to express it.

Let's be craftspeople, let's use the right design patterns, let's decouple our apps and test the right bits in abstraction, but let's also be agile and pragmatic.


This is turning into quite the flamewar. It's like Vi versus Emacs. I applaud DHH for challenging the TDD zealots and stirring the pot a bit.


The more things change, the more they stay the same...

It seems people always have a tendency to worship something, to let the means become the end or what is supposed to be their servant become their master.

TDD is a tool to ensure software quality. If TDD works for you then great. If you can achieve the same results with another method it's just as great. But I find the religion wars over it quite silly.


OT but I think that there is a place for a new programming language designed around making testing and TDD easy. Maybe the test code can be written in a higher level DSL or dialect of the same language.


It's not the arguments he uses, it's his tone. He's basically temperamental and irrespectful.

I agree with his points, but I would also have banned him.


I think author is just in wrong community. Some modern strongly typed language would suit him better. Hell even Python would do.


The original title should stay :)


tl;dr: Acronyms, abbreviations, anecdotes, and rants do not an engaged audience make.

Skip this and find a conversation with more substance, less flame, and less smoke.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: