Suunnittelumalli () on ohjelmistotekniikassa ohjelmistorakenteen käsitteelliset (abstraktit) avainkohdat määrittävä kuvaus toistensa kanssa yhteistoiminnassa olevista luokista ja olioista. Suunnittelumalli sisältää yleisellä tasolla esitetyn ratkaisun johonkin oliopohjaisen suunnittelussa esiintyvään tavanomaiseen tilanteeseen tai kohteeseen.Gamma, Helm, Johnson & Vlissides 2001, 4-5. Suunnittelumalli perustuu käytännön kokemukseen ratkaisun toimivuudesta tietyssä tilanteessa, ja sen käytöstä on pitkä kokemus. Suunnittelumallin tärkeimmät osat ovat ongelma, ongelmayhteys ja ratkaisu.Koskimies & Mikkonen 2005, 102-103 Suunnittelumallia voidaan käyttää työvälineenä suunniteltaessa ohjelman konkreettista arkkitehtuuriaKoskimies & Mikkonen 2005, 32-35 ja 101.

Yleistä

Suunnittelumalli on yleiskäyttöinen, käytännössä toimiva, uudelleenkäytettävä ja oliosuuntautunut ohjelmointilähtökohta, jota aloitteleva ohjelmoija ei tunneEriksson & Penker 2000, 221. Suunnittelumalli voi myös koskea ohjelman suppeaa yksityiskohtaaKoskimies 2000, 245. Suunnittelumallin määrittelyssä kerrotaan sen käyttökohde, käyttöä rajoittavat tekijät, mallin seuraukset ja sen vahvuudet ja heikkoudet. Suunnittelumallin käyttö edellyttää riittävät ominaisuudet omaavan oliokielen käyttöä (esimerkiksi C++).Gamma, Helm, Johnson & Vlissides 2001, 5. Paras keino ymmärtää ja omaksua suunnittelumalli on sen tutkiminenEriksson & Penker 2000, 223.

Suunnittelumallissa ei ole tärkeintä malli itse, vaan se suunnittelukokemus ja asiantuntemus, joka sitä käyttäen saadaan säilytettyä ja siirrettyä muille ohjelmoijille. Kerätty informaatio tulee esittää käytännönläheisessä, selkeässä ja järjestelmällisessä muodossa, jolloin malli antaa käytännön ohjelmointityöhön järjestetyn ja valmiin kokoelman tiettyihin tilanteisiin sopivia ratkaisuja. Suunnittelumalleja ei tule käyttää tilanteissa, joista niistä ei ole hyötyä.Koskimies 2000, 245-247

Ohjelmistoarkkitehtuurin kannalta suunnittelumallit käsittelevät yleensä suhteellisen pieniä yksiköitä (mikroarkkitehtuuria), mutta suunnittelumalleja voidaan käyttää myös koko sovelluksen perusrakenteessa (makroarkkitehtuuri). Suunnittelumallien ideaa on sovellettu käänteisenä keräämällä ns. antisuunnittelumalleja, joissa esitetään virheellisiä suunnitteluratkaisuja. Antisuunnittelumallia voidaan käyttää tunnistamaan ohjelmarakenteen virheitä ja suositeltavan suunnittelumallin soveltamiseen virheen poistamiseksi.Koskimies 2000, 247

Historia

Suunnittelumallin käyttö ohjelmistotekniikassa perustuu amerikkalaisen arkkitehdin Christopher Alexanderin esittämään ajatukseen (Alexander, C. & ym. (1977). A Pattern Language. New York: Oxford University Press) siitä, että rakentaminen perustuu hyväksi havaittujen ratkaisumallien keräämiseen, oppimiseen ja toistamiseen. Eräät ohjelmistotekniikan tutkijat (Kent Beck, Jim Coplien, Erich Gamma, ym.) tutustuivat näihin ajatuksiin, ja ryhtyivät kehittämään niiden käyttöä ohjelmointitekniikan yhteydessä.

