Living in the Punch-Card Era
July 29, 2008
Commentary on The Art of Agile Development's Ten-Minute Build practice.
I'm obsessed with fast builds. There's a good reason for this: fast builds means quicker feedback. Quicker feedback means fewer bugs. If the feedback gets fast enough (less than ten seconds), and if you have comprehensive regression tests, then your entire approach to coding changes. You stop worrying about whether your changes work or not and just program. Thoughts flow from brain to program without stopping to worry about bugs. It's an amazing way to work... and I'm willing to bet you've never experienced it because your build is too slow. (Heck, half of you have given up on me as an idiot at this point. It's okay. I'm used to it.)
Allow me to illustrate. Once upon a time, people had to worry about syntax errors. You know, when you accidentally mistype something, or leave out a semicolon? They obsessed over them, tediously desk-checking their work, to make sure that their programs had no errors, before they even thought about putting it in the computer!
"Ridiculous!", you scoff? No, just old. This happened in the punch-card era of computing, in the 60's and 70's. It could take 24 hours to get your stack of punch cards input into the computer, compiled, and run. Compiler errors meant your job was rejected and you had to find the error, fix it, resubmit, and wait another 24 hours. Painful, yes. Thus with the desk-checking.
You don't desk-check, do you. Nope... you type in your program, and if you make a typo (happens all the time, doesn't it?), then a little red squiggly appears in your IDE and you fix it! No brainer. In fact, it's so ingrained, you probably don't even notice half the syntax errors you make.
A fast build with good tests is like that. Except that the errors you find and fix are semantic errors--bugs--not syntax errors.
Good builds are game-changing.
So, how do you do it?
It's not hard, but it's not obvious, either. The obvious part is that you have to automate your build. Your IDE's build almost certainly won't cut it. It's also pretty obvious that you have to have a comprehensive regression test suite. (This is easy if you're creating a new system and you use test-driven development from the start. It's less easy when you're working with existing code.)
The part that's not obvious is that you don't just need a regression test suite, you need an awesome regression test suite. By "awesome," I mean that it has to be fast. You're going to have thousands of tests and you want this puppy to finish in less than ten minutes, and the majority of the tests need to finish in less than ten seconds. That means you have to be able to run hundreds of tests per second.
You can see why this is unobvious. Most people create tests that set up data in the database, stimulate some part of the application, then check that the database changed correctly. It's slow. For complex systems with many tiers, it's hella slow. It's also brittle and prone to breakage, and creating test environments is usually a real pain in the keister.
If you're doing the database thing, you're probably running less than ten tests per second. For some of you, your tests are taking tens of seconds each, and they're breaking all the time.
Yup, fast builds: not obvious.
Here's the key. You have to let go of the integration tests. Figure out how to replace end-to-end integration tests with unit tests. You don't have to get rid of all of them, but the better you get, the fewer you need.
Part of the challenge here is that fast tests require a different design mindset. If you're creating end-to-end tests rather than unit tests and focused integration tests (the good form of integration test: they're like unit tests, but they cross a process boundary), you can get away with all kinds of sloppy, tightly-coupled design. If you primarily write unit tests (and focused integration tests), you have to decouple, create strong responsibilities, and have ways to instantiate objects independently of each other.
Rise to the challenge. Fast builds with awesome tests will change your life. For programmers, they're the best thing you can do for your codebase, your productivity, and your enjoyment of work.
Go ahead. It's time to stop living in the punch-card era.