We’re assuming here that you’re already conceptually on board with writing specs. If you’re skeptical, Joel Spolsky will set you straight! Here’s my own mini-pitch for specs: Writing software involves a lot of backing yourself into corners. For even the simplest-seeming program, you find yourself adding duct tape and chewing gum to satisfy different requirements and logic bugs that come up. Then you gradually whittle it back down and end up with a few simple lines and it’s bewildering how you were too dumb to have not just written the nice simple thing from the start. The beauty of specs is that you can do most of that backtracking and whittling down and rethinking before you start coding.
Bee and I talk about functional specs a lot. Mostly that consists of me saying how important they are, or quoting some brilliant thing Joel Spolsky said about them, and Bee nodding absent-mindedly and sticking her head back in the guts of Beeminder’s code.
In one of those one-sided conversations I came up with a thought experiment for answering the perennial question: “OK, I wrote some things about what we should implement — how do I know if it counts as a functional spec?”
Here’s a way! Consider a nifty thing you personally built and deployed and use (or someone uses). In Bee’s case maybe it’s some circumscribed part of Beeminder or her old taskbot or some other fun side project she’s hacked up. Now imagine literally pasting the entire source code into a text document. (I’m imagining a lot of very skeptical looks and this might sound crazier before it gets saner but bear with me!)
Ok, next, imagine going through that code line by line converting it to readable prose. Only delete a line of code from the document when it’s been covered by prose. Or when the prose acknowledges the existence of implementation details not worth describing. (This is the saner part.)
The idea is that for every decision, big or small, that you had to make when writing that code, your spec makes it too. Sometimes a chunk of code has no actual decisions in it and can be replaced with a single sentence. “Do such-and-such in the obvious way.” Other bits of code are the opposite. Like so-called business logic which can be preserved verbatim. Something like “decide if a goal is derailed with the following function…”
“We can expand the continuum further, all the way from elevator pitch to production code”
In fact, a good definition of business logic, though a bit circular in this context, is: code that the functional spec should include. To be less circular, think of business logic as the core algorithm being implemented, not counting the UI or the database stuff — the things that wouldn’t change if you implemented your thing with pencil and paper or some future alien technology or anything in between. (Business logic needn’t have anything to do with business and we should probably use the synonym “domain logic” instead but “business logic” seems more common.) The point here is that it’s critical in a functional spec to fully describe the business logic, preferably with pseudocode or even snippets of actual code, if it’s clean enough.
So to answer the question we started with, when you have a candidate spec for a new thing you’re going to build, imagine if you could reach into the future and grab the final source code of it. Now imagine going through that process of prose-ifying the entirety of it. Is the spec you actually wrote a plausible output of that process?
That sounds like a technical spec, not a functional spec
Those are just two points on a continuum! In this thought experiment, for a purely functional spec, you throw away all code except the business logic. If it’s not user-visible then axe it entirely; if it is, replace it with a prosaic description of its impact on the user. Further along the spectrum is a technical spec, where every non-obvious decision is included. And in fact we can expand the continuum further in both directions, all the way from elevator pitch to full production code:
Starting on the left — 0% of a spec — we have the elevator pitch. Namely, the version you can describe in the amount of time it takes to ride an elevator. We could also call it the spitball but that sounds gross. Fleshing out that spitball (sorry) gets you to the Powerpoint version — 10% of the way to a final product — with lots of explicit hand-waving over the details. But at least you’re thinking about use cases and sketching how things will look. The (arbitrarily chosen) 25% mark is where it gets interesting. This is how you might write a spec if you’re a noob. It seems like a complete spec but is full of hand-waving that you don’t notice you’re doing. (This is what my thought experiment aims to help with.) Double that Seeming Spec (realistically much more than doubling if measured in time and effort) and you’re finally halfway to the eventual code: a full functional spec. Go another half-distance to your goal — 75% — and that’s where I’m putting the technical spec. It’s not too far from a prototype or reference implementation (90%). Finally, that last 10% (again, much more as measured in time and effort!) takes you from the prototype to production.
UPDATE: See our followup post, How To Write Functional Specs II: The Spec-List