Chapter 7. Use Case Relationships

It's easy to start a riot at a use case conference. Simply walk up to an open microphone and ask, “What is the difference between includes and extends?” and then run for cover! How to apply the includes and extends relationships effectively in use cases is a question that has perplexed both beginning and experienced use case writers.

Includes and extends were originally intended to simplify the use case model by collecting and organizing common threads in the model. Unfortunately, these simplifying relationships seem to have the opposite effect, making the model more complex and difficult to understand. Many factors contribute to this problem. First, the definitions of includes and extends are ambiguous, leading to a wide variety of interpretations as to what they really mean. Second, software professionals tend to favor formality in the use case model over usability, creating models that follow all the rules but are hard to read. Finally, instructors tend to overemphasize these techniques when teaching people to write use cases.

The UML revision task force exacerbated this ambiguity in 1998 when they attempted to bring peace to the warring factions by introducing a new definition of the use case structuring relationships. They replaced the original uses relationship with the new include relationship, made extend a UML dependency relationship, and introduced the generalization relationship. While these changes helped to remove ambiguity in the formal grammar that supports the definition of use cases in UML, this revision has led to confusion and ambiguity in the practical applications of the use case structuring relationships.

Consider this: While a programmer may understand the concepts behind these relationships, try getting the product manager, the lawyer, or the accountant who is a stakeholder in the system to understand them. These are intelligent, capable people, who have very little time to learn formal rules to verify their systems. The cardinal rule of writing is “Know your audience.” In our opinion, the best use cases are semiformal, with just enough structure to be reasonably precise and unambiguous in the way they communicate important concepts (see PreciseAndReadable [p. 138]). Yet they should be simple enough so that a stakeholder who is familiar with the problem domain can read and understand it. Rigid formality does not help this cause.

Good use case models tend to use the includes and extends relationships judiciously. Models that overuse the extends relationship tend to use extensions to describe implementation details, frequently describing alternatives on a user interface. We have seen models in which a use case has dozens of extension use cases, with extensions on extensions. Many readers would quickly throw such work back at the writer, or worse, simply ignore it.

Furthermore, writers frequently use these relationships to create director-style use cases, in which including or extending use cases specify the details of each step. The consequence of this technique is that the model usually represents the developer's point of view, causing the readers to lose sight of the important actor goal in the details.

We have identified three patterns that help use case writers understand these relationships.

  • CommonSubBehavior (p. 176) states that you should consider creating an includes relationship between use cases when two or more use cases share a common set of actions. The purpose is to consolidate common behavior and simplify your model by reducing redundancy.

  • InterruptsAsExtensions (p. 182) recommends that you consider an extension use case when an alternative interrupts a number of steps in a scenario. This technique helps simplify the model by consolidating the related interrupting actions in one use case, rather than dispersing them across several alternative courses of action.

  • PromotedAlternative (p. 190) suggests that you may also want to use extensions when you have some important alternatives to emphasize. In this case, you can “promote” these alternatives into an extension use case so that they stand out. You should use this technique sparingly, so that you don't conflict with the guidelines described in InterruptsAsExtensions or RedistributeTheWealth (p. 204).

We haven't yet seen many good models utilizing the UML generalization relationship to create a pattern for guiding its use. However, our colleague Dan Rawsthorne has provided us with a pattern called CapturedAbstraction (p. 198), that suggests an appropriate use for generalization. This pattern suggests you create an abstract use case when you have multiple use cases with the same goal and it is inappropriate to MergeDroplets (p. 209).

Includes Versus Extends

Supercharger plant workers buffing delicate airplane engine parts

CommonSubBehavior

You are writing use case descriptions as ScenarioPlusFragments (p. 125).

Writing the same steps for different use cases is wasteful and makes it more difficult to see common subprocesses within a use case model.

Maurice Wilkes once gave a lecture on his role in the development of EDSAC, the first stored-program computer. Unlike ENIAC, which was programmed from a hardware plugboard, EDSAC actually stored its instructions in the same memory that was used to store data, an approach that is the basis for all modern-day computers. Programs were fed into EDSAC, using paper tape.

