Tutorials

OO PHP Part 3: UML, Classes and Relations

by John Kleijn on Jun 21, 2008 7:09:14 AM

3. Relations

Visualizing entities separately is pretty useless; the most important use of class diagrams is to visualize the relations between these entities.

Below is a list of the most common types of relations, which I will discuss in the following sections.

  • Associations
    • Bi-directional association (standard association)
    • Uni-directional association
    • Association class (drop class)
  • Aggregation
    • Regular aggregation
    • Composition (composite aggregation)
  • Generalizations
    • Inheritance
    • Implementation (realization)
  • Dependencies

3.1 Associations

An association is a linkage between two classes. An association has navigability , indicating ‘awareness’ of one class of the existence of another.

The parties involved in the association play a role in the association, these roles can be named.

For each association end you can also specify a multiplicity value, restricting the number of times the class at that end may exist, in that relation.

Multiplicity IndicatorMeaning
0..1Zero or one
1One only
0..*Zero or more
1..*One or more
nOnly n (where n > 1)
0..nZero to n (where n > 1)
1..nOne to n (where n > 1)


Below is a figure showing the notation of these association properties:

All of these properties are optional, but specifying them can tell a lot about an association. If you don’t specify the multiplicity, it is assumed to be 1.

NOTE: This chapter will include some code examples. It is important to remember that when translating anything abstract to something concrete, interpretation is a factor. Note that the code examples are just that, examples, and not definitions of the concepts they interpret.

3.1.1 Bi-directional navigable association

Associations are assumed to be bi-directional unless indicated otherwise. Bi-directional implicates that both classes are aware of their relation to the other class. This is indicated by a plain solid line:

In this example, both ShoppingCart and Customer are aware of each other’s existence and may interact accordingly. Although ShoppingCart relates to Customer and vice versa, neither is part of the other, they are both allowed to be part of the bigger whole.

Note the multiplicity. It’s bit of an unconventional example: it allows more than one Customer per ShoppingCart.

The following diagram was made with Visual Paradigm for UML Community Edition, which has full UML 2 support.

The diagram shows a uni-directional association between Xml_Parser_Interface and all of the classes implementing it, and Xml_Implementation_Abstract and all of its children. Parties on both sides of the association are aware of the existence of the other side, and their relation.

One thing you may notice is the small closed arrowhead, next to the association label. This is a UML 2 feature, a label direction indicator. This doesn’t indicate navigability, only how the label should be read.

3.1.1a Bi-directional association: code example

Note that both classes are aware of each other’s interface.

3.1.2 Uni-directional navigable association

In a uni-directional relation only one class is ‘aware’ that the relationship exists.

In this example, class ShoppingCart is not aware of its relation to Customer, yet Customer is aware of ShoppingCart and the fact that there is a relation. Note that we kept the multiplicity value, meaning a multitude of Costumer is aware of a single ShoppingCart. The single instance of ShoppingCart will not be aware of its relation to the Customers.

In terms of navigability, this relation can be referred to as ‘Customer to ShoppingCart’. When we reverse the navigability, the diagram tells a different story.

Now a single ShoppingCart relates to a multitude of Customers, without them knowing. You’ll find it is more common to allow multiplicity on the ‘unaware’ side of an Uni-directional association.

3.1.2a Uni-directional association: code example

In contradiction to the previous example, Customer is unaware of ShoppingCart.

3.1.3 Association class

An association class (or 'drop class') is a class that is relevant to a specific association.

The dotted line in the above example indicates that whenever an instance of Customer is related to an instance of ShoppingCart, an instance of WishList will exist. The relation between Customer and ShoppingCart depends on the existence of WishList.

A drop class can apply to any relation, including aggregate associations (see the next section) with any navigability.

The circle at the intersection is optional.

3.1.3a Association class: code example

The relation between Customer and ShoppingCart is maintained by WhishList.

3.2 Aggregation (aggregate association)

Aggregation, as the term implies, indicates that one is part of another. These parties are referred to as the whole and the part, where the encapsulating class is the whole. In terms of actual code, this normally means an instance of one entity is encapsulated by another in an object property.

3.2.1 Regular aggregation

In regular aggregation, the lifecycle of the part is independent of the whole. This is also referred to as a ‘has a’ relationship. Notation: An open diamond shape on the side of the whole.

