Oliosuuntautunut suunnittelu

Systemoinnin harjoitustyö

Marko Grönroos
Turun Yliopisto, Tietojenkäsittelyoppi -89

Turussa 19. helmikuuta, 1993

Referaatti kirjasta:
Grady Booch: Object Oriented Design with applications, toinen kappale: The Method (s. 153 - 219)

Harjoitustyön ohje: ``Pyri esittämään mahdollisimman tarkasti kirjassa käsitelty oliokeskeinen suunnittelumenetelmä ja sen tuomat edut perinteisiin menetelmiin verrattuna.''

Siirretty HTML-muotoon 26.2.1998.


Sisällysluettelo

Kuvien numerointi on alkuperäisen teoksen numeroinnin mukainen, eli se saattaa tässä hieman hyppelehtiä. Kappalejako toisaalta ei aivan vastaa alkuperäistä.


Kappale 1. Merkintätapa

Erilaiset näkymät

Suunniteltavat järjestelmät ovat usein monimutkaisia hyvin monella tavalla. Järjestelmän rakenteen ja toiminnan kuvaamiseen ei yleensä riitä pelkkä luokkarakenteen kuvaaminen esim. ER-kaavioilla tai prosessien kuvaaminen tietovirtakaavioilla, vaan tarvitaan erilaisten kuvaustapojen yhdistelmiä.

Kuva 1-1. Oliollisen suunnittelun mallit

Tässä oliosuuntautuneessa suunnittelumetodissa käytettävät luokkarakennetta kuvaavat luokkakaaviot selvittävät luokkien suhteita toisiinsa, kun taas oliokaaviot kuvaavat yksittäisten luokkien olioiden tarkempaa vuorovaikutusta muihin olioihin.

Nämäkin kaaviot ovat kuitenkin luonteeltaan staattisia, eivätkä pysty kuvaamaan eri olioiden toimintaa ja tiloja ajan kuluessa. Tähän tarvitaan ajoituskaavioita , jotka kuvaavat toimintojen suoritusjärjestystä ajan suhteen, sekä tilasiirtymäkaavioita, jotka kuvaavat olioiden erilaisia mahdollisia tiloja, sekä näiden tilojen muuttumista toisiksi.

Yksikään näistä kaavioista ei puolestaan kuitenkaan kerro paljoakaan järjestelmän fyysisestä toteutuksesta ¾ siitä, millä tavalla ohjelmat on modularisoitu eri lähdetiedostoihin, eikä sitä, millaisessa laitteistossa ohjelmaa suoritetaan ja mitkä prosessorit käsittelevät tietoa ja mitkä oheislaitteet välittävät ja varastoivat sitä. Näihin tarvitaan moduulikaavioita, jotka kuvaavat lähdetiedostojen rakennetta ja käännösriippuvuutta, sekä prosessikaavioita , jotka ilmaisevat järjestelmän laitteistotason rakenteet (olivat ne sitten todellisia tai näennäisiä, kuten yhdellä prosessorilla suoritettavan virtuaalisen moniajon tapauksessa).

Vaikka järjestelmää katsottaisiin eri suunnilta, saattaa eri kuvauksista tulla ylitsevuotavan monimutkaisia, jos komponentteja on paljon, todella paljon. Tästä syystä on luokka- ja moduulikaavioille olemassa järjestelmää eri tasoilta kuvaavia hierarkiakaavioita, kuten luokkakategoriakaaviot ja alisysteemikaaviot.

Erilaisten kaavioiden lisäksi järjestelmän osista tulisi tämän menetelmän puitteissa tehdä malli (template). joka on tekstimuotoinen ja rakenteellinen siten, että niiden ylläpitäminen tietokoneavusteisesti on helppoa ja niistä pystytään helposti luomaan visuaalisia esityksiä.

Luokkakaaviot

Luokat ja niiden liittymät

Luokat. Luokkaa kuvaava symboli on muodoltaan epämääräisen pilvimäinen, kuvaten olioavaruuden karkeasti määrättyjä rajoja. Ääriviivoina oleva katkoviivoitus kuvaa sitä, että luokan käyttäjät käsittelevät yleensä luokan instansseja, eivätkä luokkaa itseään.

Kuva 1-2. Symbolit luokille, liittymille ja lukumääräsuhteille

Luokkaliittymät. Kuvassa 1-2 ovat esiteltyinä symbolit kullekin luokkien liittymätyypille. Kullakin liittymällä voi olla nimike sen roolin kuvaamiseksi. Mikäli nimikettä käytetään, voi symbolia · käyttää ilmaisemaan nimikkeen lukusuuntaa.

Käyttää-liittymää kuvataan kaksoisviivalla luokkien A ja B välillä. Kaksoisviivan A-luokan päähän asetettu ympyrä osoittaa, että luokka A käyttää luokan B resursseja. Käyttää-liittymiä on kahdenlaisia ¾ liittymään käytettäviä ja toteutukseen käytettäviä. Käyttää liittymään-liittymää kuvataan avonaisella pallolla ja se tarkoittaa A:n käyttävän luokkaa B vain osoittaakseen jotain muuta luokkaa oleviin objekteihin. Tälläisiä liittymiä on usein esimerkiksi erilaisiin Lista- ja Joukko-luokkiin. Käyttää toteutukseen- liittymää kuvataan suljetulla pallolla ja se tarkoittaa A:n käyttävän luokkaa B suoraan toteutukseensa, ei vain apuna muiden luokkien instanssien käsittelyssä.

Instantioi-liittymää kuvataan katkoviivalla ja nuolenkärjellä, joka osoittaa, että luokka, josta nuoli lähtee on osoitetun luokan instantiaatio. Instantiaatiolla tarkoitetaan luokan mallin tai geneerisen luokan 1 parametrisointia käyttöön sopivaksi. Tämä on käytännöllinen tapa rakentaa geneerisesti esimerkiksi sisällysluokkia (container classes, esim. joukko tai yleinen tietorakenne), joissa voi olla vain yhdentyyppisiä objekteja. Tälläinen liittymä on mielekäs vain, jos se on toteutuskielellä mahdollista toteuttaa.