Vuoden 1994 elokuussa pidetty PLoP-konferenssin (Pattern Language of Programming) jälkeen aloitettiin useita projekteja suunnittelumallien löytämiseksi. Vuoden 1995 alussa Erich Gamma, Richard Helm, Ralph Johnson ja John Vlissides ("Gang of Four") julkaisivat Design Patterns: Elements of Reusable Object-Oriented Software, jossa esitettiin 23 suunnittelumallia.Eriksson & Penker 2000, 222

Aikaisemmin Kent Beck ja Ward Cunningham toivat suunnittelumallit ohjelmistosuunnitteluun vuoden 1987 OOPSLA-konferenssissa. Vaikka he käyttivätkin esittelemiään suunnittelumalleja olio-ohjelmoinnin suunnittelussa, eivät ne olleet oliosuunnittelumalleja sanan nykyisessä merkityksessä, vaan niitä voidaan pitää käytettävyysmalleina. Erich Gamma oli käsitellyt suunnittelumalleja vuonna 1991 julkaistussa väitöskirjassaan, ja häntä pidetään suunnittelumallien tärkeimpänä kehittäjänä.

Suunnittelumallin sisältö

Suunnittelumallia kuvataan yleensä sen perustiedoilla, jotka määrittelevät mallin ja kuvaavat sen toiminnan.Nämä perustiedot ovat nimi, ongelman kuvaus, ratkaisun kuvaus ja ratkaisun vaikutukset ohjelmistoon ja tietokoneen laitteisiin. Muita suunnittelumallista esitettäviä tietoja voivat olla mm. luokittelu, mallista käytettävät muut nimet, esimerkki käyttötilanteesta, soveltuvuus, rakenteen esittäminen kaaviolla, malliin kuuluvat luokat ja niiden välinen tehtävien jako (vastuut), luokkien väliset rajapinnat, toteutuksessa esiintyvät ongelmat (esim. ohjelmointikielen vaikutus), esimerkki mallin toteuttamisella ohjelmointikielellä, esimerkkejä käytöstä todellisissa ohjelmissa ja mallia muistuttavat muut mallit ja mallit, joiden kanssa mallia olisi hyvä käyttää.Gamma, Helm, Johnson & Vlissides 2001, 2-3 ja 6-8

Nimi Suunnittelumallin nimi kuvaa mallin sisältämän periaatteen lyhyesti ja yksiselitteisesti. Mallin nimen perusteella voidaan nopeasti hahmottaa käytetty rakenne, sen tuottama hyöty ja siihen liittyvät rajoitukset. Mallin nimi auttaa ohjelmiston suunnittelemaan ajattelemaan ohjelmistorakennetta yleisellä (abstraktilla) tasolla, ja sen käyttö voi helpottaa suunnittelijoiden välistä keskustelua.Gamma, Helm, Johnson & Vlissides 2001, 3 Suunnittelumallin nimen tulisi olla osa suunnittelijan ammattisanastoa, mutta tilannetta on vaikeuttanut mm. se, että sama suunnittelumalli on nimetty eri nimillä tai käytännössä samat suunnittelumallit on nimetty eri nimillä. Samaa nimeä voidaan myös käyttää eri suunnittelumalleille.Koskimies & Mikkonen 2005, 106

Ongelma Ongelma (Problem) kuvaa ohjelmoinnissa esiintyvää tavanomaista tilannetta, jonka ratkaisemisessa suunnittelumalli on ollut hyödyksi. Ongelman kuvaus voi olla laaja arkkitehtuuriin liittyvä tai sitten suppeampi, esim. tietyn algoritmin kuvaus. Suunnittelumalli voi joskus sisältää ominaisuuksia, joiden vuoksi sitä ei ole tarkoituksenmukaista käyttää muissa kuin erityistilanteissa. Nämä erityistilanteet on kuvattu tässä osassa suunnittelumallin määrittelyä.Gamma, Helm, Johnson & Vlissides 2001, 5 Ongelman tulee ilmetä toistuvasti monenlaisissa ohjelmistoissa ja sen tulee olla yleisluontoinen (esim. ohjelmointikielestä riippumaton). Muut kuin arkkitehtuuri- tai yksityiskohtaiseen suunnitteluun liittyvät ongelmat rajataan pois.Koskimies & Mikkonen 2005, 105