The EDSAC team quickly noticed that while all of their programs solved different problems, they frequently employed the same sets of instructions. Punching paper tape for EDSAC was a labor-intensive and tedious activity, and people found that repunching the same instructions over and over again was even more tedious, error prone, and a waste of time.

Someone finally took the initiative and began cutting out the common sets of instructions from the paper tapes and storing them in little 35-millimeter film canisters. Then when someone wanted to write a program that used that sequence of instructions, the programmer could retrieve the paper tape, attach it with Scotch tape to the program, and then feed the paper tape into EDSAC. It made programming EDSAC much easier and less error prone.

Rewriting common steps is redundant and increases the risk of inconsistencies or inaccuracies in the model. Different processes may have common steps. For example, buying and selling stock are two distinct activities, yet each requires a valuation of the stock being traded. Similarly, paying property taxes on a house, selling a house, and buying a house are all different activities that require an assessment of the house's value. The steps for stock valuation can be rewritten for both the purchase and sale of stock, but redundancy is never a good thing to have in a model. First, it is simply a waste of time writing and reading the same steps over and over again for each process.

Second, redundancy can lead to inconsistencies in the model, if the commonly used steps must be changed. A frequent source of errors in requirements models results from the need to change a repeated behavior and forgetting to change every instance of that common behavior. For example, let's say the rules for assessing the value of a property change. We change the steps in the Purchase Property use case, but we forget to change the steps in the Pay Tax use case. We run the risk of building a system that is inconsistent in the way that it assesses property values because we have created inconsistent environments.

Partitioning individual use cases tends to scatter important behavior and makes them harder to understand. “One-stop shopping” is a useful requirements writing principle. Simply, people reading the requirements should be able to get all the information they need from one document or from one section of a document. They should not have to jump between different sections to understand the requirement.

A classic example of violating this principle is the famous The Joy of Cooking cookbook that mothers traditionally give to their sons when they leave home. The Joy of Cooking is probably one of the most complete, self-contained cookbooks written. It is also difficult to use, because each recipe forces you to jump back and forth between different sections of the book to discover how to make the white sauce, how to braise the beef, how to blanch the beans, and so on.

The greatest benefit of the use case is that it tells a story that provides the context for understanding requirements. Forcing a reader to jump between different use cases risks losing this benefit.

Misunderstanding the includes relationship leads to its misuse. Programmers are trained to break up large blocks of program logic into more manageable subroutines. But when they apply this technique to use cases, they often include more detail in the “called” use cases than in the callers, effectively turning the high-level use cases into transaction centers that simply call a number of lower level use cases to perform their tasks.

Again, the problem becomes the high probability that the use case will be too formal and the all-important story context may be lost. Many use case books encourage this practice by creating contrived examples in an effort to demonstrate includes relationships.

In addition, programmers are trained to prefer formality to informality, and UML tends to encourage an excessive level of formalism in use case models. Relationships between use cases such as includes, extends, and generalization have well-defined formal definitions in UML. Unfortunately, there is a great deal of uncertainty about how these formal concepts translate to useful concepts in the everyday world of requirements.

Therefore:

Express shared courses of action with lower-level included use cases.

Ideally, create includes relationships between use cases when two or more use cases share a common set of steps. Extract the common steps and place them into their own use case.

Avoid using includes simply as a mechanism for partitioning a long, complex use case into smaller ones, even though that might seem more manageable. A long, complex use case is often a symptom of one or more of the following problems.

  • The scope of the use case is too large (identify each CompleteSingleGoal [p. 118]) and RedistributeTheWealth [p. 204]).

  • The steps in the use case are written at too low a level of detail for the goal of the use case or are written at different levels of detail (create LeveledSteps [p. 153]).

  • Nonfunctional requirements such as user-interface details have crept into the use case (put them into Adornments [p. 133]).

Examples

Wings Over the World and Includes

A problem found in many use case sets is the “director” use case—that is, a use case that depends on several included use cases. See Figure 7.1 and Use Case 7.1, for example.

Misuse of includes to create a director-style use case

Figure 7.1. Misuse of includes to create a director-style use case

The problem is that the included use cases in this case are trivial. They are too simple and small to justify their existence as entire use cases. The included use cases are, to use a visual metaphor, droplets. The repair for droplets is to MergeDroplets (p. 209).

Instead, use EverUnfoldingStory (p. 102), as shown in Figure 7.2 and Use Case 7.2

Book Flight use case

Figure 7.2. Book Flight use case

The appropriate application of include is to eliminate redundancy that would otherwise make the set of use cases difficult to understand. If two or more use cases have a set of steps in common, then rather than rewriting those steps, we can collect them into a common use case, as illustrated in Figure 7.3.

Using include to consolidate CommonSubBehavior

Figure 7.3. Using include to consolidate CommonSubBehavior

Here, both Book Cruise and Book Flight use Collect Payment Information. No matter what kind of trip we are booking, we always collect payment the same way, so why write the same thing twice?

How not to show an includes relationship

Telegraph switchboard of the Pennsylvania Railroad in Union Station, Chicago, Illinois

InterruptsAsExtensions

You are writing a use case description as a ScenarioPlusFragments (p. 125).

An alternative that affects more than one step in a scenario can scatter related details throughout a use case, causing the reader to become confused or lose track of important information.

It seems that a lot of human resources departments go out of their way to make hiring temporary or contract employees difficult. Most firms have a conventional process they follow when they hire a new employee. Usually new hires simply fill out a personal data form, then complete some kind of tax-withholding form, sign up for company benefits, assign their intellectual property rights to the company, and finally specify where they want their pay deposited.

The human resources department seems to enjoy taking this paper-shuffling process to new heights of complexity for contract employees. Just like regular employees, contract employees usually have to fill out most of the same forms, but they may have to do some or all of the steps differently. For example, contractors may not be eligible for company benefits, or may be required to invoice the company to receive pay. They may have to negotiate the transfer of intellectual property rights. So, when hiring a new contractor, the human resources department may go through each of its normal steps for hiring, but then modify some of the steps or require additional work.

Multiple diversions or alternatives that interrupt several steps in a scenario can cause the readers to lose track of the path that they are trying to follow, and can indicate problems with the basic scenario itself. The recommended approach for coping with an alternative course of action is to write the alternative as a fragment off the main success scenario (ScenarioPlusFragments). This technique works well for most alternatives because they are usually a simple diversion from a step in either the main success scenario or a step in a fragment. In either case, once the diversion is completed, the scenario resumes from the point where the diversion took place.

However, what happens when the alternative requires repeated diversions on more than one step in the use case? You can write a diversion for each step, but then it is easy for readers to lose track of the alternative thread that ties these related diversions together.

Creating extension use cases tends to scatter important behavior and makes them harder to understand. “One stop shopping” is an important requirements writing principle. Simply, a person reading the requirements should be able to get all of the information they need from one document or from one section of a document. They should not have to jump between different sections to understand the requirement or its context.

A major benefit of use cases is that they tell a story that provides the context for understanding requirements. Forcing a reader to jump between different use cases runs the risk of negating this benefit.

Misunderstanding the extends relationships leads to its misuse. If you ask five use case experts, “What does the extends relationship mean?” you will get ten different answers. Extends has historically been likened to an inheritance relationship between use cases, and most programmers are trained to interpret inheritance as a specialization. Recently however, the UML revision task force decided to change the formal definition of extends from an inheritance relationship to that of a dependency. While this change is interesting to those concerned about the formal structure of the UML, it has made life very difficult for many analysts. In many ways, the formal definition is irrelevant in real life.

In addition, as we've said, programmers are trained to prefer formality to informality, and UML tends to encourage an excessive level of formalism in use case models. Relationships between use cases such as includes, extends, and generalization have well-defined formal definitions in UML. Unfortunately, there is a great deal of uncertainty about how to apply these formal concepts pragmatically in the everyday world of requirements.

Therefore:

