Joel Spolsky, in a post on
how to be a program manager writes:Writing a functional specification is at the very heart of agile development, because it lets you iterate rapidly over many possible designs before you write code. Compared to code, a written spec is trivial to change. The very act of writing a specification forces you to think through the design you thought you had in your head, and helps you see the flaws in it quickly so that you can iterate and try more designs. Teams that use functional specifications have better designed products, because they had the opportunity to explore more possible solutions quickly. They also write code faster, because they have a clearer picture when they start of what’s going to be needed.
I can testify from extensive personal experience that this is the absolute truth. The process of determining WHAT your software must do will pay off a million times over. Once you have a well-defined specification, the design just becomes obvious, because once you have your well-defined specification you KNOW without a doubt WHAT you must do.
You start with a general, high level view of WHAT your project must do. Break that specification into its natural divisions. They should be fairly obvious. Then for each of those natural divisions, you break that into more specific statements by asking yourself "what must be done to achieve this?" This process highlights the natural architecture of your software and helps you to structure it properly. Your end product should be a list, broken into natural sections, of specific, testable statements of functionality. Each should state one and only one thing - a single truth. If you can easily convert each statement to a simple yes-or-no/true-or-false question, you've done well. This process will raise a lot of questions for any non-trivial project. These questions are the holes in your understanding, which if left unanswered will cause your project to fail and make your customers unhappy. Finding theses gaps in understanding and getting them filled is where requirements specification shines.
While you're doing requirements specification, above all else YOU MUST NOT THINK ABOUT HOW TO IMPLEMENT IT! When you're writing requirements, you don't care HOW it gets done, just so long as WHAT you want done happens. Specifying HOW hides information. When you specify HOW, you hide WHY you did it that way and you remove the flexibility to use a better method to achieve the WHAT. Worst of all, you might specify HOW to do it, and end up doing the totally wrong thing. If your requirements have variable or class names in them, specific data structures or algorithms, they specify HOW. Throw them out!
Once you have your requirements complete, you understand WHAT must be done and the implementation will become fairly obvious. If it doesn't, then maybe you haven't broken it down well enough. After you've implemented it, you'll know your software is complete and correct because you can go through the requirements list testing each statement, asking yourself "Is this true of my software?"