Perintää ilmaistaan yhtenäisellä nuolella. Perillinen voi periä kaikkien yliluokan ominaisuuksien lisäksi myös siihen kohdistuvat metodit ja käyttötarkoitukset, jolloinka luokkaa voidaan käyttää samoissa tilanteissa kuin sen yliluokkaakin. Tällöin kyseessä on yhteensopiva tyyppi (vrt. C++:n virtuaaliset luokat ja metodit). Mikäli luokka perii vain yliluokkansa fyysiset ominaisuudet, on kyseessä uusi tyyppi, jonka käyttö on periaatteessa täysin erillistä sen yliluokan käytöstä.

Luokka-metaluokka -suhdetta ilmaistaan paksulla, harmaalla nuolella, joka osoittaa luokasta sen metaluokkaan. Metaluokat ovat ``luokkaluokkia´´, joiden instanssit ovat itsessään luokkia ja joiden avulla pystytään esimerkiksi luomaan ja muuttamaan näiden luokkien rakennetta ja toimintaa dynaamisesti. Ne siis sisältävät luokkien kuvauksia ja niiden käsittelysääntöjä. Metaluokkien käytöstä on hyötyä erityisesti järjestelmän kehitysvaiheessa, jolloin se antaa ohjemoijalle paremman käyttöliittymän olioiden määrityksiin. Esimerkiksi SmallTalkissa on jokaisella luokalla oma metaluokka, vaikka käytännössä sitä ei yleensä tarvitse muuttaa.

Määrittelemätön liittymä , jota kuvataan paksulla, harmaalla katkoviivalla, on usein käytössä suunnittelun alkuvaiheissa, jolloin tiedetään, että luokkien välillä on jonkilainen relaatio, mutta ei vielä tarkkaan tiedetä että millainen.

Nimi:tunniste
Dokumentointi:tekstiä
Näkyvyys:viety / yksityinen / tuotu
Geneeriset parametrit:parametrilista
Käyttöliittymä | toteutus:
Käyttää:lista luokkien nimistä
Kentät:lista kenttien määrityksistä
Operaatiot:lista operaatioiden määristyksistä

Kuva 1-9. Malli luokkatyökalulle

Luokkatyökalut2. Luokkatyökalu-symboli (kuva 1-3) kuvaa erillistä apuohjelmaa tai niiden joukkoa. Luokkatyökalujen nimien tulee olla yksilöllisiä luokkakategoriansa sisällä. Luokkatyökaluihin kohdistuvia liittymiä voi tarvittaessa ilmaista, mutta yleensä käytetään vain käyttää- ja instantioi-suhteita. Jos toteutuskieli ei salli tälläistä rakennetta, voi sen jättää pois. Luokkatyökalun malli on esitetty kuvassa 1-9.

Kuva 1-3. Symboli luokkatyökalulle

Luokkakaavioiden komponenttien mallit

Jokaiselle luo?kalle luokka?kaa?vi?os?sa on myös luokkamalli (luokka?temp?laatti, class template) kuvan 1-8 osoit?tamassa muodossa. Malli on melko yksityiskohtainen, mutta yleensä sitä ei odoteta täytettävän kokonaan. Malli on kuitenkin hyvin tärkeä osa suun?nit?telu?menetelmää, sillä siihen kir?joi?tetaan joitakin tietoja, joita ei kaavioista löydy.

Nimi:tunniste
Dokumentointi:tekstiä
Näkyvyys:tuotu / yksityinen / viety
Lukumääräsuhde:0 / 1 / n
Hierarkia:
Yliluokat:lista luokkien nimistä
Metaluokka:luokan nimi
Yleiset parametrit:lista parametreista
Liittymä | Toteutus:
(Julkinen/Suojattu/Yksityinen):
Käyttää:lista luokkien nimistä
Kentät:lista kenttien määrittelyistä
Operaatiot:lista operaatioiden määrittelyistä
Tilat:tilamuunnoskaavio
Samanaikaisuus:sarjamuotoinen / keskeyttävä / aktiivinen
Tilakompleksisuus:tekstiä
Pysyvyys:staattinen / dynaaminen

Kuva 1-8. Malli luokalle

Kaksi ensimmäistä mallin kenttää ovat itsestäänselviä. Kolmas kenttä, näkyvyys, kertoo, onko luokka tuotu (imported ), yksityinen (private) vai viety (exported ) suhteessa luokkakategoriaan, jossa se sijaitsee. Seuraavaksi, luokan lukumääräsuhde kertoo luokan instassien sallitun määrän; tyy?pillisesti arvot ovat 0, 1 tai n. Luokan luokkahierarkiassa esit?tämä rooli kuvataan kahdessa seu?raavassa kentässä. Toteutuskielestä riippuen luokalla on yksi, useam?pia tai ei yhtään yliluokkaa, sekä mahdollisesti metaluokka. Joka tapauksessa tässä mainitut luokat on johdettu luokkadiagrammissa näytetyistä liittymämuodoista; ne näkyvät templaatissa vain täydel?lisyyden ja ymmär?ret?tä?vyy?den vuoksi. Jos kieli sallii, antaa seuraava kenttä tälle luokalle parametrejä (esim. geneeriset pa?ra?metrit Ada:ssa tai makrot ja parametrisoidut luokat C++:ssa).

Nimi:tunniste
Dokumentointi:tekstiä
Kategoria:tekstiä
Kvalifikaatio:tekstiä
Formaalit parametrit:lista parametrinmäärityksiä
Tulos:luokan nimi
Esiehdot:PDL / objektikaavio
Toimenpiteet:PDL / objektikaavio
Loppuehdot:PDL / objektikaavio
Poikkeukset:lista poikkeusmäärityksiä
Samanaikaisuus:sarjamuotoinen / vartioitu / samanaikainen / moninkertainen
Aikakompleksisuus:tekstiä
Tilakompleksisuus:tekstiä

