Chapter 6. Structuring Use Cases

As you attempt to model the concerns about a system, you will find that they are not independent from one another. In fact, you frequently find relationships between them and must understand what these relationships are to effectively structure and separate the concerns. The use-case technique provides the means for you to model the relationships between concerns through relationships between use cases, such as use-case extend, use-case include, and use-case generalization. We pay particular attention to use-case extensions because they translate to advices in AOP during implementation. Here, we propose the modeling of pointcuts in extension use cases. This early identification of pointcuts during use-case modeling facilitates the identification of pointcuts during analysis, design, and implementation.

Use-Case Relationships

As you specify use cases for a system, you might sometimes find common behavior across use cases, which you might want to factor out. Other times, you might want to add behaviors to an existing use case, but you do not want to entangle the existing use case. So, what you must do is to specify use-case flows in a different use case from the one executing the flow. What you need then is some way for a use case to refer to another use case. For this reason and several others, as you shall see, you need to model relationships between use cases.

In UML, there are three kinds of relationships between use cases: extend, include, and generalization. These three relationships are illustrated in Figure 6-1.

Use-case relationships.

Figure 6-1. Use-case relationships.

Figure 6-1 shows the three use cases from Chapter 5, “Modeling Concerns with Use Cases”: Reserve Room, Check In Customer, and Check Out Customer, which are represented in white. Three additional shaded use cases are related to the original ones through the use-case relationships. The Handle Waiting List use case extends the Reserve Room use case. This means that it adds new capabilities on top of the existing use case. The Check Room Details use case factors out common behaviors to be included by other use cases. The Reserve Facility use case generalizes the Reserve Room use case and serves as a template for other use cases that deal with reservations. In the rest of this chapter, we discuss each of these relationships, when to use them, and how to model them.

Use-Case Extend Relationship

Extension use cases allow you to add new behaviors into existing use cases (which we call the base, or extended, use case). The use-case technique is formulated such that the new behavior is described totally separate from the base use case. Thus, the base use case is not entangled with the details of the new behavior. This bears a close resemblance to AOP, in which aspects are kept separate from the classes they extend. If you have in the past applied extension use cases, then you have in effect applied aspect orientation all along during requirements (i.e., during use-case modeling). This resemblance is important because it provides a natural transition as you proceed from use-case modeling to design and implementation with aspects.

An extension use case contains one or more extension flows. Extension flows are like alternate flows except that they add to the behaviors of a different use case. Figure 6-2 provides an example of an extension use case. The Handle Waiting List use case is an extension use case that extends the Reserve Room base use case. It introduces a waiting list capability and is used when there are no rooms available during reservation.

Extension use cases.

Figure 6-2. Extension use cases.

Listing 6-1 shows the Reserve Room and the Handle Waiting List use-case specifications side by side. The Reserve Room basic flow on the left is the same basic flow described earlier in Listing 5-1.

Example 6-1. Reserve Room Use Case and Handle Waiting List Use Case

Use Case: Reserve Room

Use Case: Handle Waiting List

Basic Flow

The use case begins when a customer wants to reserve a room(s).

  1. The customer selects to reserve a room.

  2. The system displays the types of rooms the hotel has and their rates.

  3. The customer Check Room Cost.

  4. The customer makes the reservation for the chosen rooms.

  5. The system deducts from the database the number of rooms of the specified type available for reservation.

  6. The system creates a new reservation with the given details.

  7. The system displays the reservation confirmation number and check-in instructions.

  8. The use case terminates.

Alternate Flows

. . .

Extension Points

E1. Update Room Availability

The Update Room Availability extension point occurs at step 5 of the Basic Flow

Basic Flow

. . .

Extension Flows

EF1. Queue for Room

This extension flow occurs at the extension point Update Room Availability in the Reserve Room use case when there are no Rooms of the selected type available.

  1. The system creates a pending reservation with a unique identifier for the selected Room type.

  2. The system puts the pending reservation into a waiting list

  3. The system displays the unique identifier of the pending reservation to the customer.

  4. The base use case terminates.

Extension Points

