OOP and the UML

   

When you are first learning an object-oriented language such as Java, your initial focus is likely to be solely on the mechanics of writing code in that particular language. This is perfectly reasonable as you start out, but you will quickly realize, if you have not already, that object-oriented development has brought many changes to the software design process in addition to those related to coding syntax. The guidelines of structured development and artifacts such as flowcharts have proved themselves inadequate for properly supporting the development of object-oriented systems. This has led to the establishment of many analysis and design methods created specifically to drive OOP development efforts.

The focus of this book is on programming in Java, so the detailed coverage of any object-oriented analysis and design method won't be presented here. There are numerous books already available to address such topics. However, as a Java programmer, you will no doubt encounter design information that is specified based on a particular method, or at least a particular notation. Specifically, the Unified Modeling Language (UML) developed by Grady Booch, Ivar Jacobson, and James Rumbaugh has become the de facto standard notation for communicating the design of an object-oriented system. This section provides enough UML overview to allow you to interpret a subset of the UML diagrams most closely associated with class design.

UML in Brief

UML is not a design method itself, but a means of modeling the results produced from applying one of the available methods. UML is independent of the design process you use, but it allows you to communicate the artifacts of the design to others using a common notation. Prior to its introduction, each method tended to have its own modeling notation. Although the notations were often similar, expecting developers to communicate in competing modeling languages was quickly seen as counterproductive. The common ground provided by UML is a major advance that allows designers to now focus on system design and not diagramming subtleties.

UML is not a single type of model, but actually a set of diagrams in which each diagram addresses a different aspect of a design:

  • Use Case Diagrams capture the interactions of users (referred to as actors) with a software system. The intent is to describe the system requirements in terms of concrete features that are needed by the end user . For example, "Submit Order" is an appropriate subject for a use case in an order entry system, but "Validate Username" likely isn't because, on its own, it doesn't satisfy any real need of the user.

  • Class Diagrams depict the classes found in a system and the relationships among them. These relationships include both inheritance relationships and associations between classes.

  • Sequence Diagrams depict the object interactions required to carry out the tasks required by a single use case. These interactions are represented as messages between objects (method calls) that are shown in a top to bottom flow that indicates their time ordering.

  • Collaboration Diagrams depict the same type of information as sequence diagrams, but the layout is not restricted to a vertical stacking of object messages. The sequence of messages is instead indicated with numbers , which allows the diagram to be laid out in a way that can include other information.

  • State Diagrams show the allowed states of an object and the events that cause state transitions to occur. Viewing system behavior in terms of state transitions is a long used practice that remains just as significant in OOP as it was in earlier programming techniques.

  • Deployment Diagrams go beyond the logical elements of a design and address the physical mapping of software components onto the target hardware.

This list doesn't cover every aspect of UML, but it should be enough to give you an appreciation for the breadth of this approach to modeling. The various diagrams cover every step from capturing system requirements through deployment. As far as the coverage here, the focus is only on class diagrams and sequence diagrams. Mastering the basics of these two diagrams will give you a head start toward developing Java programs using formal design procedures.

Class Diagrams

As the name implies, a class diagram provides information about the classes in a system. When a design has been completed, the resulting class diagrams are the major drivers in defining the actual code that must be written. These diagrams identify each class in a system and define the required attributes and methods. Unlike some UML diagrams, such as use cases, class diagrams are very much technical in nature and are intended for use solely by a development team and not the eventual users. Of course, this might not hold true if the eventual users are other developers intending to build on the software whose design is defined in the diagrams.

Associations and Inheritance

Class diagrams also illustrate the inheritance hierarchies and inter-class associations found among the classes they include. These diagrams communicate inheritance relationships by identifying the parent of each class that extends another class. The modeling of associations is somewhat more complicated because associations have a corresponding cardinality, and they can be defined as either bidirectional or unidirectional.

The cardinality of an association defines the number of class instances that can be involved in the relationship. For example, if a Car class is related to a Tire class, the association is referred to as one-to-many because each Tire is related to one Car and a Car has many Tire s ( strictly speaking, "many" means any value greater than one). If Car is also associated with SteeringWheel, this reflects a one-to-one association because a Car can only have one SteeringWheel (and a SteeringWheel is owned by exactly one Car ). The remaining cardinality option is referred to as many-to-many. A many-to-many relationship indicates a situation in which class instances are associated in a non-exclusive manner. In this case, neither side owns the other.