Create an extension use case when an alternative course of action interrupts a number of steps in a scenario.

This is an obscure situation and does not occur all that often. If you discover that you are frequently applying this pattern then you should re-evaluate your use cases. It may be the case that you do not have a CompleteSingleGoal (p. 118), or you do not have LeveledSteps (p. 153).

Create an extension use case by extracting all of the steps that are associated with the thread of the alternatives and placing them in an extension use case. For each statement in the extension use case, specify which statement in the original or base use case is being interrupted. This approach has two benefits.

  • The thread of an interrupting alternative is kept together, and therefore the reader can see the context of the alternative (one-stop-shopping principle).

  • The original or base use case is not cluttered with interrupting alternatives.

Examples

Wings Over the World and Extensions

Use Case 7.3 describes how a flight is booked. (See Figure 7.6.) The main success scenario is relatively straightforward, with the agent using the system to build up a travel itinerary for a client, and then to reserve it. However, there are extensions to many of the steps in the main success scenario if the client is a frequent flier, because frequent fliers get privileges and services that are not available to conventional clients.

The Book Flight use case

Figure 7.6. The Book Flight use case

In this example, it is all too easy for the use case reader (and sometimes even the use case author) to forget that all of the individual frequent flier alternatives listed in the use case's alternatives section represent the thread of an ongoing alternative course of action.

We can clarify this situation by using an extension use case that collects all of the frequent flier alternatives together, as shown in Use Case 7.4 and Figure 7.7.

The Book Flight use case diagram with frequent flier extension

Figure 7.7. The Book Flight use case diagram with frequent flier extension

Now all alternative courses of action associated with the frequent flier are collected together into one extends use case.

The extension use case keeps all the steps in the frequent flier alternatives together, making it easier to follow the frequent flier thread alternatives. It is less likely now that the reader (and even the use case author) will lose the thread of the alternatives within the other alternatives.

Extensions and UML Extension Points

Extension use cases are not independent of their base use case and must reference statements in the base use case. For example, the extension use case Book Flight for Frequent Flier directly references statements in the base use case Book Flight. Each of the alternatives and statements in Book Flight for Frequent Flier are direct references to a statement numbering of Book Flight. If Book Flight is updated and the statement numbering changes, then we will have to relabel and renumber the statements in Book Flight for Frequent Flier as well. The UML extension point feature helps mitigate this problem by providing extension points for the extension use case. (See Figure 7.9.) Technically, an extension point is a point at which additional behavior may be inserted. These extension points are like symbolic labels, and they help make the extension use case more independent of the internal structure of the base use case. Use Cases 7.5 and 7.6 illustrate the details.

UML use case diagram featuring an extension point

Figure 7.9. UML use case diagram featuring an extension point

Use Case 7.6 Book Flight for Frequent Flier Extension Use Case Referencing Extension Points

Couple on graduation day, University of Nebraska, Lincoln

PromotedAlternative

You are writing use case descriptions as ScenarioPlusFragments (p. 125).

Long or complex alternatives can dominate a use case, and appear to be more important than they really are just because they are so prominent.

Normally, the military strictly adheres to a formal, well-defined process for promoting officers. Candidates must meet all of the qualifications for their particular rank, must have served the required amount of time, and must have a spotless service record. But in wartime, especially during urgent situations, commanders will promote someone, be it an experienced enlisted man or a junior officer, to fill a critical need. They refer to these special cases as “battlefield promotions.”

Sometimes, an alternative scenario stands out. It suddenly becomes important, because it fills an important hole in the system. When it does, it makes sense to elevate it to be a use case.

Complex or long alternatives clutter a use case and can obscure other alternatives. A use case can become difficult to write and even more difficult to follow when the alternative is too long or complex, especially when it contains several alternatives itself. Use cases are supposed to be easy to read and understand, not complicated engineering documents.

Some problems are very complex, and they require complex use cases to describe them adequately. Hard technical problems don't simplify themselves just because we want to simplify our use cases. Some systems can be very complicated and hard to understand. Yet these are the kinds of systems that we need to describe especially well, so that everyone working on them will have a clear understanding of how the system is supposed to behave in all reasonable situations.

