UML eli Unified Modeling Language on standardoitu mallinnuskieli, jolla voidaan kuvata ohjelmistojen rakennetta ja toimintaa. Tässä oppaassa keskitytään luokkakaavioon, joka kuvaa luokat ja niiden väliset suhteet.
Luokka piirretään suorakaiteena, joka on jaettu kolmeen osaan: luokan nimi, attribuutit (jäsenmuuttujat) ja operaatiot (jäsenfunktiot). Kaikkia tietoja ei tarvitse näyttää jokaisessa kaaviossa, vaan mukaan valitaan kuvattavan asian kannalta olennaiset tiedot.

Luokan jäsenten suojaustasoa kuvaavat symbolit ovat:
-: private eli yksityinen+: public eli julkinen#: protected eli suojattuEsimerkiksi attribuutti -age: int tarkoittaa yksityistä int-tyyppistä jäsenmuuttujaa nimeltä age. Operaatio +getInfo(value: int): float tarkoittaa julkista jäsenfunktiota, joka ottaa int-tyyppisen parametrin ja palauttaa float-tyyppisen arvon.
Luokkien väliset suhteet esitetään viivoilla ja niiden päissä olevilla merkeillä. Viivan päässä olevan kolmion tai vinoneliön sijainti kertoo, miten suhde luetaan.
| Yhteys | Merkintä UML-kaaviossa | Merkitys ja esimerkki |
|---|---|---|
| Periytyminen | Yhtenäinen viiva, jonka päässä on ontto kolmio. Kolmio osoittaa kantaluokkaan. | Aliluokka perii kantaluokan. Kun Student perii Person-luokan, kolmio on Person-luokan päässä. |
| Assosiaatio | Assosiaatio piirretään yhtenäisenä viivana. Viivaan voidaan lisätä avoin nuolenkärki osoittamaan, kumpaan suuntaan yhteyttä voidaan käyttää. Ilman nuolta yhteyden käyttösuuntaa ei määritellä. | Luokkien olioilla on yhteys toisiinsa, esimerkiksi Doctor hoitaa Patient-oliota. |
| Aggregaatio eli heikko kooste | Yhtenäinen viiva, jonka päässä on ontto vinoneliö. Vinoneliö on kokonaisuuden päässä. | Kuvaa kokonaisuuden ja osan suhdetta, jossa osat voivat olla olemassa itsenäisesti. Team koostuu Player-olioista; vinoneliö on Team-luokan päässä. |
| Kompositio eli vahva kooste | Yhtenäinen viiva, jonka päässä on täytetty vinoneliö. Vinoneliö on omistavan kokonaisuuden päässä. | Kokonaisuus omistaa osat, ja sen tuhoutuminen tuhoaa siihen kuuluvat osat. Esimerkissä Car omistaa Engine-olion; vinoneliö on Car-luokan päässä. |
Viivan päihin voidaan lisätä lukumäärät: 1 tarkoittaa yhtä, 0..1 nollaa tai yhtä, * nollaa tai useampaa ja 1..* yhtä tai useampaa. Merkintä kertoo, kuinka monta kyseisen pään oliota voi liittyä yhteen vastakkaisen pään olioon.
Jäljempänä samat suhteet esitetään Mermaid-koodina ja siitä muodostettuina kaavioina.
UML-luokkakaavioita voidaan laatia graafisilla työkaluilla, kuten draw.iolla ja Lucidchartilla. Seuraavaksi tehdään kaaviot tekstimuotoisesti Mermaidilla.
Mermaid on työkalu, jolla voi tuottaa kaavioita kirjoittamalla yksinkertaista tekstipohjaista kuvauskieltä. Se soveltuu hyvin Markdown-dokumentteihin: kaavion kuvaus kirjoitetaan muun tekstin joukkoon, ja Mermaid-tukea käyttävä esikatselin näyttää sen kaaviona.
Mermaid-kaavioita voi näyttää myös HTML-sivuilla JavaScript-kirjaston avulla, laatia selaimessa Mermaid Live Editorilla ja viedä kuviksi esimerkiksi dokumentteja tai esityksiä varten. Tässä oppaassa keskitytään UML-luokkakaavioiden tekemiseen Markdown-tiedostoissa. Lopussa on lyhyt esimerkki saman kaavion lisäämisestä HTML-sivulle.
Tässä oppaassa keskitytään luokkakaavioihin.
GitHub tunnistaa Markdown-tiedoston mermaid-koodilohkot ja näyttää niiden sisällön kaavioina automaattisesti. Myös Visual Studio Coden Markdown-esikatselu tukee Mermaid-kaavioita. Kaikkien Markdown-lukijoiden ominaisuuksiin Mermaid-tuki ei kuitenkaan kuulu, joten käytettävän työkalun tuki kannattaa tarkistaa.
Mermaid-koodilohko merkitään .md-tiedostoon seuraavasti:
```mermaid
classDiagram
class Person
```
mermaid-koodilohkolla.Kirjoitetaan seuraava koodi Markdown-tiedostoon:
```mermaid
classDiagram
class Student {
-string firstname
+setFirstname(string fname) void
+getFirstname() string
}
```
Markdown-esikatselu näyttää koodin kaaviona:
classDiagram
class Student {
-string firstname
+setFirstname(string fname) void
+getFirstname() string
}
Edellistä luokkakaaviota vastaavan luokan määritys C++-kielellä olisi seuraava:
#include <iostream>
class Student {
private:
std::string firstname;
public:
Student();
void setFirstname(std::string fname);
std::string getFirstname();
};
Mermaid-esimerkin string vastaa tässä C++:n std::string-tyyppiä. Näissä esimerkeissä käytetään Mermaidin oman ohjeen kirjoitusasua: attribuutin tyyppi on ennen nimeä, esimerkiksi -string firstname, ja metodin paluutyyppi on sulkujen jälkeen, esimerkiksi +getFirstname() string. Näihin koodimerkintöihin ei kirjoiteta kaksoispistettä. Mermaid lisää metodin paluutyypin eteen kaksoispisteen näkyvään kaavioon automaattisesti. Attribuutin kirjoitusasu eroaa edellä esitetystä UML-merkinnästä -firstname: string, mutta kuvaa samat tiedot.
Huom! Muodostimen voi jättää luokkakaaviosta pois, jos se ei ole kuvattavan asian kannalta olennainen. Esimerkiksi pelkkä oletusmuodostin voidaan jättää näyttämättä. Muodostimen puuttuminen kaaviosta ei tarkoita, ettei luokalla olisi muodostinta.
UML-luokkakaavion perusteella voidaan kirjoittaa luokan määrittely C++:n otsikkotiedostoon (.h). Vastaavasti otsikkotiedostossa olevan luokan määrittelyn perusteella voidaan laatia UML-luokkakaavio. Luokkakaavio kuvaa luokan rakenteen, mutta metodien toteutukset kirjoitetaan yleensä erilliseen .cpp-tiedostoon.
Seuraavissa esimerkeissä 1–4 kuvataan vain assosiaation, aggregaation, komposition ja perinnän Mermaid-koodit. Siksi luokkien sisälle ei ole kirjoitettu niiden attribuutteja ja metodeja, vaikka ne kuuluisivat luokkien täydellisiin kuvauksiin. UML-kaaviossa näitä tietoja voi jättää pois, kun halutaan keskittyä luokkien välisiin suhteisiin.
Koodi:
```mermaid
classDiagram
class Doctor {
}
class Patient {
}
Doctor "1" -- "*" Patient : diagnose
```
Kaavio:
classDiagram
class Doctor {
}
class Patient {
}
Doctor "1" -- "*" Patient : diagnose
Lukumäärämerkintä 1 tarkoittaa yhtä ja * nollaa tai useampaa. Tässä yksinkertaistetussa mallissa yhdellä lääkärillä voi olla useita potilaita ja jokaisella potilaalla on yksi lääkäri.
Koodi:
```mermaid
classDiagram
class Team {
}
class Player {
}
Team "1" o-- "*" Player : has
```
Kaavio:
classDiagram
class Team {
}
class Player {
}
Team "1" o-- "*" Player : has
Koodi:
```mermaid
classDiagram
class Car {
}
class Engine {
}
Car *-- Engine : contains
```
Kaavio:
classDiagram
class Car {
}
class Engine {
}
Car *-- Engine : contains
Koodi:
```mermaid
classDiagram
class Person {
}
class Student {
}
Person <|-- Student
```
Kaavio:
classDiagram
class Person {
}
class Student {
}
Person <|-- Student
Tässä esimerkissä Classroom sisältää Student- ja Teacher-oliot arvojäseninä. Kompositio (*--) kuvaa sitä, että näiden jäsenolioiden elinkaari on sidottu Classroom-olioon. Jos mallinnetaan luokkatilasta riippumatta olemassa olevia opiskelijoita ja opettajia, suhde olisi yleensä assosiaatio.
Koodi:
```mermaid
classDiagram
class Person {
-int age
-string name
+Person()
+getAge() int
+getName() string
+setAge(int) void
+setName(string) void
}
class Student {
-string groupName
+Student()
+getGroupName() string
+setGroupName(string) void
}
class Teacher {
-string department
+Teacher()
+getDepartment() string
+setDepartment(string) void
}
class Classroom {
-Student objectStudent1
-Student objectStudent2
-Teacher objectTeacher
-string classRoomName
+Classroom()
+getClassRoomName() string
+setClassRoomName(string) void
+setClassRoomPersons() void
+showClassRoomData() void
}
Person <|-- Student
Person <|-- Teacher
Classroom *-- Student : contains
Classroom *-- Teacher : contains
```
Kaavio:
classDiagram
class Person {
-int age
-string name
+Person()
+getAge() int
+getName() string
+setAge(int) void
+setName(string) void
}
class Student {
-string groupName
+Student()
+getGroupName() string
+setGroupName(string) void
}
class Teacher {
-string department
+Teacher()
+getDepartment() string
+setDepartment(string) void
}
class Classroom {
-Student objectStudent1
-Student objectStudent2
-Teacher objectTeacher
-string classRoomName
+Classroom()
+getClassRoomName() string
+setClassRoomName(string) void
+setClassRoomPersons() void
+showClassRoomData() void
}
Person <|-- Student
Person <|-- Teacher
Classroom *-- Student : contains
Classroom *-- Teacher : contains
Mermaid-kaavioita voi näyttää myös HTML-sivulla. Tällöin sivulle lisätään kaavion kuvaus <pre class="mermaid">-elementin sisään ja ladataan Mermaidin JavaScript-kirjasto. Selain suorittaa JavaScriptin ja muuntaa kuvauksen SVG-kaavioksi.
<pre class="mermaid">
classDiagram
class Student {
-string firstname
+setFirstname(string fname) void
+getFirstname() string
}
</pre>
<script type="module">
import mermaid from
'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true });
</script>