Ongelma esittää tilanteen, jossa mallia voidaan soveltaa. Ongelman kuvaus esitetään tarkasti identifioituna, mikä helpottaa käyttöalueen määritystä. Kuvaus voi myös esittää jonkin tyypillisen joustamattoman rakenteen, jota on parannettava. Suunnittelumallia ei ole syytä käyttää ellei ongelman kuvaus vastaa toteutettavassa ohjelmistossa esiintyvää ongelmatilannetta. Yleisesti voidaan todeta, että suunnittelumallien tehokas soveltaminen vaatii huolellista pohdintaa, sillä mallien soveltaminen voidaan tehdä vain suppeasti määritellyllä ongelma-alueella. Joskus ongelman kuvaus sisältääkin listan ehdoista joiden tulee täyttyä ennen kuin on hyödyllistä soveltaa suunnittelumallia.

Ongelmayhteys

Ongelmayhteys (Context) kuvaa sen kokonaisuuden, jossa ongelma ilmenee, ja se kertoo sen, missä tilanteissa suunnittelumallia voidaan käyttää. Ongelmayhteys määrittää lisäksi ratkaisulle asetettavia vaatimuksia ja niitä ohjelman laatuominaisuuksia, joita ratkaisun tulisi parantaa. Usein ongelma ja ongelmayhteys esitetään yhdessä, ja niitä havainnollistetaan esimerkeillä.Koskimies & Mikkonen 2005, 105-106

Ratkaisu

Ratkaisu (Solution) kuvaa mahdollisen ohjelmointirakenteen ja sen osat (esim. luokat, oliot, algoritmit), osien väliset suhteet ja niiden välisen vuorovaikutuksen (yleensä funktiokutsut) yleisellä tasolla. Ratkaisun antamia ohjelmoinnin suuntaviivoja on käytettävä käsitteellisenä runkona laadittaessa käytännön ratkaisua käsillä olevaan ohjelmointiongelmaan. Ohjelmistosuunnittelija arvioi tapauskohtaisesti sen, miten mallin ratkaisu sopii kyseessä olevaan tilanteeseen. Ratkaisun tulee olla sovellettavissa yleisesti ohjelmoinnissa, ja se tulee pystyä esittämään yleisti käytössä olevalla mallinnuskielellä (esim. UML). Ratkaisun yleiskäyttöisyydestä voi seurata se, että ohjelmiston laatuominaisuudet (esim. nopeus) heikkenee.

Ratkaisu on suunnittelumallin tärkein asia, ja se esitetään usein staattisena rakenteena (esim. UML:n luokkakaavio) jota täydennetään dynaamisen vuorovaikutuksen kaaviolla (esim. UML:n sekvenssikaavio). Kuvausta voidaan täydentää pseudokoodikuvauksella, joka kuvaa ohjelman kulun vaihe vaiheelta.

Ratkaisun tehtävänä on muodostaa yleinen kuvaus ongelman ratkaisusta. Ratkaisu kuvaa toteutuksessa käytettävät luokat, rajapinnat ja oliot, sekä niiden suhteet yleisellä tasolla. Vaikka ratkaisun rakenne esitetään yleensä UML-kaaviolla tai jollain muulla oliorakennetta kuvaavalla yleisesti tunnetulla kuvaustavalla (notaatio), ei ratkaisu kuvaa mitään erityistä tilannetta vaan yleisen tavan ratkaisulle. Tosin yksinkertainen esimerkki helpottaa ratkaisun toteutustavan ymmärtämistä. Ratkaisussa ei yleensä oteta kantaa käytettävään ohjelmointikieleen, mutta esimerkiksi moniperinnän puuttuminen osasta oliokieliä saattaa hankaloittaa ratkaisun toteuttamista. Yleisesti suunnittelumalleissa ei käytetä jonkin tietyn kielen erityisominaisuuksia ongelman ratkaisuun.

