Learn to model software systems using Unified Modeling Language.
February 2026
Unified Modeling Language (UML) is a standardized modeling language consisting of an integrated set of diagrams, developed to help system and software developers for specifying, visualizing, constructing, and documenting the artifacts of software systems.
In this course, we will dive deep into:
By the end of this course, you’ll be able to architect complex systems with clarity and precision.
Instead of using drag-and-drop tools that can be tedious to update, we use PlantUML. PlantUML is an open-source tool that allows users to create UML diagrams from a plain text language.
Most diagrams start with a keyword defining the type (though often omitted in the specific component syntax we use here) and use simple arrows to define relationships.
| Symbol | Meaning |
|---|---|
-> | Solid line/arrow |
--> | Dashed line/arrow |
: | Adds text to a line/relationship |
as | Alias for a long name |
[ ] | Represents a component or node |
( ) | Represents a use case |
as to keep your code clean.
participant "Very Long Service Name" as Service
User -> Service: Request
node "Server" #LightBlue
In most modern IDEs (like VS Code), you can install the PlantUML extension to see a live preview of your diagrams as you type.
Class diagrams are the foundational structural diagrams in UML. They represent the static view of a system, detailing classes, their internal structure, and how they relate to one another.
A class is represented as a box with three compartments:
+ Public: Accessible from anywhere.- Private: Accessible only within the class.# Protected: Accessible within class and subclasses.~ Package/Internal: Accessible within same package.Understanding relationships is the core of UML. The arrow style defines the semantics.
| Relationship | Notation | Meaning | Property |
|---|---|---|---|
| Generalization | Solid line + Hollow Triangle | Dog is an Animal. | Inheritance |
| Realization | Dashed line + Hollow Triangle | ArrayList implements List. | Interface implementation |
| Association | Solid line (opt. arrow) | Teacher has Students. | General link |
| Aggregation | Hollow Diamond | Car has Wheels. | ”Part-of” (Weak: Parts can exist alone) |
| Composition | Filled Diamond | Building has Rooms. | ”Part-of” (Strong: Parts die with parent) |
| Dependency | Dashed Arrow | A uses B. | Temporary usage (parameter/local) |
Multiplicity defines how many instances of one class link to one instance of another:
1: Exactly one.0..1: Zero or one.* or 0..*: Zero or more.1..*: One or more.A common dilemma: Should something be an attribute of a class or its own entity (class)?
String address.Address as a class if you need to track Street, City, and Zip separately or validate them.PlantUML Code:
interface Playable {
+play()
}
abstract class Instrument {
-String brand
#float price
{abstract} +tune()
}
class Guitar extends Instrument implements Playable {
-int stringCount
+play()
+tune()
}
class Case {
-String material
}
Guitar "1" *-- "1" Case : has >
Guitar "1" o-- "0..*" String : uses >
public interface Playable {
void play();
}
public abstract class Instrument {
private String brand;
protected float price;
public abstract void tune();
}
public class Guitar extends Instrument implements Playable {
private int stringCount;
private Case storageCase = new Case(); // Composition
public void play() { /* ... */ }
public void tune() { /* ... */ }
}
Sequence diagrams are interaction diagrams that show how objects operate with one another and in what order. They are time-centric, showing the chronological sequence of messages.
The arrow heads matter significantly:
| Symbol | Message Type | Description |
|---|---|---|
-> | Synchronous | Caller waits for a response before continuing. (Full arrowhead) |
->> | Asynchronous | Caller continues without waiting for response. (Open arrowhead) |
--> | Return | Response sent back to the caller. (Dashed line) |
-> (to self) | Self-Message | A method call within the same object. |
Sequence diagrams use “fragments” to handle logic:
alt (Alternative): If/else logic. Only one branch executes.opt (Optional): If then. Executes only if condition is true.loop (Iteration): Repeats a sequence of messages.par (Parallel): Messages that happen concurrently.PlantUML Code:
actor User
participant "Web UI" as UI
participant "Auth Service" as Auth
database DB
User -> UI: Enter Credentials
UI -> Auth: login(user, pass)
activate Auth
Auth -> DB: findUser(user)
activate DB
DB --> Auth: userPayload
deactivate DB
alt #LightGreen credentials valid
Auth --> UI: token
UI --> User: Dashboard
else #Pink invalid
Auth --> UI: error 401
UI --> User: Show error message
end
deactivate Auth
Use Case diagrams describe the high-level functional requirements of a system. They show what a system does, not how it does it.
Use cases can relate to each other:
<<include>>: One use case must include another to complete its task.
<<include>> “Authenticate User”.<<extend>>: One use case optionally adds behavior to another under specific conditions.
<<extend>> “Place Order” (only if tax applies).PlantUML Code:
left to right direction
actor "Customer" as c
actor "Bank Clerk" as b
rectangle "ATM System" {
c -- (Withdraw Cash)
c -- (Check Balance)
(Withdraw Cash) ..> (Authenticate) : <<include>>
(Check Balance) ..> (Authenticate) : <<include>>
(Withdraw Cash) <.. (Print Receipt) : <<extend>>
b -- (Maintenance)
}
Activity diagrams are essentially advanced flowcharts. They model the flow of control from one activity to another, supporting parallel behavior and complex logic.
Swimlanes group activities based on who performs them (e.g., “User”, “System”, “Database”).
PlantUML Code:
|Customer|
start
:Place Order;
|Order System|
:Validate Order;
if (Order Valid?) then (yes)
fork
:Process Payment;
fork again
:Prepare Shipping;
end fork
:Ship Goods;
stop
else (no)
:Notify Error;
stop
endif
While Activity Diagrams show the flow of a process, State Machine Diagrams (or Statecharts) show the lifecycle of a single object as it transitions between states in response to events.
Idle, Pending, Processing).buttonClicked, timeout).[condition] that must be true for the transition to occur. / action() performed during the transition.Event [Guard] / Action
PlantUML Code:
[*] --> Draft
Draft --> Submitted : submit()
Submitted --> Published : approve() [isUserAdmin]
Submitted --> Draft : reject()
Published --> Archived : archive()
Archived --> [*]
State machines are often implemented in code using the State Design Pattern, where each state is a class, or a simple switch-case if the logic is simple.
These diagrams shift focus from code structure to the physical and logical organization of the system.
A Component is a modular part of a system that encapsulates its contents and whose manifestation is replaceable.
<<component>>.PlantUML Code:
package "Order System" {
[Order Logic] --() IOrder
[Payment Service] --() IPayment
}
[Web UI] ..> IOrder : use
[Order Logic] ..> IPayment : use
These diagrams show the physical hardware and software mapping.
PlantUML Code:
node "Application Server" {
artifact "OrderService.jar"
}
node "Database Server" {
database "PostgreSQL"
}
"Application Server" -- "Database Server" : JDBC / TCP:5432
Modeling is not just about drawing; it’s about making architectural decisions. Here is how to navigate common design challenges.
When modeling a piece of data (e.g., Address), ask:
Don’t use every diagram for every feature. Pick based on what you need to communicate:
| Goal | Diagram Type |
|---|---|
| High-level requirements | Use Case |
| Logic/Workflows | Activity |
| Static structure/Database | Class |
| Time-sensitive interaction | Sequence |
| Complex object lifecycle | State Machine |
| System deployment/Network | Deployment |
ID fields or getters/setters.extends.implements.Always prefer text-based modeling over graphical tools for: