Component Diagrams

After a while, clusters of classes that strongly interact and form a unit will start to peel out from the architecture. To express this, the corresponding clusters can be represented as components. If taken far enough, this can lead to a highly reusable component architecture. But such an architecture is hard to design from scratch and usually evolves over time.

Component diagrams are often used to model high-level software components and how they interact. The interfaces between these components become clearer as the model grows, which provides a much clearer delineation of duties of each component.

Figure 10-2. A Component diagram.

When working extensively with Component diagrams, it is a good idea to turn off automatic edge rendering from Edit -> Settings -> Diagram display -> Add dependent edges automatically. This will prevent potentially confusing edges to appear when working with multiple representations of the same element within a single diagram.

Components

The update from UML 1.x to 2.0 where the actual meaning of the term 'component' was altered necessitated some changes to the Component Diagram. Previously, a component referred to an item to be implemented, such as an executable. As of UML 2.0, components are treated as encapsulated entities that serve as a black box to hide behavior and provide interfaces to the component. This transforms them into more logical elements that can be easily replaced as required by the design.

Required and Provided Interfaces

Components hide the inner workings of a component; each component is a general logical unit. Truly essential to Component diagrams are the provided and required interfaces that determine how the components are wired together and how they interact with one another.

Interfaces can be represented with 'ball and socket' notation: sockets indicate required interfaces and balls (or lollipops) indicate provided interfaces. They can be shown together as a single interface:

Or they may be shown shown separately. The 'Split Assembly Connector' rapid button will disconnect them and display the same interface in two places.

Interfaces may also be shown within the components themselves, regardless of whether the ball and socket notation is being used simultaneously. To do this, select the 'Provided Interfaces' and 'Required Interfaces' checkboxes from the Visibility dropdown menu in the Details Pane toolbar.

Add an Interface to a Component

To simply add an interface to a component, you can create a new component in a Component diagram, then create the new interface with either the required interface or the provided interface rapid buttons. See the Section called Interfaces in Chapter 12 for more information on working with interfaces in Poseidon.

The method mentioned above will certainly create the interfaces, but they are lacking the semantic information that makes UML so useful. If we take a look at the class diagram below, we can see behind the scenes. We have an interface called Interface_1 that is implemented by Class_1 (Class_1 has Interface_1 as a Provided Interface), and that is used by Class_2 (Class_2 has Interface_1 as a Required Interface).

It is in these classes and interfaces that the true behaviors of the component are defined.

When seen from the Component diagram, we see that Component 1 is realized by Class_2. Logically, Component_1 has the same interfaces as Class_2, which we see here in three ways.

First, we see the use relationship between Class_2 and Interface_1 along with the realization between Class_2 and Component_1. Next, we see the list of required interfaces within Component_1. And finally, we see Interface_1 in socket notation. Any one of these methods is sufficent, we have simply chosen to use all three for this demonstration.

To display the representation of an interface that already is listed by a component, select an interface from the Properties tab, then click the 'Add Representation' button from the toolbar above the interfaces list.

Try it Yourself - Add a Provided Interface to a Component

  1. Open a Class diagram.

  2. Create a new interface by clicking the 'New Interface' button on the toolbar, then click in the diagram to create 'Interface_1'.

  3. Create a new Component diagram by clicking the 'New Component Diagram' button.

  4. Add a component to the diagram by clicking the 'New Component' button, then clicking in the diagram.

  5. From the Navigation pane, drag Interface_1 into the Component diagram.

  6. Click and drag from Interface_1's 'Realization' rapid button to Component_1. Component_1 now has Interface_1 as a Provided Interface.

Try it Yourself - Add a Required Interface to a Component through a Class Realization.

  1. Open a Class diagram.

  2. Create a new class by clicking the 'New Class' button on the toolbar, then click anywhere in the class diagram. By default, it will be called 'Class_1'.

  3. Create a new interface by clicking the 'New Interface' button on the toolbar, then click in the diagram to create 'Interface_1'.

  4. Click on the 'Dependency' button in the toolbar, then click and drag from 'Class_1' to 'Interface_1'.

  5. In the Properties tab of the dependency, click the Ellipse button to open the Stereotype dialog.

  6. Click 'use' from the left column, then click the arrow pointing to the right, then click 'Apply' to add the 'uses' stereotype to the dependency.

  7. Create a new Component diagram by clicking the 'New Component Diagram' button.

  8. Add a component to the diagram by clicking the 'New Component' button, then clicking in the diagram.

  9. From the Navigation pane, drag Class_1 into the Component diagram.

  10. Click and drag from Class_1's 'Realization' rapid button to Component_1. Component_1 now has Interface_1 as a Required Interface.

    Extra hint: Class_1 can be taken out of the diagram by selecting the class, then clicking the 'Remove from Diagram' button in the Properties pane.

Ports

Along with interfaces, ports may be added to components. For full details about how to work with ports, please see the Section called Ports in Chapter 12.

Instance Specifications

Objects from UML 1.4 have been redefined in UML 2.0 as instances using Instance Specifications.

Assembly and Delegation Connectors

An assembly connector is a connector between two components that defines that one component provides the services that another component requires. An assembly connector is a connector that is defined from a required interface or port to a provided interface or port. - OMG UML 2.0 Superstructure Specification p. 150

In Poseidon, an assembly connector between two components with compatible interfaces will automatically add these interfaces to the component. Their display can be controlled from the Properties panel.

A delegation connector is a connector that links the external contract of a component (as specified by its ports) to the internal realization of that behavior by the component's parts. It represents the forwarding of signals (operation requests and events): a signal that arrives at a port that has a delegation connector to a part or to another port will be passed on to that target for handling. - OMG UML 2.0 Superstructure Specification p. 150

Diagram Elements

Toolbar

Select

Add or remove space between elements

Component

Instance Specification

Node

Realization

Assembly Connector

Delegation Connector

Link between two Instance Specifications

Dependency

Association

Directed Association

Aggregation

Composition

Association Class

Class

Package

Interface As Circle

Collaboration

Comment

Connect Comment to Element

Text

Circle

Rectangle

Polygon

Polyline

Repaint

Do layout

Update layout

Zoom to 100%

Zoom to Fit

Zoom to Selection