The concept of modeling requirements often strikes people as odd. Most of us think of requirements in the form that we usually see them—the written word. So, how do you model words?
Well, you don't. Think of “modeling” requirements as an exercise in organization. Most systems have dozens, hundreds, or in large systems, thousands of requirements. The only way to mentally grasp these requirements is to organize them into understandable chunks. You can do this organization in many ways—by function, location, platform, management structure (not a good choice), performance needs, and so on. However, many of these choices would begin to constrain the future designs before you even fully understand the needs of the users. In other words, it's too early to interject such restrictions (but you may do so later in the development lifecycle). So, how should you begin?
At this point, if you have done your business modeling (as discussed previously), you know much about your customer and how she wants to run her business (or at least how she runs it today). This is what makes use cases a great way to begin your requirements modeling. Use cases organize your system by describing how the system is used. Not only does this leverage all the work you have done while business modeling, but this approach also serves as a bridge between what the business wants to be (which is expressed in the business models) and what your system design will be (which is expressed in your future architecture and application design models). This approach also keeps you focused on the customer, which is often forgotten in systems development.
As the earlier discussion on business modeling showed, a business use case depicts how the business actors will use your business and the intended functions of the business. However, remember that those were business use cases. They are much larger and broader in scope than the system-level use cases we will be talking about here.
Taken together, the system use cases provide the functionality specified by the business use cases. These system use cases will capture the scenarios of how the various actors will use the system you are building. For example, if your business is all about handheld Global Positioning System (GPS) devices, one of your business use cases might be Provide Positioning Services, whereas an application-level use case in this same domain might be Report Location.
|
Let us examine the vital characteristics of use cases and the related pitfalls by way of analogy—a map. Use cases specify the behavior of a system as individual, complete scenarios. A map specifies how to reach a destination by depicting a complete route. Use cases do not specify only part of a scenario, only individual steps in a scenario, or individual functions of your application. Similarly, a map would not be useful if it only showed half of the route or if it showed only the third left turn on the route. You do not decompose use cases into smaller pieces and call those pieces use cases. Likewise, a map does not group together all the left turns, then all the right turns, and then the straight segments and then call each of these groups a route. (Functional decomposition using use cases is a common mistake. We will discuss this later in this chapter.)
A use case depicts a specific scenario (or flow of events) that illustrates how the actor will use the system. A use case will typically have a main flow of events and also various alternate scenarios, just as a map depicts your main route but also shows other roads that could also be taken. Use cases do not specify all the possible ways to use the system. Otherwise, you would end up with the monolithic “Do Everything” use case (or a map of the entire world, showing all possible routes to the chosen destination).
How do you determine what the main and alternate scenarios are and how many alternates are needed? This is a judgment call you have to make based on the context of your system, what the actor wants to accomplish, and what is important to you. For example, in our earlier discussion on requirements in this chapter, we described two simple use case scenarios for ordering food at a restaurant, either of which could be the main scenario for an Order Meal use case. Which you would choose would depend on the context you have—is this a fast-food restaurant or a more traditional restaurant? As for the alternate flows, there could be many flows, slightly different yet still very similar, that accomplish ordering a meal—in one case, beverages may be ordered first and then the main meal, or the meal first and then beverages, and so forth. These are probably not the type of alternate scenarios you would want to capture (unless the sequence of ordering is important to you). But you probably would want to capture variants for situations such as when a customer requests a meal be prepared in a certain way, when you can't provide a certain meal because you have run out of a certain food, when you are offering special meals, when discounts are available, and so forth. You will want to capture alternate scenarios that are significant for your particular situation. What ties all these various flows together? They are all about accomplishing the specific outcome of the use case that the actor desires, in this case, ordering a meal.
Let's consider these key characteristics further. As discussed earlier, use cases should not be too small or too large. So, we have two initial boundaries for the scope of a use case (see Figure 3-2):
Use cases are not individual steps or functions.
Use cases do not contain every possible step that might ever be taken.
Within these two extremes, how do we know the proper scope for use cases? The first key characteristic you must keep in mind is to construct the use case in terms of what the system should do. This key characteristic immediately limits the scope of the use case because it eliminates all the “hows.” Use cases should not describe how the scenario will be implemented. Again, we use the analogy of a map—at this point, you need to determine the requirements on the system (i.e., what the system must do), not the implementation (i.e., how the system will do it), just as a map shows what needs to be done (i.e., travel from point 1 to point 2) without showing how you should get there (e.g., by bus, train, automobile—see Figure 3-3).
As another example, let us consider an automotive diagnostics system used by an auto technician. The technician can perform many diagnostic actions on an automobile. The use case Compare Results To Compression Profile In Database is a use case that doesn't specify what needs to be done—it specifies how to do it (compare to the database). A better use case would be Evaluate Vehicle Compression (that's what needs to be done).
Another characteristic that limits the scope of a use case is taking the actor's point of view. This means use cases should be defined from the viewpoint of the actor that would use them, not from the system's viewpoint. The actor's viewpoint for use of a map is to “Determine a Route,” not “Read Map Database,” which is the viewpoint of a mapping software application (see Figure 3-4).
In our auto diagnostics example, Provide Timing Information would be taking the system's point of view. The actor's point of view would be Test Vehicle Timing.
The next key characteristic is that use cases, with their actors, must capture an entire flow of events (a.k.a. a complete use case scenario) that will be performed. Today, autos have millions of lines of code onboard. So, the technician might use the diagnostics system to upload new software to the auto—but “upload new software” is not a use case. The upload is just one step in a larger flow that would contain actions such as getting the maintenance order, driving the auto into the proper service bay, making the proper electrical connections, discovering the current version of software that is onboard, querying for all software upgrades that are available and mandated, and performing the upload, not to mention conforming to any safety protocols along the way and so forth. A better use case might be Perform Software Maintenance Cycle. That use case scenario can include these or other steps.
Upload New Software is not an entire flow, and therefore is not a complete scenario. Each use case must portray the entire flow of how the actor(s) will use your system for a given scenario. This characteristic helps prevent the creation of single-step use cases, partial use cases, or functionally decomposed use cases (see Figure 3-5).
But the use case can't just be any collection of steps. The last key characteristic is that the use case must provide some recognizable value to its actors. In our example, raising the automobile on a lift provides no value on its own. However, when we add draining the oil, replacing the oil filter, adding new oil, and bringing the auto back down (i.e., doing the entire oil change), then we have described something of value. Likewise, a map may be extremely accurate, but if it doesn't cover the area you are interested in or doesn't provide a route to your destination, it provides no value (see Figure 3-6).
|
When creating use case scenarios, if you are having difficulty with the idea of value, you might want to look at one of the other key characteristics—taking the actor's point of view. If the technician only raised the automobile on a lift, drained the oil, and removed the oil filter, would the customer (another actor) be satisfied? No, she came to get an oil change, not to get an oil drain. If you are not sure, try asking the real person who will eventually be that actor. When you have the opportunity to ask the users, do so; this can help you avoid career-limiting mistakes.
A simple way to validate that you are on the right track with your use cases is to use the “WAVE” tests. [NAIB1] The WAVE acronym captures the essence of the previously mentioned characteristics:
W | Does the use case describe What to do, not how to do it? |
A | Is the use case described from the Actor's point of view? |
V | Does the use case include Value for the actor? |
E | Is the flow of events an Entire scenario? |
The WAVE tests are a great way to keep yourself on track when creating new use cases, and they are also useful for checking your set of candidate use cases afterward to validate that they are proper. If they pass the WAVE test, you are well on your way to success with properly scoped use cases (see Figure 3-7) and have avoided the major flaws often seen in use case models.
One final way to evaluate that you have properly scoped your system use cases is to count how many you have. The number of use cases in the largest systems should number in the “tens” range, not the “hundreds.” Simple systems might have less than ten use cases. So, if you have a very high use case count, and you are not building a very large, complex system, you should reassess the scope of your project and your use cases against the criteria discussed earlier in this chapter.
So, who uses these use cases? In Chapter 2, we discussed business actors. They are the people, companies, or systems that come to do business with you. That was at the business modeling level of abstraction. Now that we are at the requirements elicitation/specification phase, we merely refer to actors. Actors are the people or things that interact with your system (that will be created to implement those business processes). They are not specific people. They represent a role that the actor (person or system) plays with respect to your system.
For example, “Mary” would not be a proper actor. If you wanted to include what Mary does in your models, you would ask, “What does she do (i.e., what role does she play)?” If she is Head of Security, the actor could be “Security Chief”—this is the role she plays within the system.
|
|
Use cases interact with more than actors—they can have relationships with other use cases. Let's say you are developing a use case around a driver taking an automobile on a drive. For discussion purposes, let us say that the basic use case, Take Trip, has the basic flow of planning the trip, fueling the car, driving to the destination, sightseeing, and driving home. This use case could have many different alternate scenarios. As you develop other use cases, you'll note that one thing is always included in the scenarios—fueling the auto. The act of fueling the auto is the same across the use cases. This common behavior can be represented with a special association, as shown in Figure 3-10, as a dashed arrow labeled with “<<include>>.”
The include association means that the included use case behavior (Fuel Vehicle) is inserted in the flow of the base use case (Take Trip). Use cases that are included are use cases that are reusable—common to many use cases. Even though they are common, included use cases are also mandatory. In this example, the base use case, Take Trip, is incomplete without its included use case, Fuel Vehicle. When the base scenario reaches the inclusion point in the flow where Fuel Vehicle is to be included (as specified in the base use case scenario), the Fuel Vehicle use case is executed.
As mentioned, there could be many alternate scenarios for Take Trip. Many different optional behaviors could be added to the base scenario. For a longer trip, you might want to stop for a meal. This can be represented with a dashed arrow labeled with “<<extend>>” as in Figure 3-11.
The extend association means that the base use case (Take Trip) can be extended with the optional extending use case (Eat Meal). An extending use case actually changes the flow of the base use case. Whether the extending use case behavior is executed is based on a decision point in the main flow. In this case, when the base scenario reaches the extension point in the flow where the Eat Meal option might be taken, the driver must decide whether he wants to eat. If so, Eat Meal would be executed. If not, the base flow would continue.
Unlike the include relationship, which inserts behavior at a single point in the flow, an extend relationship can change the base use case flow at multiple places. For example, let's say that one alternate flow of Take Trip includes photographing the interesting sites. So, we add an extending use case, Photograph Sites (see Figure 3-12).
We can define Photograph Sites so that when the decision point is reached and the driver decides to take photos, the base use case will be altered at numerous specified points with various behaviors. In this example, not only will the Photograph Sites use case extend the base behavior to take photos after sightseeing, but it also will extend behavior later in the trip's base flow to stop at the film processing store and drop off the film to have pictures made.
The include and extend relationships are similar in some ways yet different in others. The significant differences are summarized in Table 3-1.
Included Use Case | Extending Use Case | |
---|---|---|
Is this use case optional? | No | Yes |
Is the base use case complete without this use case? | No | Yes |
Is the execution of this use case conditional? | No | Yes |
Does this use case change the behavior of the base use case? | No | Yes |
Includes and extends are useful tools to help you structure your use case models—includes to identify common use cases and extends to simplify complex scenarios. However, remember the most important task is to properly define and elaborate your use case scenarios. Don't get bogged down by focusing on includes and extends instead of building good use cases.
|
We've talked repeatedly of how a use case should specify a complete flow of events. So, what form should that specification take? One is a type of UML interaction diagram called a sequence diagram (we will discuss these later in this chapter). The other is a textual specification of what the use case does, typically called a use case specification.
The use case specification is a structured, textual document that describes the use case scenario in natural language. An example is seen in Figure 3-13. This example is from a fictitious Online Medical Records system. It describes one use case for recovering archived clinical records (in this context, “records” refers to all the medical information about a person under care, not to individual database records).
There are many formats for use case specifications, and you should tailor them to your specific needs. Figure 3-13 contains key information that should be included in your spec: name, short purpose, contact and change information, pre-conditions that must be true for the use case to execute, post-conditions that must be true after the use case is run, known limitations, and assumptions. This is followed by the basic flow. The basic flow is the “good day” scenario where everything goes as planned. Alternate scenarios are also documented. The alternate scenarios describe how the use case flow can be altered based on a specific condition. If the alternate flow is captured in another use case related to the main use case through an extends association, where that extension occurs in the specification is identified by an extension point. Similarly, if this use case included other use cases (an include relationship), we would identify this by using an inclusion point for each use case.
As you can see, use case specifications are intentionally short—no more than a few pages. The intent is to succinctly capture the flow of the use case. If it gets too large, your use case might be trying to do more than it should be doing, or you might be getting bogged down in trivial alternate flows.
Use Case Description | ||||||
---|---|---|---|---|---|---|
Use Case Name: | Unarchive Clinical Records | |||||
Use Case Purpose: | The purpose of this use case is to recover Clinical Records from the archive. | |||||
Point of Contact: | Jan Tarmand | |||||
Date Modified: | 11/29/03 | |||||
Pre-Conditions: | None Identified | |||||
Post-Conditions: | The Records Closure Schedule and Records Destruction Schedule may be updated. | |||||
Limitations: | The Clinical Records to be recovered are specified by Resident name. | |||||
Assumptions: | Clinical Records are to be closed 14 days after the Resident leaves the facility. | |||||
Basic Flow: | ||||||
A. | The Archive is locked against update. | |||||
B. | The specified Clinical Record is searched for in the Records Destruction Schedule | |||||
C. | Extension Point—Condition 1 | |||||
D. | The Record Destruction Schedule is updated to remove the requested Clinical Record from the Schedule. | |||||
E. | The specified Clinical Record is recovered from the Archive | |||||
F. | Extension Point—Condition 2 | |||||
G. | If the Resident has left the facility, the Record Closure Schedule is updated to schedule the Clinical Record for closure. | |||||
H. | Archive is closed and exclusive access is released. | |||||
Alternate Flows: | ||||||
Condition Triggering Alternate Flow: | ||||||
Condition 1: The specified record is not found in the Record Destruction Schedule. | ||||||
C1. | An error message is displayed to the user and is also logged, indicating the Specific Clinical Record was not found in the Record Destruction Schedule. | |||||
C2. | Step H in the Basic Flow is then executed. | |||||
Condition Triggering Alternate Flow: | ||||||
Condition 2: The specified record is not found in the Archive. | ||||||
F1. | An error message is displayed to the user and is also logged, indicating the Specific Clinical Record was not found in the Archive. | |||||
F2. | Step H in the Basic Flow is then executed. |
Text-based use case specifications have several benefits:
Simple to use; no CASE tools required.
No methodology knowledge required.
No training needed.
Portable.
Can be done anytime and anywhere.
Can express the use case in the customer's language.
These characteristics make these specifications ideal for working with your nontechnical stakeholders (e.g., customers, business sponsors).
|
Specifying use cases in text has one significant drawback. They suffer from the same weakness as all textual specifications: when they get more complex, you cannot easily understand all the relationships and interactions. This is where the strength of the UML sequence diagram lies.
You will recall that in Chapter 2, we introduced sequence diagrams. To review, a sequence diagram shows the interactions between the model elements for a given scenario in time order (time runs vertically down the page). The arrows on this diagram indicate the messages that flow between the various model elements. The dashed lines that run vertically below the model elements are called lifelines. Lifelines show the existence of the model element. The sequence diagram for the use case specified in Figure 3-13 can be seen in Figure 3-14.
We used a few additional elements in this sequence diagram. You can see we used “notes” (the rectangular symbol with a folded-over corner, which can be used on any diagram type) as one way to indicate where any extension points are. Such notes can also be used to “link” sequence diagrams together. This is especially useful for long sequences or to link to the sequence diagrams for included or extending use cases. Also, one way you can use conditions on messages is shown on message 7 in Figure 3-14 (in brackets). Some additional notations you might see are in Figure 3-15.
Here, we use notes to identify different diagram elements. We have seen previously the operation call, shown as an arrow with a solid, filled-in arrowhead. When such calls are made, control is passed to the element on the arrowhead end of the message. You can see the scope (duration) of such control by the focus of control bar. This is the rectangular bar on the lifeline, which indicates when this element (or a subordinate element) is performing processing. A message that does not transfer control is the asynchronous message, show as a line with an “open,” sticklike arrowhead. When this type of message is sent, the sending element continues on with its processing.
On the end of this particular asynchronous message is a destruction marker, the large “X” on the lifeline. (You might hear this referred to as a “Stop” per UML 2.0.) This indicates when that instance of the object is destroyed. Last, as we saw in Chapter 2, a return message is represented as a dashed arrow. These indicate a return from a called operation. Return messages are optional because if you showed every return, the sequence diagram would become quite cluttered. Use them for key, meaningful returns only.
We have found that the sequence diagram is the most generally useful of all the UML diagrams. Not only can they clearly depict the flow of use case scenarios, but they also can do the following:
Provide control flow information.
Depict database transactions (as a transaction map showing the initiating user role and all the entities that are touched during the transaction).
Identify key parameters that must be shared among elements of your system.
Give insight into the creation and destruction of objects in your system.
Show when an object might be doing too much. (Does one of your objects send most of the messages out and thus control the entire application? Was that intended?)
Indicate when the design might have performance issues. (Does one of your objects receive most of the messages and thus become a performance bottleneck?).
Provide an easy, visual way for users to validate the steps they really take (or want to take) and in what order.