Seuraukset

Seuraukset kuvaa mallin vaikutusta ohjelman sisäiseen ja ulkoiseen toimintaan, sekä sen käytöstä seuraavia hyviä ja huonoja seikkoja. Ohjelmistojen toiminnan kannalta tärkeitä seurauksia ovat mm. muisti ja suoritusaika ja ohjelmiston uudelleenkäyttö. Ohjelmiston uudelleenkäytön kannalta tärkeitä seurauksia ovat mm. käytetyn mallin vaikutus ohjelman laajennettavuuteen, muunneltavuuteen ja siirrettävyyteen. Mikään suunnittelumalli ei tuota joka suhteessa parasta ratkaisua, vaan kukin niistä optimoi tietyt ohjelman laatuominaisuudet ja heikentää muita. Seurausten kuvaaminen auttaa suunnittelijaa arvioimaan sitä, miten malli soveltuu käsillä olevaan suunnittelutilanteeseen. Seurauksista kertominen helpottaa suunnittelumallin soveltamista käytännön ohjelmistotyössä.

Toteutusnäkökulma ja esimerkit

Toteutusnäkökulma kertoo käytännön ohjelmoinnissa esiintyvien tilanteiden ratkaisemisesta, esimerkiksi kertomalla mallin käytöstä eri ohjelmointikieliä käytettäessä. Toteutusnäkökulma on pidettävä erillään suunnittelumallin esittämästä teoreettisesta ajattelutavasta. Suunnittelumallin käytöstä voidaan antaa esimerkki todellisen järjestelmän toteutuksessa tai ohjelmointikielikohtaisena.Koskimies & Mikkonen 2005, 107

Luokittelu Suunnittelumallit luokitellaan yleensä sen tarkoituksen (luonti, rakenne, käyttäytyminen) ja sen kohteen (luokka, olio) perusteella. Mallit voidaan luokitella lisäksi myös sen mukaan, mitä malleja käytetään yleensä toistensa kanssa, mitkä mallit ovat toistensa vaihtoehtoja tai rakenteeltaan toisiaan vastaavia. Mallien luokittelun tarkoituksena on jäsentää ohjelmistoa käsitteellisiä lähestymistapoja (abstraktiotaso) kuvaavat mallit toistensa suhteen ja nopeuttaa mallien oppimista.Gamma, Helm, Johnson & Vlissides 2001, 9-11

Luontimallit

Luontimalli on suunnittelumalli, jolla ohjelmassa toimivan olion rakentaminen esitetään käsitteellisellä tasolla. Luontimalli peittää konkreettisesti käytettävien tuotantoluokkien näkyvyyden niitä käyttäviltä luokilta ja sen, miten tuotantoluokkia luodaan ja yhdistellään toisiinsa, eli tuotantoluokkia käyttävä tilaajaohjelma tuntee niistä vain niiden abstraktissa luokassa esitettävän rajapinnan. Rajapinnan käyttö mahdollistaa sen, että tuotantoluokkia ja niiden välisiä suhteita on helppo muuttaa ilman että sillä olisi vaikutusta luokkia tilaavan ohjelman toimintaan.Gamma, Helm, Johnson & Vlissides 2001, 81 Luontimalli kuvaa olioiden luomisprosessin, eli sen, kuinka, koska ja mitä olioita luodaan, ja huolehtivat luokkien ja olioiden asetusten konfiguroinnistaErikssen & Penker 2000, 223.