Partitioning individual use cases tends to scatter important behavior and makes them harder to understand. One of the biggest benefits of using use cases is that they tell stories that provide a context for understanding requirements. Forcing readers to jump between different use cases risks negating this benefit, because it violates the one-stop-shopping principle. We believe that people should be able to get all of the information they need about a requirement from one place, without having to refer to several documents to understand it.

Therefore:

Consider moving complex alternatives that overly dominate a use case into a separate use case.

An alternative course of action should never dominate a use case. After all, it's supposed to be an alternative and represents a less common behavior than the main success scenario. The best way for handling alternative courses of action is to write them as fragments based on a main success scenario (ScenarioPlusFragments). But sometimes there are alternatives which may require a long, complex series of steps (such as control break processing and boundary conditions). Under these circumstances, you may consider extracting the alternative from its base use case and creating a separate use case for it.

You need to exercise caution when using this pattern to justify the creation of an extending use case, because complex alternatives may indicate that the use case is too detailed or too large (see EverUnfoldingStory [p. 102], LeveledSteps [p. 153], CompleteSingleGoal [p. 118], and RedistributeTheWealth [p. 204]). If this is not the case, then promoting the alternative to its own use case is a reasonable course of action.

Examples

Wings Over the World

All of us who have to fly frequently in those small things the airlines pass off as seats appreciate seat upgrades. Use Case 7.7 shows when a seat upgrade may be requested at the time of booking.

Notice how the Seat Upgrade alternative obscures the other alternatives, and dominates the use case. According to PromotedAlternative, Seat Upgrade is clearly a candidate for a separate use case, and making it such is fairly straightforward. But how to reference it from the original use case is another matter altogether. Two competing schools of thought exist: one using includes and one using extends. As we mentioned at the start of this chapter, the question has perplexed both beginning and experienced use case writers. Our recommended approach is to promote the alternative as an included use case. This makes the main use case much simpler to follow, as you can see in Use Case 7.8, 7.9 and Figure 7.10.

Diagramming the includes relationship between use cases

Figure 7.10. Diagramming the includes relationship between use cases

Using Extends

Some use case writers prefer to promote a complex alternative, as shown in Use Case 7.10 and Figure 7.11.

Diagramming the extend relationship between use cases

Figure 7.11. Diagramming the extend relationship between use cases

The difference in using extends to promote an alternative is that the base use case—Book Flight—does not reference the extending use case (contrast with using include for promotion in Use Case 7.8). Instead, the extending use case directly references the base use case as shown in Use Case 7.11.

Trade-offs and Collaborations

These guidelines improve the organization of the ScenarioPlusFragments (p. 125) by helping us either to reduce complexity or to eliminate redundancy in our use cases. But these benefits can be expensive, because adding extension use cases can break up the flow of the story, making it harder for the reader to find and follow additional use cases. Therefore, you need to weigh the benefit of reduced complexity against the benefits of better readability when deciding whether to create specialized use cases.

These patterns govern the extraction of information from a use case under different circumstances. CommonSubBehavior (p. 176) recommends that you extract behavior only when it is common to several use cases, to reduce redundancy and potential inconsistencies. InterruptsAsExtensions (p. 182) and PromotedAlternative (p. 190) focus solely on alternative courses within a scenario. InterruptsAsExtensions describes creating extending use cases when an alternative affects multiple steps within a scenario, so that the alternative course is easier to follow. Sometimes, though, alternatives can be so complex, or contain so much important information, that it makes sense to create a new use case by using PromotedAlternative, so that the alternative doesn't overshadow the base use case.

The question is “When should you use these constructs?” The answer is to do so judiciously, and only when their use adds some demonstrable value to your use cases. Properly used, they can greatly improve the quality and even readability of a set of use cases. The danger is that they are quite easy to abuse, and can cause more problems than they solve. For that reason, you're better off avoiding them when their use is questionable; apply them only when you can show some benefit from doing so. As a general rule, “If in doubt, don't use them.”

