TDD isn't dead just because DHH can't do it
rubylove.io
rubylove.io
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.
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?
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).
Plus:
> fight fire with fire
Seriosly.
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.
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>
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.
Are other communities like this or is it more pronounced in the ruby community?
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.
"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.
TDD isn't dead, but it also isn't a silver bullet.
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!
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)...
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.
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.
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.
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.
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.
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.
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 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.
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.
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.
I agree with his points, but I would also have banned him.
Skip this and find a conversation with more substance, less flame, and less smoke.