Ratkaisumallien hyväksikäyttö ohjelmistotyökaluissa Jaakko Vuolasto Helsinki 24.10.2000 Seminaariesitelmä HELSINGIN YLIOPISTO Tietojenkäsittelytieteen laitos
Sisällys 1 Johdanto...1 2 Ratkaisumallin olemus...1 3 UML ja ratkaisumallit...2 4 Ohjelmistotyökalujen tuki ratkaisumalleille...2 4.1 Sirpalemalli...3 4.2 Lähdekoodin generointi ratkaisumalleista...4 4.3 FRED...6 4.4 Pattern Lint...8 5 Loppusanat...9 Lähteet...10
1 Johdanto Ratkaisumalli (Design Pattern) on käytännössä hyväksi todettu tapa ratkaista jokin tietty ongelma. Käsite on peräisin arkkitehtuurin alalta, sen esitteli arkkitehti Christopher Alexander 1970-luvun lopulla. Ohjelmistotuotantoon se löysi tiensä 1990-luvulla [BMR96]. Tämän esityksen tavoitteena on kuvata, mitä ratkaisumalli tarkoittaa ja miten niitä voidaan kuvata UMLtekniikoilla sekä esitellä lyhyesti muutamia välineitä, jotka joko tukevat mallien käyttöä tai ovat nimenomaan kehitetty ratkaisumalleja silmällä pitäen. Termiä malli käytetään tässä esityksessä ratkaisumallin synonyyminä. 2 Ratkaisumallin olemus Ratkaisumalli muodostuu asiayhteydestä, ongelmasta ja ratkaisusta [BMR96]: Jokainen ratkaisumalli liittyy aina johonkin tiettyyn asiayhteyteen. Asiayhteydellä tarkoitetaan käytännössä tilannetta ja ympäristöä, jossa ongelma esiintyy. Ratkaisumallin esittämä ongelma esiintyy toistuvasti. Ongelma voidaan määritellä joukkona jännitteitä (forces). Ratkaisu kuvaa suunnitteluun kuuluvat elementit ja niiden väliset suhteet, eri elementtien vastuut sekä yhteistoiminnan. Ratkaisu on kokoonpano, joka tasapainottaa jännitteet. Niin sanottu Gang of Four ryhmä (Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides) painottaa teoksessaan [GHJ95] yllä mainittujen ominaisuuksien lisäksi ratkaisumallin nimeä ja seurauksia: Ratkaisumallin nimi toimii tunnisteena ja viestinnän välineenä; se kasvattaa ohjelmistokehittäjien yhteistä sanastoa. Ratkaisumallin soveltamisella on aina tiettyjä seurauksia. Mallissa on etuja ja haittoja, ja niitä on syytä punnita kun mallia käytetään. Uusia ratkaisumalleja ei keksitä, vaan ne löydetään olemassa olevista ohjelmistoista. Silti malli ei ole yhtä kuin valmis koodinpätkä, jonka voi leikata ja liimata lähdekooditiedostosta toiseen. Toki ratkaisumalliin voi liittyä esimerkkitoteutus jollakin ohjelmointikielellä. Ytimeltään ratkaisumalli on kuitenkin aina abstrakti kysymyksessä on uudelleenkäyttö suunnittelun, ei toteutuksen tasolla. 1
3 UML ja ratkaisumallit Unified Modeling Language, UML, on saavuttanut melko vankan aseman ohjelmistojen suunnittelun ja dokumentoinnin välineenä. Näin ollen UML:n ja ratkaisumallien suhdetta kannattaa tarkastella hiukan, sillä ihanteellinen CASE-työkalu tukee sekä UML:n että ratkaisumallien käyttöä. Vaikka osa tässä artikkelissa esiteltävistä työkaluista onkin peräisin UML:ää edeltävältä aikakaudelta, se ei kuitenkaan tee niistä kelvottomia. Jos työkalun teoreettinen perusta on riittävän vankka, UML-tuen mahdollinen lisääminen tuskin aiheuttaa ylitsepääsemättömiä ongelmia. UML-käyttäjän oppaassa [BRC99] käytetään termiä mekanismi (mechanism) ratkaisumallin synonyyminä. Lisäksi puhutaan kehyksistä (framework), jotka vastaavat jokseenkin arkkitehtuuria kuvaavia ratkaisumalleja. Mekanismit voidaan kuvata yhteistyökaavioiden (collaboration) avulla. Yhteistyökaavion rakenne kuvataan luokkakaaviolla, ja sen käyttäytyminen kuvataan sekvenssikaavion avulla. Tämän kuvaustekniikan ongelmana on, että yksittäistä ratkaisumallia ei oikeastaan esitetä atomisena yksikkönä, vaan kokoelmana UML:n peruselementtejä. Ratkaisumalli joudutaan aina rakentamaan uudestaan. Kehysten eli arkkitehtuurimallien kuvaamiseksi esitetään pakkausta, jolla on tietty stereotyyppi (stereotyped package). Tämäkään ratkaisu ei kuitenkaan ole ongelmaton: miten kuvata tilanne, jossa luokka on osallisena useammassa kuin yhdessä ratkaisumallissa [Lai00]. UML sallii yksittäisen luokan kuulumisen useampaan eri pakkaukseen, mutta tällöin pakkausten on oltava aidosti sisäkkäisiä. Laine esittääkin, että ratkaisumallit voisi kuvata stereotyyppien avulla. Määritellään ratkaisumallin rakennekuvaus stereotyyppinä PatternTemplate, ja sille edelleen luokkakohtaiset liittymät olioiden luomista varten. Tämän tekniikan hyödyntäminen käytännössä tietenkin vaatisi työkalun, joka tukee ratkaisua. 4 Ohjelmistotyökalujen tuki ratkaisumalleille Artikkelissa [Vil97] listataan toivottavia ominaisuuksia ratkaisumalleja tukevalle CASEvälineelle: luettelo ratkaisumalleista, mahdollisuus valita ja hakea malleja 2
mallien lisääminen suunnitelmaan ja mallin roolien jakaminen eri luokille mallien oikeellisuuden tarkistaminen, mahdollisten ristiriitojen ratkaisu mallien visualisointi järjestelmän esittäminen eri abstraktiotasoilla: arkkitehtuurista yksittäisiin luokkiin automaattinen mallien tunnistus koodista mahdollisuus muokata malleja ja luoda kokonaan uusia ryhmätyöominaisuudet Seuraavien kappaleiden esimerkit ovat keskenään hyvinkin erilaisia ja sijoittuvat ohjelmistoprosessin eri vaiheisiin. Ne kuitenkin sisältävät ainakin joitakin yllä mainituista ominaisuuksista. Kustakin työkalusta esitellään lyhyesti sekä sen teoreettista taustaa että käytännön toteutusta. 4.1 Sirpalemalli Gert Florijn, Marco Meijers ja Pieter van Winsen esittelevät artikkelissaan [FMW97] ohjelmistotyökalun, joka tukee ratkaisumallin elementtien (luokat, hierarkiat) luomista, olemassa olevien elementtien kytkemistä jonkin ratkaisumallin rooleihin ja edelleen tuloksen validointia, siis että luokat ja niiden roolit täyttävät ratkaisumallin asettamat ehdot. Tavoitteena on ollut, että ratkaisumalleja voidaan käyttää ohjelman suunnittelun peruspalasina. Työkalun pohjana ovat sirpalemalli (fragment model) ja sitä vastaava sirpaletietokanta (fragment database). Yksi sirpale kuvaa yhtä elementtiä esimerkiksi luokkaa, metodia, yhteyttä tai ratkaisumallia. Sirpaleella on rooleja, joihin voi sisältyä viittauksia toisiin sirpaleisiin. Työn alla oleva ohjelmisto esitetään eri tyyppisten sirpaleitten verkkona. Sirpaleeseen voi liittyä myös jokin tietty käyttäytyminen, vaikkapa ratkaisumalliin liittyvän operaation toteutus. Järjestelmä koostuu ratkaisumallivarastosta ja kahdesta työkalusta sirpaleitten käsittelyä varten. Ratkaisumallivarasto on toteutettu joukkona erilaisia sirpaleitten kokoonpanoja. Ratkaisumalli otetaan käyttöön kloonaamalla haluttu kokoonpano varastosta työn alla olevaan ohjelmistoon. Sirpaleiden tutkimista ja valintaa varten on oma selaimensa (fragment browser). Selain tarjoaa globaalin näkymän työn alla olevaan sirpalerakenteeseen, luettelon niistä ratkaisumalleista, jotka löytyvät varastosta, sekä operaatiot sirpalerakenteen manipulointiin eli ratkaisumallien 3
käsittelyyn. Yksittäisen sirpaleen ja sen ominaisuuksien tutkimista varten on oma välineensä (fragment inspector). Näiden kolmen jossain mielessä alemman tason osan ohella järjestelmä sisältää OMTtekniikkaan pohjautuvan mallinnustyökalun, jonka tavoitteena on olla helppokäyttöisempi kuin sirpaletietokantaa suoraan käsittelevät työkalut. Kokonaisuuteen kuuluu myös import- ja exporttoiminnot Smalltalkilla kirjoitetuille ohjelmille. OMT-työkalu Selain (browser & inspector) Smalltalk import Sirpaletietokanta Ratkaisumallien prototyyppejä Ohjelman sirpaleita Sirpalemalli Kuva 1. Sirpalemalliin pohjautuvan järjestelmän arkkitehtuuri Järjestelmä on toteutettu Visualworks Smalltalk ohjelmointikielellä, ja sitä on kirjoittajien mukaan käytetty Smalltalkilla toteutetun WWW-selaimen kehitystyössä. Työkalu on prototyyppiasteella. Yhtenä jatkotavoitteena mainitaan kieliriippumattomuus, sillä nykyinen toteutus on ilmeisen voimakkaasti sidottu Smalltalkiin. 4.2 Lähdekoodin generointi ratkaisumalleista Artikkelissa [BFV96] kuvataan WWW-ympäristössä toimiva ohjelmistotyökalu, joka tuottaa ratkaisumallin toteuttavan lähdekoodin automaattisesti, kun käyttäjä on ensin määritellyt riittävät parametrit. Toteutus sisältää myös hypertekstiversion kirjasta [GHJ95] John Vlissides on yksi artikkelin kirjoittajista ja mukana kehitystyössä. 4
Tavoitteena on ollut luoda väline, jota on helppo kehittää edelleen ja toisaalta helppo käyttää. WWW-ympäristö valittiin työkalun alustaksi, koska haluttiin hyödyntää mahdollisimman paljon olemassa olevia sovelluksia ja teknologiaa (selaimet ja palvelimet), ja toisaalta koska WWW mahdollistaa hajautetun toteutuksen. Esittäjä Sovittaja Koodigeneraattori Ulkonäön kuvaukset (HTML) Sovittajan kuvaukset (Perl) COGENT Kuva 2. Koodigenerointityökalun arkkitehtuuri Työkalu koostuu kolmesta osasta: esittäjä (presenter), sovittaja (mapper) ja koodigeneraattori (code generator). Esittäjä toteuttaa käyttöliittymän, joka on siis selainpohjainen. Koodigeneraattori tuottaa ratkaisumallia vastaavan lähdekoodin ja sovittaja määrittelee, kuinka koodigeneraattorin ja esittäjän yhteistyö tapahtuu. Koodigeneraattori on COGENT-tulkki (COde GENeration Template). COGENT on kirjoittajien kehittämä kieli lähdekoodin generoimista varten. Se ei ole sidottu tuottamaan mitään tiettyä ohjelmointikieltä. Suunnittelun lähtökohtana on ollut yksinkertaisuus, joten kieli sisältää vain viisi perusrakennetta: makrojen korvaaminen, ehdollinen sisällytys (COGENT-koodin katkelma otetaan mukaan jonkin ehdon perusteella), toistuva sisällytys (COGENT-koodin katkelma otetaan mukaan monta kertaa), eräänlainen aliohjelmamekanismi ja arvojen sijoittaminen 5
makroille. Kirjoittajien mukaan näillä ominaisuuksilla saadaan riittävän ilmaisuvoimainen kieli tähän tehtävään. Sovittaja on Perl-tulkki, ja sovittajan kuvaukset (Kuva 2) ovat siis Perl-skriptejä. Sovittajan tehtävänä on liittää käyttöliittymän elementit vastaaviin COGENT-parametreihin ja toisaalta vastata käyttäjän pyyntöihin eli näyttää uusi HTML-sivu tai suorittaa COGENT-skripti. Tiedonkulku käyttöliittymästä Perl-skriptille perustuu CGI-mekanismiin. Käyttäjä asettaa käyttöliittymässä (HTML-lomake) haluttuun ratkaisumalliin liittyvät parametrit ja lähettää pyynnön eteenpäin. Sovittaja kutsuu COGENT-tulkkia, joka tuottaa ratkaisumallia vastaavan lähdekoodin. Lähdekoodi palautuu käyttäjälle uutena WWW-sivuna, joten se täytyy leikata ja liimata varsinaiseen kehitysympäristöön. Tämä ei tietysti ole ohjelmoijan kannalta paras mahdollinen tapa. Ongelmia tulee myös, kun generoitua koodia muokataan, ja sitten generoidaan uudestaan miten säilyttää käsin tehdyt muutokset? Kirjoittajat esittävät ratkaisuksi kahden luokan generoimista: luokka ja sille aliluokka. Kaikki muutokset tehdään aliluokkaan. Näin muutokset eivät katoa, jos varsinaisen luokan koodi täytyy generoida uudestaan. WWW-tekniikkaan pohjautuva CASE-työkalu, joka tukee ratkaisumallien käyttöä, on ajatuksena kiinnostava. Kirjoittajat listaavat jatkotutkimuksen aiheina esimerkiksi saman toimintaajatuksen soveltamisen vaatimusten määrittelyyn, dokumentointiin tai virheenjäljitykseen. 4.3 FRED FRED on Helsingin ja Tampereen yliopistojen tietojenkäsittelytieteiden laitosten yhteinen projekti, jonka tuotteena on syntynyt samanniminen ohjelmistotyökalu sovelluskehysten kehittämistä varten [HHT98]. FRED on toteutettu Javalla ja se on tarkoitettu Java-sovellusten ja -sovelluskehysten luomiseen. Kirjoittajien mukaan FREDin takana oleva ajatusmalli ei kuitenkaan ole sidottu mihinkään tiettyyn ohjelmointikieleen. Sekä yksittäiset sovellukset että sovelluskehykset ovat arkkitehtuureja (architectures). Arkkitehtuuri muodostuu elementeistä kuten ratkaisumallit, luokat ja rajapinnat. Näitä elementtejä kutsutaan yhteisellä nimellä rakenne (structure). Rakenteet voidaan luokitella yhdistettyihin (composite) ja lehtiin (leaf). Arkkitehtuurin rakenteet muodostavat suunnatun 6
verkon, ja koska tietotyyppi kuten luokka voi kuulua useampaan eri ratkaisumalliin, kysymyksessä on nimenomaan verkko eikä puu. Jokainen rakenne on joko toteutus (implementation) tai kaava 1 (template). Toteutus on sovelluksessa olemassa oleva rakenne ja kaava puolestaan määrittelee joukon mahdollisia toteutuksia. Kaikki rakenteet perustuvat vastaaviin metarakenteisiin (meta structure). Uusia rakenteita saadaan luomalla mallin ilmentymiä. FRED esittää ratkaisumallit nimenomaan kaavoina. Työkalun käyttöliittymä on kolmiosainen (Kuva 3): vasemmalla olevien puurakenteiden avulla voidaan selailla ja manipuloida arkkitehtuuria ja sen eri näkökohtia. Rakenteita muokataan oikean puolen Desktop-ikkunassa, ja Notes-ikkunassa näkyy käsiteltävän rakenteen dokumentaatio. 1 Suomennos on hieman hankala, termin template voisi kääntää myös malliksi, mutta tällöin törmätään ratkaisumallin käsitteeseen. 7
Kuva 3. FREDin käyttöliittymä Kirjoittajien mukaan FREDin ansiona on se, ettei ratkaisumallien tuki rajoitu vain lähdekoodin generoimiseen, vaan mallit ovat eksplisiittisesti mukana koko ajan, suunnittelusta toteutukseen. Näin vältetään koodin uudelleen generoimiseen liittyvät ongelmat. 4.4 Pattern Lint Pattern Lint on ohjelmistotyökalu, jonka tarkoitus on auttaa kehittäjiä varmistamaan, ettei toteutusvaiheessa ajauduta liian kauas suunnitelmasta [SSC96]. Se analysoi sekä ohjelman staattista että dynaamista rakennetta, ja varmistaa eri tasoilla, että ohjelma noudattaa suunnitelmia. Näitä eri tasoja ovat konkreettiset säännöt kuten ohjelmointityyli, erilaiset heuristiikat kuten koheesio ja kytkentä sekä tämän esityksen kannalta kiinnostavimpana näkökohtana arkkitehtuuriin liittyvät säännöt, esimerkiksi ratkaisumallit. Ratkaisumallit (ja arkkitehtuurisäännöt yleensä) määritellään Prolog-lauseina. Lauseita on kahdentyyppisiä: sellaisia, jotka pyrkivät löytämään tukea sille, että toteutus noudattaa suunnitelmaa ja toisaalta sellaisia, jotka pyrkivät löytämään suunnitelman ja toteutuksen välisiä ristiriitoja. Kirjoittajien mukaan näiden sääntötyyppien käyttö yhdessä auttaa vähentämään vääriä hälytyksiä. Käyttöliittymässä voidaan valita ratkaisumalli ja tutkia, kuinka lähdekoodi noudattaa haluttua mallia. Pattern Lintin ensimmäisinä komponentteina ovat jäsennin, joka lukee analysoitavan lähdekoodin, ja tietokantageneraattori, joka luo tietokannan koodissa esiintyvistä relaatioista. Prologilla toteutettu päättelyrutiini vertaa sitten näitä koodissa olevia relaatioita mallin määrittelemiin relaatioihin, ja kertoo, onko toteutus mallin mukainen vai ei. Staattinen korrelaattori (static correlator) tuottaa vertailun lopputulosta vastaavan graafisen datan. Tässä vaiheessa käyttäjä voi niin halutessaan tuottaa analyysin ohjelman dynaamisesta rakenteesta instrumentointityökalun avulla. Lopuksi erillinen näyttökomponentti luo visuaalisen esityksen sekä staattisesta että dynaamisesta analyysista. Työkalua on käytetty Choices-käyttöjärjestelmän kehittämisessä, erityisesti laitehallinnan toteutuksessa. Kirjoittajat mainitsevat lähdekoodin generoinnin yhtenä mahdollisena parannuksena nykyiseen versioon. 8
5 Loppusanat Tässä artikkelissa on kuvailtu ratkaisumallin käsite, sekä käsitelty lyhyesti UML:n ja ratkaisumallien suhdetta, erityisesti ratkaisumallien kuvaamisen problematiikkaa. Artikkelissa on esitelty kuinka muutamat ohjelmistotyökalut tukevat ratkaisumallien käyttöä. Tavoitteena ei ole ollut minkään yksittäisen työkalun perinpohjainen läpikäynti, vaan pikemminkin yleiskatsaus. Painopiste on ollut akateemisissa eikä kaupallisissa välineissä. Aiheesta tuntuu olevan melko runsaasti tutkimusta, joten yhden seminaariesitelmän puitteissa ei välttämättä päästä vielä kovin syvälle. 9
Lähteet BFV96 Budinsky F., Finnie M., Vlissides J., Yu P., Automatic Code Generation from Design Patterns. IBM Systems Journal 35, 2, 1996, 151-171. BMR96 Buschmann F., Meunier R., Rohnert H., Sommerlad P., Stal M., A System of Patterns Pattern-Oriented Software Architecture. John Wiley & Sons, 1996. BRC99 Booch R., Rumbaugh J., Jacobson I., The Unified Modeling Language User Guide. Addison-Wesley, 1999. FMW97 Florijn G., Meijers M., van Winsen P., Tool support for object-oriented patterns. <URL:http://www.serc.nl/people/florijn/papers/pattern-tool-overview.ps.gz> GHJ95 Gamma E., Helm R., Johnson R., Vlissides J., Design Patterns Elements of Reusable Object-Oriented Software. Addison-Wesley, 1995. HHT98 Hakala M., Hautamäki J., Tuomi J., Viljamaa A., Viljamaa J: Pattern - Oriented Framework Engineering Using FRED. <URL:http://www.cs.helsinki.fi/research/fred/reports/FRED.ps.gz> Lai00 Laine H., Ohjelmistoarkkitehtuurit. Luentomoniste, Helsingin yliopiston tietojenkäsittelytieteen laitos, 2000. SSC96 Sefika M., Sane A., Campbell R.H., Monitoring Compliance of a Software System With Its High-Level Design Models. Proc. of ICSE 96, Berlin 1996, IEEE Computer Society Press 1996. Vil97 Viljamaa J., Tools Supporting the Use of Design Patterns in Frameworks. Report C-1997-25, University of Helsinki, Department of Computer Science, 1997. <URL:http://www.cs.helsinki.fi/research/fred/reports/pfw.ps.gz> 10