The Unified Modeling Language User Guide SECOND EDITION [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

The Unified Modeling Language User Guide SECOND EDITION [Electronic resources] - نسخه متنی

Grady Booch, James Rumbaugh, Ivar Jacobson

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید



Terms and Concepts


A relationship is a connection among things. In object-oriented modeling, the four most important relationships are dependencies, generalizations, associations, and realizations. Graphically, a relationship is rendered as a path, with different kinds of lines used to distinguish the different relationships.

Dependencies


A dependency is a using relationship, specifying that a change in the specification of one thing (for example, class SetTopController) may affect another thing that uses it (for example, class ChannelIterator), but not the reverse. Graphically, a dependency is rendered as a dashed line, directed to the thing that is depended on. Apply dependencies when you want to show one thing using another.


The basic properties of dependencies are discussed in Chapter 5 .

A plain, unadorned dependency relationship is sufficient for most of the using relationships you'll encounter. However, if you want to specify a shade of meaning, the UML defines a number of stereotypes that may be applied to dependency relationships. There are a number of stereotypes, which can be organized into several groups.


The UML's extensibility mechanisms are discussed in Chapter 6 .

First, there are stereotypes that apply to dependency relationships among classes and objects in class diagrams.


Class diagrams are discussed in Chapter 8 .

1. bind

Specifies that the source instantiates the target template using the given actual parameters

You'll use bind when you want to model the details of template classes. For example, the relationship between a template container class and an instantiation of that class would be modeled as a bind dependency. Bind includes a list of actual arguments that map to the formal arguments of the template.


Templates and bind dependencies are discussed in Chapter 9 .

2. derive

Specifies that the source may be computed from the target

You'll use derive when you want to model the relationship between two attributes or two associations, one of which is concrete and the other is conceptual. For example, a Person class might have the attribute BirthDate (which is concrete) as well as the attribute Age (which can be derived from BirthDate, so is not separately manifest in the class). You'd show the relationship between Age and BirthDate by using a derive dependency, showing Age derived from BirthDate.


Attributes are discussed in Chapters 4 and 9; associations are discussed in Chapter 5 and later in this chapter.

3. permit

Specifies that the source is given special visibility into the target

You'll use permit when you want to allow a class to access private features of another class, such as found with C++ friend classes.


Permit dependencies are discussed in Chapter 5 .

4. instanceOf

Specifies that the source object is an instance of the target classifier. Ordinarily shown using text notation in the form source : Target

5. instantiate

Specifies that the source creates instances of the target

These last two stereotypes let you model class/object relationships explicitly. You can use instanceOf when you want to model the relationship between a class and an object in the same diagram, or between a class and its metaclass; usually, however, this is shown using text syntax. You'll use instantiate when you want to specify that a class creates objects of another class.


The class/object dichotomy is discussed in Chapter 2 .

6. powertype

Specifies that the target is a powertype of the source; a powertype is a classifier whose objects are the children of a given parent

You'll use powertype when you want to model classes that classify other classes, such as you'll find when modeling databases.


Modeling logical databases is discussed in Chapter 8; modeling physical databases is discussed in Chapter 30 .

7. refine

Specifies that the source is at a finer degree of abstraction than the target

You'll use refine when you want to model classes that represent the same concept at different levels of abstraction. For example, during analysis you might encounter a Customer class which, during design, you refine into a more detailed Customer class, complete with its implementation.

8. use

Specifies that the semantics of the source element depends on the semantics of the public part of the target

You'll apply use when you want to explicitly mark a dependency as a using relationship, in contrast to the shades of dependencies other stereotypes provide.

Continuing, there are two stereotypes that apply to dependency relationships among packages.


Packages are discussed in Chapter 12 .

1. import

Specifies that the public contents of the target package enter the public namespace of the source, as if they had been declared in the source.

2. access

Specifies that the public contents of the target package enter the private namespace of the source. The unqualified names may be used within the source, but they may not be re-exported.

You'll use import and access when you want to use elements declared in other packages. Importing elements avoids the need to use a fully qualified name to reference an element from another package within a text expression.

Two stereotypes apply to dependency relationships among use cases:


Use cases are discussed in Chapter 17 .

1. extend

Specifies that the target use case extends the behavior of the source

2. include

Specifies that the source use case explicitly incorporates the behavior of another use case at a location specified by the source

You'll use extend and include (and simple generalization) when you want to decompose use cases into reusable parts.

One stereotype you'll encounter in the context of interactions among objects is


Interactions are discussed in Chapter 16 .

send

Specifies that the source class sends the target event

You'll use send when you want to model an operation (such as found in the action associated with a state transition) dispatching a given event to a target object (which in turn might have an associated state machine). The send dependency in effect lets you tie independent state machines together.


State machines are discussed in Chapter 22 .

Finally, one stereotype that you'll encounter in the context of organizing the elements of your system into subsystems and models is


Systems and models are discussed in Chapter 32 .

TRace

Specifies that the target is a historical predecessor of the source from an earlier stage of development

You'll use trace when you want to model the relationships among elements in different models. For example, in the context of a system's architecture, a use case in a use case model (representing a functional requirement) might trace to a package in the corresponding design model (representing the artifacts that realize that use case).


The five views of an architecture are discussed in Chapter 2 .

Note

All relationships, including generalization, association, and realization, are conceptually kinds of dependencies. Generalization, association, and realization have enough important semantics about them that they are treated as distinct kinds of relationships in the UML. The stereotypes listed above represent shades of dependencies, each of which has its own semantics, but each of which is not so semantically distant from plain dependencies to warrant treatment as distinct kinds of relationships. This is a judgment call on the part of the UML, but experience shows that this approach strikes a balance between highlighting the important kinds of relationships you'll encounter and not overwhelming the modeler with too many choices. You won't go wrong if you model generalization, association, and realization first, then view all other relationships as kinds of dependencies.

Generalizations


A generalization is a relationship between a general classifier (called the superclass or parent) and a more specific classifier (called the subclass or child). For example, you might encounter the general class Window with its more specific subclass, MultiPaneWindow. With a generalization relationship from the child to the parent, the child (MultiPaneWindow) will inherit all the structure and behavior of the parent (Window). The child may even add new structure and behavior, or it may override the behavior of the parent. In a generalization relationship, instances of the child may be used anywhere instances of the parent applymeaning that the child is substitutable for the parent.


The basic properties of generalizations are discussed in Chapter 5 .

Most of the time, you'll find single inheritance sufficient. A class that has exactly one parent is said to use single inheritance. There are times, however, when a class incorporates aspects of multiple classes. Then multiple inheritance models those relationships better. For example, Figure 10-2 shows a set of classes drawn from a financial services application. The class Asset has three children: BankAccount, RealEstate, and Security. Two of these children (BankAccount and Security) have their own children. For example, Stock and Bond are both children of Security.

Figure 10-2. Multiple Inheritance

Two of these children (BankAccount and RealEstate) inherit from multiple parents. RealEstate, for example, is a kind of Asset as well as a kind of InsurableItem, and BankAccount is a kind of Asset as well as a kind of InterestBearingItem and an InsurableItem.

Some superclasses are only used to add behavior (usually) and structure (occasionally) to classes that inherit their main structure from ordinary superclasses. These additive classes are called mixins; they do not stand alone but are always used as supplementary superclasses in a multiple inheritance relationship. For example, InterestBearingItem and InsurableItem are mixins in Figure 10.2.

Note

Use multiple inheritance carefully. You'll run into problems if a child has multiple parents whose structure or behavior overlap. In many cases, multiple inheritance can be replaced by delegation, in which a child inherits from only one parent and then uses aggregation to obtain the structure and behavior of more subordinate parents. For example, instead of specializing Vehicle into LandVehicle, WaterVehicle, and AirVehicle on one dimension and into GasPowered, WindPowered, and MusclePowered on another dimension, let Vehicle contain a meansOfPropulsion as a part. The main downside with this approach is that you lose the semantics of substitutability with these subordinate parents.

A plain, unadorned generalization relationship is sufficient for most of the inheritance relationships you'll encounter. However, if you want to specify a shade of meaning, the UML defines four constraints that may be applied to generalization relationships:

1. complete

Specifies that all children in the generalization have been specified in the model (although some may be elided in the diagram) and that no additional children are permitted

2. incomplete

Specifies that not all children in the generalization have been specified (even if some are elided) and that additional children are permitted


The UML's extensibility mechanisms are discussed in Chapter 6 .

Unless otherwise stated, you can assume that any diagram shows only a partial view of an inheritance lattice, so it is elided. However, elision is different from the completeness of a model. Specifically, you'll use the complete constraint when you want to show explicitly that you've fully specified a hierarchy in the model (although no one diagram may show that hierarchy); you'll use incomplete to show explicitly that you have not stated the full specification of the hierarchy in the model (although one diagram may show everything in the model).


The general properties of diagrams are discussed in Chapter 7 .

3. disjoint

Specifies that objects of the parent may have no more than one of the children as a type. For example, class Person can be specialized into disjoint classes Man and Woman.

4. overlapping

Specifies that objects of the parent may have more than one of the children as a type. For example, class Vehicle can be specialized into overlapping subclasses LandVehicle and WaterVehicle (an amphibious vehicle is both).

These two constraints apply only in the context of multiple inheritance. You'll use disjoint to show that the classes in a set are mutually incompatible; a subclass may not inherit from more than one. You'll use overlapping to indicate that a class can multiply inherit from more than one class in the set.


Types and interfaces are discussed in Chapter 11; interactions are discussed in Chapter 16 .

Note

In most cases, an object has one type at run time; that's a case of static classification. If an object can change its type during run time, that's a case of dynamic classification. Modeling dynamic classification is complex. But in the UML, you can use a combination of multiple inheritance (to show the potential types of an object) and types and interactions (to show the changing type of an object during run time).

Associations


An association is a structural relationship, specifying that objects of one thing are connected to objects of another. For example, a Library class might have a one-to-many association to a Book class, indicating that each Book instance is owned by one Library instance. Furthermore, given a Book, you can find its owning Library, and given a Library, you can navigate to all its Books. Graphically, an association is rendered as a solid line connecting the same or different classes. You use associations when you want to show structural relationships.


The basic properties of associations are discussed in Chapter 5 .

There are four basic adornments that apply to an association: a name, the role at each end of the association, the multiplicity at each end of the association, and aggregation. For advanced uses, there are a number of other properties you can use to model subtle details, such as navigation, qualification, and various flavors of aggregation.

Navigation

Given a plain, unadorned association between two classes, such as Book and Library, it's possible to navigate from objects of one kind to objects of the other kind. Unless otherwise specified, navigation across an association is bidirectional. However, there are some circumstances in which you'll want to limit navigation to just one direction. For example, as Figure 10-3 shows, when modeling the services of an operating system, you'll find an association between User and Password objects. Given a User, you'll want to be able to find the corresponding Password objects; but given a Password, you don't want to be able to identify the corresponding User. You can explicitly represent the direction of navigation by adorning an association with an arrowhead pointing to the direction of traversal.

Figure 10-3. Navigation

Note

Specifying a direction of traversal does not necessarily mean that you can't ever get from objects at one end of an association to objects at the other end. Rather, navigation is a statement of knowledge of one class by another. For example, in the previous figure, it might still be possible to find the User objects associated with a Password through other associations that involve yet other classes not shown. Specifying that an association is navigable is a statement that, given an object at one end, you can easily and directly get to objects at the other end, usually because the source object stores some references to objects of the target.

Visibility

Given an association between two classes, objects of one class can see and navigate to objects of the other unless otherwise restricted by an explicit statement of navigation. However, there are circumstances in which you'll want to limit the visibility across that association relative to objects outside the association. For example, as Figure 10-4 shows, there is an association between UserGroup and User and another between User and Password. Given a User object, it's possible to identify its corresponding Password objects. However, a Password is private to a User, so it shouldn't be accessible from the outside (unless, of course, the User explicitly exposes access to the Password, perhaps through some public operation). Therefore, as the figure shows, given a UserGroup object, you can navigate to its User objects (and vice versa), but you cannot in turn see the User object's Password objects; they are private to the User. In the UML, you can specify three levels of visibility for an association end, just as you can for a class's features by appending a visibility symbol to a role name. Unless otherwise noted, the visibility of a role is public. Private visibility indicates that objects at that end are not accessible to any objects outside the association; protected visibility indicates that objects at that end are not accessible to any objects outside the association, except for children of the other end. Package visibility indicates that classes declared in the same package can see the given element; this does not apply to association ends.

Figure 10-4. Visibility


Public, protected, private, and package visibility are discussed in Chapter 9 .

Qualification

In the context of an association, one of the most common modeling idioms you'll encounter is the problem of lookup. Given an object at one end of an association, how do you identify an object or set of objects at the other end? For example, consider the problem of modeling a work desk at a manufacturing site at which returned items are processed to be fixed. As Figure 10-5 shows, you'd model an association between two classes, WorkDesk and ReturnedItem. In the context of the WorkDesk, you'd have a jobId that would identify a particular ReturnedItem. In that sense, jobId is an attribute of the association. It's not a feature of ReturnedItem because items really have no knowledge of things like repairs or jobs. Then, given an object of WorkDesk and given a particular value for jobId, you can navigate to zero or one objects of ReturnedItem. In the UML, you'd model this idiom using a qualifier, which is an association attribute whose values identify a subset of objects (usually a single object) related to an object across an association. You render a qualifier as a small rectangle attached to the end of an association, placing the attributes in the rectangle, as the figure shows. The source object, together with the values of the qualifier's attributes, yield a target object (if the target multiplicity is at most one) or a set of objects (if the target multiplicity is many).

Figure 10-5. Qualification


Attributes are discussed in Chapters 4 and 9 .

Composition

Aggregation turns out to be a simple concept with some fairly deep semantics. Simple aggregation is entirely conceptual and does nothing more than distinguish a "whole" from a "part." Simple aggregation does not change the meaning of navigation across the association between the whole and its parts, nor does it link the lifetimes of the whole and its parts.


Simple aggregation is discussed in Chapter 5 .

However, there is a variation of simple aggregationcompositionthat does add some important semantics. Composition is a form of aggregation, with strong ownership and coincident lifetime as part of the whole. Parts with non-fixed multiplicity may be created after the composite itself, but once created they live and die with it. Such parts can also be explicitly removed before the death of the composite.


An attribute is essentially a shorthand for composition; attributes are discussed in Chapters 4 and 9 .

This means that, in a composite aggregation, an object may be a part of only one composite at a time. For example, in a windowing system, a Frame belongs to exactly one Window. This is in contrast to simple aggregation, in which a part may be shared by several wholes. For example, in the model of a house, a Wall may be a part of one or more Room objects.

In addition, in a composite aggregation the whole is responsible for the disposition of its parts, which means that the composite must manage the creation and destruction of its parts. For example, when you create a Frame in a windowing system, you must attach it to an enclosing Window. Similarly, when you destroy the Window, the Window object must in turn destroy its Frame parts.

As Figure 10-6 shows, composition is really just a special kind of association and is specified by adorning a plain association with a filled diamond at the whole end.

Figure 10-6. Composition

Note

Alternately, you can show composition by using a structured class and nesting the symbols of the parts within the symbol of the composite. This form is most useful when you want to emphasize the relationships among the parts that apply only in the context of the whole.


Internal structure is discussed in Chapter 15 .

Association Classes

In an association between two classes, the association itself might have properties. For example, in an employer/employee relationship between a Company and a Person, there is a Job that represents the properties of that relationship that apply to exactly one pairing of the Person and Company. It wouldn't be appropriate to model this situation with a Company to Job association together with a Job to Person association.


Attributes are discussed in Chapters 4 and 9 .

That wouldn't tie a specific instance of the Job to the specific pairing of Company and Person.

In the UML, you'd model this as an association class, which is a modeling element that has both association and class properties. An association class can be seen as an association that also has class properties or as a class that also has association properties. You render an association class as a class symbol attached by a dashed line to an association line as in Figure 10-7.

Figure 10-7. Association Classes

Note

Sometimes you'll want to have the same properties for several different association classes. However, you can't attach an association class to more than one association, since an association class is the association itself. To achieve that effect, define a class (C) and then have each association class that needs those features inherit from C or use C as the type of an attribute.

Constraints

These simple and advanced properties of associations are sufficient for most of the structural relationships you'll encounter. However, if you want to specify a shade of meaning, the UML defines five constraints that may be applied to association relationships.


The UML's extensibility mechanisms are discussed in Chapter 6 .

First, you can specify whether the objects at one end of an association (with a multiplicity greater than one) are ordered or unordered.

1. ordered

Specifies that the set of objects at one end of an association are in an explicit order.

For example, in a User/Password association, the Passwords associated with the User might be kept in a least-recently used order and would be marked as ordered. If this keyword is absent, the objects are unordered.

Second, you can specify that the objects at one end of an association are uniquethat is, they form a setor whether they are nonuniquethat is, they form a bag.


These changeability properties apply to attributes as well, as discussed in Chapter 9; links are discussed in Chapter 16 .

2. set

The objects are unique with no duplicates.

3. bag

The objects are nonunique, may be duplicates.

4. ordered set

The objects are unique but ordered.

5. list or sequence

The objects are ordered, may be duplicates.

Finally, there is a constraint that restricts the changeability of the instances of an association.

6. readonly

A link, once added from an object on the opposite end of the association, may not be modified or deleted. The default in the absence of this constraint is unlimited changeability.

Note

To be precise, ordered and readOnly are properties of an association end. However, they are rendered using constraint notation.

Realizations


A realization is a semantic relationship between classifiers in which one classifier specifies a contract that another classifier guarantees to carry out. Graphically, a realization is rendered as a dashed directed line with a large open arrowhead pointing to the classifier that specifies the contract.

Realization is different enough from dependency, generalization, and association relationships that it is treated as a separate kind of relationship. Semantically, realization is somewhat of a cross between dependency and generalization, and its notation is a combination of the notation for dependency and generalization. You'll use realization in two circumstances: in the context of interfaces and in the context of collaborations.


Interfaces are discussed in Chapter 11; classes are discussed in Chapters 4 and components are discussed in Chapter 15; the five views of an architecture are discussed in Chapter 2 .

Most of the time you'll use realization to specify the relationship between an interface and the class or component that provides an operation or service for it. An interface is a collection of operations that are used to specify a service of a class or a component. Therefore, an interface specifies a contract that a class or component must carry out. An interface may be realized by many such classes or components, and a class or component may realize many interfaces. Perhaps the most interesting thing about interfaces is that they let you separate the specification of a contract (the interface itself) from its implementation (by a class or a component). Furthermore, interfaces span the logical and physical parts of a system's architecture. For example, as Figure 10-8 shows, a class (such as AccountBusinessRules in an order entry system) in a system's design view might realize a given interface (such as IRuleAgent). That same interface (IRuleAgent) might also be realized by a component (such as acctrule.dll) in the system's implementation view. Note that you can represent realization in two ways: in the canonical form (using the interface stereotype and the dashed directed line with a large open arrowhead) and in an elided form (using the interface lollipop notation for a provided interface).

Figure 10-8. Realization of an Interface

You'll also use realization to specify the relationship between a use case and the collaboration that realizes that use case, as Figure 10-9 shows. In this circumstance, you'll almost always use the dashed arrow form of realization.

Figure 10-9. Realization of a Use Case


Use cases are discussed in Chapter 17; collaborations are discussed in Chapter 28 .

Note

When a class or a component realizes an interface, it means that clients can rely on the class or component to faithfully carry out the behavior specified by the interface. That means the class or component implements all the operations of the interface, responds to all its signals, and in all ways follows the protocol established by the interface for clients who use those operations or send those signals.


/ 215