Writing software requirements is hard! There’s no formulaic approach to it, and yet clarity is essential. High-quality requirements begin with proper grammar and spelling, well-constructed sentences, and a logical organization.
This article presents numerous style guidelines to keep in mind when writing functional requirements. However, I’m not a fan of arbitrary writing rules. Some I’ve heard are:
- A requirement may not contain the word and. And indicates the presence of two requirements, which must be separated.
- A requirement may not contain more than one sentence.
- A requirement may not contain more than 22 words.
Such simplistic rules are intended to help business analysts (BAs) write good requirements, but too often they aren’t good advice.
As you write your requirements, always remember your key objective: clear and effective communication among the project stakeholders.
I Shall Call This a Requirement
Shall is the traditional keyword for identifying a functional requirement. Functional requirements describe behaviors the system shall exhibit under certain circumstances or actions the system shall let the user take.
Some people object to the use of shall because it feels stilted. It’s not the way people normally talk, at least not outside English period-piece movies. True — but so what? Using a distinctive word like shall clearly distinguishes a requirement from other information in a specification.
Too many requirements documents use a random mix of verbs: shall, must, will, should, could, would, is recommended, is desirable, is requested, can, may, and might. People use many of these words interchangeably in casual conversation. The listener relies on context and the chance to ask for clarification to understand the speaker’s point. But this can become confusing in a document.
The reader is left to wonder if there’s a subtle but important distinction between these various keywords. Does must carry some different connotation than can? Does might (which conveys a sense of possibility in normal dialog) mean the same thing as may (which conveys a sense of permission)? I’ve also heard of conventions in which shall identifies a requirement, will indicates a design statement, and must signifies a constraint. That makes me nervous.
My preference is to use shall to identify functional requirements as a rule. It’s a well-established convention in requirements development. Perhaps you prefer must over shall, but avoid should, may, might, and similar words that don’t make it clear whether the statement really is a requirement. You might try replacing should with probably won’t and see if that’s all right with the customer. It probably won’t be.
Some organizations use shall to indicate a required function required, should to mean the function is desired, and may to indicate the function being described is optional. This combines two concepts: the statement of intended functionality and the relative priority of that functionality. The priority information is being communicated using words that, again, have similar meaning in everyday conversation. You have to trust that all readers will understand the priority implied by these words in the same way.
Instead of using the shall–should–may convention to communicate priority, I’d rather see three requirements in the form:
“The system shall … [Priority = High].”
“The system shall … [Priority = Medium].”
“The system shall … [Priority = Low].”
System Perspective or User Perspective?
Some people believe requirements ought to describe only the system’s behavior, because “the system” is what you create when you implement all the functional requirements. However, I think it’s appropriate to write functional requirements from either the system’s perspective or the user’s perspective. Use whichever structure offers the clearest communication in a given situation. Remember, that’s our prime directive.
Requirements written from the system’s perspective conform to this general structure:
Conditions: “When [some conditions are true]…”
Result: “… the system shall [do something]”
Qualifier: “…[response time goal or quality objective].”
The conditions part of the requirement could identify an event that triggers the system to respond in some way:
“When the Patron indicates that he does not wish to order any more food items, the system shall display all food items ordered, the individual food item prices, and the total payment amount within 1 second.”
This describes an event the system can detect and the action the system takes in response. This requirement also includes a performance goal, the one-second response time. That’s a nonfunctional requirement associated with this specific bit of system functionality.
In some cases, it makes more sense to describe actions the system will let the user perform under certain circumstances. Use this general structure when writing functional requirements from the user’s perspective:
User type: “The [user class or actor name]…”
Result type: “… shall be able to [do something]…”
Object: “… [to something].”
Qualifier: [response time goal or quality objective]
An alternative phrasing is “The system shall let (or allow, permit, or enable) the user to [do something].” It’s more meaningful to refer to the affected user class by name, rather just saying user:
“The Patron shall be able to reorder any meal he had ordered within the previous six months, provided that all food items in that order are available on the menu for the meal date.”
Use the Active Voice
Note that these examples are written in the active voice. They explicitly identify the entity that takes each action: the system, a particular type of user, or some other system component. I see many functional requirements written in passive voice:
“When the output state changes, it is logged in the event log.”
This doesn’t specify who exactly does the logging: one user or another, the system, or another system, component, or device. Whenever you can, recast such requirements in the much clearer active voice:
“When the output state changes, the system shall record the new state and the time of the state change in the event log.”
The more explicit and precise you can make each requirement statement, the more effectively readers can use it to guide their project work.
Parent and Child Requirements
When writing requirements in a hierarchical fashion, you record a parent requirement and one or more child requirements. The parent requirement is satisfied by implementing its children. Here’s an illustration of a hierarchical requirement with some problems:
3.4. The Requester shall enter a charge number for each chemical ordered.
3.4.1. The system shall validate charge numbers against the master corporate charge number list. If the charge number is invalid, the system shall notify the requester and shall not accept the order.
3.4.2. The charge number entered shall apply to an entire order, not to individual line items in the order.
This parent, 3.4, is itself written in the form of a functional requirement. So, are there two requirements here or three? It’s not clear. Also notice the conflict between the parent requirement and its child 3.4.2. If each chemical ordered is a line item, just how many charge numbers is the requester supposed to enter?
These problems disappear if the parent requirement is written as a heading or title instead of in the form of a functional requirement. Here’s an improved version:
3.4. Charge Numbers
3.4.1. The Requester shall enter a charge number for each chemical in an order.
3.4.2. The system shall validate charge numbers against the master corporate charge number list. If the charge number is not found on this list, the system shall notify the requester and reject the order.
What Was That Again?
Once when I was talking with my father about cars years ago I said, “I’d like to get one of those high-mileage gas-electric hybrids.” My father replied, “I don’t know if you’ll be able to find a used one.”
Used one? I didn’t say anything about buying a used car. Ah, I figured it out. When I said high-mileage I meant “gets many miles per gallon.” When my father heard high-mileage he thought “big number on the odometer.” These are both perfectly sensible, but distinct, interpretations of the ambiguous term high-mileage. Everyday natural language led to a puzzling miscommunication.
Similarly, ambiguity is a huge source of problems with requirements, and the author isn’t always standing right there to sort out the confusion. See my article “Six Tips for Writing Unambiguous Requirements” for a discussion of several common problem areas: synonyms and near-synonyms, pronouns, the abbreviations i.e. and e.g., the A/B construct, similar-sounding words, and adverbs.
The following sections offer some cautions about various sources of requirements ambiguity to watch for and some suggestions about how to avoid them. Nearly all the examples here are drawn from actual requirements documents I have reviewed for my consulting clients.
Complex logic offers many opportunities for ambiguities and missing requirements. Consider this paragraph:
If an order is placed for a chemical to a vendor, the system shall check to see if there are any other pending orders for that chemical. If there are, the system shall display the vendor name, vendor catalog number, and the name of the person who placed each previous order. If the user wishes to contact any person who placed a previous order, the system shall allow the user to send that person an e-mail message.
This long requirement is not easy to follow. It contains multiple functionality descriptions that should be split into separate requirements. Writing requirements in this style makes it difficult to tell if the outcomes of all the if/then branches are specified, along with any “else” conditions.
Rather than using natural language like this, it’s better to represent the logic visually in a decision table or decision tree. The decision tree in Figure 1 makes the flow clearer. It also reveals that the system’s behavior is unspecified if there aren’t any pending orders for the chemical being requested.
The original requirement also failed to describe how to handle other false outcomes from the various decisions. The reader might conclude that the system should do nothing if the various if conditions described here are false, but that’s an assumption forced by the incompleteness. Decision tables and trees are powerful tools for representing complex logic.
Negative — or inverse — requirements present another source of confusion. Constraining business rules sometimes describe actions that specific users are not permitted to take. This isn’t desirable in requirements, though. Try to recast inverse requirements in a positive sense, to state what the system will do under certain circumstances.
Table 1 states several (again, real) functional requirements that contain negation, along with possible ways to rewrite them in a positive sense. I’ve also recast these passive-voice requirements into the clearer active voice to show what entity is taking each action.
Changing a negative requirement into a positive one often requires inserting the word only to identify the conditions that permit the system response to take place. Note also the ambiguity in the third example in Table 1: is cannot (as in “not able to”) equivalent to may not (as in “not permitted to”), or are they different? So many traps to avoid!
Avoid double and triple negatives always. Consider this example:
Training rewards and points will not be visible to users who cannot participate in training rewards.
We can rephrase this double negative into a clearer positive statement:
The system shall display training rewards and points only to users who are permitted to participate in training rewards.
Multiple negations can lead to confusion, as illustrated here:
Records, however, should not fail validation if these attributes are not present at all.
Does this mean that the records should fail validation if the attributes are present? Probably not. The context might make the meaning of this requirement clearer, but as written, it raises a question in my mind. The main message here is to think positive when writing requirements!
Requirements sometimes lack important information. This makes it hard for all readers to interpret them in the same way unless they make precisely the same assumptions.
A requirement might describe a behavior without identifying the triggering cause that leads to that behavior:
The system shall generate a parsing error report and forward it to the user.
But what stimulus leads the system to produce the error report? It’s not indicated.
Another common error class involves missing descriptions of how exceptions should be handled. In the previous example, what should happen if no errors occur during the processing being described? It’s unspecified, thereby leaving it up to the developer to decide what to do. Options include:
- Do nothing (an assumed default perhaps).
- Present a “Congratulations! No errors found” message but do not generate a report.
- Generate an empty report and forward it to the user.
- Generate a report stating that no errors were found and forward it to the user.
Perhaps we add the following requirement to address the case in which no errors are encountered:
If parsing is successful, the system shall not generate an error report.
This is another description of the system doing nothing, though, as we discussed under “Negative Requirements” above. It would be better to state what the system will do if there aren’t any parsing errors, even if it’s to simply continue the processing.
Another kind of incompleteness occurs when requirements describe system behaviors involving some type of symmetry. Suppose you’re specifying the requirements for a bookmark feature. You might say:
The system shall display the user’s defined bookmarks in a collapsible hierarchical tree structure.
But what if the user wants to expand the tree structure after collapsing it? It’s easy to overlook that sort of symmetrical or reverse operation. You could add a second requirement stating that the tree can be expanded, or you could alter this requirement to say “…in a collapsible and expandable hierarchical tree structure.”
If you omit the reverse operation, the customer and BA might assume the missing half of the symmetrical requirement is implied. If you request an undo function, of course you want a redo capability as well, right? But implicit requirements make me nervous. They involve too many assumptions about other stakeholders’ knowledge and thought processes to ensure that we all get the product we expect.
Suppose you’re writing software for a point-of-sale system and a business rule states, “Only supervisors may issue cash refunds greater than $50.” A BA might derive several functional requirements from that rule:
1. If the amount of the cash refund is less than $50, the system shall open the cash register drawer.
2. If the amount of the cash refund is more than $50 and the user is a supervisor, the system shall open the cash register drawer. If the user is not a supervisor, the system shall display a message: “Call a supervisor for this transaction.”
But what if the amount of the cash refund is exactly $50? Is this a third, unspecified case? Or is it one of the two cases already described? If so, which one? Boundary value ambiguity like this forces the developer either to make his best guess or to track down someone to answer the question.
You can resolve boundary ambiguities in two ways. First, you could rewrite requirement #1 above as:
If the amount of the cash refund is less than or equal to $50, the system shall open the cash register drawer.
This preserves the original intent of the business rule and eliminates the ambiguity.
Alternatively, you could use the words inclusive and exclusive to indicate whether or not the endpoints of a numerical range lie within the range. To illustrate with a different example, you might say:
The system shall calculate a 20% discount on orders of 6 to 10 units, inclusive.
This wording makes it perfectly clear that both endpoints of the range, 6 and 10, lie within the range subject to the 20-percent price discount.
You still need to review a set of similar requirements to make sure the range endpoints don’t overlap, though. Note the inconsistency between the following two requirements:
1. The system shall calculate a 20% discount on orders of 6 to 10 units, inclusive.
2. The system shall calculate a 30% discount on orders of 10 to 20 units, inclusive.
The boundary value of 10 is incorrectly included in both ranges. Using a table to show this sort of information is more concise and makes these kinds of errors more evident:
When we talk about “writing requirements” we typically think in terms of writing out natural language statements. Often, though, you’re better off using other ways to represent information, such as in tables.
It’s Worth the Extra Effort
You won’t learn how to write good requirements just from reading about how to do it; you need practice. Write requirements to the best of your ability and then enlist some colleagues to review them. Constructive feedback from reviewers can help anyone become a better writer. In fact, it’s essential.
Remember that requirements quality is in the eye of the reader of the requirements, not their author. No matter how fine you think your requirements are, the ultimate arbiters are those who must base their own work on them.
This article is adapted from More About Software Requirements by Karl Wiegers. If you’re interested in software requirements, business analysis, project management, software quality, or consulting, Process Impact provides numerous useful publications, downloads, and other resources. Karl’s latest book is The Thoughtless Design of Everyday Things.