Proof-Driven Development


Mon Jan 28 14:15:00 -0800 2008

In developing the early implementation of Heroku, I stumbled upon an interesting design/development technique: numerous throwaway proof-of-concepts for potential features. Heroku is an unusual product, and many of the features we envisioned were things we weren’t even sure could be accomplished in a reasonable way with current browser technology. Writing these proofs let us explore the problem space without committing to a single product direction or internal architecture too early.

Each proof was something I threw together in a day or two, usually a single evening. I always made them as standalone project, showing the feature being proofed in isolation. One example I posted publicly was the proof of the javascript code editor.

You might argue that this is nothing new - they’re called prototypes or tracer rounds. Although it does have much in common with prototype-driven development, proof-driven development actually comes in from the opposite side. Prototypes are supposed to be skeletal demonstrations of the entire application - as Dave Thomas puts it, to “show people how it’s going to hang together.” The hard implementation details are left as stubs; it’s about the big picture, not details.

Proof-driven development is about the details. You prove that a specific feature can be implemented well, and that it will deliver useful value. It’s a vertical slice of the application, instead of a horizontal one.

There are a few interesting effects that emerge from working this way. First, since you’re starting from scratch each time, it means you’re not constrained by any existing code or design. This gives a lot more room for creativity and experimentation. Normally you decide on a big-picture architecture up front, and then force features to fit into that architecture as they are built. Proof-driven development allows you to try out a bunch of cool ideas without worrying how they fit together. Then, you can select your favorites from the list, and think about what kind of high-level architecture would tie them all together.

Another effect of this approach is that it prevents you from getting to attached to any one idea or design choice. When working in an agile environment, developers often throw in experimental features somewhat on a whim to see how they’ll work. That’s great - often your best features come from this sort of spontaneous inspiration. But other times - probably most of the time - it adds to feature and code clutter, without adding much value. The problem is, once they are in the codebase, they tend to stay.

But since proofs are developed as standalone apps, you have to make a conscious choice to bring that code into your production app. The manual work of cut-and-paste as enough to deter you from bringing in some code unless it’s really valuable. Which is a highly desirable effect, since it keeps your main codebase streamlined.

So now when our team is kicking around ideas for new components, the resolution on many points is “ok sounds cool, write a proof.” The chief proponent for the idea can then go put together a standalone proof, spending at most a couple of hours, to demonstrate the value of the idea. When they’re done it’ll either be obvious that the new feature is really kick-ass and deserves to be included; or, perhaps it won’t be too hot, in which case it can quietly be dropped without having dirtied our main code at all.

I do recommend keeping a git/svn/whatever repo for your proofs though. Even for ones you don’t use, being able to come back and examine a failed technique can be useful in the future. In some cases, we’ve even written proofs that have not been deemed useful at the time, but later on serve as inspiration for something else.