Very few computer systems today exist outside of some kind of network. In addition to serving an internal user community, most systems also provide some type of value or service to entities external to that community. In return, most systems also make use of services provided by other systems such as client-side operating systems, Web browsers, external databases, and third-party service providers. With the advent of Web services, we may soon find ourselves developing systems to provide services to an even broader range of applications.
In this installment of the UML workbook series, we'll talk about the role of the actor in designing complex systems. To facilitate our discussion, I'll introduce two design patterns that are commonly used for developing such systems, using them to show you how a system model changes as our process evolves from requirements gathering into analysis and design. Throughout this installment, we will work with the Loan Application use case we have developed in previous installments of the UML workbook series (see Resources).
Modeling external interactions
When it comes to modeling interactions between our system and external elements (such as other systems), it is common practice to create classes that represent the way those elements interact with our system. The design pattern for representing external entities as classes is called the Mirror Image pattern. Basically, when we invoke the Mirror Image pattern, we analyze the behavior of an external entity and then create its likeness in our own system. This likeness tends to be very shallow, because it is only intended to abstract out the services that we need (in the case of a single use) or that the system provides (in the case of a class library such as the Java Networking classes). It is not intended to implement the services in any way.
To illustrate, let's examine how TCP/IP works in the Java SDK (package
java.net). TCP/IP is a base function of
most operating systems. As a service, TCP/IP resides in the OS and enables the flow
of traffic across a network. If we were to write a file-transfer
program in Java code, we might use the TCP/IP classes in the Java class
library to access the OS services for this protocol. These classes
would become part of our application, but they would ultimately
reside in the OS, not in our application.
Figure 1 is a UML diagram depicting the classes that represent TCP/IP services for the Java networking classes.
The important thing to understand here is that the above-illustrated classes represent the services provided by the OS. They are not the services themselves. We include these representations in our application design because they allow us to more easily interact with the OS. We interact with these representations as if we were interacting with the services themselves. The representations ensure that the interactions are correctly communicated to the other system, and that any results of these interactions are returned in a manner consistent with our expectations. This is the role of the TCP/IP classes in the Java class library.
Identifying external interactions
Interactions with external entities are identified during the requirements gathering phase of establishing a use case model. In previous columns, we have established a use case model in which actors represent external entities that interact with our system. In the last column in the UML workbook series, we devised a system that would interact with both a human actor (a loan applicant) and an external system actor (a credit bureau).
Figure 2 shows the original use case model for the loan processing system. If you need to further refresh your memory of this system, see the previous installments in the UML workbook series available in Resources.
Figure 2. The loan processing use case model
It is important, when we initially conceptualize a system, to identify the actors that will impact that system. Understanding the interplay of requirements and services between our system and its actors lets us allocate system resources accordingly. The actor's role in a system determines the degree to which it may impact the system.
The role of the actor
We discussed the various roles available to an actor in the first article in the UML workbook series. You may recall that there are four potential roles that an actor may play in a use case: initiator, server, receiver, and facilitator. An actor is an initiator when its role is to set the use case in motion. It acts as a server when it provides one or more services necessary to achieving the goal of the use case. An actor is called a receiver when its role is to receive information from the system -- a data warehouse is one example of a system receiver. And, finally, an actor is called a facilitator when it performs an action on behalf of another actor in a system.
Actors may play multiple roles simultaneously. An actor may be human or machine, and its identity may be anonymous or known. If an actor is anonymous, its identity has no impact on the system. An end user may play many roles in a system without ever being identified; likewise, regardless of which end user plays that role -- Tom, Mike, or Judy -- he or she will experience the exact same functionality. Machines may also act as anonymous actors, particularly in the Web services domain.
In contrast, a system may require identifying information in order to handle matters such as security or quality of service. In these cases, the actor must be known. Anytime that a system requires information about an actor -- whether that information is a precise identification or just some particular information -- that actor is considered to be a known entity.
From requirements to implementation
As we move from use case diagrams into sequence and class diagrams, we will immediately notice the impact of known actors. Our initial sequence diagrams (developed in previous installments of the UML workbook) included known actors. At this level of analysis we describe the interaction between our system and its actors as a series of messages. As such, we are not dealing with individual people or systems; rather, we have encapsulated the details of those who interact with the system in an abstract entity that we call the actor. Figure 3 depicts part of the sequence diagram for the Loan Application use case. For the complete diagram, see the previous installments of the UML workbook.
Figure 3. A partial sequence diagram for the Loan Application use case
As we move from the sequence diagram to the class diagram, our system analysis becomes more refined. We are no longer dealing with actors, since at this level actors are associated with requirements and behavior. Instead the abstract idea behind the actor may be brought forward. Most of the "actors" that appear at this level will be identified by at least one attribute; otherwise they are not interesting to the system in the analysis phase. Any level of identification -- even one attribute -- renders an actor a known actor. Furthermore, in the class diagram the known actor is no longer an actor; it becomes a class.
The shift could be as simple as creating a single class to represent our actor, as shown in Figure 4. Alternatively, the system may "see" our actor as a more complex element. In this case, several abstractions may be put in place. It is in the latter circumstance that the Mirror Image pattern comes into play. The Mirror Image takes our external entity and turns it into part of the system.
In our loan application example, two classes result from translating known actors into classes. Both the applicant and the credit bureau must have identifying characteristics. (If our system did not require identifying characteristics of both of these entities it would be left open to the possibility of fraud.)
Figure 4. A class diagram utilizing the Mirror Image pattern
In our simple model, there is a one-to-one mapping between actors and the class additions. Actors commonly represent "deeper" interactions, however, which can result in multiple classes and more complex interactions. A single actor may result in the addition of many classes, none of which carries the name of the original actor.
In addition to representing known actors, the class diagram will often represent the server and receiver roles. These roles may or may not be known, but for the system to use the services provided by the roles, one or more classes must represent the provided services. We saw this with the TCP/IP example.
An anonymous actor such as an initiator or facilitator may also result in the addition of classes. But this addition will be related to design rather than analysis. We inject these classes for reasons having to do with our actual system implementation, rather than as a reflection of a business constraint. For example, we might add user interface logic that we want to keep separate from our model, or we might add some classes for performance reasons.
In EJB development, the Session Facade pattern is often used to minimize network traffic and ensure transaction consistency. This pattern also plays a big role in the development of Web services, and is a prime example of the use of anonymous actors in systems design. The Session Facade pattern substitutes a single call to a session bean for multiple calls to an entity bean. The new session bean makes calls to the entity beans on the server on behalf of a client.
To illustrate the Session Facade pattern, let's consider a use case where the user can debit her checking account to make a loan payment. If we used entity beans to implement the Make Payment use case, a simple transaction might require four calls across the network, as shown in Figure 5. You may recall, at this point, that the slanted arrow in a sequence diagram indicates a message with slower response times (the result of sending a message across a network instead of sending it directly to an object). Furthermore, there is some chance that one of the transactions might never actually complete.
Figure 5 illustrates how an entity bean would manage the Make Payment use case.
Figure 5. The entity bean approach to making a loan payment
The entity bean alone is obviously not a good implementation for our use case. Performance is problematic, and the failure to complete the final step (of making the payment) would be an even bigger problem. The Session Facade pattern resolves these issues by injecting a session bean into the scenario. The session bean acts as a local representative of our actor.
Modeling with session beans
Logically, the session bean encapsulates the expected actions of the actor that it represents. As such, the session bean provides a facade for our interactions with entity beans. Instead of dragging data across the network several times, the session bean lets us achieve our goals with a single transaction on the server. Additionally, injecting the session bean ensures that user transactions remain atomic and payments will safely be credited. For example, the session bean might roll back any debit for a payment that couldn't be made. This would insure our users against losing money into thin air.
The session bean can also perform multiple operations on an actor's behalf. The session bean's behavior follows the collected behavior of the actor across the use case model. Therefore, if an Applicant actor initiated an Apply for Loan and an Accept Loan use case, the workflow for these use cases would be collected in the Applicant session bean. The Applicant session bean could apply for a loan and later accept it in another transaction.
Figure 6 illustrates how the introduction of a session bean modifies our Make Payment use case.
Figure 6. The Session Facade approach to making a payment
As we have seen, the session bean uses its particular knowledge of the actor to which it is assigned to both facilitate that actor's transactions and enhance system performance. The Session Facade pattern can be used with both known and unknown actors. It isn't often that this pattern has to be applied to actors in the server and receiver roles. Most often, the pattern is implemented for actors in the initiator or facilitator role. Obviously, the customer in the Make Payment use case was an initiator.
The Mirror Image and Session Facade patterns are useful for changing actors in use case diagrams into valid abstractions in class diagrams, which ultimately results in a cleaner translation to code. Known actors usually find their way, in some form, into the logic of the system; anonymous actors may as well.
The greater implication of the translation from diagram to code is traceability. Using patterns such as Mirror Image and Session Facade, we can trace the creation of classes to reflect the identity of, or services provided by, an external entity. Reversing the process, we can understand the elements that brought these classes into being. The goal of these translations is better abstraction and code that is easier to understand and maintain.
- Visit the developerWorks SOA and Web services zone to read up on Web services development.
- You might also want to take the "Getting started with Enterprise JavaBeans technology " tutorial (developerWorks, April 2003) for more step-by-step learning about EJB development.
- The "Java design patterns 101" tutorial (developerWorks, January 2002) is an excellent place to start learning more about Java programming with design patterns.
- For more advanced readers, Paul Monday's tutorial "Java design patterns 201" (developerWorks, April 2002) will take you well beyond the basics. Find out how design patterns can help you to better understand software design.
- Of course, the ultimate reference for learning about design patterns is the original: Design Patterns: Elements of Reusable Object-Oriented Software (Gamma, Helm, Johnson, Vlissides, Addison-Wesley, 1994).
- It bears noting that the WebSphere Application Server provides an ideal environment for building, testing, and deploying the enterprise-level applications described in this column.
- Granville's newest book just recently hit the stands. A Practical Guide to eXtreme Programming (co-authored with David Astels and Miroslav Novak) is now available from Prentice Hall.
- Read all of Granville Miller's Java modeling articles.
- You'll find hundreds of articles about every aspect of Java programming in the developerWorksJava technology zone.