Kuva 1-10. Malli operaatiolle

Seuraavia kolmea kenttää on kutakin yhdestä neljään erilaista: kolmea erilaista luokkaliittymää ja yksi on luokan toteutusta varten, siis yhteensä aina kahteentoista asti. Jos toteutuskieli nimittäin sallii, voidaan luokkaliittymä jakaa julkiseen, suojattuun ja yksityiseen osaan. Siten C++ pystyisi toteuttamaan kaikki kolme osaa, Ada vain julkisen ja yksityisen ja Object Pascal vain julkinen-osan. Joka tapauksessa tämä on luokkatemplaatin tärkein osa, sillä juuri tässä pystymme määräämään luokan ulkopuolisen näkymän. Tämä ulkoinen näkymä sisältää instanssimuuttujia ja luokkamuuttujia (kentät -kentässä), sekä kaikki operaatiot. Kutakin kenttää (siis kenttä-liittymää, ei mallin kenttää..) kohden voimme dokumentoida sen nimen, onko se vakio vai muuttuja, sen luokan, arvoaluerajoitteita (esim. 'var i:integer [1..100];') ja kuinka kenttä alustetaan.Edelleenkään kaikkea ei ole pakko dokumentoida; vain se, minkä koemme tarpeelliseksi. Operaatiot-kenttä luettelee joukon operaatioita, joille kullekin on edelleen oma mallinsa (kuva 1-10). Käyttää-relaatio on siinä samanlainen kuin yliluokat ja metaluokka, että se kuvataan tässä mallissa vain täydellisyyden ja ymmärrettävyyden vuoksi.

Tilat-kenttä osoittaa tilasiirtymäkaavioon, Samanaikaisuus-kenttä kertoo, josko luokan instanssit ovat sarjamuotoisia (sequential), keskeyttäviä (blocking) vai aktiivisia. Tämän tulee olla yhtäpitävä kuhunkin luokan ope?raatioon liittyvän samanaikaisuussemantiikan kanssa, eli jos luokka on esimerkiksi määritelty sarjamuotoiseksi, sen operaatiot eivät voi olla vartioituja, samanaikaisia tai moninkertaisia seman?tiikaltaan. Toiseksi viimeinen, tilakomp?leksisuus-kenttä, kertoo luokan instanssien käyttämän muistimäärän. Tämä voidaan ilmoittaa vakiona tai suhteellisemmin esimerkiksi Ordo-funktion avulla. Viimeinen kenttä määrittelee luokan instanssien pysyvyyden. Olio on pysyvä, jos sen tila ja luokka säilyvät yli sen luoneen ohjelman keston. Tilapäinen olio tuhoutuu viimeistään kyseisen ohjelman suorituksen loppuessa.

Tilasiirtymäkaaviot

Kuva 1-12. Symbolit tilamuutoskaavioille. Ympyrä esittää yhtä tilaa, jolla tulee olla kaaviossa yksilöllinen nimi. Nuoli esittää tilan muuntumista toiseen tai takaisin itseensä. Tilamuutoksen nimen ei tarvitse olla yksilöllinen. Avoin kaksoisympyrä kuvaa alkutilaa ja tummennettu lopputilaa (vapaaehtoisia).

Luokkakaaviosta ei pysty päättelemään mitään luokkien instanssien dynaamisesta käyttäytymisestä. Tämä dynaaminen käyttäytyminen on parhaiten kuvattavissa tilasiirtymäkaaviolla (tai tilamuutoskaavio, engl. state transition diagram ). Kyseisenlainen kaavio kuvaa luokan tila-avaruutta, tapahtumia , jotka aiheuttavat muutoksen tila-avaruuden tilasta toiseen ja toimenpiteitä, jotka tuollaisesta tilanmuutoksesta aiheutuvat.

Tilasiirtymäkaavioilla ei välttämättä ole alku- eikä lopputilaa, sillä kun objekti luodaan, se asetetaan asiakohtaisesti suoraan johonkin tilaan. Samoin kun objekti tuhotaan, tulee tila merkityksettömäksi. Mikäli alku- ja lopputiloja välttämättä halutaan kuvata, voidaan se tehdä.

Ainoa mielekäs suhde tilojen välillä on tilan muunnos, joka tapahtuu tilasta toiseen tai takaisin itseensä.

Tilasiirtymämallit. Myös tilasiirroksille tehdään malli. Siirtymässä tapahtuva toimenpide voidaan kuvata PDL3:n tai objektikaavion avulla.

Tapahtumat:lista tunnuksista
Dokumentointi:tekstiä
Toimenpiteet:oliokaavio

Kuva 5-12b. Malli tilasiirtymäkaaviolle

Kuva 1-13. Tilasiirtymäkaavio puutarhan ylläpitojärjestelmän YmpäristöKontrolleri-luokalle.

Oliokaaviot

Oliokaavioita käytetään kuvaamaan olioiden olemassaoloja ja niiden suhteita toisiinsa. Kaavioista käyvät ilmi ennen kaikkea olioiden toisilleen lähettämät viestit, sekä olioiden näkyvyydet. Oliokaaviot ovat toisinaan kuvauksia jostain tietystä hetkestä olioiden elämästä ja toisinaan niitä taas käytetään kuvaamaan luokkien varsinaista fyysistä kokoonpanoa, eli kenttiä ja parametrisointia, jota luokkakaaviosta ei saa selville.

Kuva 1-14. Symbolit olioille ja viesteille

