Saturday, November 21, 2009

Section 14.1.  Analyzing an Infrastructure Use Case










14.1. Analyzing an Infrastructure Use Case


A resilient system attempts to separate the infrastructure from the application. This separation must begin with requirements and be preserved through analysis, design, and implementation. In Chapter 7, "Capturing Concerns with Use Cases," we discussed the treatment of infrastructure use cases as extensions to application use cases. This makes the application independent of the infrastructure. At the same time, you want to minimize the dependency from the infrastructure to the application. So, you describe infrastructure use cases as extensions to some application use-case pattern. We have such a use-case pattern known as the Perform Transaction use case. As an example, in Figure 14-1, we show the Handle Authorization infrastructure use case as an extension of the Perform Transaction use case.



Figure 14-1. Infrastructure use cases as extensions to application use cases.







As can be seen in Figure 14-1, the application and the infrastructure are separated from a use-case-modeling perspective. Now we want to maintain that separation when we realize the system. We demonstrate briefly how this is achieved through the Handle Authorization as an example.


Infrastructure use cases may have basic flows, which means that actors can initiate them directly. For example, the Handle Authorization use case depicted in Figure 14-2 has basic flows for defining user permissions.



Figure 14-2. Handle Authorization







The infrastructure is an important part of a system, and much of the technical complexities in a system lie in the infrastructure. Therefore, you need to spend time analyzing its requirements and establish a resilient structure, as you did for application use cases. In the discussion to follow, we use analysis stereotypesboundary, control, and entityas the constructs to conduct analysis. We do not advocate jumping straight to the platform specifics when dealing with infrastructure (i.e., crossfunctional or nonfunctional) requirements. If you do so, you will be quickly swarmed by the platform specifics and lose sight of the requirements you have to meet. Instead, you ought to proceed from a platform-independent perspective. You will find the analysis stereotypes extremely useful to hide the implementation details. Furthermore, at this level of abstraction, it is easier for you to define a structure for the lower layers of the system. It is also easier for you to borrow from your past experience on the infrastructure (which could be on a different platform altogether).


Analyzing infrastructure use cases is similar to analyzing application use cases. The analysis of the Define Permissions use-case flow is simple, and we do not need to describe it further. The analysis of the Check Authorization extension flow, however, needs further discussion, which is the goal of this section. Unlike a normal extension use case in the application layer, which usually extends a single base use case, an infrastructure use case may extend or crosscut many application use cases. Thus, you analyze extension flows (e.g., Check Authorization in Figure 14-2) with reference to an application use-case pattern. As mentioned earlier, such a generic use case can be modeled through the reference Perform Transaction use case. The Perform Transaction use case serves as a template and a reference by which other application use cases are modeled and analyzed.



14.1.1. Identifying Classes


Let us identify the classes that participate in the realization of the Check Authorization extension flow. This will comprise the parameterized classes: Boundary, Control, and Entity, which realize the Perform Transaction use-case pattern. These classes are shown on the left of Figure 14-3. We put these classes in brackets, , to indicate that they are parameters to the Handle Authorization use-case slice. We subsequently bind these parameters using pointcuts.



Figure 14-3. Candidate classes: Handle Authorization.







In addition, you need classes to provide the authorization capability. These classes are listed on the right-hand side of Figure 14-3. The Authorization Handler coordinates the interactions between classes that are involved in this use-case realization. The Access Control List class keeps track of which user is able to do what with the system. The Session class tracks the user actions from the time she logs in to the time she logouts.




14.1.2. Identifying Pointcuts


You normally start the analysis of a use-case flow at the point when the use-case flow is triggered. For basic flows, the triggering event is typically the result of some actor initiation. For alternate flows, or for that matter, extension flows, the triggering point occurs at the point designated by the pointcut. Thus, the first step in analyzing an infrastructure use-case extension flow is to determine where the pointcut will be pointing to in the realization of the Perform Transaction use case.


The basic flow of the Perform Transaction use case is shown in Listing 14-1. It describes the pattern involving how an actor retrieves and displays some data on the form. Please note that Listing 14-1 describes only a general and simple case. There are, of course, many variations to this simple case, and you can describe them if necessary using alternate flows or extension flows in a separate infrastructure use case.



Listing 14-1. Perform Transaction Use-Case: Basic Flow