For an association to be useful, at least one of the objects involved must be able to access, or navigate to, the other. You can use a class diagram to indicate whether both sides of a relationship or only one can be navigated.

Notation

The first step in working with class diagrams is to learn the notation so that you can interpret design information produced by other developers. Figure 1.2 shows a representative diagram that includes the major components of this type of diagram.

Figure 1.2. Class diagrams illustrate class attributes, methods, and associations.

graphics/01fig02.gif

The example in Figure 1.2 is a subset of the classes that might be designed to support an order-entry system that allows a customer to order one or more products from a catalog. This diagram includes an inheritance relationship and associations of each of the three cardinality types. Walking through this example will give you a good introduction to the notation used within this part of UML.

First of all, the example in Figure 1.2 shows that two types of Product s can be ordered in this system, objects typed by either ClothingItem or Appliance. These classes are each defined in terms of their attributes, such as the size field associated with ClothingItem. In a system such as this, different product types can have unique attributes, but the bulk of the handling of products is independent of this specific detail. Using good OOP techniques, this is best addressed with inheritance. The open -arrow drawn from ClothingItem and Appliance to Product indicates that Product is the parent class for each of these specific product classes. The model for the parent class Product also shows how method signatures can be included for a class in addition to attribute definitions.

Each Product that can be ordered might appear in one or more Catalog s. This relationship is drawn as a many-to-many association between the two classes. Notice how the cardinality is indicated with numbers placed adjacent to the line drawn between the classes. Cardinality can be expressed as either a single value or a range of values. An asterisk is a special value that can be used either alone or as the upper value in a range. Used alone, an asterisk indicates an association to zero or more instances of a class. When used in a range, an asterisk represents some number greater than or equal to the corresponding lower bound. Here, a Catalog must reference at least one Product, but there is no upper bound expressed. Similarly, a Product can be in any number of Catalog s, but it might also be left out of all the Catalog s given that the lower bound of this part of the relationship is zero.

Note

The asterisks used in the upper bounds of the association between Catalog and Product are the only indications in Figure 1.2 that the design is intended to support multiple catalogs and multiple products. Cardinality information in a class diagram is intended to describe how two classes are related, but it often provides additional information about the overall design as well.


Also, note that the line drawn between Catalog and Product has an arrowhead at one end. An arrowhead on one end of an association line indicates unidirectional navigation. Here, a Catalog knows the Product s it contains, but a Product has no knowledge of the Catalog s that include it. Instead of including arrowheads at both ends, bidirectional associations are shown without any arrows to avoid cluttering the diagram.

The rest of the diagram can be interpreted in similar fashion. A Customer in the system has a single associated address and some number of Order s. An Order is associated with a single Customer and one or more OrderLineItem s. The filled diamond shown on the association between Order and OrderLineItem indicates a special type of association known as composition . This notation indicates that an Order is composed of OrderLineItem s that are wholly owned by their order (composition is the one type of association that implies ownership of one object by another). This implies that the removal of an order also removes its line items. Each OrderLineItem references a single Product. Notice that no cardinality value is shown on the OrderLineItem side of this association. Often when a relationship is unidirectional, the specification of this value is omitted because it can be assumed that an object that has no knowledge of the objects that reference it can be referenced by many of them. This is, in effect, a unidirectional one-to-many relationship.

Sequence Diagrams

Sequence and collaboration diagrams are collectively referred to as interaction diagrams because they both focus on how objects interact to perform a requested operation. A sequence diagram is used for the example here given the two are so similar. Where class diagrams are geared toward static relationships that show how classes are linked, sequence diagrams provide a dynamic view that illustrates how associations are created and then used to perform meaningful work. The work shown in a particular sequence diagram is typically the set of steps required to satisfy a single use case.

Messages

As discussed previously in this chapter, method calls made on a class instance can be thought of as messages being passed to an object. Basically, a method call is a request passed to an object that instructs it to do something specific and then return control to the caller. The goal of creating a set of sequence diagrams for a system is to capture all the object interactions that are needed to satisfy the system's functional requirements. The messages identified by these diagrams then provide a basis for defining the complete set of class methods that must be implemented.

Notation

Just like class diagrams, sequence diagrams have their own notation that must be learned. Figure 1.3 shows an example sequence diagram that builds on the previous class diagram to indicate some of the steps necessary to select a product from a catalog and order it.