Oliot. Kuva 1-14 näyttää symbolin, jota käytämme kuvaamaan oliota oliokaaviossa. Tämä on samankaltainen, kuin se, jota käytettiin kuvaamaan luokkaa, mutta tässä käytämme kiinteitä viivoja kuvaamaan, että kyseessä on instanssi, eikä luokka. Olioiden nimien ei tarvitse olla yksilöllisiä, vaan itse asiassa monilla ohjelman olioilla ei ole eksplisiittisesti tunnettua nimea lähdekooditasolla. Tästä syystä nimien ei tarvitse olla tarkkoja, mutta ne voivat kuvata sopivan käsitteellisesti määräämätöntä instanssia, kuten eräsJäähdytin tai eräsLämpötilaMittari . Tietysti myös spesifisiä instansseja voi kuvata, jos tilanne sitä vaatii, kuten Kasvihuone3 tai KuumaVesiVenttiili7 . Olion ominaisuudet, kuten lukumääräsuhteet, samanaikaisuus tai pysyvyys, voivat näkyä olion symbolin vasemmassa alakulmassa, jolloin ne havaitsee helposti.

Olioiden liittymät. Liittymä kahden olion välillä tarkoittaa yksinkertaisesti sitä, että oliot voivat lähettää viestejä toisilleen. Koska viestit ovat yleensä kaksisuuntaisia, käytämme viivoja ilman nuolenkärkiä näiden liittymien kuvaamiseksi, kuten kuva 1-14 osoittaa. Käytämme kiinteitä viivoja olioliittymille, joita voimme kuvata järjestelmän sisällä olevassa ohjelmassa, ja harmaita viivoja liittymille, jotka ovat järjestelmän ulkopuolella. Suunnittelun varhaisessa vaiheessa on riittävää kuvata vain olioiden liittymät ilman, että määritellään, että mitä varsinaiset viestit tulevat olemaan.

Kuva 1-15. Symbolit näkyvyyksille ja viestityypeille

Näkyvyys ja synkronisointi

Olioiden näkyvyys. Ensinnäkin voimme dokumentoida sen, kuinka oliot näkevät toisensa. Tähän on olemassa kuusi erilaista tapaa, joiden visuaaliset esitykset esitellään kaaviossa 1-15. Jos esimerkiksi olio R on olion S jaettu kenttä, kuvaamme tätä asettamalla jaetun kentän ikonin R:stä S:ään, R:n viereen. Myös olioiden asettelulla voi selkeyttää kaaviota, mikä tapahtuu esimerkiksi asettelemalla toimintaoliot kaavion ylälaitaan ja palvelinoliot alalaitaan. Samaten voimme kuvata sisältämistä asettamalla olioiden-symboleja toistensa sisään. Näkyvyyden kuvaaminen ei aina ole täysin välttämätöntä ja se tulisikin tehdä vain, jos sille on jotain aihetta.

Viestien synkronisointi. Yhtä tärkeää, kuin on näyttää olioiden liittyminen toisiinsa, on näyttää kuinka ne vuorovaikuttavat toistensa kanssa. Merkintätapamme avulla voimme esittää viestien lähettämisen oliolta S oliolle R piirtämällä suunnatun viivan olioliittymän mukaisesti, johon on liitetty kulkevan viestin nimi. Tämä viiva osoittaa operoitavaan olioon, vaikkakin tieto voi virrata kumpaan tahansa suuntaan (myötäsuuntaan operaation parametrinä ja vastakkaiseen suuntaan funktion palauttamana arvona).

Puhtaan sarjamuotoisissa järjestelmissä on yksinkertaisen nuolenkärjellä varustetun viivan piirtäminen riittävää olioiden vuorovaikutuksen osoittamiseksi. Asia mutkistuu kuitenkin useampien kontrollipolkujen läsnäollessa. Jos esimerkiksi kaksi oliota ovat aktiivisia, voi viestiä S:stä R:ään viivyttää (koska R ei ole valmis vastaanottamaan viestiä), tai se voi epäonnistua (koska S ei voi odottaa vastausta). Voi olla olemassa myös viestejä, jotka keskeyttävät muuten kiireisen olion suorituksen. Kaiken kaikkiaan on viisi erilaista viestien synkronisointitapaa: yksinkertainen, synkroninen, torjuttava, ajastettu ja epäsynkroninen, jotka näkyvät kaaviosta 1-15. Kaikille näille symboleille voidaan antaa nimikkeeksi viestien nimien lista.

Oliokaavioiden komponenttien mallit

Oliomallit. Kuva 1-17 esittelee mallin oliolle. Tämä malli dokumentoi olion luokan, joka implikaatioiden kautta kertoo operaatiot, joita asiakkasoliot voivat suorittaa oliolle oliokaaviossa. Malli kertoo myös olioiden säilyvyyden, joka on sellainen olioiden ominaisuus, jonka täytyy olla yhtenevä olion luokan säilyvyysmäärittelyjen kanssa. Mikäli mallia vastaava luokkamalli määrää, että kaikkien instanssien kuuluu olla tilapäisiä, olion säilyvyys voi olla vain staattinen (olio on olemassa ohjelman koko ajoajan) tai dynaaminen (olio luodaan ja tuhotaan dynaamisesti ohjelman suorituksen aikana). Jos luokkamalli kertoo, että instanssit voivat olla säilyviä, voivat oliot olla dynaamisia, staattisia tai säilyviä (ne ovat olemassa sen jälkeen kun ohjelman, jossa ne luotiin, suoritus päättyy).

Viestimallit. Kuva 1-17 esittelee myös mallin viesteille. Tämä malli palvelee kertoakseen olion luokalle määritellyn spesifisen operaation, joka vuorostaan kertoo operaation yksityiskohtaisen semantiikan. Voimme myös tallentaa ajoitustietoa tänne, kuten josko viesti lähetetään ajoittaisesti, ja jos niin on, niin kuinka usein.

OlioViesti

Nimi:tunniste Operaatio:operaation nimi
Dokumentointi:tekstiä Dokumentointi:tekstiä
Luokka:luokan nimi Frekvenssi:periodinen / epäperiodinen
Pysyvyys:pysyvä / staattinen / dynaaminen Synkronisointi:yksinkertainen / synkroninen / torjuva / ajastettu / asynkroninen

