Hacker News new | ask | show | jobs
by megaduck 4846 days ago
I work at one of those "contracting shops" (Pivotal Labs), and I think you're misunderstanding the reason we push TDD so damn hard: It's not about speed. It's about predictability.

Good TDD forces you into building loosely-coupled code that's easy to refactor and change. When new business requirements come in, the effort for implementing them isn't increased because of your previous code getting in the way. There's an overhead to writing the tests, but it's a fixed continuous cost. As a result, you're always in a position where you can ship a new feature in a predictable (and reasonably fast) fashion.

Not doing TDD often leads to tightly-coupled brittle software, which can be very fast to implement but also difficult to change down the road. It certainly doesn't have to, but in reality that's what happens 90% of the time.

There's a few successful startups that immediately spring to mind that use TDD (Taskrabbit and Modcloth spring immediately to mind). However, the real question you should be asking is, "Which startups died because they got buried under the weight of their own codebase?" That's a long and very depressing list. In many of those situations, some TDD might have helped.

In short: TDD won't make your startup healthy, but it helps ward off some of the more common fatal diseases.

3 comments

I don't understand this. You give a disclaimer saying TDD won't make your startup healthy, but then your second paragraph implies that "Good TDD" is a silver bullet by "forcing you" into building "loosely-coupled code that's easy to refactor and change".

TDD can test a monolithic `public static void main(String[] args)` just as well as the most dainty collection of python scripts. In fact, assuming you wrote the two to behave the same, your tests wouldn't know the difference. Isn't one of the larger problems of TDD that it simply tests quantifiable results, not profile the machinations of the code?

Writing truly good code is hard. It takes time, practice and a wealth of knowledge... No "process" (as the GP states) will shortcut these requirements for you.

Clarification: Your code != your startup.

You can have a polished high quality codebase, but still have a dying startup because you've built something that nobody wants. Conversely, having a desirable product makes up for a vast multitude of sins.

However, technical debt is expensive. Having a clean well-factored codebase makes changes cheaper, which means your company will have lower overhead and be more responsive to market demands.

As far as "forcing you to build loosely coupled code", good TDD should involve a thin layer of integration tests (Selenium/Capybara/Whatever), which drive out unit tests for the individual components. If you let the tests drive your code design, and follow the "Red -> Green -> Refactor" workflow, it tends to shepherd you into writing small easily testable functions and objects that are loosely coupled.

You can also use TDD to salvage crappy code, and derive good design even after the damage has been done. For a beautiful demonstration of this process at work, I strongly recommend Katrina Owen's video on "Therapeutic Refactoring". http://www.youtube.com/watch?v=J4dlF0kcThQ

Of course, there's no substitute for having good technical instincts. I couldn't agree with you more on that point. TDD isn't a silver bullet. It's just a damn useful tool, and more startups should be using it.

> "Which startups died because they got buried under the weight of their own codebase?" That's a long and very depressing list. In many of those situations, some TDD might have helped.

Could you give some examples? PG doesn't include that in his list: http://www.paulgraham.com/startupmistakes.html, and in my personal experience I've never met a startup that failed because they had an unmanageable codebase.

Quite a few actually. I can name two off the top. You've probably never heard of them (why would you, they failed). Saber, and Lucid. Oh, there are certainly others. What kills them is a code base that's too tangled to manage. Estimates grow by an order of magnitude, costs skyrocket, defects mount, customers flee, investors cut their losses.
Because of a bad codebase Netscape ended up rewriting their system which took 3 years. In the meantime their browser lost market share: http://www.joelonsoftware.com/articles/fog0000000069.html
> Not doing TDD often leads to tightly-coupled brittle software, which can be very fast to implement but also difficult to change down the road. It certainly doesn't have to, but in reality that's what happens 90% of the time.

This is flatly wrong. It may be a tool for productive programmers to keep their code on the right track, but assuming that loosely-coupled code isn't written without it is a huge overreach. Certainly, tests do help, but TDD is just a tool in the toolbox. I have seen many very talented programmers and many of them do not need TDD to produce stable, well-architected projects.

I can only speak from my experience (20 years) of developing web apps, but I've never seen a cohesive, loosely coupled web app, that was both over 2 years old AND not using some form of TDD.
Phrased that way, I agree completely. An established codebase needs to be verified in some ways. But writing code and running it against tests is not exactly equivalent to TDD.

TDD as I understand it is characterized by writing a failing test, followed by implementation code, followed by test-fixing, etc.

However, I can write plenty of good code that does what it's supposed to and works and is stable. THEN I'll refactor as needed, write tests, and since I anticipated my needs, making those tests good and the code testable will be relatively straightforward. That's not TDD, though. It's a pragmatic approach that doesn't prioritize setting requirements (or solidifying an API) over starting simple and iterating quickly.

Funny, I had a comment ready before Matt's that started "I can only speak from my experience..."

So, yeah...in my experience this has played out exactly so: in practice, coders who ignore TDD are probably also ignoring a lot of other good practices. The two principles may be "orthogonal" in theory, but the correlation has strong anecdotal support for me.