Use Cases Don’t Replace Functional Requirements
One book about use cases states, “To sum up, all functional requirements can be captured as use cases, and many of the nonfunctional requirements can be associated with use cases” (Bittner and Spence 2003). I agree with the second part of this sentence but not with the first part. It is certainly true that use cases are a powerful technique for discovering the functional requirements for a system being developed. However, this statement suggests that use cases are the only tool needed for representing a software system’s functionality.
This notion that all functional requirements can fit into a set of use cases and that use cases contain all the functional requirements for a system appears in many of the books and methodologies that deal with use cases. The thinking seems to be that the use cases are the functional requirements. If the analyst writes good use cases, the developers are supposed to be able to build the system from that information, along with nonfunctional requirements information that’s included in a supplementary specification.1 Nonfunctional requirements, such as performance, usability, security, and availability goals, typically relate to a specific use case or even to a particular flow within a use case.
Unfortunately, despite the thousands of students I’ve taught in requirements seminars over the years, I have yet to meet a single person who has found this pure use case approach to work! Perhaps some people have successfully done it, but I haven’t met any of them. On the contrary, dozens of requirements analysts have told me, “We gave our use cases to the developers and they got the general idea, but the use cases just didn’t contain enough information. The developers had to keep asking questions to get the additional requirements that weren’t in the use cases.” I suppose you could argue that they must not have been very good use cases. But when dozens of people report the same unsatisfactory experience when trying to apply a particular methodology, I question the methodology’s practicality.
There are three problems with adhering to this philosophy of use case purity. First, your use cases must contain all the functional detail that the analysts need to convey to the developers. That requires writing highly detailed use cases. The sample use cases in some books do include some complex examples. But elaborate use cases become hard to read, review, and understand.
The second problem with this approach is that it forces you to invent use cases to hold all the functional requirements because a use case is the only container you have available to describe system functionality. However, some system functionality does not fit appropriately into a use case. I have seen many new use case practitioners struggle to create inappropriate use cases to hold all the bits of functionality, to no useful end.
Logging in to an ATM or a Web site is an example that illustrates this problem. Bittner and Spence (2003) provide this good definition of use case:
Describes how an actor uses a system to achieve a goal and what the system does for the actor to achieve that goal. It tells the story of how the system and its actors collaborate to deliver something of value for at least one of the actors.
By this definition, logging in to a system is not a legitimate use case because it provides no value to the person who is logging in. No one logs in to a system and feels as though he accomplished something as a result. Logging in is a means to an end, a necessary step to being able to perform use cases that do provide value. Nevertheless, the functionality to permit login and everything associated with it (such as business rules or integrity requirements regarding passwords) must be defined somewhere. If you’re using only use cases to capture functional requirements, you wind up inventing artificial use cases—those that don’t provide user value—just to have a place to store certain chunks of functionality. This artificiality does not add value to the requirements development process.
A third shortcoming of the use case–only philosophy is that use cases are organized in a way that makes good sense to users but not to developers. As Figure 11-1 illustrates, a use case consists of multiple small packages of information. A typical use case template contains sections for preconditions, postconditions, the normal flow of events, zero or more alternative flows (labeled with Alt. in Figure 11-1), zero or more exceptions (labeled with Ex.), possibly some business rules, and perhaps some additional special requirements.
Figure 11-1. Use case organization (left) differs from SRS organization (right)
These small packages are easy to understand and review, but they make it hard for the developer to see how the pieces fit together. As a developer, I find it more informative to see all the related requirements grouped together in a logical sequence. Suppose I read a functional requirement that implements a step in the normal flow. I want to see the requirements dealing with branch points into alternative flows and conditions that could trigger exceptions immediately following that one functional requirement. I’d like to see the requirements that handle each business rule in context, juxtaposed with the relevant system functionality.
As Figure 11-1 illustrates, the functional requirements that come from the various chunks of a use case can be sprinkled throughout a hierarchically organized SRS. Traceability analysis becomes important so that you can make sure every functional requirement associated with the use case traces back to a specific part of the use case. You also want to ensure that every piece of information in the use case leads to the necessary functionality in the SRS. In short, the way a use case is organized is different from the way many developers prefer to work.
It gets even more confusing if you’re employing use cases to describe the bulk of the functionality but have placed additional functional requirements that don’t relate to specific use cases into a supplemental specification (Leffingwell and Widrig 2003). This approach forces the developer to get some information from the use case documentation and then to scour the supplemental specification for other relevant inputs. Before your analysts impose a particular requirements-packaging strategy on the developers, have these two groups work together to determine the most effective ways to communicate requirements information. (See Chapter 12.)
My preference is for the analyst to create an SRS as the ultimate deliverable for the developers and testers. This SRS should contain all the known functional and nonfunctional requirements, regardless of whether they came from use cases or other sources. Functional requirements that originated in use cases should be traced back to those use cases so that readers and analysts know where they came from.