Guidelines and Assumptions for Sequence Diagram Development

advertisement
Guidelines and Assumptions for Sequence Diagram Development
Several guidelines that can help you develop a design for a use case or scenario using sequence
diagrams. Several assumptions are also implicit in this process. (Note that the tasks aren’t done
sequentially but only when necessary to build the sequence diagram. We identify
them here as separate tasks simply to ensure that all three are completed.)
Guidelines
Designing a use case or scenario by using sequence diagrams involves performing these tasks:
■ Take each input message and determine all the internal messages that result
from that input. For each message, determine its objective. Determine what
information is needed, what class needs it (the destination), and what class
provides it (the source). Determine whether any objects are created as a
result of the input.
■ As you work with each input message, identify the complete set of classes
that will be affected by the message. In other words, select all the objects
from the domain class diagram that need to be involved. You
learned about use case preconditions and postconditions. Any classes that
are listed in either the preconditions or postconditions should be included in
the design. Other classes to include are those that are created, classes that
are the creators of objects for the use case, classes updated during the use
case, and those that provide information used in the use case.
■ Flesh out the components for each message; that is, add iteration, true/false
conditions, return values, and passed parameters. The passed parameters
should be based on the attributes found in the domain class diagram.
Return values and passed parameters can be attributes, but they may also
be objects from classes.
These three steps will produce the preliminary design. Refinements and modifications may be necessary; again, we are focusing only on the problem domain
classes involved in the use case.
Assumptions
The development of the first-cut sequence diagram is based on several assumptions, including:
■ Perfect technology assumption—
The assumption continues here. We don’t include messages such as the user having to log on.
■ Perfect memory assumption—You might have noticed our assumption that
the necessary objects were in memory and available for the use case. We
didn’t ask whether those objects were created in memory. We will change
this assumption when we get to multilayer design. In multilayer design,
we do include the steps necessary to create objects in memory.
■ Perfect solution assumption—The first-cut sequence diagram assumes that
there are no exception conditions. No logic is included to handle a situation
in which the requested catalog or product isn’t found. More serious exception conditions, such as the failure of a credit check, might also be encountered. Many developers design the basic processing steps first and then add
the other messages and processes to handle the exception conditions later.
We do the same here.
Developing a Multilayer Design
The development of the first-cut sequence diagram focuses only on the classes in
the problem domain layer. In many instances, this may be sufficient documentation
to program the solution—either by yourself or with another programmer. Once
you have a solid design for the problem domain classes, adding the view layer and
the data access layer is a straightforward process.
Every system will need view layer classes to represent the input and output
screens for the application. Data access layer classes aren’t always required.
The data access layer is required when the business logic is fairly complex and
should be isolated from the SQL statements that access the database. In the
sequence diagram shown in Figure 11-8, which illustrates the creation of a new
customer account, the business logic and data access logic are combined. Each
domain layer object also contains the SQL insert statements to write itself to the
database. We can do that because there really is no business logic required.
Hence, Figure 11-8 shows a two-layer design after the view layer is added. In this
section, we show a complete three-layer design for the Fill shopping cart use case.
Designing the Data Access Layer
The principle of separation of responsibilities is the motivating factor behind
the design of the data access layer. On large, complex systems, designers create
three-layer designs, including classes whose sole responsibility is executing database SQL statements, getting the results of the query, and providing the information to the domain layer. As hardware and networks became more
sophisticated, multilayer design was used to support multitier networks in
which the database server was on one machine, the business logic was on
another server, and the user interface was on several desktop client machines.
This way of designing systems creates more robust and more flexible systems.
In most cases, problem domain classes are also persistent classes, which
means that their data values must be stored by the system even when the application isn’t executing. The whole purpose of a relational database is to provide this
ability to make problem domain objects persistent. Executing SQL statements on a
database enables a program to access a record or a set of records from the database. One of the problems with object-oriented programs that use relational databases is that there is a slight mismatch between programming languages and
database SQL statements. For example, in a database, tables are linked through
the use of foreign keys, such as a cart having a CustomerID as a
column so the order can be joined with the customer in a relational join. However,
in object-oriented programming languages, the navigation is often in the opposite
direction (i.e., the Customer class may have an array of references that point to the
OnlineCart objects, which are in computer memory and are being processed by the
system). In other words, design classes don’t have foreign keys.
Here, we take a somewhat simplified design approach in order to
teach the basic ideas without getting embroiled in the complexities of database
access. Let us assume that every domain object has a table in a relational database. (More complex situations exist in which tables must be combined to provide the correct set of objects in memory.) There are several techniques (that
provide different designs) for linking the domain layer to the data access layer.
One way is to have the constructor method of each problem domain object
invoke the data access object to get the necessary information to complete the
instantiation of the new object. Another way is to send a message to the data
Figure 11-8
access layer object and have it read the database and then instantiate a new
problem domain object. This second technique is better when a set of objects
needs to be created from a database access that returns an unknown number of
rows. However, both techniques are good solutions.
The Data Access Layer for the Fill shopping cart Use Case
To design the data access layer, we no longer assume that the objects are automatically in memory when we need them; that is, we disregard the perfect memory assumption. The design of the use case now requires additional messages to
save data to the database and to retrieve data to instantiate classes. Inasmuch as
there are two sets of almost identical messages, we will only illustrate the upper
set of messages from Figure 11-12.
Figure 11-13 is the sequence diagram that includes the domain classes and the
data access classes. Notice that all the original internal messages from Figure 11-12
Figure 11-12
are still there. However, associated with each problem domain object is a data
access class, and associated with each original internal message are additional messages to retrieve data from or save data to the database via the data access object.
It is important during this process to ensure that source objects have navigation visibility to destination objects so messages can be sent. We assume but
don’t show that the data access objects have global visibility. (In your programming class, you will learn that factory or singleton classes are often designed
with global methods.) After the appropriate problem domain object is created,
a reference to it is returned to the object that needs visibility. As you look
closely at Figure 11-13, note that every object that sends a message to another
object must have navigation visibility to that object. Remember this important
design point as you develop your design solutions.
An effective method for understanding what is going on in Figure 11-13 is
to begin with the internal messages from the first-cut sequence diagram in
Figure 11-12. Let us review each one and see what changes are required.
■ [firstTime]createCart—The cart handler is going to send a message to a customer object to create a cart. First, it needs to ensure that there is a customer
object in memory. It sends a findCustomer message to the aC:Customer object
to find and create itself from the database. It does so by sending a message to
the :CustomerDA object to read the database and return the appropriate customer object. Only then can it send the createCart message to aC:Customer.
Also, note that at the end of this execution, the aCrt:OnlineCart object sends
a message to the data access object to save the data to the database.
■ addItemToCart—This message is initially the same in both figures. After
aCrt:CartItem has been created and populated with data, a message is sent
to the data access object to save the data to the database.
■ getPrice, getDesc, updateQty—These three messages all access or update the
database. Therefore, each also requires a previous message to find the appropriate data from the database, which is stored in a domain object in memory.
Even though Figure 11-13 appears rather crowded, looking at each internal
message to a problem domain class makes the figure easier to understand. The
primary thing to remember is that data access objects are necessary to retrieve
data and thereby provide navigation visibility to the required object.
Figure 11-13
Download