Hacker News new | ask | show | jobs
by jdlshore 4924 days ago
This is a really good and interesting question, and it's one I've been struggling with myself.

The problem boils down to this: TDD makes your software more maintainable (if you do it well) and it lowers your cost of development. However, it also takes significant time and effort to figure out how to test-drive a technology for the first time. Everybody can TDD a Stack class; TDD'ing a database, or a web server, or JavaScript [0] is a lot harder.

So the answer seems simple: use TDD for the parts you already know how to TDD.

But it's not so simple! It's much harder to add tests to existing code than it is to TDD it from scratch. Sometimes, it's flat-out impossible. The expense is so high, there's a very good chance that you'll never get around to adding tests to the un-TDD'd code. It will hang around causing bugs, preventing refactoring, and sapping your agility forever, or until you rewrite... and a rewrite of any significance will halt your company in its tracks, so you won't do that.

So the reality is that, anything you don't TDD from the beginning, you'll probably never be able to TDD. Companies that go down this road find themselves doing a major rewrite several years down the road, and that's crippling [1].

There's another wrinkle on top of this: manually testing code and fixing bugs is expensive. Once your codebase gets above a certain size--about six developer-weeks of effort, let's say--the cost to manually test everything exceeds the cost to TDD it. (The six weeks number is a guess. Some people argue it's less than that.)

So the real answer is a bit more nuanced:

1. If your MVP is truly a throw-away product that will take less than six weeks to build and deploy and you'll never build on it after that, use TDD only where it makes you immediately faster.

2. If your MVP is the basis of a long-lived product, use TDD for the parts you know how to TDD and don't do the parts you don't know how to TDD. Be creative about cutting scope. If you must do something you don't know how to TDD, figure it out and TDD it.

3. It's okay to be a bit sloppy about TDD'ing the edges of your app that are easily rewritten or isolated in modules. But be very careful about the core of your system.

That's my opinion based on 13 years of doing this stuff, including building five successively-less-minimal MVPs over the last nine months for my JS screencast. The first three MVPs were zero coding, the fourth was a throw-away site, and the fifth was TDD'd with aggressive scope cutting to minimize the number of technologies that had to be TDD'd.

[0] Shameless plug: I have a screencast on TDD'ing JavaScript that I'll be opening up to the public, on a subscription basis, in a month or so. http://www.letscodejavascript.com .

[1] Rewrites are crippling: See Joel Spolsky's "Things You Should Never Do, Part I." http://www.joelonsoftware.com/articles/fog0000000069.html (There is no Part II, by the way.)

3 comments

I think this is the comment I agree with the most so far.

I believe TDD is important, especially for a MVP one could argue. Do MVPs change a lot? Yes, obviously because you are learning and adapting to the needs of you customers. This is where have good test coverage (thanks to TDD) is a big asset. You can refactor, change, pivot, all you want, without the worry that removing this feature, tweaking that feature, or adding this other feature, won't break something else.

And manual testing is way more expensive then investing in automated testing.

In my opinion, unless it is a very short lived project that you don't plan to iterate on and isn't very important, you should have good test coverage. And good test coverage is best achieved with TDD.

This is of course just my 2 coins

I completely agree, and let me add to your point:

> manually testing code and fixing bugs is expensive

The codebase almost always starts small and simple, and the ratio of cost of development to the cost of testing will look misleadingly acceptable. Here's a made-up ratio:

2:1

As the codebase and complexity increase, keeping those ratios in the same proportion when manually testing is pretty much impossible, and the ratio may actually invert. Again, a made-up number:

1:2

If the business is relying on rolling out new features to continue to grow the business, this could become a big problem if revenue isn't growing at an even faster pace.

If you do decide to add tests to an existing code base, I found "Working Effectively with Legacy Code"[1] to be a good guide. Check out the table of contents.

[1] http://www.amazon.com/Working-Effectively-Legacy-Michael-Fea...