The use case begins when an actor instance performs a transaction to access or manipulate the values of an entity instance. The system prompts the actor instance to identify the desired entity instance. The actor instance enters the values and submits his request. The system accesses the entity instance and displays its values. The use case terminates.



The realization of the Perform Transaction use case is shown in Figure 14-4. It contains actor instances and class instances, each parameterized with brackets. The interaction between the instances is described simply, as follows: the actor instance performs a request through a Boundary instance, which delegates the processing to a Control instance. This Control instance invokes some data-access operations on an Entity instance. The Boundary instance then displays the results.



Figure 14-4. Perform Transaction use case: interaction diagram.







You now identify the context for executing the authorization check. This is based on the Check Authorization extension flow in the Handle Authorization use case (Listing 14-2).



Listing 14-2. Check Authorization Extension Flow

This extension flow occurs around the pointcut



PerformingTransactionRequest.


The system checks if the actor has sufficient authorization for the request to be performed. If the actor has sufficient authorization, the system proceeds with the request. Otherwise, an error is raised.


Extension Pointcut



PerformingTransactionRequest = Perform Transaction.Perform
Request.




Operation Extension

You now map the extension flow to analysis. This means you have an operation extension that is responsible to checkAuthorization. You also need to identify the structural and behavioral context whereby this operation extension executesthat is, you must map the extension pointcut in the extension flow to the pointcut in the operation extension.




Structural Context

You choose a class and responsibility (which will be refined into operations during design) where you can get information about the user or the session conveniently. Let's assume that you have access to such information at the Boundary class. You execute the operation extension theremore specifically, within the handleRequest operation.




Behavioral Context

You now decide where within the handleRequest operation the checkAuthorization operation extension will execute and how it will execute (i.e., the behavioral context). This occurs when a call to the performRequest operation in the Control instance is made. Thus, you have a pointcut:



performingRequest = call (Control.performRequest )


In addition, you want to gain control of the performRequest operation in the Control instancecontrol in the sense that the checkAuthorization operation extension will determine if performRequest can proceed. You achieve this using the around modifier, because if the checkAuthorization fails, the entire performRequest operation will be bypassed; that is, execution will go around the whole performRequest operation. If checkAuthorization passes, the whole performRequest operation will proceed.


You now have the complete operation extension declaration in analysis, which is formulated as follows:



handleRequest { around (performingRequest) checkAuthorization}


Since the Perform Transaction use case is not an actual use case but a pattern or template, the pointcut performingRequest is also a parameter. You must bind the parameters to actual use-case realizations subsequently. We demonstrate that in Section 14.3.





14.1.3. Allocating Use-Case Behavior to Classes


Now that we have identified where the checkAuthorization extension needs to be executed within the Perform Transaction use-case realization, we can describe the interaction between the participating class instances as shown in Figure 14-5. Figure 14-5 contains two frames. The first is labeled as follows:



around (performingRequest) checkAuthorization



Figure 14-5. Check Authorization interaction.

[View full size image]




It represents the operation extension inserted into the handleRequest operation of the Boundary class. This operation extension gets the Boundary to check authorization through the AuthorizationHandler. The AuthorizationHandler instance gets the user from the Session instance. You can assume that the user details have been associated with the Session instance when the user logs in to the system. This is achieved through the realization of the Login basic flow of the Handle Authorization use case. Based on the user details (i.e., user Id, user role), it checks the user's privileges through the Access Control List. If the user has the required authorization, the rest of the handleRequest proceeds. Otherwise, an error is raised.


Proceeding with the rest of the handleRequest in the Boundary is represented by the second frame. AOP provides a proceed keyword to achieve this.


The way you describe the interaction between the instances participating in an infrastructure use case is the same as that for a normal application use case. The usual practice applies. For example, an entity instance should not invoke a boundary instance subscribes to changes in the entity instance). In general, you should let a control instance do most of the coordinating work.



Describing Class Responsibilities

From the messages between the instances, you can identify the responsibilities of the participating classes. You can summarize the class responsibilities and the pointcut definitions in a class diagram, as shown in Figure 14-6.



Figure 14-6. Participating classes in Check Authorization extension flow.







Each box in Figure 14-6 represents a partial definition of classes relevant to the realization of the Check Authorization flow. You must explore the complete set of flows to find all responsibilities of each participating class. This takes place iteratively across the project life cycle. Note that the pointcut is not shown in the class diagram below. It is shown later when we define the aspect that contains the class extensions specific to the Handle Authorization use case.












    No comments: