We continue our exploration of UML Class Diagrams with this article that explores how to represent basic business relationships in a class diagram. Drawing these relationships can dramatically clarify requirements documents. Using a class diagram to supplement other requirements documents provides for a centralized reference that enables a shared understanding of the problem domain. That understanding prevents mistakes in interpreting requirements.
Getting Up To Speed
The business cares about customers. And customers have addresses and credit ratings.
Classes and Attributes
How do you know when something should be an attribute, and not another class? In our example above, think about Customer and Address and Credit Rating. One way to make a distinction is to say that if an attribute has other attributes, it should be a class. A credit rating is just a number. But an address is a compound object made up of multiple attributes.
An address can have multiple lines of street address information, as well as city, state, zip code and country information. That is a good indicator that it is likely to be a class of its own. If we were to represent an address as attributes of a customer, we would have to include each of the “sub attributes” as a separate attribute of customer. That feels bad, from a design standpoint.
The distinction is one of design, but generally speaking, if the concept stands on its own, it should be its own class. An address is related to the customer. A credit rating is a property of a customer.
How do we show a relationship between a customer and an address?
The customer receives bills at an address. That is the relationship between the customer and the address. The business wants to know where to send bills for the customer. We’ll talk more about relationships in a bit. First, we’ll cover the steps in visio for creating the relationship shown above.
Showing Relationships With Visio’s UML Stencil
The relationship shown above is called a binary association, because it shows the association between two classes. There is an object (Visio calls it a “master shape”) in the Static Structure template for creating these, aptly named binary association.
Drag that onto the page, and connect the two classes for which you wish to show a relationship.
The default display properties for the binary association shape cause the shape to display some weird information – called the “end names” of the relationship. The shape also does not give us the arrowhead, or the name of the relationship, Receives Bills At. Right click on the line and select “Shape Display Options…”
Remember this, you will use the dialog that pops up a lot.
We want to do three things for now:
- Check “Name” so that the name of the relationship (Receives Bills At) will show up.
- Un-check “First end name” so that it is hidden.
- Un-check “Second end name” so that it is hidden too.
Click OK, and the shape will have updated to look like the following:
The name is defaulted (to “Association1”), and no arrowheads are showing up. We also have two asterisks, an no “1.” We need to update the shape’s properties (not display properties) to include that information. Double click on the line and you will see the following dialog (Fill it out to match):
- Name: Enter “Receives Bills At.” for the name. Note – some people prefer mixed case or lower-case. Any approach is fine, just be consistent. The name is the name of the relationship and it indicates the meaning of the relationship.
- Name Reading Direction: forward and backward will confuse you. It confused me for years. This is what determines where the small solid triangle shows up to indicate the direction of reading. Customer Receives Bills At Address, instead of Address Receives Bills At Customer. One day, I realized that this field only controls if the triangle shows up before or after the text. With up-down relationships, I still get confused. Use the standard of top-to-down is the same as left-to-right, and you’ll eventually get used to it.
- Association Ends: This section shows the two ends as rows in a table – with five columns describing each end. For now, we will only focus on the last two columns. This is another area for confusion – the first row represents the top-left end of the line (when you drag it onto the page) and the second row represents the bottom-right end of the line. You can move the ends of the line around after you place it on the page, and the rows in this table will maintain their original associations. Try not to get frustrated when you get these backwards. I still make that mistake all the time, after creating a few hundred diagrams over the course of a decade. Think of the top-left end of the line as the “first” end, and the bottom-right as the “second.” Then when you move it around, you might remember which is which. If you get in the habit of attaching the line first to the “from” class, and then to the “to” class, you will start to get the hang of it.
- Multiplicity: Multiplicity allows you to specify how many objects can be on either end of the relationship. In our example, a customer can receive bills at only one address, but multiple customers could share the same address. My stepdaughter and I each have iTunes accounts. We are two separate customers, but we have the same address. Since I attached the “first” end to the Customer class, there is an asterisk in the first row, and a “1” in the second row. [*See below for explanations]
- IsNavigable: Either the UI designers for Visio expected all of their users to be Java programmers, or they ran out of space. “IsNavigable” can be translated into “Should the arrow be shown on this end of the line?” Since, as a business, we care about the address at which a customer receives bills, we show the arrow for the “second” end. But we don’t anticipate (commonly) needing to determine all of the customers that receive bills at a particular address – so we don’t show the arrow in the opposite direction.
Types of Multiplicity
There are a few different concepts that can be displayed for multiplicity. Your developer co-workers and math geeks will call this cardinality. That’s probably even the better term to use. But since Visio chose multiplicity, so will we, at least for this article.
- 1: Exactly one object of this type is involved in the relationship. A customer has one billing address.
- *: Any number of objects (or none at all) are involved in the relationship. Any number of customers can receive bills at a given address.
- 0..1: Zero or one objects are involved in the relationship. A driver may or may not have a drivers license.
- 0..*: Same as “*”
- 1..1: Same as “1”
- 1..*: Any number of objects (as long as there is at least one) may be involved in the relationship. A shipment can include any number of items, and it must include at least one item.
This brings us back to our original relationship example.
The small class diagram above represents the following:
- A customer has a credit rating.
- An address includes three fields for “street information”, city, state/province/county, zip or postal code, and country fields.
- A customer receives bills at exactly one address.
- Any number of customers (or none at all) can receive bills at any one address.
Simple Relationships Revisited
With the mechanics of using Visio out of the way, we can show some examples of some other simple relationships.
- A sales rep sells products to any number of customers.
- Any number of customers purchase products from a sales rep.
Both examples above depict the same relationship, and either is acceptable. What would be bad would be to use the passive voice and say “any number of customers are sold products by a sales rep.” This is the same advice that applies when writing use case names – don’t use passive voice.
There are opportunities to misread requirements when relying solely on UML. Imagine we had a requirement that any customer always make purchases from a single sales rep. The goal is to provide a sense of relationship for that customer. Both of the diagrams above technically express that requirement. If a customer could have more than one sales rep, we would show “1..*” instead of “1” for the multiplicity on the sales rep side of the relationship.
Someone reading the examples above could reasonably be unsure about the intended requirement. Is there a single sales rep for a given transaction? Is there a single sales rep for a given customer, regardless of the number of transactions? Only the latter interpretation is technically accurate – but either is a reasonable interpretation. Professor Daniel Berry, author of The Ambiguity Handbook [The actual title is From Contract Drafting to Software Specification: Linguistic Sources of Ambiguity, A Handbook], explained in a lecture last year at the 2007 IBRF that UML stands for Undefined Modeling Language. This is a good example of that.
By including the diagram within, or as a reference from, a requirements document, you provide both the context and the graphical clarity needed to understand the intent. Don’t rely solely on the diagram!
A product has a price. One product has one price. This relationship is almost too simple, making it difficult to come up with a good name for the relationship. “A product has a price of price” is awkward.
“A product will be sold for a price” is better. If we were limited to “has a”, we could make an argument that the price should be an attribute. But the price may have properties (like currency used), or may be calculated dynamically based on coupons or contracts.
Using action verbs will help with both understanding and elicitation. If you are reviewing the diagram above with a stakeholder, you are not likely to get any discussion from “product has a price” – of course it does. But if you show “product will be sold for a price” you will immediately trigger responses. Especially if you ask “how do you know what price to sell the product for?” Use active verbs with explicit meanings instead of “weasel words” like “has a.”
This is a very clear way to indicate that from a business perspective, the customer has a billing address and a shipping address, and no reason to expect them to be the same. If you have to worry about export compliance, you may add an “end use” address – the location where the product will ultimately be used. Imagine how messy that would be if we had used attributes instead of classes!
As messy as that would be, this highlights why we use classes. Think about some other business relationships we have not drawn. Credit card authorization uses the billing address. Taxes may be* calculated based upon the billing address or the shipping address. Shipping charges would be based upon the shipping address. [*I believe that for physical goods, the shipping address is used, and for electronic downloads, the billing address is used.]
There is no limit to the number of entities and relationships that can be represented in a class diagram. As a guideline, think about usability. Are you producing class diagrams as part of exploring specific areas of the business? Are you making sure that a complex set of relationships do not get oversimplified? Are you “boiling the ocean” with a giant encyclopedia of the business domain? If you are – why?
Summary So Far
So far, we have discussed classes as a means to represent entities from a business perspective. We’ve also introduced some simple relationships. Those relationships show how pairs of entities interact or inter-relate. We’ve shown how to make the relationships directional and bidirectional – depending on which way(s) the business needs to look at things. And we’ve covered multiplicity – how many of each type of object are involved in the relationship.
There is still a fair amount of ground to cover between here and Scott Ambler’s comprehensive reference. If any of the concepts so far are unclear, or if there’s something you want to make sure we cover – add a comment!
In our next article on using UML Class Diagrams for unearthing requirements, we will look at more complex relationships.
Uncovering Requirements With UML Class Diagrams Part 3: Combining objects into collections and concepts.