While Access itself is a development product, developers need to think about much more than writing code. When working with clients, it's crucial to understand the requirements for the application before writing code. In this article, Mike looks at some of the fundamentals of requirements management for the Access developer.
Let me start with a true story from my own consulting history. I won't tell you who the client was (my lawyer would frown on that, since he had to get involved in extricating us from the situation), but this was well after I was established in the Access field as a trainer, writer, and developer. Along with a couple of other coders, I signed on to do a major job for a mid-sized (about 100 employees) manufacturing company. What they wanted seemed fairly simple: a bill of materials database, with links back to their accounting system, to let them track the custom work they were doing for various clients of their own. The company's vice president was pretty savvy about PCs himself and had decided that Access was the language of choice for this project.
We started early one Monday morning with some simple entity-relationship analysis, talked to enough people to make sure we understood the structure of their bills of materials, and started writing code. Not wanting to spend much time in their small town, we did the bulk of our work off-site, issuing periodic, upbeat progress reports by phone and e-mail. After a month, we went back with what we thought was a finished application and a large invoice.
That was when the trouble started. "I was promised it would do inventory forecasting," said one person in the accounting department. "Where's my daily report?" was the question of someone high up in production. In short order, we realized that what we built had nothing to do with what they needed, wanted, or expected. Worse yet (from our point of view), our contract called for building software to the client's satisfaction. We clearly hadn't ascertained what would satisfy them, and things quickly turned ugly over the issue of a large invoice for a product that they didn't think was relevant to their needs.
In retrospect, what we left out of the picture was requirements management. "Build a bill of materials database" isn't a requirement. "Generate a report on expected inventory levels for the next three weeks, for all base-level items, on a daily basis" is a requirement: It's clear enough to build a bit of software from. Had we taken the time to collect requirements, we could have avoided the nasty end result of a canceled project and a dissatisfied customer.
What is a requirement?
Let's start with the basics. Before you can make good use of requirements, you need to understand what a requirement is. The definition I use is that a requirement is a specification that tells you what should be implemented in an application. Some typical requirements you might see for an Access database could include:
|•||A user-level facility: "The user must be able to specify how many weeks the aging report covers." |
|•||A general system property: "All employee data must be encrypted so it's not available to an external program." |
|•||A development constraint: "All code must use the Reddick VBA naming convention."|
It's just as important to understand what a requirement is not. Requirements don't include:
|•||A completely abstract description of the system: "Build an accounting program." |
|•||Database language: "The employees table must have a many-to-one relationship to the departments table."|
In the first case, the demand for an accounting system isn't detailed enough to be considered a requirement. Think of this in terms of testability: What test would determine if you had built an accounting system? If you can't think of a way to prove that a requirement was met by the final software, then it's probably too abstract to be a good requirement. When that happens, you must break the requirement down into smaller requirements. For example, one requirement for an accounting system might be: "The system should store supplier and payment information on all invoices received."
The second case fails because requirements should always be written in the language of users (the problem domain), not in the language of developers (the computer domain). Leave the computer talk for the design phase of your project. The second requirement should probably be rewritten as: "Each employee should be a member of precisely one department."
The fact that requirements should be in "user language" means that developers are usually the worst possible people to come up with the requirements for a project. There's no substitute for talking to the actual users of the system. Asking over and over again: "What else do you want the program to do?" is a vital part of the process. If you're not thoroughly versed in your user's business, you'd better alternate that question with, "Can you explain to me what that means?" Some developers dislike this sort of interaction, thinking it somehow lowers their prestige. I suspect they're the least likely developers to deliver useful systems.
Requirements as contract
A thorough set of requirements represents a contract between the client and the developer. On one side, it says, "I expect you to build software that does these things." On the other, it says, "I understand that this is what you need the software to do." The mistake many developers make is to consider the requirements as an immutable contract. This is simply unrealistic. For one thing, no matter how patient you are in eliciting requirements from users, you're not likely to get everything in a few meetings. For another, the business changes even while you're building the software.
I was recently involved in a project to build a utility with a graphical "Wizard" interface. After the Wizard asked some questions, it would build a text file that was used by another program. The written specification for this program ran five pages, and when it was done both the client and I were satisfied that the requirements described the software. When I was about 75 percent done, the lead developer for the other program came to me with an additional requirement: For some scenarios, they needed to be able to launch the utility I was writing from a command line, supplying all the necessary arguments and suppressing the user interface entirely.
I could have reacted as many developers would, by simply saying, "That's not in the spec!" Instead, I took the time to sit with the other developer and the manager involved and write some additional concrete requirements so that we both understood the work involved. Then I worked up an estimate for the additional work. The manager approved the estimate, we amended the requirements document (and kept both the old and new versions so we could track the changes), and the additional work proceeded. The result was a satisfied customer and more billable hours for me.
According to research reported by Capers Jones in Assessment and Control of Software Risks (Yourdon Press, 1994), "Creeping requirements changes average about 1% per month." For a project of any magnitude, you simply must plan ahead for this. On a year-long contract, the expected requirements changes will amount to an extra month of work. Clients who aren't expecting this will be unhappy with the additional cost. If you're not expecting this, you won't finish the job. Make sure that all parties understand up front that the requirements document is subject to change, and that major changes will incur additional costs. As Steve McConnell says in Code Complete (Microsoft Press, 1993), "A plan to follow the requirements rigidly is actually a plan not to respond to your customer."
What do you do with a customer who won't understand this point or, worse yet, won't budget any money for requirements analysis at all? Walk away and find another customer. If this simply isn't feasible, make sure your contract is strictly time and materials, and have your lawyer check that you won't incur any penalties when the project is canceled without being finished. Anything else is a huge gamble. (For more on which projects to walk away from, see Ed Yourdon's book, Death March [Prentice Hall PTR, 1997].)
Requirements and iterative prototyping
Fortunately, those of us working in Access have a powerful tool for helping elicit the requirements that users didn't think of during the first set of interviews: iterative prototyping, or "false-front" development. The idea is pretty simple. Armed with the requirements, go back to your cubicle and slap together the user interface for the application. Don't get hung up on the final data model, report design, menus, or anything else. Forms with buttons leading to other forms with textboxes are plenty. Hardwire the text in the textboxes to reasonable values -- that is, when you open the customer form, it should show a customer, but it doesn't have to be coming from a customer table. Write the minimum code, or even macros, necessary to make the demonstration application flow when you push buttons, select values from combo boxes, or whatever.
Then, take the demonstration version of the application back to the users and run through it. Show which buttons lead where, how you've grouped functionality together, and what input controls exist. Talk through the application, relying on paper when necessary ("When you push this button, we'll print a report that looks sort of like this sketch"). All the while, of course, take notes on where the users see problems with the demonstration.
On one recent project, the requirement was to allow selection of a customer service agent and display a list of the orders handled by that agent. When I got to that point in the demonstration, I showed the customer how to select an agent from a combo box and see the orders in an associated listbox. "How do I sort the orders so I see the oldest ones first?" was the response, and I knew immediately that we'd missed a requirement. I assured the user that they'd be able to do that in the final version and added that to my list of requirements for the day. No, I didn't insist that the manager sign off on a new estimate for something that minor. Your initial estimate should be realistic enough to handle this sort of minor change without having to quote a new price to the customer.
Other requirements management techniques
There are whole books out there on requirements engineering (the discipline that analyzes the software requirements process) that explore techniques ranging from simply standardizing on a template for your requirements documents to using a formal, mathematical language for specifications. Without trying to cover the field, let me suggest a few techniques from my own experience:
1. Don't assume that you know everything, even after talking to the users. Any software project of substantial size will affect multiple stakeholders: end users, managers, technical support people, customers, and more. Make sure you collect requirements from every group of stakeholders that you can identify. It's up to your client to decide on the requirements that are actually important enough to be implemented, but you should try for a complete wish list.
2. Plan for a requirements review. This should be a formal meeting between the developers and the client after the requirements document has been compiled. Often, you can convince the client to schedule this meeting by simply insisting that you can't refine your cost estimate until they sign off on a set of requirements.
3. Plan for conflict resolution. In an ideal world, this wouldn't be the job of the software developer. In the real world, you'll often be the one who discovers that two groups of users have contradictory requirements for the software. Make sure you understand who holds the political power in the organization, so you know who can settle these disputes. Try to limit your participation to collecting information and suggesting the relative costs of different implementations of the software.
4. Do everything you can to make the requirements document easy to read. Don't use technical terms if you can avoid it, especially computer technical terms. If you must use technical terms, define them. If the document is long, include a table of contents and possibly an index. When you print the document, leave margins wide enough to scribble in. It's in your best interest to have this document widely reviewed in the client's organization. Encourage people to submit their comments before the requirements review so that they can be incorporated.
5. Spell out who is responsible for what in your requirements document. I usually include a section labeled "Ownership" that, at the minimum, lists who has the responsibility for funding the project, maintaining the requirements document, writing the code, testing the code, and signing off on the final product.
6. Either keep all versions of the requirements document that you circulate or put the requirements document into your source code control system. Using change bars and annotation marks in your document also helps. Keep track of when changes are made, why they're made, and who authorized them. Toward the end of the development process, you might find that you need to be able to justify additional time spent. It's much better to say "Tom in accounting needed this, and your project manager approved it in our June 3rd meeting" than "I think someone in accounting asked for that feature."
How do you justify all this concentration on requirements to clients who might not understand the software development process as well as you do? One way is to cite some figures from Code Complete, based on studies done at IBM, TRW, and GTE. Suppose that one of the requirements for a project is erroneous and that it would take an hour of your time -- $100 -- to correct by doing a more rigorous requirements analysis. Without that requirements analysis, that same defect would cost:
|•||$500 to correct during design. |
|•||$1,000 to correct during coding. |
|•||$2,000 to correct during unit test. |
|•||$5,000 to correct during system test. |
|•||$10,000 to correct during maintenance.|
All but the most devil-may-care customer will understand this argument and be willing to spend the extra time up front to avoid spending a lot more time (and money) down the road. In fact, it's a general principle of software construction that errors detected closest to the point at which they happen are cheapest to correct. Had I understood this basic point, the debacle I described at the beginning of this article would never have happened. With no requirements, 100 percent of the requirements must be wrong, and the cost of correcting this problem during the system test is simply prohibitive.
Fortunately, the problem is relatively simple to correct. Even the simple act of sitting down with the customer and the users for a few meetings to generate a Word document listing requirements is a powerful tool for making sure that you're building the software the client wants. If you do this much, you'll generally be ahead of the majority of developers in Access, VBA, and Visual Basic. Once you're at that point, you can investigate using a more formal process. In a future Smart Access article, I'll review a product, Requisite Pro, that will help you set up such a formal requirements management process.