Most J2EE projects I run across today have little in the way of analysis and design deliverables to show how they got where they are. The whole endeavor lacks the ability to be tracked; that is, it lacks traceability. In this article, I present the Use Case pattern as a mechanism to improve a projects chances of hitting its delivery goal, but more importantly, as a mechanism that establishes a sound architecture that is much more accommodating to future change. The Use Case pattern provides J2EE applications with more insight into how new applications, and modifications to existing applications, will affect such things as the selection of the type of EJB component and the ramifications to existing transaction boundaries.
When we hear the word pattern, it is usually in the context of design patterns. However, design patterns are typically used in a tactical sense, attending to one vertical challenge of the application. The important question to ask is how can patterns be applied in a strategic sense, taking into consideration all the aspects of a projects lifecycle? For instance, little is provided in the way of patterns that focus on the testing aspects of the project. An even larger gap that is created in the rush to the design pattern is the projects inability to absorb future change. For instance, if the application needs to change, either during development or after the move to production, how does the team trace the effects both forwards and backwards? Fine-grained design patterns just dont get their maximum benefit unless a super pattern for the entire project is brought into focus at the same time.
The Use Case Pattern is a super pattern that encourages project teams to recognize the needs of all the players on the project and more importantly, to instill traceability as a key goal of all deliverables. The Use Case Pattern relies on three artifacts that the UML offers : the Use Case, Class, and Interaction Diagrams. Diagrams in and of themselves are useless without some level of additional support material. This is especially true of the Use Case diagram, whose worth would be suspect without the support of an accompanying template.
Use cases represent the uses of the application. Use cases are coarse-grained and if presented with one, the user will tell you they represent major categories of functionality. As an example, Take Orders is a use case in an online shopping cart application. However, Verify Customer Number is merely a step in the course of some pathway in that use case and is not a use case in its own right. A use cases template then,describes several pathways through a use case. These pathways can range anywhere from the happy path, or the most commonly occurring pathway, to alternate pathways, and of course exception paths, or as one of my clients calls them crappy paths. Figure 1 provides a brief view of a use case diagram and its happy path. We can also make the bold statement that every single pathway is testable. Quite early in the inception phase of the project, the testing team can create test cases, or use case scenarios, to exercise every pathway in an application.
Figure 1 Use Case and Happy Path
Most software engineers today know the purpose of the class diagram. Classes represent both the structure and behavior of some collection of real-world entities in the system. The UML defines three types of classes: boundary, control, and entity. Most classes in an application, particularly the entity classes, are found directly in the use cases. However, as we shall see in a moment, the use case is also a key source of both the boundary and control classes as well.
The UML offers two forms of interaction diagrams: the sequence diagram and the collaboration diagram. It is important to state early in the discussion of interaction diagrams that they are design models of the pathways through the use cases. They represent objects bubbling with excitement, sending messages to one another to satisfy the ultimate goal of the user. From the UML diagrams described so far, traceability is afforded both forward and backward. If requirements change, we start with the use case and assess the impact on the remaining two diagrams.
So what does all this have to do with Java? This is where the architectural aspect of the use case pattern comes into play. One might still get the diagrams right but quite often when I go into a client project, there is still no bridge between what the diagrams describe and the code. At this point, the diagrams become dead, lifeless hulks of some previous view of the application. What follows in the remainder of the article are the pieces that tie the applications deliverables in the analysis and design portion of the application to what we deliver in the form of code.
First, every use case the application defines will have an associated use case control class created for it. Control classes act as coordinators of activity. Others have also suggested this approach as a means to limit access to the internal workings of the application as well as a way to reduce network chatter. Second, every happy and stand-alone alternate path in that use case will have a corresponding operation defined in its related use case control class. The method implementing the operation will directly manage the messaging defined in its corresponding interaction diagram (sequence/collaboration). Exception paths are usually dealt with within the course of some other pathway. The same is true for variation paths, which are alternate paths that dont stand on their own, but are merely left or right turns along the course of some other pathway.
In the EJB world, these use case control classes are implemented as Session Beans. Depending on the nature of the use case, the session bean may be either a stateless session bean (SLSB) or stateful session bean (SFSB). If you follow the suggestion of Tyler Jewell in his excellent article Stateful Session EJBs: Beasts of Burden http://www.onjava.com/pub/a/onjava/2001/10/02/ejb.html , one would hope they would all be SLSB. Each use case session bean will have a corresponding operation as described above which implements the messaging defined in its corresponding interaction diagram. Most of the messaging within the use case operations will be directed at entity beans. However, it could be directed at other session beans as well, particularly if you have includes relationships between use cases. In the non-EJB world, all the classes referred to are simply Java Beans. However, the architecture is identical. Figure 2 provides an overview of the traceability afforded by the Use Case pattern.
Figure 2 Mapping of Components using the Use Case Pattern
As Figure 2 shows, there is an order to the progression of mapping to components: (1) From use-cases we find our entity classes (2, 3). (4) From the use-cases we create interaction diagrams (e.g., sequence/collaboration) that model our classes now acting as living objects sending messages to one another with the sole purpose of accomplishing the goal of the use-case pathway. (5) For each use-case, a use-case controller will be implemented as either an SFSB or an SLSB. This use-case controller bean will contain operations that implement the orchestration logic to carry out an individual interaction diagram. Again, these map directly to the use-case pathways.
This pattern also quite successfully predicts how transaction boundaries are distinguished. Many times I see projects struggle with where to place the logic that controls the boundaries for the pathways through the application. With the use case pattern the guesswork is removed. All transaction demarcation occurs within the use case control classes, ALWAYS. In the case of EJB applications, each method within each use case session bean is assessed as to its need for a transaction. All update-oriented operations in the session beans will be marked RequiresNew. All other operations in the session beans will be marked Supports. All entity beans can be marked at the bean level as Supports.
Right away, without going any further, we have some awesome traceability going for the project team at this point. New requirement? Find which use case the requirement belongs to (perhaps it is a new pathway or a variation on an existing pathway), find its owning use case control class and related operation which houses the messaging for the pathway and assess the impact. This is where the leap over the wall usually happens in most architectures I run across. There may be use cases defined for the project but the resulting code implementing the behavior has absolutely no traceability back to the use case. In this approach, everything bridges back to the use case What a novel idea, actually tying code back to the reason were building the code in the first place. This way, the test team knows the impact on their test plans and even the users know the impact on any training documentation or procedure manuals they might be creating.
The good news isnt over yet. What about the externalization of what the use case pathways represent? If we have a pathway through the Order Inquiry use case, where do we describe what the results look like? One requirement may demand the result be delivered as an HTML page. Another requirement might also require it be rendered on a cell phone or PDA device using Wireless Markup Language (WML). The inner workings of the use case control class method which implements the interaction diagram for the order inquiry pathway should be void of any display logic. It should function the same regardless of what its ultimate destiny may be. This is where the notion of the use case realizations comes into play.
A use case realization can be thought of as an instance of a use case pathway which considers its unique rendering requirements. For both the HTML and WML implementations, there is an interaction diagram that deals with its unique user interface requirements. However, both the HTML and WML requirements would utilize the services of the sequence diagram implemented in the use case control class that just deals with returning a value object back to the order information. How we choose to render the result is done in both a user interface boundary and a control class. In the Java world (regardless of EJB/non-EJB status) this is accomplished using two architecture components: A Servlet that initially intercepts the client request (control) and a Java Server Page (JSP) to render the output back to the client (boundary). Using custom tag libraries, a JSP page would format WML back to the PDA device and yet a different JSP page would format HTML to the browser. Figure 3 shows a UML component diagram outlining the different components working together.
Figure 3 UML Component diagram with the Use Case pattern
The use case pattern provides a framework that serves the needs of many project participants. It provides a basis for all project communication regardless of the lifecycle phase of the project. Of premier importance is the traceability it provides the project. Impact analysis due to change is built into the application by virtue of its architecture. When to use session beans is now quite clear. The operations in the session beans are also direct decendents of the interaction diagrams created during design. EJB transaction definition decisions become less of an issue because all work begins with the session bean acting in the role of use case controller. The application also benefits from a more agile use of the UML, focusing in on those key artifacts that provide the application the biggest bang for their buck. The use case pattern can go a long way towards providing more predictability to not only the end result of a project deliverable, but also to the ability of the application to discover, assess, and absorb future change.
This article is a synopsis of the topics covered in the book, "Developing Applications with Java and UML" published by Addison-Wesley (Nov 2001) by Paul R. Reed, Jr. Paul is president of Jackson-Reed, Inc. (www.jacksonreed.com), a training and consulting firm that focuses on the implementation of Object-Oriented and Distributed systems for clients in the United States, Europe, Asia, and the Middle East. Reach Paul at firstname.lastname@example.org.