UML Modeling
Lesson 4 of 5
4UML Modeling, the Language for Drawing Software Systems
The big pictureEverything you need to understand about UML Class Diagrams and Sequence Diagrams, the six relationships between classes, with Python examples and ready-made Mermaid diagrams.
What the picture shows: A class box has three layers: the name, the attributes, the methods. A line then links it to another class, and the star on each end means "any number".
Map of this part
The concepts in order, click any one to jump to it:
Two ways into the same idea
UML is like the architect's plan before a house is built. The class diagram shows the rooms and how they connect, and the sequence diagram shows who walks where, and in what order, on an ordinary day. A drawing exposes a mistake while it is still a line on paper, before it becomes a wall that is hard to knock down.
A Class Diagram describes each class's attributes and methods and the six relations: association, generalisation, aggregation, composition, realisation and dependency, with multiplicities like 1..*. A Sequence Diagram shows messages over time, and Mermaid writes both as text kept next to the code.
Required Fundamentals
Before diving into UML, make sure you're comfortable with these object-oriented concepts (the three object lessons before this one):
| Concept | Why it matters here |
|---|---|
| Class / Object | UML is fundamentally about drawing classes and their relationships, if you don't understand the difference between a class and an object, the diagram won't mean anything to you. |
| Attributes / Methods | Every class box in UML shows its attributes and methods, these are the same things you write inside __init__ and the class's functions. |
| Inheritance | One of the six most important UML relationships (Generalization) is simply the inheritance you already know as class Dog(Animal). |
| Abstract Classes | You'll need this to understand the Realization relationship (implementing an interface). |
A Quick Look Before the UML modelling and Design patterns lessons
- Part Nine (UML) teaches you how to "draw" a software system's design before writing any code, a unified visual language every programmer understands regardless of programming language.
- Part Ten (Design Patterns) teaches you ready-made, proven solutions to recurring design problems: how to create objects, how to make them communicate, and how to extend their behavior without breaking old code.
- The two parts are really two sides of the same coin: the first teaches you how to document your system's structure, and the second teaches you how to design a good structure from the start. UML is the language, and Design Patterns are the ready-made vocabulary in that language.
Core Concepts
UML (Unified Modeling Language) is a unified visual language, a blueprint, used to represent any software system's design before or while writing code. Instead of explaining your design with long sentences, you draw it with boxes and arrows that any other programmer understands immediately.
1Why use UML at all?
To visualize relationships between classes before writing code, to save future refactoring time, and to communicate the design idea to the rest of the team in a shared language that doesn't depend on a specific programming language.
2Class Diagram
Shows the system's static structure: what the classes are, what their attributes and methods are, and how they relate to each other. It's a "still picture" of the system.
3Sequence Diagram
Shows behavior over time: who calls whom, and in what order, during a specific scenario's execution. It's a "video" of a single event, not a still image.
4Why Mermaid?
Mermaid is a simple text format for drawing UML diagrams (and others) by writing code instead of dragging and dropping, which makes it storable in Git and reviewable like any other code, which is why diagrams are kept as .mmd files next to the code.
5Anatomy of a UML Class Box
Every class in a UML diagram is drawn as a three-layer box:
- title: str
- is_available: bool
+ mark_as_available()
+ mark_as_unavailable()
A (−) sign means Private, and a (+) sign means Public, exactly like Python conventions (a single or double leading underscore).
6The Six Relationships Between Classes
This is the heart of the project: any correct UML diagram depends on choosing the right relationship between each pair of classes. The difference between them is often one question: can either side exist without the other?
Diagram 8, four fundamental "structural" relationships in UML, from the weakest coupling (Association) to the strongest (Composition/Generalization).
| Relationship | Symbol | Meaning | Example | Does the other side survive without it? |
|---|---|---|---|---|
| Association | --> | A general usage relationship between two independent classes | Teacher ↔ Student | Yes, always |
| Generalization | --|> | An "is-a" relationship, inheritance | Dog inherits from Animal | Not really applicable (a subtype) |
| Aggregation | o-- | "Whole-part" but the part has an independent life | Department ↔ Employee | Yes, the employee stays |
| Composition | *-- | "Whole-part" but the part dies with the whole | Computer ↔ Processor | No, it's deleted with it |
| Realization | ..|> | A class implements an interface contract | Dog implements the abstract Animal | , |
| Dependency | ..> | A temporary, execution-time-only dependency | ReportGenerator depends on DataFetcher | Yes, the dependency is momentary only |
Diagram 9, Realization (implementing an interface) and Dependency (a temporary reliance): both use dotted lines, but the difference is that the first is a permanent commitment to a contract, and the second is a passing use.
Quick Python Examples for Each Relationship
7Association
class Teacher:
def __init__(self, name):
self.name = name
self.students = []
class Student:
def __init__(self, name):
self.name = name
8Generalization
class Animal:
def speak(self):
raise NotImplementedError
class Dog(Animal):
def speak(self):
return "Woof!"
9Aggregation
class Department:
def __init__(self, name):
self.name = name
self.employees = [] # independent lifecycle
class Employee:
def __init__(self, name):
self.name = name
10Composition
class Computer:
def __init__(self, speed):
# Processor is created and destroyed with it
self.processor = Processor(speed)
class Processor:
def __init__(self, speed):
self.speed = speed
11Realization
from abc import ABC, abstractmethod
class Animal(ABC):
@abstractmethod
def speak(self): ...
class Cat(Animal):
def speak(self):
return "Meow!"
12Dependency
class DataFetcher:
@staticmethod
def fetch():
return "data"
class ReportGenerator:
def generate(self):
data = DataFetcher.fetch()
return f"Report: {data}"
Sequence Diagram, How Do You Show Behavior Over Time?
While a Class Diagram answers "what are the parts?", a Sequence Diagram answers "what exactly happens, and in what order, when a specific event occurs?", for example, "what happens when a new loan is created?"
Diagram 10, the core elements of a Sequence Diagram: the vertical line (Lifeline) for each object, the Activation bar, and the three types of arrows.
| Element | Shape | Meaning |
|---|---|---|
| Lifeline | A dotted vertical line under each participant | Represents the object's existence over time |
| Activation Bar | A thin rectangle on the line | The period during which the object is "active" processing a request |
| Synchronous message (Sync) | A solid arrow (→) | The sender waits for a response before continuing |
| Asynchronous message (Async) | An open arrow (⇢) | The sender continues its work without waiting |
| Return message | A dashed arrow | The final response from the receiver back to the sender |
A Complete Applied Example: a Student Course Registration System
To cement the idea with an example entirely different from your project (so you practice applying the same logic yourself later on your own system), let's model a simple university registration system:
- Student: has a name and email, and can enroll in courses.
- Course: has a title and credit hours, completely independent of any specific student.
- Enrollment: represents linking a student to a course on a specific date, it has no meaning without both together (Composition from the process's side).
Diagram 11, notice the numbers 1 and * on either end of each relationship: this is Multiplicity, one student may have several enrollments, and one course appears in several enrollments.
Diagram 12, the same system, but from the perspective of "what happens the moment a student enrolls in a course" instead of "what are the fixed parts".
Myth vs. Reality
| The myth | The reality |
|---|---|
| UML is an old tool nobody uses today | It's still used daily in technical documentation, design reviews, and System Design interviews. |
| You must draw every detail of the system in UML | The goal is clear communication, not complete coverage, the best diagram is the simplest one that conveys the idea. |
| Aggregation and Composition are basically the same thing | The difference is fundamental: who controls the part's lifecycle? This changes real programming decisions (when is the part automatically deleted?). |
| Sequence Diagrams are only used for final documentation | It's an excellent early thinking tool for discovering design gaps before writing any code. |
Where Is UML Actually Used?
Designing systems before building
Large engineering teams draw Class/Sequence Diagrams before writing code to align understanding among developers.
System Design interviews
You're often asked to sketch a quick diagram to explain how your proposed system's components interact.
Technical documentation
UML diagrams get included in software engineering documents (ADRs, RFCs) to communicate design decisions.
Reviewing legacy code
When dealing with complex old code, reverse engineering a diagram helps quickly understand its structure.
Try it yourself
In a class diagram, what does - before an attribute mean?
- means private and + means public. The sign says who may reach it, nothing about its value.
Quick Review Flashcards
Check Your Understanding
1. What's the practical difference between Aggregation and Composition?
In Aggregation, the part continues to exist even if the whole is deleted (example: an employee stays even if the department is deleted). In Composition, the part is automatically deleted with the whole because it has no meaning on its own (example: the processor gets deleted with the computer).
2. When do you use Realization instead of Generalization?
Generalization is for actual inheritance from a real class (a genuine is-a). Realization is when a class implements an abstract interface's contract without inheriting ready-made behavior, just a commitment to method signatures.
3. Why does Sequence Diagram care about chronological order while Class Diagram doesn't?
Because they answer two entirely different questions: Class Diagram documents the static structure while Sequence Diagram documents one specific execution scenario in its chronological order (behavior), the same system might have one structure diagram but dozens of behavior diagrams for different scenarios.
4. In a "library" system, why is Loan specifically Composition with Library and not Aggregation?
Because a loan record has no logical meaning existing independently without the library context that manages it, its lifecycle is completely tied to the process that created it, unlike the book or the user which continue to exist independent of any specific library.
Resources for this part
Sorted by kind: start with the official docs when you want the precise reference, or with an article or video when you want the explanation first.
Resources for this lesson
Grouped by type. Start with the official docs for precision, or an article or video for the explanation.
Official docs1
Articles2
Done with this lesson?
Sign in to save your progress.