• Ei tuloksia

2 JÄRJESTELMÄLTÄ VAADITTAVAT OMINAISUUDET

2.2 Laskennalliset ominaisuudet

2.2.1 Yleistä

OMT-metodologian mukaisesti [Rumb91] järjestelmän funktionaalinen malli kuvaa mitä, dynaaminen malli milloin ja oliomalli mille järjestelmässä tapahtuu.

Rakennettavan laskentasääntömekanismin tarkoituksena on toteuttaa sovelluksen funktionaalisen ja dynaamisen mallin vaatimat ominaisuudet.

Funktionaalinen malli kuvaa, miten laskennan lopputulokset saadaan laskettua alkuarvoista ottamatta kantaa yksittäisten arvojen laskentajärjestykseen. Ohjelmointi­

kielen kääntäjä koostuu lähes yksinomaan funktionaalisesta mallista, joka esittää lähdekoodin syntaksista riippuvan kuvauksen ajettavaksi ohjelmaksi. Toisaalta tietokannoissa on usein triviaali funktionaalinen malli, sillä niiden tarkoituksena on tallettaa tietoa, ei muuttaa sitä. Taulukkolaskinlomake on eräänlainen funktionaalinen malli. Taulukkojen soluihin liitetyt lausekkeet kertovat solujen riippuvuudet toisistaan aritmeettisina laskentakaavoina. Funktionaalinen malli on suunnittelujärjestelmissä asiakaskohtainen ja se koostuu malliin liitetyistä laskentasääntölausekkeista.

Dynaaminen malli määrittelee laskentaj ärj estyksen. Deklaratiivisesti esitetyn funktionaalisen mallin laskentaj ärj esty s on periaatteessa mielivaltainen ja laskentaa voidaan suorittaa jopa rinnakkain. Tärkein toiminto on toisistaan riippuvien tietojen uudelleenlaskenta lähtötietojen muuttuessa. Laskentasääntömekanismi määrittelee suurimman osan asiakaskohtaisen suunnittelujärjestelmän dynaamisesta mallista.

Käyttäjän ei tarvitse erikseen määritellä laskentaj ärj esty stä tai käynnistää muuttuneiden tietojen laskentaa. Käytännön sovelluksissa voi kuitenkin esiintyä tarpeita tiettyjen kontrollirakenteiden esittämiseen. Käyttäjän on poikkeustapauksissa voitava vaikuttaa laskentaj ärj estykseen laskentasääntömekanismin avulla.

2.2.2 Laskentasäännöt

Laskentasääntö on objekti, jonka avulla voidaan yksikäsitteisesti laskea mallissa olevan johdetun attribuutin arvo. Jokainen laskentasääntö liittyy yhteen olioluokassa määriteltyyn johdettuun attribuuttiin. Tätä attribuuttia kutsutaan säännön omistaja- attribuutiksi. Jokaisella laskentasäännöllä on lisäksi ainakin nimi ja lauseke.

Nimi identifioi laskentasäännön yksikäsitteisesti ja sen perusteella käyttäjä voi tulkita laskennan aikana mahdollisesti tulostettavia ilmoituksia sekä valita haluamansa säännön useita sääntöjä käsittävästä listasta. Järjestelmä antaa uudelle säännölle oletusarvona yksikäsitteisen nimen, jota käyttäjä voi halutessaan muuttaa.

Lauseke on laskentakielen syntaksin mukainen merkkijono, jolle voidaan laskea yksikäsitteinen arvo. Kielen syntaksin oli oltava helposti ymmärrettävissä ja luettavissa.

Esimerkki mahdollisesta syntaksista on esitetty liitteessä A. Lausekkeessa oli voitava esittää ainakin vakioita, operaattoreita, funktiokutsuja ja viittauksia mallissa esiintyviin instansseihin ja näiden attribuutteihin. Viittaukset mallin komponentteihin oli voitava tehdä valitsemalla valintalistoista. Mallin komponenttien - esimerkiksi attribuuttien - nimien muuttuessa oli laskentasäännön lausekkeen päivityttävä automaattisesti.

Kielen oli sisällettävä riittävä määrä valmiita funktioita sovellusten rakentamiseksi.

Hyvänä esimerkkinä tarvittavista funktioista pidettiin Microsoft Excel - taulukkolaskin- ohjelmistoa [Micr94b], Uusien funktioiden lisäämisen ajonaikaisesti tuli olla mahdollista kokeneelle loppukäyttäjälle. Operaatioina oli toteutettava rajallinen joukko

käyttäjälle tuttuja perusoperaatioita. Uusien operaatioiden lisäämistä ajonaikaisesti ei haluttu sallia.

Laskentasääntökielen tuli kokonaisuudessaan olla polymorfmen [Budd91].

Primitiivisistä laskennallisista tietotyypeistä oli toteutettava ainakin merkkijonot, luvut ja lukulistat. Operaatioiden tuli olla määriteltyjä kaikkien tietotyyppien välille.

Esimerkiksi laskettaessa yhteen lukulista [1 2 3] ja yksittäinen luku 4, on tulokseksi saatava lukulista [5 6 7]. Funktioiden on mahdollisuuksien mukaan hyväksyttävä vaihtoehtoisia primitiivisiä tietotyyppejä argumentteinaan.

Funktioiden tyypitykseen tuli kiinnittää erityistä huomiota. Järjestelmän oli tehtävä tyyppitarkistukset sellaisille argumenteille, joiden tulee olla tietyn tyyppisiä. Mikäli argumentin tyyppi ei ole funktion haluama, on argumentti koetettava muuttaa halutun tyyppiseksi. Funktion haluaman argumentin tyyppi voidaan myös jättää avoimeksi.

Tällöin funktio itse huolehtii polymorfisen argumenttinsa käsittelystä. Funktioita oli myös voitava kutsua vaihtelevalla määrällä argumentteja ja funktioiden oli itse saatava päättää, evaluoidaanko argumentit valmiiksi ennen kutsua.

2.2.3 Laskennan suorittaminen

Johdetun attribuutin arvo oli osattava laskea siihen liitetyn laskentasääntökielisen lausekkeen perusteella. Lausekkeessa esiintyvien attribuuttien arvot tuli hakea suhteellisina lähtien siitä instanssista, jonka attribuutille sääntöä ollaan parhaillaan laskemassa.

Laskennan oli oltava mahdollisimman nopeaa ja käytettävä säästeliäästi keskusmuistia.

Laskennan aikana tapahtuvista virhetilanteista piti pystyä antamaan informatiivisia virheilmoituksia tai varoituksia ja mahdollisuuksien mukaan pyrittävä opastamaan käyttäjää korjaustoimenpiteiden löytämisessä.

2.2.4 Laskennan ohjaus

Sääntöjen avulla kuvatun laskennan tuli tapahtua aina tarpeen tullen mallin sisältämien lukuarvojen tai viittausten muuttuessa. Käyttäjän kannalta katsottuna laskennan oli ajallisesti tapahduttava lähtötietojen muuttumisen ja tulosten tarkastelemisen välissä.

Laskentasääntölauseke määrittelee yksikäsitteisesti joukon perusattribuutteja, joiden arvoista yksittäisen sääntöä käyttävän johdetun attribuutin arvo riippuu. Toteutuksen kannalta oli haastavaa rakentaa mekanismi, joka osaa sääntölauseketta käänteiseen suuntaan tarkastelemalla päätellä kaikki ne attribuutit, joihin yhden perusattribuutin muutoksella on vaikutusta. Esimerkiksi lausekkeen 'Myynti - OmaMyynti + sumfTuotteet.Myynti)' arvo muuttuu instanssissa olevan OmaMyynti-tietoalkion arvon muuttuessa, instanssissa olevan Tuo/teei-relaation arvon muuttuessa tai jonkin ko.

TMøtteef-relaatiossa olevan instanssin Myy/tfz-tietoalkion arvon muuttuessa.

Laskennan ohjaukselle on seuraavat neljä vaihtoehtoa:

1. Lasketaan johdettujen attribuuttien arvot aina tarvittaessa, mutta ei talleteta saatuja tuloksia. Edut: Säästetään tilaa. Ei tarvita invalidointia. Haitat: Tietojen katselu on erittäin hidasta. Koska laskennan aikana esiintyviä välituloksiakaan ei talleteta, saattaa monesta johdetusta attribuutista johdetun attribuutin laskenta kestää vuorokausia.

2. Lasketaan yhdenkin muutoksen jälkeen kaikkille johdetuille attribuuteille uudet arvot ja talletetaan saadut tulokset. Edut: Lasketun mallin tarkastelu on nopeaa. Ei tarvita invalidointia. Haitat: Koko malli joudutaan laskemaan uudestaan, jolloin laskenta saattaa kestää tunteja.

3. Lasketaan jokaisen muutoksen yhteydessä välittömästi uudet arvot kaikille muutetusta attribuutista riippuville attribuuteille. Edut: Ei tarvitse laskea koko mallia. Haitat: Lasketaan turhaan sellaisia lukuja, joiden arvoista käyttäjä ei ole kiinnostunut. Laskenta joudutaan suorittamaan myös peräkkäisten muutosten välissä.

4. Invalidoidaan muutosten yhteydessä kaikki muutetusta attribuutista riippuvat muut attribuutit. Lasketaan tulosten tarkastelun yhteydessä arvot niille invalidoiduille attribuuteille, joiden arvoja kysytään. Edut: Lasketaan vain kulloinkin tarvittavat arvot. Haitat: Toteutuksen kannalta vaikein vaihtoehto.

Tässä työssä oli toteutettava vaihtoehdon 4 mukainen laskennan ohjausmekanismi. Tätä varsin monimutkaista toiminnallisuutta varten oli rakennettava erityinen epäkelpoisuus- tiedon levittämismekanismi, jolla jäsennettyjä laskentasääntölausekkeita takaperin seuraamalla pystytään selvittämään kaikki muutosten aiheuttamat mallin uudelleen- laskentatarpeet. Vaihtoehdon 4 mukainen laskennan ohjaus on siis puskuroitua ja viivästettyä. Puskuroinnilla tarkoitetaan sitä, että jokaisen attribuutin arvo lasketaan valmiiksi ja saatu arvo talletetaan attribuutin arvoksi. Kysyttäessä attribuutin arvoa useita kertoja peräkkäin suoritetaan laskenta tarvittaessa vain ensimmäisellä kerralla.

Koska attribuuttiin itseensä on talletettu sen arvo, tulee tämän arvon paikkansapitävyyttä seurata tarkasti. Talletettu arvo menettää merkityksensä silloin, kun jokin attribuutin arvoon vaikuttava mallin tekjä muuttuu. Tällaisia tekijöitä ovat esimerkiksi tietoalkioiden muuttuneet arvot, instanssien välisissä viittauksissa tapahtuvat muutokset, uusien instanssien, luokkien tai attribuuttien luominen tai tuhoaminen ja instanssien nimien muuttuminen. Kun attribuuttiin talletettu arvo menettää merkityksensä, täytyy arvo laskea uudestaan. Tämä laskenta voidaan kuitenkin tehdä viivästetysti laskemalla arvo vasta sitten, kun arvoa seuraavan kerran attribuutilta kysytään. Attribuutin arvon menettäessä merkityksensä sille ei siis lasketakaan uutta arvoa heti, vaan entinen arvo mitätöidään eli invalidoidaan. Viivästetystä laskennasta saavutetaan seuraavat hyödyt:

• Päivitettäessä malliin useita uusia arvoja, ei päivitysten välissä tarvitse laskea muuttuneista tiedoista riippuvia attribuutteja moneen kertaan.

• Koko malliin vaikuttavan parametrin muutoksen vaikutuksia voidaan tehokkaasti tarkastella haluttujen muuttujien suhteen. Vaikka lähes kaikki mallin attribuutit invalidoituvat, joudutaan vain osan arvo laskemaan uudestaan.

Viivästetty laskenta aiheuttaa seuraavia ongelmia:

• Koska laskentaa ei invalidointivaiheessa todellisuudessa suoriteta, joudutaan kaikki muuttuneista tiedoista mahdollisesti riippuvat attribuutit invalidoimaan, vaikka tietojen muutos ei vaikuttaisikaan näiden arvoihin. Viivästetty mekanismi siis olettaa, että jokainen muutos propagoituu kaikkien riippuvien attribuuttien arvojen muuttumiseen.

• Tietyt sivuvaikutukselle! laskentasäännöt halutaan usein suoritettaviksi heti muutosten tapahduttua. Tällainen sivuvaikutus voi olla esimerkiksi arvon muuttumisesta kertovan viestin tulostaminen käyttäjälle.

Laskentasääntökohtainen laskennan ohjaus

Edellä havaittujen ongelmien ratkaisemiseksi oli laskentaa voitava ohjata laskentasääntökohtaisesti. Yksittäisen säännön laskenta-algoritmi oli voitava valita seuraavista neljästä vaihtoehdosta:

1. Normaali viivästetty laskenta ja invalidointi. Attribuutin arvo invalidoidaan jonkun lausekkeessa tapahtuvan muutoksen jälkeen ja invalidoitumistieto välitetään eteenpäin. Attribuutille lasketaan uusi arvo viivästetysti silloin, kun sitä ensimmäisen kerran tarvitaan.

2. Muutostapahtuman jälkeen välittömästi tapahtuva laskenta, mutta normaali invalidointi. Eroaa edellisestä siinä, että uusi arvo lasketaan välittömästi käyttäjän tekemien muutosten jälkeen.

3. Uuden arvon laskenta ennen invalidoitumistiedon välittämistä. Attribuutin uusi arvo lasketaan välittömästi invalidointitiedon saapuessa. Mikäli arvo muuttuu, invalidoidaan attribuutti ja välitetään invalidoitumistieto eteenpäin.

4. Ainoastaan Ca//-käskyllä tapahtuva laskenta, invalidoituminen täysin estetty. Tämä vaihtoehto toteuttaa tavanomaisen metodin käsitteen. Uusi arvo lasketaan aina ja vain silloin kun attribuuttia kutsutaan laskentasääntökielen Ca//-funktion avulla.

Kutsu laskee ja palauttaa attribuutin arvon, eli käytännössä suorittaa kutsuttavan funktion koodin. Tällaisia laskentasääntöjä käyttäviä attribuutteja ei koskaan invalidoida, koska ei ole mielekästä tarkkailla potentiaalisia funktioiden paluuarvojen muutoksia.