At the bottom of Listing 6-1 is a section called Extension Points, a standard compartment of a use case in UML. An extension point identifies a specific execution point in the execution path of a use-case instance where additional behaviors can be inserted. In practice, they are named steps in a use-case specification. In our example, the step of interest is when the use-case instance attempts to Update Room Availability, which occurs at step 5 of the basic flow.

In AOP, the points in the execution flow are known as join points. They correspond to extension points in use cases. You do not need to explicitly identify join points in classes, since they are described with a programming language with a formal syntax. The expressiveness of AOP allows you to refer to any possible join point using a combination of pointcut primitives (call, execution, set, cflow, etc.). The semantics of these pointcut primitives identifies join points.

Since use cases are meant for stakeholders, who are usually not as technically inclined as developers, we should not make use cases too formal. That is why use cases are described textually and informally. Consequently, use-case specifications are not as precise as using a programming language to describe them. This means that the use of pointcut primitives, which have formal semantics, is not suitable during use-case modeling. To overcome the informality in use cases, you name a step in the use-case flow that you want to extend. This is achieved with extension points. Note that it is not necessary to name every step, nor should you attempt to do so.

Extension Pointcuts

The right-hand side of Listing 6-1 shows the specification of the Handle Waiting List use case. The Handle Waiting List use case has basic flows that permit an actor to view the contents of the waiting list and so on, but that is not the focus of our discussion at the moment. So we leave the basic flow with “...” in Listing 6-1. Let’s bring our attention to the extension flows. In our example, we have one extension flow named Queue for Room. It describes the additional behavior that occurs when a reservation is submitted. The text in italics is very important because it specifies where the extension flow will be inserted into the base use-case instance.

There is currently no construct in UML for the text in italics. In AOP terminology, it corresponds to a pointcut. A pointcut is an expression that indicates where operation extensions are to be inserted into an existing operation. The concept behind pointcuts and the text in italics are the same except that we are dealing with use cases as opposed to classes. We call the text in italics extension pointcuts.

Please do not get confused between extension points and extension pointcuts. They are different things and occur on different ends of the extension relationship. Extension points are defined in the base use case (see left side of Listing 6-1), whereas extension pointcuts are defined in the extension use case (see right side of Listing 6-1).

The author of the extension use case should not make a reference to the actual step in the base use case, as he has no control of how the base use case will be written or updated. Thus, the author of the base use case is responsible to name the extension points, which are then referenced by the extension pointcuts. In Part 3, we show how use-case pointcuts are mapped to pointcuts during design.

As suggested by UML, the current approach to visually model extension pointcuts is to use a note, as shown in Figure 6-3, but we find this approach inadequate. It is not uncommon to have extension use cases that may be applied to multiple base use cases. Using a note implies that you have a note per extension point-extension flow pair. You may encounter situations in which there are multiple extension flows in one extension use case that are applicable to different extension points in another use case. Thus, you end up with many notes for a single extend dependency between use cases. In both cases, using notes makes the use-case diagram extremely cluttered.

Handle Waiting List extends reserve room.

Figure 6-3. Handle Waiting List extends reserve room.

In addition, some segments of the extension pointcut descriptions may be reusable across flow and extension flow pairs. The UML note does not provide a way for you to systematically reuse such segments.

We apply the approach taken by AOP and define a new compartment to house all extension pointcuts. An extension pointcut is an expression that specifies where the base use case is extended. Figure 6-4 illustrates how the extension use case looks if you use this approach.

Extension pointcut as a compartment.

Figure 6-4. Extension pointcut as a compartment.

Figure 6-4 depicts both use cases using the standard rectangle classifier notation. The Reserve Room use case has a basic flow, tagged {basic}.

Extension Flow Declaration

The extension use case has an extension flow Queue for Room. Since an extension flow is, in reality, an alternate flow defined in a different use case, we tag the Queue for Room flow as an alternate flow {alt}. The extension flow has a suffix to indicate when this extension flow will execute. In the case of Figure 6-4, the suffix indicates that the Reserve Room basic flow will be extended after the extension point referenced by pointcut UpdatingRoomAvailability yields NoRoomAvailable. The extension condition (e.g., yields NoRoomAvailable) is not always necessary. Sometimes, you might want an extension flow to always execute. For example, you might want to monitor use-case behaviors all the time.