Kuva 1-17. Mallit olioille ja viesteille

Kuva 1-16. Esimerkki KasvihuoneKontrolleri -luokan olioista

Ajoituskaaviot

Oliokaaviot ovat itsessään staattisia; ne näyttävät toistensa kanssa yhteistyössä olevien olioiden kokoelman, jotka lähettävät viestejä toisilleen, mutta ne eivät näytä kontrollin siirtymistä, eivätkä tapahtumien järjestystä. Joihinkin luokkiin liittyvät tilasiirroskaaviot eivät auta nekään, sillä ne näyttävät tilasiirtymät vain yksittäisten olioiden sisällä, eivät olioiden ryhmien sisällä. Tätä oliodiagrammissa tapahtuvan viestinsiirron dynamiikkaa kuvaamaan käytämme kolmea eri menetelmää.

Ensimmäinen lähestymistapa on hyvin yksinkertainen. Annamme jokaiselle viestille oliokaaviossa numerolapun, joka ilmaisee sen suorituksen suhteellisen järjestyksen. Tällöin viesti 1 lähetetään ensimmäisenä, viesti 2 toisena, jne. Tämä menetelmä toimii hyvin, jos kontrollin siirtyminen on tiukkaa, mutta on riittämätön, jos haluamme esittää kotrollin ehdollista siirtymistä (eli jos ehti C on tosi, lähetetään viesti M, tai muutoin lähetetään viesti N). Toisessa menetelmässä sisällytämme PDL:än jokaiseen oliokaavioon kuvaamaan tapahtumia.

Symbolit ajoituskaavioille. Kolmas lähestymistapa, joka on havaittu käyttökelpoiseksi, on saanut lähtönsä laitteistotason suunnittelun ajoituskaavioista. Kuva 1-18 esittelee, kuinka tämä tekniikka on sovellettu oliosuuntautuneeseen suunnitteluun. Kuten tässä näemme, on ajoituskaavio kuvaaja, jossa aika on horisontaalisella akselilla ja oliot vertikaalisella akselilla. Aikaa voi esittää joko absoluuttisina tai suhteellisina yksiköinä. Mitä olioihin tulee, otamme mukaan vain ne, joiden yhteisen vuorovaikutuksen haluamme näyttää mekanismin dokumentoimiseksi.

Ajoituskaavioissa voidaan merkitä myös olioiden luonti (*-merkki) ja tuhoaminen (), sekä reaalimaailmasta tuttuja sääntöjä, kuten erääntymisaika, joka saadaan annetulle operaatiolle budjetoidusta ajasta. Tyypillisesti yhdellä oliokaaviolla voi olla useampia ajoituskaavioita, vaikkakaan ne(kään) eivät ole mitenkään välttämättömiä.

Kuva 1-18. Esimerkki ajoituskaavioista

Moduulikaaviot

Luokka-ja oliokaavioita käytetään järjestelmän loogisen suunnitelman dokumentointiin. Seu?raavaksi esitellään merkintätapa järjestelmän fyysiselle rakenteelle, joka koostuu lait?teistosta, sekä ohjelmistomoduuleista, jotka konkreettisesti toteuttavat loogisen suunnittelun.

Moduulikaaviota käytetään näyttämään luokkien ja olioiden sijoittelu moduuleihin; yksi moduuli kuvaa kaikkia tai yhtä osaa järjestelmän moduuliarkkitehtuurista. Jotkin oliopohjaiset ja oliosuuntautuneet ohjelmointikielet tukevat moduulin käsitettä luokasta tai oliosta erillisenä. Tämä rakenne voi olla yhtä yksinkertainen, kuin erikseen käännettävät tiedostot, kuten C++:ssa, tai kehittynyt pakettien ajatus, kuten Adassa. Molemmissa tapauksissa on suunnittelijan työnä päättää, kuinka luokat, luokkatyökalut, oliot ja muut määrittelyt sijoitellaan fyysisiin moduuleihin. Kielet, jotka eivät tue moduuleita eivät selvästikään tarvitse tätä merkintätapaa.

Kaksi tärkeintä elementtiä moduuliarkkitehtuurissa ovat moduulit ja moduulien näkyvyys.

Kuva 1-19. Symbolit moduuleille ja niiden näkyvyydelle

Nimi:tunniste
Dokumentointi:tekstiä
Määritykset:määritysten lista
Kuva 1-23. Malli moduulille

Modulit. Kuvassa 1-19 näkyvät symbolit, joita käytämme esittämään erityyppisiä moduuleita moduulikaaviossa. Moduulin nimi vaaditaan ja se asetetaan symbolin ylälaitaan. Nimi, joka on ympäröity suorakaiteella, esittää moduulia, joka on sisällytetty alijärjestelmästä. Jokaisessa suunnitelmassa tulee olla ainakin yksi pääohjelma, joka kuvaa juurta, josta ohjelma aktivoidaan. Järjestelmillä, jotka on tarkoitettu toimimaan hajautetussa tietokoneympäristössä, voi olla useampia pääohjelmia.