These patterns apply to only a few situations that deal specifically with alternative courses and repetitive behavior. You are likely to find other problems with your use cases, such as excessive complexity, which require you to reorganize them significantly. That subject is the topic of the next chapter.

Before we move on to the next chapter, we would like to offer a supplemental relationship pattern covering UML's generalization construct, contributed by our colleague, Dan Rawsthorne.

Trade-offs and Collaborations

Sailors looking at painting entitled “Sailors Beware,” Fine Arts Building, San Diego, California

CapturedAbstraction—A Pattern for Applying UML Generalization, by Dan Rawsthorne

You are writing use case descriptions as ScenarioPlusFragments (p. 125).

Trying to document two or more distinct alternatives, neither of which is dominant, is very difficult and confusing in a single use case.

In Europe, business travelers are as likely to take trains as planes for business trips. For example, to travel from Frankfurt to Munich by train takes approximately four hours door to door, while it takes three hours by plane. The plane costs slightly more.

Sometimes there is more than one dominant scenario for a single use case. Each scenario could be its own use case, but they all fill the same hole in the system, meeting the same goals for the same actors. When this happens, it makes sense to create an abstract use case that documents the actors and goals, put each dominant scenario in its own use case, and have them inherit from the abstract one.

Complex or long alternatives clutter a use case and can obscure other alternatives. A use case can become difficult to write and even more difficult to follow when the alternatives are too long or complex, and cannot be easily written as a main scenario plus fragments. Use cases are supposed to be easy to read and understand, not complicated engineering documents.

Some problems are very complex, and have several distinct solutions. Keeping the solutions in separate use cases makes writing them easier, but it sacrifices the traceability to the problem. Yet this traceability is important, so that everyone working on the system will understand how the system is supposed to behave in all reasonable situations.

Having many individual use cases tends to scatter important behavior and makes the behavior harder to understand. Again, one of the biggest benefits of using use cases is that they tell stories that provide a context for understanding requirements. Forcing readers to jump between different use cases to understand solutions risks negating this benefit, because it violates the one-stop-shopping principle. We believe that people should be able to get all of the information they need about a requirement from one place, without having to explore several documents to understand it.

Therefore:

Consider creating a generalized abstract use case. Put each distinct variant scenario that specializes the abstraction in its own, specialized use case.

A use case is defined by its goal. When more than one use case has the same goal, there is the possibility of confusion. Logically, in this situation you have multiple use cases that collectively contain a number of scenarios of the same use case. The first option would be to combine the use cases using MergeDroplets (p. 209), but this can't be done if the individual scenarios are complex. The second choice would be to document the dominant scenario in the main use case, and have the secondary ones as extending use cases, using InterruptsAsExtensions (p. 182) or PromotedAlternatives (p. 190). You should consider using an abstraction only if there is no dominant alternative.

You need to exercise caution when using this pattern to justify the creation of an abstract use case, because complex alternatives may indicate that the use case is too detailed or too large (see EverUnfoldingStory [p. 102], LeveledSteps [p. 153], and CompleteSingleGoal [p. 118]). If this is not the case, then putting each distinct alternative in its own use case that specializes an abstract use case is a reasonable course of action.

Examples

Wings Over the World

Assume that retinal scanners are being installed in order to identify agents who want to use the system. If it is also possible to login to the system in the usual way (via name and password), then we are in a situation where an abstraction named Validate Agent may be appropriate, as shown in Figure 7.13. (Note that italics indicate abstraction in the UML.)

UML generalization relationship

Figure 7.13. UML generalization relationship

Note that there is a natural tension between this pattern and TechnologyNeutral (p. 167), as these abstractions are often used to eliminate technology variations that lie in the specializations. In fact, it could be argued that this example is just such a thing. However, sometimes discussion of technology is necessary, because it is part of the problem domain and not the solution domain. A general rule is that mentioning technology is permissible if it is an intrinsic part of the goal, but not when it is part of the solution documented in the alternatives.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.51.153