In general, you can insert before or after the extension point referenced by an extension pointcut. When the extension flow completes, the existing flow resumes. Sometimes, you need to bypass the existing flow if some conditions are not met. For example, if a customer is blacklisted, he cannot make a reservation. AOP permits us to bypass execution of a join point using an around keyword, and you can likewise in your models use this keyword with the same semantics.

Extension Pointcut

The extension pointcut UpdatingRoomAvailability is defined in the extension pointcuts compartment. In this case, it is an expression with two segments connected by a dot.

  1. The first segment points to the existing use case, Reserve Room.

  2. The second segment points to the extension point, Update Room Availability.

Listing 6-2 also shows how you specify the extension flow and extension pointcut within the use-case specification.

Example 6-2. Use-Case Specification: Handle Waiting List

Use Case: Handle Waiting List

Basic Flows

. . .

Extension Flows

EF1.Queue For Room

This extension flow occurs after UpdatingRoomAvailability yields No Rooms Available.

  1. The system creates a pending reservation with a unique identifier for the selected Room type.

  2. The system puts the pending reservation into a waiting list.

  3. The system displays the unique identifier of the pending reservation to the customer.

  4. The base use case terminates.

Extension Pointcuts

extension pointcut UpdatingRoomAvailability = Reserve Room.Update Room Availability

In Listing 6-2, we did not describe the basic flow. If you were to write the full specification for this use case, you would indeed have one. For example, you might have a basic flow that is initiated periodically to notify customers the subsequent availability of a room.

In general, extension use cases may or may not have basic flows. Unlike the Handle Waiting List use case, some will be pure extensions. They do not have basic flows, and they can never be instantiated directly. We discuss more about pure extensions in Section 6.5.

Let us look at what happens when you execute the Reserve Room use-case instance. This is depicted in Listing 6-5. An actor instance triggers the base use case (Reserve Room) and a use-case instance it created. This Reserve Room use-case instance goes through the steps in the basic flow until step 5. The use-case execution environment knows that there is an extension flow and executes this extension flow (Queue for Room). The first step of the extension flow checks if there are rooms available. In this case, none is available, and the rest of the extension flow is executed. In the last step of the extension, the base use-case instance is terminated.

Execution of use-case extensions.

Figure 6-5. Execution of use-case extensions.

Use-Case Include Relationship

You often find certain steps that are similar across different use cases. You can factor these common flows of events into what is termed an inclusion use case. Other use cases can then reference the flows within this inclusion use case. This referencing from an including use case to an inclusion use case is modeled with an include relationship. Figure 6-6 provides an example of the use-case-include relationship. The Check Room Details, shown shaded, is an inclusion use case. This use case is included by the Reserve Room and Check In Customer use cases to allow actors to check availability of rooms, find rooms that are available for specified periods, and so on.

Use-case inclusions.

Figure 6-6. Use-case inclusions.

Figure 6-7 depicts the relationship between the Reserve Room and Check Room Details use cases in greater detail than by explicitly listing the use case flows. We have relocated the use case flow Check Room Cost from the Reserve Room use case (see Listing 5-1).

Reserve Room includes Check Room Details.

Figure 6-7. Reserve Room includes Check Room Details.

The tag {basic} indicates that a flow can be triggered by an actor, whereas the tag {sub} indicates that a flow can be referenced or included only by another flow. The execution of a Reserve Room use case instance is illustrated in Figure 6-8.

Execution of use case inclusion.

Figure 6-8. Execution of use case inclusion.

The execution path begins at the Reserve Room use case, continues through an included flow within the Check Room Details use case, and resumes at the Reserve Room use case. In this example, the included flow is used to Check Room Availability.

Note that the referencing from an including use case flow to an included use case flow is not the same as a function call. As we mentioned in Chapter 5, use-case flows are not functions. When you do an include, you take the included flow and expand it in the including flow. You can think of include conceptually like macro expansions such as #include and inline in C++ and JSP, and like include in Web modeling. The included files are not invoked but are inserted and expanded at the same level as the including use case at the point when the inclusion is made.

Also note that no use-case instances are instantiated when an include occurs. The same goes for all kinds of use-case relationships. Remember, use-case instances do not communicate. The various use-case relationships discussed in this chapter are just different means for you to reuse flow descriptions.

