![]() |
![]() ![]() |
The flip side of the principles we just discussed takes the form of a number of common errors that we have seen students make when they're doing use case modeling on their projects for the first time. Our "Top 10" list follows.
Write functional requirements instead of usage scenario text.
Requirements are generally stated in terms of what the system shall do. Usage scenarios describe actions that the users are taking and the responses that the system generates. Eventually, we're going to use our use case text as a runtime behavioral spec for the scenario we're describing, and this text will sit on the left margin of a sequence diagram. We want to be able to easily see how the system (shown with objects and messages) is implementing the desired behavior, as described in the use case text. So, we need to keep a clear distinction between (active voice) usage descriptions (behavior) and (passive voice) system requirements.
Describe attributes and methods rather than usage.
Not only shouldn't your use case text include too many presentation details, but it should be relatively free of details about the fields on your screens, as well. Field names often match up directly with the names of attributes on your domain classes, which we talked about in Chapter 2. If you find yourself starting to list the names of, say, 13 fields from the screen in your use case text, stop. Open the domain model, find the class(es) where those attributes belong, and capture them where they'll do you some good-as attributes. Later, when you need them, they'll be there. Methods shouldn't be named or described in case text because they represent how the system will do things, as opposed to what the system will do.
Write the use cases too tersely.
When it comes to writing text for use cases, expansive is preferable to terse. You're going to need to address all of the details of user actions and system responses as you move into robustness analysis and interaction modeling, so you might as well put some of those details in your use cases up front. Remember also that your use cases will serve as the foundation for your user manual, and it's always better to err on the side of too much detail rather than not enough when it comes to user documentation.
Divorce yourself completely from the user interface.
One of the fundamental notions of "use case driven" is that the development team conforms the design of the system to the viewpoints of the users. You can't do this without being specific as to what actions the users will be performing on your screens. As we mentioned for item 9, you don't need to talk about fields in your use case text, and you also don't want to go into any detail about the cosmetic appearance of your screens; you can let your prototypes, in whatever form they take, do that work for you. You do, however, need to discuss those features of the user interface that allow the user to tell the system to do something.
Avoid explicit names for your boundary objects.
Boundary objects are the objects with which actors will be interacting. These frequently include windows, screens, dialogs, and menus. In keeping with our themes of including ample detail and being explicit about user navigation, we submit that it's necessary to name your boundary objects explicitly in your use case text. Another reason that it's important to do this is that you're going to explore the behavior of these objects during robustness analysis (see Chapter 5), and it can only help reduce ambiguity and confusion to name them early.
Write using a perspective other than the user's, in passive voice.
A use case is most effectively stated from the perspective of the user as a set of present-tense verb phrases in active voice. The tendency of engineers to use passive voice is well-established, but use cases should state the actions that the user performs, and the system's responses to those actions, and this kind of text is only effective when it's stated in active voice.
Describe only user interactions; ignore system responses.
The narrative of a use case should be event-response oriented, as in, "The system does this when the user does that." The use case should capture a good deal of what happens "under the covers" in response to what the actor is doing, such as creating new objects, validating user input, or generating error messages. Remember that your use case text describes both sides of the dialog between the user and the system, and that all of the software behavior that you're trying to discover happens on the system side of that dialog. If you leave out the system responses, you ignore the software behavior.
Omit text for alternative courses of action.
Basic courses of action are generally easier to identify and write text for. That doesn't mean, however, that you should put off dealing with alternative courses until, say, detailed design. In fact, it's been our experience that when important alternative courses of action are not uncovered until coding and debugging, the programmer responsible for writing or fixing the code tends to treat them in ways that are most convenient for him or her. Needless to say, this isn't healthy for a project.
Focus on something other than what's "inside" a use case, such as how you get there or what happens afterward.
Several prominent authors advocate the use of long, complicated use case templates. Spaces for preconditions and postconditions are generally present on these templates. We like to think of this as the 1040 "long form" approach to use case modeling, in comparison to the 1040EZ-like template that we advocate (two headings: Basic Course and Alternate Course). You shouldn't insist on using long and complex use case templates just because they appeared in a book or article. Don't waste your time.
Spend a month deciding whether to use includes or extends.
In our years of teaching use case driven development, we have yet to come across a situation in which we've needed more than one mechanism for factoring out commonality. Whether you use the UML's include construct, or the OML's invoke and precede mechanisms, or something else that you're comfortable with, doesn't matter; what matters is that you pick one way of doing things and stick with it. Having two similar constructs is worse than having only one. It's too easy to get confused-and bogged down-when you try to use both. Don't spin your wheels.
![]() |
![]() ![]() |