Below is a scenario that you can probably easily relate to.

A single instantiation of Customer encapsulates a single ShoppingCart, in the role of currentCart. However, Customer is passed an existing instantiation of ShoppingCart, making it independent from the Customer instantiation.

3.2.1a Aggregation: code example
3.2.2 Composite Aggregation (composition)

In composite aggregation the whole is composed of parts which lifecycles are dependant on the whole.

There should be a strict relation in which the whole is composed of it’s parts.

  1. A car has wheels, but four wheels don’t make a car.
  2. A star cluster is composed of stars, and the collection of stars in it make the cluster.

Example 2 adheres to this strict rule. This rule is impossible to apply in it’s strictest sense, so consider the following example as a sensible compromise:

The USA is composed of states.

Arguably the collection of states doesn’t equal the United States, but it does have a stronger relation than regular aggregation: the whole (the USA) can not exist without it’s parts. A car can exist without wheels, a customer can exist without a shopping cart.

Think about the strength of the relation before you decide to apply lifecycle dependency. Not the other way around: the lifecycle dependency shouldn’t be adding to the strength of the relation when modelling the relation, it is merely a result of the strong relation.

If the relation is weaker, regular aggregation is the better choice: other components may want to use the part(s) when development progresses. Which may be impossible if you make the part’s lifecycle dependant on the whole.

To stick with our e-commerce example: in our system, we decided that a ShoppingCart cannot exist without a Customer (which makes sense). We also decided that the ShoppingCart is the centre of our Universe, and make it the whole in our relation.

The result of these decisions is that a Customer cannot exist without ShoppingCart either. This is an e-commerce system, if you’re not buying, get out. :P

Whether these are good choices, I’ll leave in the middle, this is just for demonstration purposes.


3.2.2a Composite Aggregation: code example

3.3 Generalizations

Also referred to as ‘is a’ relationships, these are the relationships you should already be familiar with: inheritance and implementations. I’ll give you a quick example of the notation of both:

Abstract class ProductList implements interface ItemList, ShoppingCart extends ProductList.

3.4 Dependencies

Dependencies indicate that change in the structure of one may require a change in the other.

In many cases, other types of relations already imply some form of dependency, but if a more descriptive relation is not applicable, you can use dependency to establish relations between elements. This implies that dependency is a ‘weaker’ and less descriptive relation than associative relations.

Consider the following diagram:

Customer is dependant on WhishList because it fetches an array containing wish list items. The underlined operation indicates that getWishList is a static operation. Customer is dependant on the signature (calling routine and return value) of getWishList.

In contradiction to associations, dependencies can not be labelled, nor can the roles of the elements involved in the relation. Dependencies also do not necessarily relate to entities able to be instantiated (in which cases an association is more applicable), also to those that can not, like packages or static operations. Multiplicity is not applicable to dependencies.

To get a look at the dependencies in a larger scope, a package diagram is essential. A package diagram is essentially a class diagram only showing packages and their dependencies.

This package diagram show two packages: e-commerce and user_management. e-commerce is dependant on user_management, for things like authentication and the like. This particular dependency seems unavoidable, but one of your main goals when designing an application should be to reduce dependency between elements, and making them interchangeable. Bear in mind that a class diagram can not specify the level of dependency, something that can be greatly reduced but not eliminated, by enforcing an strict interface.

Package diagrams can also feature other class diagram relations and ‘subsystem’ package elements, but that is out of the scope of this article.

Comments

For starters, I absolute love these tutorials. They go beyond just OO syntax to best practices and application design.
On a different note, you mentioned you would provide a list of free UML editor, but I haven't found this list.

1. judahtanthony on Jun 27, 2008 1:23:04 PM

Thanks. I forgot about that. Will rectify, later.

2. John Kleijn on Jun 28, 2008 11:50:41 AM

This is nice work. As a newcomer to PHP, this is easy for me to assimilate. Thanks.

3. loydster on Jun 30, 2008 2:04:53 PM

I'm glad you guys like it. I will be doing one more about Design Patterns before taking a break to work on a different project, after launch of that I will continue with part 5+ :)

4. John Kleijn on Jun 30, 2008 3:57:32 PM

Very well explained. Hope u'll write on the Observer pattern. How can we use that kind of pattern in php ?

5. abouchoud on Aug 21, 2008 8:56:38 AM
Login or register to post a comment.