Moduulien näkyvyys. Ainoa liittymä kahden moduulin välillä on käännösriippuvuus, jota kuvataan kuvassa 1-19 esitetyllä nuolella. Esimerkiksi, näyttääksemme, että moduuli G riippu moduulista H (C-termeissä sanottuna, G:ssä on #include-lause, joka viittaa H:hon), piirrämme nuolen G:stä H:hon, näyttäen, että H on näkyvä G:lle.

Alijärjestelmät


Kuva 1-21. Symboli alijärjestelmälle

Suuri järjestelmä voi koostua useista sadoista, jos ei tuhansista moduuleista. Tuollaisen järjestelmän fyysisen rakenteen ymmärtäminen on mahdotonta ilman pidemmälle vietyä niputtamista. Käytännössä suunnittelijat käyttävät lukuisia epämuodollisia tapoja kerätäkseen läheisiä moduuleja hakemistorakenteisiin. Alijärjestelmäsymboli (kuva 1-21) voi kuvata esimerkiksi yhtä tälläistä hakemistoa. Nykyiset kielet eivät tue tälläisten näin suurten pakettien kunnollista käsittelyä, vaan yleensä kaiken joutuu aina tekemään käsin.

Prosessikaaviot

Prosessiarkkitehtuuri. Monet suuret järjestelmät vaativat, että suunnitellaan yhden valtavan ohjelman sijaan useita ohjelmia, jotka toimivat hajautetussa joukossa tietokoneita. Tästä syystä käytetään prosessikaavioita kuvaamaan eri prosessien sijoittumista eri prosessoreille. Yleensä näitä kaavioita on vain yksi, vaikkakin monimutkaisissa järjestelmissä niitä voi olla useampia.

Kuva 1-24. Symbolit prosessoreille, oheislaitteille ja kytkennöille

Prosessori on laite, jossa suoritetaan ohjelmia. Oheislaitteet voivat olla levy-yksiköitä, tulostimia, A/D-muuntimia, päätteitä, jne.

Kytkennät voivat olla käytännössä minkä pituisia tahansa; laitteet voivat sijaita samalla piirikortilla tai eri puolilla maapalloa, joista jälkimmäisessä tapauksessa kytkentä kuvaisi esimerkiksi satelliittilinkkiä. Kytkentöjen oletetaan yleensä olevan kaksisuuntaisia, mutta joissain tapauksissa, kuten tulostimien tapauksessa, ne voivat olla myös yksisuuntaisia, jolloin symboliin voi liittää nuolenkärjen mukaan.

ProsessoriProsessiLaite ja kytkentä
Nimi:tunnisteNimi:tunnisteNimi:tunniste
Dokumentointi:tekstiäDokumentointi:tekstiäDokumentointi:tekstiä
Piirteet:tekstiäPrioriteetti:kokonaislukuPiirteet:tekstiä
Prosessit:lista prosesseista
Ajoitus:pre-emptiivinen / ei -pre-emptiivinen / syklinen / suoritus / manuaalinen
Kuva 1-26. Mallit prosessoreille, prosesseille, oheisleitteille ja kytkennöille


Kappale 2. Suunnittelu kasvavana ja iteratiivisena prosessina

Ammattisuunnittelijoiden suunnitteluprosessia tarkkailemalla on havaittu, että suunnittelu harvoin tapahtuu tehokkaasti perinteisellä tiukalla top-down tai down-top menetelmällä, tai koko suunnittelun elinkaarta tarkasteltaessa vesiputousmallin mukaisena. Tehokkaammaksi on havaittu näiden sekoitus, jossa suunnitelmaa käydään toistuvasti läpi eri tasoilla siten, että aluksi tehdään ylimalkainen ja puutteellinen malli, jota sitten tarkennetaan ja korjataan eri tasojen vaatimusten mukaisesti. Pyritään siis aluksi ratkomaan ongelman sellaiset osat ja aliongelmat, jotka pystytään nopeasti ja helposti tekemään, ja tämän jälkeen käymään visaisempien aliongelmien kimppuun ja optimoimaan ja yleistämään rakenteita. Koska jokainen suunnitteluprojekti on yksilöllinen, on niissä aina yksilöllisiä ongelmia ratkaistavana. Tällöin suunnitteluprosessin evolutiivisesta luonteesta on se hyöty, että käymällä aihetta läpi useita kertoja pintapuolisesti pystymme suunnittelun aikana keksimään uusia ratkaisumenetelmiä, joita sitten sovellamme ylemmillä tai alemmilla suunnittelun tasoilla. Suunnittelun tulee siis olla luova prosessi, eikä sellainen, jossa vain noudatamme järjestyksessä meille annettuja suunnitteluohjeita.

Oliosuuntautuneen suunnittelun on havaittu noudattelevan seuraavanlaista tapahtumajärjestystä:

  1. Luodaan luokat ja oliot halutulla abstraktiotasolla

  2. Luodaan semantiikka näille luokille ja olioille

  3. Luodaan liittymät näiden luokkien ja olioiden keskuudessa

  4. Toteutetaan kyseiset luokat ja oliot
Tätä järjestystä tulkittaessa on jälleen huomattava, että kyseessä on kasvava prosessi: luokkien ja olioiden luominen, määritteleminen ja toteuttaminen usein johtaa muiden luokkien ja olioiden parantelemisen ja luomisen tarpeeseen. Seuraavassa neljässä alikappaleessa tarkastellaan erikseen näitä askelia.

Luokkien ja olioiden luominen

Ensimmäisenä askeleena on löytää ongelma-alueen merkittävät luokat ja oliot luokitteluprosessin avulla. Tämä tapahtuu ongelma-alueen analyysin (domain analysis) avulla, jolloin suunnittelijan on tultava tutuksi aiheen sanaston ja käsitteiden kanssa.

Koska, kuten edellä mainittiin, suunnittelu on evolutiivinen prosessi, ovat nämä määrittelyt vain ehdotuksia ja saattavat myöhemmin muuttua. Yleensä on kuitenkin oletettavaa näiden alussa määriteltävien luokkien ja olioiden säilyvän pääpiirteissään koko suunnittelun ajan.

Tämän askelen tulokset voivat vaihdella hyvin epämuodollisesta hyvin muodolliseen. Voi olla riittävää vain luetella merkittävien luokkien ja olioiden nimiä, mieluiten mielekkäitä, jotka kuvaavat parhaiten olioiden semantiikkaa. Tämän listan nimien voidaan myöhemmin havaita olevan luokkia, olioita tai olioiden attribuutteja. Toisaalta voimme heti formaalisti määritellä näiden abstraktioiden ja mekanismien tarkoituksen täyttämällä asiaankuuluvat luokka- tai oliokaaviot. Voi olla tarpeellista piirtää joitakin luokka- ja oliokaavioita, ja tarvittaessa myös moduli- ja prosessikaavioita.

Luokkien ja olioiden semantiikan määrittely

Tässä toisessa askeleessa määritellään ensimmäisessä löydettyjen luokkien ja olioiden merkitykset. Tällöin päätetään, että mitä asioita voimme tehdä luokkien instansseille ja mitä asioita oliot voivat tehdä toisille. Tämä on vaikeampi ja aikaavievämpi vaihe, kuin ensimmäinen, ja prosessin iteratiivinen luonne tulee parhaiten näkyviin juuri täällä.

Tässä vaiheessa siis jalostetaan ensimmäisessä aikaansaatuja malleja, jolloin tulee dokumentoida kaikki pääabstraktioiden ja päämekanismien staattiset ja dynaamiset semantiikat, niin hyvin kuin pystytään. Voidaan myös piirtää uusia oliokaavioita dokumentoidaksemme tässä vaiheessa mahdollisesti löytämiämme uusia mekanismeja. Lopuksi voidaan päättää tehdä suunnitelman joistakin osista prototyyppi tämänhetkisen suunnitelman analysoimiseksi ja vaihtoehtoisten ratkaisujen arvioimiseksi.

Liittymien määrittäminen luokkien ja olioiden keskuudessa

Tässä kolmannessa vaiheessa määrittelemme tarkemmin olioiden välisen vuorovaikutuksen. Tällöin määrittelemme luokille liittymät käyttäen käyttää-, perii- ja muita liittymiä. Olioille meidän tulee määritellä kaikkien mekanismien staattinen ja dynaaminen semantiikka. Teemme päätöksiä perinnästä ja luokkien ja olioiden näkyvyydestä, ja pyrimme näiden avulla uudelleenorganisoimaan ja yksinkertaistamaan luokkarakenteita ja yleistämään olioiden toimintamekanismeja.

Tuloksena tästä vaiheesta saamme suunnitelman useimpien loogisten osien täydentämisen loppuun. Piirrämme oliot ja päätämme, että mitä viestejä ne lähettävät toisilleen ja kasaamme modulikaavioita tekemiemme näkyvyyspäätösten pohjalta.

Luokkien ja olioiden toteutus

Neljäs vaihe sisältää kaksi toimintaa: keksimiemme luokkien ja olioiden esitysmuotoa koskevien päätöksien tekeminen, ja näiden olioiden ja luokkien jakaminen moduleihin, sekä ohjelmien jakaminen prosessoreille. Tällöin ensimmäistä kertaa tarkastelemme luokkia ja moduleita sisältäpäin ja päätämme kuinka niiden käyttäytyminen tulisi toteuttaa.

Tässä vaiheessa saamme siis luotua täydellisen, konkreettisen liitynnän ulospäin kullekin kyseisen abstraktiotason luokalle ja oliolle.


Kappale 3. Pragmatiikkaa

Oliollinen suunnittelu elinkierrossa

Ohjelmiston kehitystyön elinkierron toteuttaminen käyttäen oliosuuntautunutta suunnittelua rohkaisee järjestelmän suunnitelman kasvavaan ja iteratiiviseen luonteeseen.

Rakenteellinen analyysi on houkutteleva käyttöliittymä oliosuuntautuneeseen suunnitteluun; oliosuuntautunut analyysi antaa entistäkin käyttökelpoisemman esiasteen myöhempien vaiheiden käyttöön.

Kuva 3-2. Oliosuunnittelu ohjelmiston kehityksen elinkierrossa.

Projektin käsittely

Suunnittelu voi alkaa milloin hyvänsä kun on mahdollisesti epätäydellinenkin formaali tai epäformaali malli ratkaistavasta ongelmasta.

Oliosuuntautuneessa suunnittelussa ei ole samanlaista järjestelmän integroinnin hyökyaaltoa, kuin perinteisissä järjestelmissä, sillä integrointia käsitellään jatkuvana ja paikallisena tapahtumana. Sama pätee jossain määrin myös muihin vaiheisiin, varsinkin koodaukseen.

Kuva 3-3. Resurssien jakaminen oliosuuntautuneessa suunnittelussa

Kehitystyöhenkilöstö

Mitä tulee kehitystyön tekijöiden taitoihin, vaaditaan seuraavanlaisia suunnittelijoita:

Virstanpylväät ja tuotantotulokset

Oliosuuntautunut suunnittelu voi vaikuttaa hyvin vieraalta projektijohtajille, sillä sen edistymisen seuraaminen on hankalaa. Parhaiten tämä tapahtuu luomalla suunnittelun virstanpylväitä ja suunnittelun edistyessä tekemällä katsantoja kunkinhetkisestä tilanteesta. Tämä voi sisältää kaavioiden tilan tarkastelua ja tuloksena saatujen prototyyppien testausta.

Oliollisen suunnittelun edut ja riskit

Edut

Oliosuuntautunut suunnittelu

  1. Käyttää kaikkien oliopohjaisten ja oliosuuntautuneiden ohjelmointikielten ilmaisuvoimaa

  2. Rohkaisee ohjelmakomponenttien uudelleenkäyttämistä

  3. Johtaa järjestelmiin, jotka epätodennäköisemmin muuttuvat

  4. Vähentää kehitysriskiä

  5. On ihmisen kognitiivisen ajattelutavan mukainen

Riskit

Suorituskyvyn riskit. Oliosuuntautuneet ohjelmointikielet ovat usein paljon raskaampia suoritusnopeuden kannalta, kuin perinteiset imperatiiviset kielet. Viestien lähettäminen kuluttaa runsaasti resursseja, varsinkin esimerkiksi (toteutuksesta riippuen) aktiivisten tai funktionaalisten olioiden välisessä viestinnässä, joissa joudutaan olioista ottamaan runsaasti kopioita ja välittämään näitä kopioita viesteinä. Keskimäärin tutkimukset osoittavat viestien lähetyksen olevan n. 1.75-2.5 kertaa aikaa vievämpi, kuin vastaava aliohjelmakutsun tekeminen.

Myös oliosuuntautuneiden kielten tietorakenteet, varsinkin käännösaikaiset, ovat usein paljon massiivisempia kuin vastaavien perinteisten kielten, johtuen lähinnä luokkamäärittelyjen runsaudesta ja sisäisestä monimutkaisuudesta.

Aloituskustannukset. Aloituskustannukset saattavat muodostaa merkittävän kynnyksen oliosuuntautuneiden menetelmien käyttöönottamiselle. Kehitystyötä suorittava organisaatio joutuu kehittämään ongelma-alueeseen liittyvät työkalut ja alkeispalaset alusta alkaen, jollei jonkinlaisen liittymän rakentaminen vanhoihin vastaaviin ole mahdollista.

Myös suunnittelijoiden kannalta siirtyminen oliosuuntautuneeseen suunnitteluun on hankalaa. Oliosuuntautunut kieli ei ole "vain yksi uusi kieli opittavaksi", sillä sen täysin uusi ajattelutapa saattaa olla vanhalle suunnittelijalle vaikeampi oppia, kuin sellaiselle, joka ei aiemmin ole suunnitellut tahi ohjelmoinut perinteisellä kielellä.


Kappale Vertailua

...ja hieman havaintoja, sekä myös jonkin verran omia mielipiteitäni menetelmän eri alueista... Huom: Nämä eivät ole kovinkaan loppuun mietittyjä ja niissä saattaa olla väärinymmärtämisestä aiheutuneita virheitä.

Merkintätavasta

Ensimmäinen kenties häiritseväkin tekijä on eri tekstimuotoisten templaattien välttämättömyys tietyissä tapauksissa kunnollisen graafisen notaation puuttuessa. Ennen kaikkea tämä koskee luokka- ja oliokaavioista puuttuvia kentät - ja operaatiot-symbolien puutetta. Nimenomaan yksinkertaisten yksityisten kenttäolioiden, kuten esimerkiksi kokonais- ja liukulukujen ja merkkijonojen kuvaaminen luokkakaavioissa, jonne niiden kuvaus ainakin jossain määrin ilmeisesti kuuluisi, tuntuu mahdottomalta ilman, että niille tehdään omat instantioidut luokat ja kuvataan ne epäselvästi ja sekavasti käyttää-relaatioilla luokkakaavioissa. Periaatteessa näiden kenttien merkintä ei välttämättä ole merkityksellistä metodin ideologian kannalta, sillä jos ne ovat niin ``merkityksettömiä´´, ettei niillä ole mitään relaatiota muihin luokkiin ja olioihin, vaan ovat luokalle täysin yksityisiä, ei niitä ole edes hyvä merkitä mihinkään. Mielestäni ne luokkakaavioon merkittyinä kuitenkin visualisoivat luokkaa paremmin kuin pelkkä nimi epämääräisen pilven keskellä tekisi. Tästä syystä ainakin itse merkitsen ne pienessä pilvessä ohuella kaksoisviivalla varsinaiseen luokan pilveen.

Toinen ero ER-malliin verrattuna on liittymäluokkien kuvaustavan puute4, mikä on kyllä hieman ymmärrettävissä objektisen filosofian kannalta ¾ oliot ovat olioita, relaatiot relaatioita, piste. Tämä liittyy samalla myös kunnollisen identifikaationotaation puutteeseen. Tästä nimittäin aiheutuu, että luokkakaaviosta ei suoraan selviä, että minkä luokan instanssit identifioivat muiden luokkien instanssit, vaan täytyy turvautua moneen kappaleeseen erilaisia objektikaavioita. Esimerkiksi, jos meillä on luokat Asiakas ja Kirja (joka sijaitsee kirjastossa) ja niiden välillä käyttää -liittymä nimeltään "lainaa" ja haluaisimme vaikkapa tallentaa järjestelmään tiedon siitä, että mitkä kirjat kukin asiakas on elämänsä aikana lainannut, täytyy luoda näiden luokkien välille kolmas luokka, Lainaus. Saamme relaatiosarjan Kirja(1)¾(n)Lainaus(n)¾(1)Asiakas. Nyt se, että mikä luokka identifio kunkin muun voi jäädä hieman epäselväksi, eli kaaviosta ei kovin selvästi käy ilmi, että Asiakas ja Kirja identifioivat Lainaus:ksen molemmat ja samanaikaisesti, vaan se täytyy päätellä luokkien nimien semantiikasta ja lukumääräsuhteista.

Nämä mainitut 'puutteet' eivät sinänsä varsinaisesti ole puutteita, sillä merkintätapa kyllä pystyy ilmaisemaan asiat yleensä aina jollain tavalla. Kyse on vain lähinnä siitä, että merkintöjä on menetelmän filosofian vuoksi hajautettu liikaa eri kaavioiden välille ja samalla jostain syystä ikään kuin vältetty kaavioiden välistä redundanssia (lukuunottamatta järjetöntä redundanssia mallien ja kuvallisten kaavioiden välillä).

Tavallaan luokkakaavioita voi ajatella myös perinteisen suunnittelun tietovirtakaavioina, jossa olioita käsitellään 'koneina', eli prosesseina, jotka ottavat vastaan informaatiota viestien muodossa ja lähettävät sitä edelleen. Oliokaavion ilmaisuvoima on tietysti kyllä suurempi, kuin tietovirtakaavion, samoin sen liittyminen vastaaviin luokkakaavioihin on tältä kannalta ajateltuna uusi piirre.


Pääsivu Takaisin Last modified: Thu Feb 26 14:57:33