Class Diagrams

This tutorial covers class diagrams. First we touch on Rust and Object Oriented Programming, then we cover how to use PlantUML to create class diagrams, and finally there is one small exercises to practice drawing these diagrams.

More information on using PlantUML can be found on the official PlantUML website.

More information on class diagrams in UML can be found in section 11.4 of the UML specification.

Rust and OOP

Class diagrams were created in the context of Object Oriented Programming languages such as C++, Java, or C#. Since class diagrams map quite closely to code, the diagrams are a written in a way typical for those languages. For example, field types are typically written before the field name, such as String firstName. You can also notice that camelCase is often used for field and method names. Methods that do not return anything are said to return void, which could be thought of as an equivalent to unit () in Rust. Class diagrams are also used to show inheritance, which is a language feature that Rust does have.

PlantUML supports "non-traditional" class diagrams which write fields in a perhaps more familiar notation such as field_name: Type, and it also has struct and enum keywords for representing these constructs.

In the example below, we show how some Rust code could be represented with class diagrams, showing both styles.

#![allow(unused)]
fn main() {
pub struct Student {
    pub name: String,
    pub net_id: String,
    student_number: u32,
    courses: Vec<Course>,
    faculty: Faculty
}

impl Student {
    fn change_name(&mut self, new_name: String) { todo!() }
    pub fn completed_ects(&self) -> u32 { todo!() }
}

struct Course {
    course_code: u32,
    ects: u32
}

enum Faculty {
    Architecture,
    CivilEngineeringAndGeoSciences,
    ElectricalEngineeringMathematicsAndComputerScience,
    IndustrialDesignEngineering,
    AerospaceEngineering,
    TechnologyPolicyAndManagement,
    AppliedSciences,
    MechanicalEngineering
}
}

We can get this class diagram by translating the code almost exactly:

@startuml rust-to-class-1

struct Student {
    + name: String
    + net_id: String
    - student_number: u32
    ' the fields below are shown in the diagram as their own classes
    ' - courses: Vec<Course>
    ' - faculty: Faculty

    - change_name(String)
    + completed_ects(): u32
}

struct Course {
    - course_code: u32
    - ects: u32
}

enum Faculty {
    Architecture
    CivilEngineeringAndGeoSciences
    ElectricalEngineeringMathematicsAndComputerScience
    IndustrialDesignEngineering
    AerospaceEngineering
    TechnologyPolicyAndManagement
    AppliedSciences
    MechanicalEngineering
}

Student "1" *- "*" Course
Student "*" *-- "1" Faculty

@enduml

A literal translation of the Rust code into a class diagram

We can also write it using more typical class diagram notation:

@startuml rust-to-class-2

class Student {
    + String name
    + String netId
    - Integer studentNumber

    - void changeName(String)
    + Integer completedEcts() 
}

class Course {
    - Integer courseCode
    - Integer ects
}

class Faculty <<enumeration>> {
    ARCHITECTURE
    CIVIL_ENGINEERING_AND_GEOSCIENCES
    ELECTRICAL_ENGINEERING_MATHEMATICS_AND_COMPUTER_SCIENCE
    INDUSTRIAL_DESIGN_ENGINEERING
    AEROSPACE_ENGINEERING
    TECHNOLOGY_POLICY_AND_MANAGEMENT
    APPLIED_SCIENCES
    MECHANICAL_ENGINEERING
}

Student "1" *- "*" Course
Student "*" *-- "1" Faculty

@enduml

A more typical class diagram showing the same information as above

Constructing a Class

To make a class, use the class keyword. Classes have fields and methods. The two are differentiated based on whether they contain parentheses ().

@startuml constructing-class

class Box {
    ' fields
    Float width
    Float height
    Float depth
    ' methods
    void open()
    void close()
    ' method with a return type
    Integer countItems(ItemKind)
}

@enduml

Diagram showing a box class

Visibility

Both fields and methods can have their visibility (public or private) annotated in the diagram using - for private and + for public. Other visibility modifiers exist but we will not be using them.

@startuml public-private

class Example {
    - SomeType privateField
    + OtherType publicField
    - ReturnType privateMethod()
    + void publicMethod()
}

@enduml

Example of public and private visibility

Cardinality

To show the cardinality between two classes, use double-quotes " " on each side of the relation. You can also add a label to the relation by using a colon afterwards : followed by the label.

@startuml cardinality
left to right direction
User "1" -- "0..*" Account
University  "1" -- "1..*" Department
Account "1" -- "1" University : An account can be linked with exactly one University
@enduml

Diagram showing how to display cardinality between classes

Class Relationships

We covered three different types of relations between classes:

@startuml class-relations

' a dog is a kind of animal
Animal <|-- Dog: Generalization
' the tail is a part of the dog
Dog "1" *-left- "1" Tail: Composition
' the favourite food exists even if the dog does not
Dog "*" o-right- "1" Food: Aggregation

@enduml

A class diagram showcasing relations between classes


Exercises

1. Shopping Centre

Draw a class diagram that models the following scenario:

You are modeling the shopping and managing system for the Westfield Mall of the Netherlands. The mall provides both online and offline services that allow a customer to access their services either at physical locations or at the online website. The shopping mall includes different stores, supermarkets, restaurants, and some places of entertainment. Each one of them is made of several departments and employees. Note that a product and service can be offered by different stores in the shopping mall that allows the customer to compare and select.