|laziness, impatience, and hubris|
Specifications can have a way of taking on a life of their own, chewing up resources both to write and argue about them, and to keep them updated. Finding the right balance can be tricky, particularly when there are non-designing, non-coding "process" people in the mix.
I've found that it helps to clearly distinguish two types of specifications:
External specifications talk about externally visible aspects of the system. These specs serve as an interface between the development team and other stakeholders, such as documentation and QA. Getting these as close to right as possible on a large project is important. The trick is to put as little effort into getting them there as you can, since the process can a time vampire.
The type of external specification that I've gotten the most mileage out of over the past few projects has been Use Cases that describe concrete interactions between a user and the system. Uses Cases give the customer an early chance to say "yeah, that's how it's supposed to work" or "no, that's not the way we do things." And once the customer has signed off, they're a good customer proxy to have when a customer isn't available to talk with.
One thing I've seen projects skip doing when writing external specifications, to their eventual dismay, is to include a list of what the product won't do. A negative specification is a good way to keep Sales and Marketing in check! And you avoid some messy battles of the "you said you were going to do X!", "no I didn't!" type.
Internal specifications talk about what goes on under the hood. The conundrum here is that while most people say they need more in the way of internal specifications, most of what's produced (in my experience) has a short shelf-life, and little long-term value. The lasting internal non-code artifacts are typically diagrams: A one- or two-page object model, an interaction diagram, a decorated database schema. Other documents, unless they're close to the code, tend to drift off towards the bottom shelf or the back of some desk drawer. So, draw pictures.
Since the final authority is always code, keeping internal specs as close to code as possible can be a win. A lot of Perl code gets this right by using POD, which is easy to extract it into HTML for on-line specifications. Judicious use of javadoc is a win if you're working there. On my current project, we write PODs and javadoc as part of the design process.