
Class Diagrams – Part 1
Hello my esteemed fellow Softects (Software + Architects… maybe it will stick). Today I would like to discuss Class Diagrams. If you want to talk software architecture it is good to have a common way of express ideas. Now UML is really extensive and somewhat flexible and thus I am a believer that the Pareto Principle (or 80/20 Rule if you will) should be applied. What I mean is: Learn that 20% of the tools that will help you on 80% of the cases.
Class Diagrams
Class Diagrams are a good tool to show how the Classes or Objects of the system relate to each other in a static way. This can give you a good overview on your dependencies.
There is a lot that one can talk about class diagrams and I am definitely not going to do a deep-dive here (remember: Pareto principle). But there is still a lot to cover and I have split this in two parts to be more easily digested. So check part 2!
Note: Throughout this post I’ll be using the PlantUML renderer. This might, in some places, give a different representation than the one in the original UML, but this should not prevent the understanding of the concept.
When to use?
Class Diagrams should be used when you need to explain dependencies, describe the way classes and modules are structured or if you are trying to understand how the parts in a system relate. They are not, as any other tool, a one-for-all tool. There are other moments, such as when understanding the flow of information, when you have to make use of other tools which we will cover in other posts.
Basic Components
The Class in Class Diagram
To represent a class, we use a rectangle. Using PlantUML it shows a “C” on it symbolizing it is a class (it can be an interface, enum, etc) but that is not strictly a requirement of UML.
The class representation may carry more information, but we will get to those. Right now you should notice that the rectangle has the name of the class and that is pretty much it.
Attributes
Let’s expand our previous class representation!
Now most of the classes have attributes/fields inside, i.e. information that it is carrying around with it to perform its tasks. We can represent these in UML by only the name of the attribute:
OR by adding a bunch of information in such a form:
visibility name: type multiplicity = default {property string}
Now that is a LOT of information! As mentioned before, just the name is required, but if you want more you have to use your own discretion on the amount of information you are putting on your class diagrams.
Let’s go through the elements of the attribute:
Visibility
There are 4 different types of visibility modifiers: public, private, protected and package-private.
The two you might most see/use are the public and private. The others might not make sense to represent (no need to expose an internal variable, unless you want of course) or are just not used at all.

Type
It is the restriction you put on which type of object this attribute can be. If you think about it from a programming perspective this is the type of the attribute. If you do that, then this is of course language dependent and might be a primitive of the system (String/int/boolean in Java) or another object/data structure.
Multiplicity
This is an indication of how many of that object type can fill the attribute. List for example can contain many, however a single boolean can only hold, well you’ve guessed: 1 value!
Usually multiplicity is defined with a lower bound (a minimum value from 0 to any positive number) and an upper bound (a maximum value any positive number or * for unlimited). These are usually not used on attribute description but when representing the attributes as its own square (opposed to inside the class). We will see this in a bit.
The most common values you will see are:
- 1 (ex.: a car has 1 owner)
- 0..1 (ex.: An owner can own none or one car)
- * (ex.: a car factory can own zero or more cars)
Default Value
This is the value the attribute will receive unless otherwise specified such as in a setter or constructor.
Property String
This just allows you to indicate any additional information for the attribute you might need.
Associations
Now there is another way you might see attributes being represented in Class Diagrams and that is by using associations.
This basically denotes the same thing than before but it makes use of another rectangle instead of adding it directly to the class description:
Both of these are equivalent an convey the same idea. You have to decide which one you think it is the best. I for once prefer to keep primitives as attributes and complex objects or data structures as associations
The arrows on associations show the source and target, i.e. which one is the owner and which one is the attribute (arrow from and to, respectively).
Bidirectional Associations
Associations can also be bidirectional. We saw before unidirectional associations, however in your designing of systems you may come across a situation where you need to have a bidirectional association such as:
On both cases we have the situation where Car contains a Person attribute (an owner) and a Person has a Car attribute, hence the bidirectional association.
On the second case you are naming your association. Now I find that I only use this IF this actually adds understanding, i.e. value, to the diagram. Else I just leave it out!
Operations
Operations are actions that a class knows to perform. These can be considered like functions or methods in programming.
Normally, any operations like getters or setters are not shown, since they can be inferred and do not add value to the Class Diagrams. But any other action you assume it is useful for your audience can be added here.
As with operations here is the full syntax:
visibility name (parameter-list) : return type {property string}
And here is an example of it in UML:
note how we put these operations in the second compartment of the rectangle!
Now let’s go through the parameters:
Visibility
Just as before there are 4 different types of visibility modifiers: public, private, protected and package-private.
Here is the image again just so you don’t have to scroll up again (you’re welcome)

Name
Simply the name of the method. No complications here!
Parameter-list
The list of parameters/inputs you are passing to this operation. This can be empty or a huge list (please don’t do a huge list, it is a code smell… use Builders or Wrappers).
These are notated similar to attributes. Like:
direction name: type = default
Name, type and default were already covered, however direction is new. Direction simply denotes if it is an input or output. These are denoted with a ‘+’ and a ‘-‘ respectively.
If there is no direction given it is assumed to be an input. (It is usually seen like this!)
Return Type
This is the type of the value that will be returned (if any) to the user/action calling this operation.
Property String
Same as before: it allows you to indicate any additional information for the attribute you might need
Wrapping up Class Diagrams (Part 1)
As mentioned before this will be continued: check part 2 here.
We saw:
- the basics of a Class Diagram component.
- showing operations
- representing attributes:
- inside the class object
- as an association
This might surprise you but this would take you a LONG way already! On the next part you will learn a bit more about Generalization, Constrains and Notes on the Class Diagram.
Some last remarks
There is a lot of information you can put into a UML representation. Class diagrams are no exception and can get extremely packed of information pretty quick. Try to be reasonable when adding these and remember:
- Not everything needs to be depicted; avoid naming every association, avoid adding all the info for each attribute, etc.
- Not every part of the system must be on the representation; If it is not necessary for the understanding, leave it out.
- Remember the golden rule: “If it doesn’t add value to the explanation of the system, leave it out!”
- Finally: don’t care about any of these suggestions: if you judge it necessary do it! You are the architect!
Yours truly,
Archie