Inclusions and Extensions

Inclusions and extensions are opposites. With extensions, an extension flow inserts itself into the existing use-case flow, whereas with inclusions, it is the responsibility of the existing use-case flow to insert the inclusion flow.

The question is then which one to use. Since an inclusion is essential to follow the flow of a use case, one way to determine whether a flow is an inclusion flow is to remove it. For example, if we remove Check Room Cost completely from the Reserve Room use case, the Reserve Room makes no sense because checking Room Cost is an integral part of making a Reservation. You do not make a Reservation without knowing the cost. Thus, Check Room Cost is in an inclusion use case, not an extension use case.

By contrast, if we were to remove the waiting list completely, making a reservation would still be useful to the actor by itself. So, we find that the waiting list is quite a separate capability of the system and, hence, we have a separate extension use case for it.

Use-Case Generalization

Use-case generalization is another technique to structure the use-case model. It takes the same meaning as class generalization and connotes an “is-a-kind-of” relationship between use cases. You apply use-case generalization when a group of use cases have similar sequences or when similar set of constraints are imposed on them. Rather than specifying the sequences and constraints repeatedly in individual use cases, you generalize them and describe them in parent use cases. Child use cases then inherit these properties. The parent use case is usually abstract, which means it has some flows that have been identified but are deliberately left unspecified. These flows are considered abstract because at the parent level, terms are still generic and details are not yet described. The actual specifications of these abstract flows are postponed to child use cases because the child use cases include the details. In UML-speak, we say that the child use cases make the flows concrete—by providing the specifications for these flows.

In the Hotel Management System example, there are different kinds of facilities in addition to just Rooms. Customers can make reservations for restaurants, video equipment, and other hotel services. You can generalize Reservations with a Reserve Facility use case. Figure 6-9 shows our use-case model with the Reserve Facility use case added.

Use-case generalization.

Figure 6-9. Use-case generalization.

Figure 6-9 depicts an additional Reserve Restaurant use case. For every generalized use case in your use-case model, you should have at least two child use cases. Otherwise, there is no point in generalizing. It is only when you have several concrete use cases that generalizations can be meaningful. You need to go through all of them at once to sift out the common sequences and push them to a generalized use case.

Listing 6-3 shows the specifications of the Reserve Facility and Reserve Room use cases side by side.

Example 6-3. Reserve Facility Use Case Generalizes Reserve Room Use Case

Use Case: Reserve Facility

Use Case: Reserve Room

Basic Flow

The use case begins when a customer wants to reserve a facility (s).

  1. The system displays the facilities available.

  2. The customer Choose Facility.

  3. The system displays the total costs for the facilities chosen.

  4. The system deducts from the database the number of facilities available.

  5. The system creates a new reservation for the chosen facilities.

  6. The system displays the reservation confirmation number.

  7. The use case terminates.

Alternate Flows

. . .

Subflows

{abstract} Choose Facility

Basic Flow

. . .

Subflow

S1.Choose Facility

  1. The customer selects to Reserve Room.

  2. The customer selects his desired room type and indicates his period of stay.

  3. The system computes the cost for the specified period.

The left-hand side of Listing 6-3 shows the specification of the Reserve Facility use case. In our example, the steps to reserve a facility are all the same. Thus, the basic flow Reserve Facility is concrete. In step 2, it includes a subflow to Choose Facility. This subflow is intentionally left unspecified (i.e., abstract) because it is specific to the child use case. On the right-hand side of 3, we have a concrete case for Reserve Room.

Figure 6-10 shows the generalization relationship between Reserve Facility and Reserve Room. The Reserve Facility use case is an abstract use case because it has an abstract flow. Note that an abstract use case can have concrete flows, but it must have at least one abstract flow.

Reserve Room specializes Reserve Facility.

Figure 6-10. Reserve Room specializes Reserve Facility.

In UML, the way to represent an abstract element is to use italics. However, when attempting to draw diagrams on paper, and especially if you conduct use-case modeling by hand on a whiteboard (as opposed to using a modeling tool), italics are not easily recognizable. To circumvent this problem, we use an {abstract} tag in Figure 6-10.

