Luku 1.3: UML-mallinnusta
Tästä sivusta:
Pääkysymyksiä: Kuinka luen / luon UML-luokkadiagrammeja
Mitä tehdään? Luetaan ja lopuksi kokeillaan kaavion piirtämistä käytännössä
Suuntaa antava vaativuusarvio: Keskivaikea.
Suuntaa antava työläysarvio:? Useampi tunti.
Oheisprojektit: Ei ole.
Suuresta määrästä luokkia ja niiden välisistä suhteista voi olla vaikea saada kokonaiskuvaa. Vastaavasti voi olla vaikea selittää sanallisesti kuinka jokin rinnakkaisohjelmoinnin algoritmi toimii, tai kuinka ohjelman suoritus siirtyy oliosta toiseen kun metodit kutsuvat toisiaan.
UML on yleiskäyttöinen ohjelmistokehityksessä käytetty visualisointi ja mallinnuskieli joka tarjoaa yhden ratkaisun. Mallinnuskielen avulla on helppo suunnitella karkealla tasolla suurempia järjestelmiä, esittää tietoa nopeasti ja pienessä tilassa ja vaikkapa selittää asioita muillekin kuin ohjelmoijille. UML luotiin 90-luvun puolivälissä korvaamaan joukko erilaisia mallinnuskieliä, jotka oli kehitetty ratkaisemaan erilaisia visualisointi jamallinnustarpeita.
Käytännössä UML, Unified Modeling Language, on kokoelma erilaisia ohjelmistojen tuottamisprosesseihin liittyviä merkintätapoja. Tässä luvussa tutustumme luokkakaavionotaatioon, joka on yksi yleisimmin käytetyistä UML:n osista. Luokkakaavio on kätevä työkalu ohjelmaa suunniteltaessa, sille sen avulla on helppo luonnostella millaisia luokkia ohjelmaan on tarkoitus laatia jo ennen ohjelmakoodin kirjoittamista.
Kun projektiaiheet on julkaistu ja valittu, jokainen opiskelija tekee ohjelmalleen alustavan suunnitelman. Tarkoitus on tehdä työlle _alustava_ luokkarakenne. Työn tekniseen suunnitelmaasi on tarkoitus piirtää UML-luokkakaavio. Kun olet piirtänyt kaavion, voit pohtia kuinka jotkin ohjelmasi ominaisuudet toimivat: Kuinka luokkien metodit kutsuvat toisiaan kun jotain ominaisuutta käytetään. Onko kaaviossa kaikki tarvittu?
Luokkadiagrammi
Luokka
Alla on annettu yksinkertainen Python-luokka Suorakaide
, jossa on luonnollisesti neljä sivua, jotka tässä ovat luokan Viiva
ilmentymiä.
class Suorakaide:
def __init(self, yla, ala, vasen, oikea):
# koodia ...
def laskePintaala(self):
# koodia ....
def asetaVari(self, vari):
# koodia ....
Luokkadiagrammissa jokaista luokkaa kuvataan suorakaiteella, jossa on yhdestä kolmeen osiota. Aina ei luokasta tarvitse kertoa enempää kuin sen nimi, joka kirjoitetaan ylimpään osioon. Keskimmäiseen osioon (joka usein jätetään pois), voi listata luokan instanssimuuttujat. Alimpaan osioon tulevat luokan metodit.
![../_images/uml_luokka.png](../_images/uml_luokka.png)
Jos vertaat kaaviota ja koodia keskenään, huomaat toivottavasti, että luokkakaaviosta on helppo lukea samat asiat kuin ohjelmakoodista. UML:n muuttujien ja metodien esittämiseen käyttämä notaatio on iloksemme vielä hyvin samankaltainen kuin vastaava ohjelmakoodi. Muuttujien, parametrien ja paluuarvojen tyypit listataan tutulla tavalla kaksoispisteen jälkeen.
Muuttujien ja metodien eteen kirjoitetut miinus- ja plus-merkit kertovat näkyvyydestä.
..admonition:: Näkyvyys Pythonissa
Tähän selitys näkyvyyksistä Pythonin kannalta.
Detaljien määrää voi ja kannattaakin säädellä.
UML tarjoaa mahdollisuuksia ilmaista asioita joko hyvinkin tarkasti tai hyvinkin yleisellä tasolla. Luokasta voidaan haluttaessa esittää vain nimi. Vastaavasti muttujien ja metodien näkyvyttä ei ole pakko merkitä jos se ei ole kaavion käytön kannalta hyödyllistä. Tutustumme kohta luokkien välisiin suhteisiin, joita kuvataan nuolilla. Myös näihin voidaan lisätä lisätietoa määristä, suhteiden roolista, jne, mutta tämä informaatio voidaan tarvittaessa jättää myös pois.
Assosiaatio
Luokkien välisiä suhteita kuvataan luokkakaaviossa kahden luokan välisellä viivalla, johon liitetyt erilaiset nuolenkärjet kertovat millaisesta suohteesta on kyse. Assosiaatiosuhde tarkoittaa tyypilisesti sitä että jonkin luokan instanssimuuttuja viitaa toisen luokan olioon. Tätä suhdetta kuvataan viivalla jossa joko ei ole kärkiä lainkaan, tai sillä on viereisessä kuvassa näytetyn kaltainen avoin kärki.
![../_images/uml_navigability.png](../_images/uml_navigability.png)
Viivan kumpaakin päähän voidaan listata multiplisiteetti, eli kuinka monta oliota suhteen kummallakin puolella on. Esimerkissämme suorakaiteella on neljä sivua, ja jos kaksi suorakaidetta sattuu olemaan kyljet vastakkain, voisi sama viiva kuulua kahteen suorakaiteeseen.
3 | 3 kappaletta |
2..5 | 2-5 kappaletta |
2..* | vähintään 2 |
* | mikä tahansa määrä |
Viivan päihin voidaan myös kirjoittaa rooli, eli mikä on kyseisessä päässä suhdetta olevan olion merkitys juuri tässä suhteessa. Esimerkissämme Viiva:t ovat suorakaiteen reunat.
Jos suhteelle haluaisi antaa nimen, voisi keskelle viivaa kirjoittaa sille oman otsikon. Tästä ei ole materiaalissa mallikuvaa.
viimeisenä, mutta ehkä tärkeimpänä, tulee nuolenkärki. Navigability -nuolenkärki korostaa mihin suhtaan luokkien välinen suhde osoittaa. Esimerkissämme Suorakaide-luokasta viitataan Viiva-olioihin, mutta Viiva-olioista ei ole viittausta takaisin. Tällä on merkitystä, kun ruvetaan tutkimaan, mitä suunnitellulla allillame voidaan tehdä ja miten jostakin luokasta päästään käsiksi toisen luokan sisältöön.
Kompositio ja Aggregaatio (kompositio ja kooste)
Kompositio ja aggregaatio kuvaavat, että jokin koostuu pienemmistä osasista. Jos ”pääolioon” kohdistetaan operaatioita, ne kohdistuvat jollain tavoin myös sen osasiin. Tällaista suhdetta merkitään “salmiakkisymbolilla”, joka merkitään suhteen “painavampaan” päähän, eli luokkaan, jonka oliot jollain tavoin sisältävät suhteen muita olioita.
![../_images/uml_composite.png](../_images/uml_composite.png)
“Neliö koostuu viivoista, jos neliö poistetaan viivatkin häviävät.”
Aggregaatiolla on tarkoitus ensisijaisesti korostaa millaisesta suhteesta on kyse. Kompositio on aggregaatiota jyrkempi “kooste”, sillä se kertoo myös suhteessa olevien olioiden olemassaolosta. Ylläoleva kuva kuvateksteineen selventää suhteiden eroa. Suhteista vahvempaa, kompositiota, merkitään mustalla salmiakilla, kun heikompi aggregaatio merkitään täyttämättömällä salmiakilla.
Kompositio ja aggregaatio ovat lisäinformaatiota, joka kannattaa lisätä kun se tuo lisäarvoa, mutta joka voidaan tarvittaessa korvata tavallisella assosiaatiolla. “If in doubt - leave it out.”
Riippuvuus
Riippuvuus on suhde, jossa jokin luokka tarvitsee tai käyttää toista luokkaa jonkin toimintansa osana. Tällaisten riippuvuuksien dokumentoiminen kaavioon helpottaa ohjelman muokkaamista tulevaisuudessa, sillä jos jokin luokka muuttuu, niin kaavio näyttää siitä riippuvat luokat joiden toimintaa on syytä tarkastella.
![../_images/uml_use.png](../_images/uml_use.png)
Riippuvuutta merkitään assosiaationuolen kaltaisella merkinnällä, jossa nuolen varsi merkitään katkoviivalla.
Perintä
Perintäsuhdetta merkitään luokkakaaviossa nuolella jonka kärki on täyttämättön kolmio. Nuolet osoittavat aina yliluokkaa kohden.
![../_images/uml_perinta.png](../_images/uml_perinta.png)
Ylläolevasta kuvasta nähdään, että Nelio
on kuvio, jolla on yleisestä kuviosta poiketen tarkalleen neljä reunaa. Periytymistä käsiteltiin materiaalin luvussa 6.4 ja jos vilkaiset sinne, huomaat että käytimme UML-notaatiota myös siellä.
(Kumppani)oliot
Yksittäisiä olioita voi luokkakaaviossa esittää lähes samalla notaatiolla kuin luokkiakin. Olion erottaa luokasta siitä, että sen otsikko on alleviivattu ja mahdollisesta kaksoispisteestä sen nimen edessä.
![../_images/uml_object.png](../_images/uml_object.png)
Rakenteellinen rekursio ja useampi suhde olioiden välillä
Allaolevassa kuvassa esitetään luokkakaavio sukupuusta. Yksittäisellä Ihmisellä
on suhteita toiseen ihmiseen
, jotka ovat joko hänen lapsiaan tai vanhempiaan. Tässä suhteet erotetaan toisistaan rooleilla “lapset” ja “vanhemmat”.
![../_images/uml_recursion.png](../_images/uml_recursion.png)
Kahden olion välillä voi olla myös samanaikaisesti useampi suhde. Tällöin vastaavien luokkien väliin piirretään useampi suhde, jotka voidaan (kuten rekursioesimerkissämme) erottaa toisistaan käyttäen joko rooleja tai nimeämällä suhde.
![../_images/uml_multiple.png](../_images/uml_multiple.png)
Ylläolevassa kaaviossa pankin asiakkaalla on omia tilejä, sekä muiden tilejä johin on annettu käyttöoikeus.
Oliko siinä kaikki?
Noh. Käytännössä kaikki oleellinen ainakin. Lisäksi löytyy vielä joukko pienempiä detaljeja joita tarvitaan harvemmin, kuten suhteiden välisiä rajotteita tai suhteisiin liittyviä luokkia jne.
Tehtävä:
Paras tapa tutustua UML:ään on tehdä sitä itse.
Kierroksen ainokainen tehtävä liittyykin esimerkkiprojektiimme. Tarkoitus on että jatkat käyttäjätarinoiden läpikäyntiä ja tarkennat luotuja luokkia oman harkintasi mukaan. Kun olet niihin tyytyväinen, piirrä luokista UML-kaavio ja palauta se PDF-muodossa allaolevan linkin kautta. Kaaviosi arvostellaan käsin ja saat siitä palautetta, joten tee työ huolella. Tehtävästä saa 250 pistettä.
Työn voi tehdä joko dedikoidulla UML-ohjelmalla, piirto-ohjelmalla, tai aivan hyvin myös käsin paperille josta sitten kuvaa/skannaa lopputuloksen PDF:ksi. Online-työkaluista toimivaksi on havaittu vaikkapa http://draw.io.
Käytännössä kaikki uudet toimisto-ohjelmat tuottavat PDF-dokumentteja, joten jos et muuten saa kaaviotasi PDF-muotoon, liitä se kuvana (Open/Star/MS)Office dokumenttiin ja tallenna/tulosta lopputulos PDF:ksi.
Tehtävä palautetaan Rubyriciin osoitteeseen https://rubyric.com/submit/68. Luo itsellesi uusi ryhmä omalla sähköpostiosoitteellasi.