Figure 1.3. Sequence diagrams illustrate object interactions using time-ordered messages.

graphics/01fig03.gif

Each box along the top of a sequence diagram is an object (not a class, but a single instance). An object is identified by its class name preceded by a colon that might optionally be preceded by an object name. The inclusion of object names is necessary if more than one object of a particular class type participates in the sequence of events, but it is usually omitted otherwise . The order of the objects across the top of the diagram is unimportant; you should, however, select an order that places the objects with the most interaction near each other to reduce clutter in the diagram.

The vertical line that extends beneath each object in a sequence diagram is a lifeline. A lifeline begins when an object is created and ends when it is destroyed . If a lifeline begins at the top of the diagram (just beneath an object box), the associated object exists before the task described by the diagram starts. Similarly, if a lifeline extends to the bottom of a diagram, the associated object still exists when the task is completed. The horizontal arrows between lifelines indicate messages being passed to objects as execution control is transferred. The rectangles drawn along the lifelines are known as activations . An activation indicates that the associated object is either performing work at that time or waiting for another object to return control to it after being sent a message. Activation rectangles are often omitted from sequence diagrams that do not include any concurrent processing by the objects involved. In those cases, the transitions of object activity coincide with the message arrow locations.

Sequence diagrams borrow a bit of notation from class diagrams in that they typically include an actor (denoted as User in Figure 1.3) that initiates the sequence of events. In this example, the first event is a showProducts message sent to a Catalog. This message represents a request to view the items available for purchase. The Catalog responds by iterating through its associated Products and sending a getDescription message to each one to obtain information that can be returned to the User. Although multiple Products participate in this activity, only one representative object is needed in the diagram because there is no interaction between Products and no two Products are active simultaneously .

After the Product descriptions are collected by the Catalog, control returns to the User. UML notation includes the concept of a return action that is indicated by a dashed horizontal line between lifelines, but you only need to include that indication if the return is unclear. Here, the activation rectangles indicate that the Catalog stops processing prior to the new message from the User to an Order, so the return is implied .

The new message from the User causes the creation of an Order object (note the start of the object's lifeline). A request to add a product to the order is then submitted. The actual definition of the addProduct message would at least need to include an input parameter to identify the selected Product, but showing the message parameters in a sequence diagram is optional. Here, an Order would have to be told what Product to add, so including the parameter in the diagram wouldn't add any information that wasn't already implied by the context.

The response of the Order to an addProduct message demonstrates the use of a conditional in a sequence diagram. The Order checks the availability of the requested Product, and then creates an OrderLineItem only if the Product is currently available. If an OrderLineItem is created, it gets the price of the Product and control is returned to the User.

The preceding steps would normally complete a use case corresponding to a simple product order scenario, but an additional action is included to illustrate how a sequence diagram indicates the deletion of an object. When the User requests that a Product be removed from an Order, the corresponding OrderLineItem is deleted. The end of an object's lifeline is denoted with a large "X."

UML Guidelines

The preceding UML examples covered the fundamentals you need to interpret class and sequence diagrams created by other developers and begin using the notation to express your own designs. However, UML is a complex topic with numerous books dedicated to it alone, so you should view what you have been equipped with so far as a foundation upon which to build as you gain experience in OOP. To conclude this section, here are several guidelines to keep in mind as that occurs:

  • Always remember that object modeling is intended to be an iterative process. For other than trivial applications, you shouldn't expect the first set of sequence and class diagrams produced for a system to fully capture all the requirements or even reflect the best design to satisfy the requirements that are known. One of the strengths of UML is that it supports the communication of proposed designs between developers so that they might be improved upon through iteration.

  • As pointed out in the examples, UML includes notation to cover a variety of circumstances that can (and often should) be omitted when that notation doesn't add to the reader's understanding of a diagram. The goal of a UML diagram is to clearly communicate some aspect of a system's requirements or design; any details that do not add to what is being communicated might be unnecessary clutter.

  • If you choose to use UML to document your designs, use the standard notation consistently and correctly. The primary benefit of this standard notation is that the readers of your diagrams who are familiar with UML can spend their time focused on the information you are providing rather than learning the mechanisms by which you are trying to convey it.

   


Special Edition Using Java 2 Standard Edition
Special Edition Using Java 2, Standard Edition (Special Edition Using...)
ISBN: 0789724685
EAN: 2147483647
Year: 1999
Pages: 353

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net