The execution of a child use-case instance is illustrated in Figure 6-11. Instantiation occurs at the child use case (Reserve Room in our example) and follows a basic flow. The execution path of a child use-case instance follows through a number of flows. If a flow is defined in the child, it is executed; otherwise, the flow defined in the parent is executed. In our example in Figure 6-11, the Reserve Room use-case instance follows the basic flow of the Reserve Facility use case. This is because the Reserve Room use case does not define it, but inherits it from the parent. When the use-case instance reaches the point to choose a facility, we find that the parent use case has left it abstract. Thus, the Choose Facility flow of the Reserve Room use case is executed.

Execution of use-case generalization.

Figure 6-11. Execution of use-case generalization.

Generalization and Extensions

Generalization and extensions should not be confused with each other. If you are a developer, you may be familiar with the extends keyword in Java. Extends in our discussion refers to generalization, not extension.

With generalization, we want to factor out the common behavior into a parent use case and put the specific behavior in a child use case. It is the child use case that is instantiated and executed. With extension, there is no requirement for common behavior: the extension flow merely hooks on to some location in the existing use-case flow to add new behavior.

In addition, with generalization, parent and child use cases have between them an is-a-kind-of relationship. For example, Reserve Room is a kind of Reserve Facility. With extensions, this is not true. For example, Handle Waiting List is not a kind of Reserve Room, nor vice versa.

Generalizations and Inclusions

Generalizations and inclusions are both used to factor out the common behavior of use cases, so at times they can be confused with one another. They are different ways of achieving reuse of common behaviors. Generalizations always require an is-a-kind-of semantics between the parent and the base so that inheritance is meaningful, but this is not necessary with inclusions.

With inclusions, we reuse common behavior by merely delegating the description of a flow to another use case. When the execution of a use case reaches a step that needs common behavior, the use case must make an explicit reference to the included use case and the flow therein.

Utility Use Cases

In addition to generalization, inclusion, and extension use cases, we also have another kind of use case called a utility use case. Utility use cases, by nature, do not provide functionalities that are of direct usefulness to actors and stakeholders, so they are never instantiated on their own. There are either pure inclusions or pure extensions. For example, a utility use case might have functions such as open file, close file, and rename files. These functions need to be used in a larger context before they are useful. Therefore, utility use cases can never be instantiated. They always execute in the context of another use-case instance.

Recall that the purpose of basic flows is to specify the behavior that emerges when a use case is instantiated. Therefore, a use case without a basic flow cannot be instantiated. Since utility use cases are never instantiated, they do not need any basic flow. This is a distinguishing characteristic between utility and non-utility use cases.

Utility use cases are analogous to utility classes in UML. They are merely a container of related flows very much like utility classes, which are containers for related methods.

There are two kinds of utility use cases: utility inclusions and utility extensions. Utility inclusion use cases have subflows that are included by other use cases, whereas utility extension use cases have alternate flows that hook onto other use cases. Neither has basic flows.

Examples of utility inclusions are file operations and basic create, read, update, and delete operations on different kinds of information stored within the system. Such operations are always performed as part of a larger goal of the system, such as to reserve a room.

Utility extensions usually appear as add-on features that do not require further processing. Context-sensitive help is one such example, and so are features that help remember information about a customer so that default values can be entered automatically for her. Such utility extension use cases work simply by hooking on to existing use cases. With aspect orientation, it is very easy to hook such utility extensions onto existing use cases and, therefore, we can make them highly reusable.

Summary and Highlights

The whole idea of use-case modeling and structuring use cases is to clarify stakeholders’ concerns and to make the requirements of the system more understandable. The use-case-extend relationship is one possible technique you can use. In this chapter, we propose the explicit representation of pointcuts in extension use cases. The extension pointcuts help to identify pointcuts during analysis, design, and implementation. This provides a seamless transition as you move ahead in subsequent development activities.

In addition to use-case extend, you can apply use-case include and generalization as well. You can also apply use-case packages to group-related use cases. But structuring use cases occurs not just at the use-case model but also within the use-case specification itself through basic, alternate, and subflows. In fact, the bulk of the time spent in use-case modeling is with the use-case specifications. You normally make several iterations before you can finally evolve a good structure for your use-case model.

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

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