I once read a book about use cases that stated, “To sum up, all functional requirements can be captured as use cases, and many of the nonfunctional requirements can be associated with use cases.” 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. In most cases, they aren't.
Use Cases Don’t Replace Functional Requirements
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 BA writes good use cases, the developers are supposed to be able to build the system from that information, along with additional nonfunctional requirements information that’s included in a supplementary specification. 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.
After querying the thousands of students I've taught in requirements seminars over the years, I have met very few people who have found this pure use case approach to work. On the contrary, dozens of BAs 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 ask a lot of 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 into an ATM or a Web site is an example that illustrates this problem. In their book Use Case Modeling (Addison Wesley, 2003) Kurt Bittner and Ian Spence provide this good definition of a 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 as a container for functional requirements, you wind up being forced to invent 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.
Use Cases and an SRS Organize Information Differently
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 necessarily to developers. As Figure 1 illustrates, a use case consists of multiple small packages of information. A typical use case template contains sections for preconditions, post conditions, the normal flow of events, zero or more alternative flows (labeled with Alt. in Figure 1), zero or more exceptions (labeled with Ex.), possibly some business rules, and perhaps some additional special requirements.
Figure 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 myself, 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. This is easier than having to figure out just what bits of the use case the business rule affects on my own.
As Figure 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. 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.
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.
In the final article of this three-part series, I’ll describe the thought process I go through when deriving functional requirements from the various elements of a use case.
Author: Karl Wiegers is Principal Consultant at Process Impact, www.processimpact.com. His interests include requirements engineering, project management, peer reviews, and process improvement. His most recent book is Software Requirements, 3rd Edition (Microsoft Press, 2013), co-authored with Joy Beatty.