![]() |
![]() ![]() |
The task of building use cases for your new system is based on identifying as many as you can up front and then establishing a continuous loop of writing and refining the text that describes them. Along the way, you will discover new use cases and also factor out commonality in usage.
You should keep one overriding principle in mind at all times in your effort to identify use cases: They should have strong correlations with material in the user manual for the system. It should be obvious what the connection is between each use case and a distinct section of your user guide. This reinforces the fundamental notion that you are conforming the design of your system to the viewpoints of the users. It also provides a convenient summary of what "use case driven" means: Write the user manual, then write the code. If you're reengineering a legacy system, you can simply work from the user manual backward, making any necessary changes as you go.
Once you have some text in place for a use case, it's time to refine it by making sure the sentences are clear and discrete, the basic format of your text is noun-verb-noun, and the actors and potential domain objects are easily identifiable. You should also update your domain model (see Chapter 2) as you discover new objects and expand your understanding of the objects you'd previously found. And, it's very important to think of all possible alternate courses of action for each use case wherever possible, which should be a large majority of the time. Note that robustness analysis (see Chapter 5) will be very helpful toward accomplishing all of this refinement.
Although some authors encourage the use of voluminous use case templates, here's what we recommend to every one of our clients:
Create a use case template that has areas labeled Basic Course and Alternative Courses. Don't put anything else in there; it'll just distract you.
Ask "What happens?" This will get the basic course of action started.
Ask "And then what happens?" Keep asking that question until you have all the details of your basic course on paper.
Ask, "What else can happen?" Be relentless. Are there any other things that can happen? Are you sure? Keep asking those questions until you have a rich set of alternative courses written down. Trust us: Grief at this point is much easier to take than grief during, say, integration testing.
The goal is not to construct an elegant use case model; the goal is to account for everything the user might do.
You'll review this material during a requirements review (see Chapter 4); you'll review it again during a preliminary design review (see Chapter 6); and you'll review it once more during a critical design review (see Chapter 8). This may seem excessive, but keep in mind that the more well-defined the system behavior, the easier it's going to be to build the system.
You can use several mechanisms to factor out common usage, such as error handling, from sets of use cases. This is usually a good thing to do because breaking usage down to atomic levels will make your analysis effort easier and save you a lot of time when you're drawing sequence diagrams. Whether you use the UML's use case generalization and include and extend relationships, or the invoke and precede relationships from the Open Modeling Language (OML), which we recommend in Use Case Driven Object Modeling with UML, your goal should be a set of small, precise, reusable use cases.
We recommend grouping use cases into packages, primarily because these packages form logical boundaries for dividing work among subteams. A good rule to follow is: Each package should correspond with a chapter, or at least a major section, in your user manual.
You should feel comfortable proceeding to the next phases of the development process when you've achieved the following goals of use case modeling:
You've built use cases that together account for all of the desired functionality of the system.
You've produced clear and concise written descriptions of the basic course of action, along with appropriate alternative courses of action, for each use case.
You've factored out scenarios common to more than one use case, using whichever constructs you're most comfortable using.
![]() |
![]() ![]() |