arvostelija Aspektiohjelmointi Juuso Hyvönen Helsinki Kandidaatintutkielma HELSINGIN YLIOPISTO Tietojenkäsittelytieteen laitos

Samankaltaiset tiedostot
arvostelija OSDA ja UDDI palveluhakemistoina.

Selainpelien pelimoottorit

Aspektiohjelmointiympäristöt

Sisällys. JAVA-OHJELMOINTI Osa 7: Abstrakti luokka ja rajapinta. Abstraktin luokan idea. Abstrakti luokka ja metodi. Esimerkki

15. Ohjelmoinnin tekniikkaa 15.1

11/20: Konepelti auki

1. Olio-ohjelmointi 1.1

Arkkitehtuurinen reflektio

Avoimet ohjelmistokehykset

15. Ohjelmoinnin tekniikkaa 15.1

5. HelloWorld-ohjelma 5.1

Concurrency - Rinnakkaisuus. Group: 9 Joni Laine Juho Vähätalo

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Pakkaukset ja määreet

Olio-ohjelmointi Javalla

ELM GROUP 04. Teemu Laakso Henrik Talarmo

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. X Poikkeusten käsittelystä

Common Lisp Object System

Aalto Yliopisto T Informaatioverkostot: Studio 1. Oliot ja luokat Javaohjelmoinnissa

Javan perusteita. Janne Käki

TIE PRINCIPLES OF PROGRAMMING LANGUAGES Eiffel-ohjelmointikieli

9. Periytyminen Javassa 9.1

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. II Johdanto olio-ohjelmointiin

12. Monimuotoisuus 12.1

5. HelloWorld-ohjelma 5.1

Sisällys. JAVA-OHJELMOINTI Osa 6: Periytyminen ja näkyvyys. Luokkahierarkia. Periytyminen (inheritance)

812341A Olio-ohjelmointi Peruskäsitteet jatkoa

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Rajapinnat ja sisäluokat

14. Poikkeukset 14.1

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

Ohjelmistoarkkitehtuurit Syksy 2009 TTY Ohjelmistotekniikka 1

Rajapinta (interface)

Olio-ohjelmointi Virhetilanteiden käsittely

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä. Tiedonkätkentä. Aksessorit. 4.2

812341A Olio-ohjelmointi, IX Olioiden välisistä yhteyksistä

Oliosuunnitteluesimerkki: Yrityksen palkanlaskentajärjestelmä

812341A Olio-ohjelmointi, I Johdanto

Java-API, rajapinnat, poikkeukset, UML,...

815338A Ohjelmointikielten periaatteet

Luokat ja oliot. Ville Sundberg

Aspektiohjelmointi ja hauraat liitoskohtamääritykset

JReleaser Yksikkötestaus ja JUnit. Mikko Mäkelä

14. Poikkeukset 14.1

SEPA REFAKTOROINTI Antti Ahvenlampi, 57408L Erik Hakala, 57509T

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

Test-Driven Development

Sisällys. Yleistä attribuuteista. Näkyvyys luokan sisällä ja ulkopuolelta. Attribuuttien arvojen käsittely aksessoreilla. 4.2

Tutoriaaliläsnäoloista

Yksikkötestaus. import org.junit.test; public class LaskinTest public void testlaskimenluonti() { Laskin laskin = new Laskin(); } }

TIE Principles of Programming Languages CEYLON

Aika/Datum Month and year Kesäkuu 2012

Rajapinnasta ei voida muodostaa olioita. Voidaan käyttää tunnuksen tyyppinä. Rajapinta on kuitenkin abstraktia luokkaa selvästi abstraktimpi tyyppi.

Sisällys. Metodien kuormittaminen. Luokkametodit ja -attribuutit. Rakentajat. Metodien ja muun luokan sisällön järjestäminen. 6.2

1.3 Lohkorakenne muodostetaan käyttämällä a) puolipistettä b) aaltosulkeita c) BEGIN ja END lausekkeita d) sisennystä

Pong-peli, vaihe Koordinaatistosta. Muilla kielillä: English Suomi. Tämä on Pong-pelin tutoriaalin osa 2/7. Tämän vaiheen aikana

Ohjelmointi 1. Kumppanit

Ohjelmointi 1 / syksy /20: IDE

Test-Driven Development

Ohjelmistojen mallintamisen ja tietokantojen perusteiden yhteys

Object Framework - One. OF-1 is a high-productive Multi-UI OpenEdge data driven development framework. Veli-Matti Korhonen

Java kahdessa tunnissa. Jyry Suvilehto

16. Javan omat luokat 16.1

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++?

1. Miten tehdään peliin toinen maila?

Liite 1: KualiKSB skenaariot ja PoC tulokset. 1. Palvelun kehittäjän näkökulma. KualiKSB. Sivu 1. Tilanne Vaatimus Ongelma jos vaatimus ei toteudu

812347A Olio-ohjelmointi, 2015 syksy 2. vsk. IX Suunnittelumallit Proxy, Factory Method, Prototype ja Singleton

Pong-peli, vaihe Aliohjelman tekeminen. Muilla kielillä: English Suomi. Tämä on Pong-pelin tutoriaalin osa 3/7. Tämän vaiheen aikana

Ohjelmoinnin peruskurssien laaja oppimäärä

4. Luokan testaus ja käyttö olion kautta 4.1

Ohjelmistojen mallintaminen, mallintaminen ja UML

Sisällys. 1. Omat operaatiot. Yleistä operaatioista. Yleistä operaatioista

1. Omat operaatiot 1.1

1.3Lohkorakenne muodostetaan käyttämällä a) puolipistettä b) aaltosulkeita c) BEGIN ja END lausekkeita d) sisennystä

Harjoitus Olkoon olemassa luokat Lintu ja Pelikaani seuraavasti:

Työn laji Arbetets art Level Aika Datum Month and year Sivumäärä Sidoantal Number of pages

812347A Olio-ohjelmointi, X Reflektiivisyys

1 Tehtävän kuvaus ja analysointi

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op. Poikkeukset ja tietovirrat: Virhetilanteiden ja syötevirtojen käsittely

12. Näppäimistöltä lukeminen 12.1

8/20: Luokat, oliot ja APIt

Ohjelmointi 2 / 2010 Välikoe / 26.3

Solidity älysopimus ohjelmointi. Sopimus suuntautunut ohjelmointi

Tutkittua tietoa. Tutkittua tietoa 1

Sisällys. 9. Periytyminen Javassa. Periytymismekanismi Java-kielessä. Periytymismekanismi Java-kielessä

Imperatiivisten ohjelmien organisointiparadigmojen. historia

Imperatiivisten ohjelmien organisointiparadigmojen historia

Sisällys. 12. Näppäimistöltä lukeminen. Yleistä. Yleistä

JavaRMI 1 JAVA RMI. Rinnakkaisohjelmoinnin projekti 1 osa C Tekijät: Taru Itäpelto-Hu Jaakko Nissi Mikko Ikävalko

P e d a c o d e ohjelmointikoulutus verkossa

Koht dialogia? Organisaation toimintaympäristön teemojen hallinta dynaamisessa julkisuudessa tarkastelussa toiminta sosiaalisessa mediassa

Pro gradu -tutkielma Meteorologia SUOMESSA ESIINTYVIEN LÄMPÖTILAN ÄÄRIARVOJEN MALLINTAMINEN YKSIDIMENSIOISILLA ILMAKEHÄMALLEILLA. Karoliina Ljungberg

4. Lausekielinen ohjelmointi 4.1

Ohjelmoinnin perusteet, syksy 2006

Rekursiolause. Laskennan teorian opintopiiri. Sebastian Björkqvist. 23. helmikuuta Tiivistelmä

Sisällys. 6. Metodit. Oliot viestivät metodeja kutsuen. Oliot viestivät metodeja kutsuen

Ohjelmointitaito (ict1td002, 12 op) Kevät Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen

7/20: Paketti kasassa ensimmäistä kertaa

Apuja ohjelmointiin» Yleisiä virheitä

Ohjelmoinnin perusteet Y Python

Sisällys. 11. Rajapinnat. Johdanto. Johdanto

Metodit. Metodien määrittely. Metodin parametrit ja paluuarvo. Metodien suorittaminen eli kutsuminen. Metodien kuormittaminen

Transkriptio:

hyväksymispäivä arvosana arvostelija Aspektiohjelmointi Juuso Hyvönen Helsinki 10.12.2012 Kandidaatintutkielma HELSINGIN YLIOPISTO Tietojenkäsittelytieteen laitos

HELSINGIN YLIOPISTO HELSINGFORS UNIVERSITET UNIVERSITY OF HELSINKI Tiedekunta Fakultet Faculty Laitos Institution Department Matemaattis-luonnontieteellinen tiedekunta Tekijä Författare Author Juuso Hyvönen Työn nimi Arbetets titel Title Tietojenkäsittelytieteen laitos Aspektiohjelmointi Oppiaine Läroämne Subject Tietojenkäsittelytiede Työn laji Arbetets art Level Aika Datum Month and year Sivumäärä Sidoantal Number of pages Kandidaatintutkielma 10.12.2012 23 sivua Tiivistelmä Referat Abstract Aspektiohjelmointi on ohjelmointiparadigma, joka pyrkii lisäämään ohjelmakoodin modulaarisuutta kapseloimalla läpileikkaavat ongelmat omiksi komponenteikseen. Läpileikkaavilla ongelmilla tarkoitetaan ohjelmointiongelmia, joiden ratkaiseminen perinteisillä ohjelmointiparadigmoilla on mahdotonta tai hyvin vaikeaa ilman toteutuksen hajoamista toisteisena järjestelmän eri komponentteihin. Läpileikkaavia ongelmia ovat esimerkiksi lokikirjoitus, transaktioiden hallinta sekä poikkeusten käsittely. ACM Computing Classification System (CCS): D.2.13 [Reusable Software]: Reuse models D.3.2 [Language Classifications]: Multiparadigm languages D.3.4 [Processors]: Compilers Avainsanat Nyckelord Keywords Aspektiohjelmointi, ohjelmointitekniikka, ohjelmointiparadigmat, AspectJ, kääntäjät Säilytyspaikka Förvaringsställe Where deposited Muita tietoja övriga uppgifter Additional information

Sisältö ii 1 Johdanto 1 2 Läpileikkaava ongelma 3 2.1 Ratkaisun modularisointi......................... 4 3 Aspektiohjelmointikieli 7 3.1 Määrällistäminen ja tietämättömyys.................. 7 3.2 AspectJ.................................. 9 4 Toteutustekniikat 11 4.1 Koodin generointi............................. 11 4.2 Suoritusaikainen punonta......................... 13 5 Hyödyt 14 5.1 Koodin laatu............................... 14 5.2 Koodin tehokkuus............................. 16 5.3 Ohjelmoijan tuottavuus......................... 17 6 Yhteenveto 19 Lähteet 21

1 Johdanto 1 Ohjelmointiongelma ratkaistaan tyypillisesti pilkkomalla ongelma pieniin aliongelmiin, jotka ratkaisemalla saadaan koottua ratkaisu varsinaiseen ongelmaan. Olioohjelmointi tuo perinteisen proseduraalisen ohjelmoinnin ja funktionaalisen ohjelmoinnin rinnalle uuden paradigman, jossa loogisesti samaan ongelmaan kuuluva koodi kirjoitetaan yhteen luokkaan, josta suoritusaikana luodaan ilmentymiä olioita [Pok89, s. 97]. Näin ongelmanratkaisun vastuujako saadaan suoritettua helposti hahmotettavalla tavalla, mikä lisää esimerkiksi ohjelman ylläpidettävyyttä. Jotkin ongelmat ovat kuitenkin luonteeltaan sellaisia, että niiden ratkaiseminen edellä mainituilla ohjelmointiparadigmoilla ei ole luontevaa. Kun ohjelmointiparadigma ei ole optimaalinen ongelman ratkaisuun, on mahdollista, että ongelman ratkaisu hajautuu toisteisena eri puolillle ohjelman lähdekoodia. Samalla koodista tulee helposti vaikealukuista ja huonosti ylläpidettävää [Kic97, s. 1-2]. Luokkaa ohjelmoidessaan ohjelmoija joutuu usein toteuttamaan luokkaan perustoiminnallisuuden lisäksi lokikirjaukset toteuttavan logiikan sekä tietoturvaominaisuuksia kuten käyttöoikeuksien tarkistamisen. Lisäksi esimerkiksi tietokantaa käyttäviin luokkiin joudutaan toteuttamaan transaktionhallintamekanismi. Näiden ominaisuuksien sisällyttäminen jokaiseen niitä tarvitsevaan luokkaan lisää ohjelman koodimäärää merkittävästi. On myös huomattava, että jos esimerkiksi tietoturvaratkaisuihin tulee muutoksia, on ympäri järjestelmää hajautetun tietoturvakoodin päivittäminen työlästä ja virhealtista. Edellisen kappaleen esimerkissä luokkaan mainittiin varsinaisen perusongelman ratkaisun lisäksi kolme toimintoa, jotka eivät varsinaisesti ole luokan toiminnan kannalta olennaisia tai joiden toteutusvastuun antaminen luokalle ei ole aivan yksiselitteistä. On hyvin todennäköistä, että nämä samat toiminnot joudutaan toteuttamaan suureen osaan järjestelmän komponentteja, jolloin syntyy huomattava määrä tois-

2 teista koodia. Tällaisia järjestelmän monia komponentteja koskettavia ongelmia kutsutaan luonteeltaan järjestelmää läpileikkaaviksi (Cross-cutting concern) [Kic97, s. 7]. Niitä on vaikea ratkaista hajauttamatta ratkaisun vaatimia koodijaksoja moniin järjestelmän komponentteihin. Ongelman ratkaisuista perinteisin menetelmin seuraa seuraavia ongelmia [Påh02, s. 5]: Koodin uudelleenkäytettävyys huononee, kun komponenteissa on ylimääräisiä järjestelmäspesifisiä yksityiskohtia. Ohjelmoijan tuottavuus laskee, kun ohjelmoidessa tulee kiinnittää huomiota perusongelman ulkopuolisiin yksityiskohtiin. Järjestelmän jatkokehitettävyys kärsii, kun uusien vaatimusten toteuttaminen vaatii eri puolilla järjestelmää tehtäviä muutoksia myös osiin, jotka eivät muuten olisi uuden vaatimuksen toteuttamisen kannalta olennaisia. Läpileikkaavien ongelmien ratkaisuksi on ehdotettu kokonaan uutta ohjelmointiparadigmaa, aspektiohjelmointia (Aspect-Oriented programming) [Kic97]. Aspektiohjelmointi tukee ajatusta haasteiden eriyttämisestä (Separation of concerns) [Dij82]. Sen ideana on lisätä ohjelman modulaarisuutta liittämällä läpileikkaavan ominaisuuden toteuttava komponentti ennalta määriteltyihin liitoskohtiin (Join point). Liitoskohtia voivat olla esimerkiksi metodin tai konstruktorin kutsu, olion alustus tai poikkeuskäsittelijän suoritus. Aiemmin esitellyt ongelmat voidaan ratkaista toteuttamalla kunkin ongelman ratkaisemiseksi oma, vain kyseisen ongelman ratkaisuun erikoistunut komponentti ja liittämällä se pääohjelmaan tekemällä erityinen liitoskohtamääritys (Pointcut). Liitoskohtamääritys sekä liitoskohdissa suoritettava komponentti, jota kutsutaan neuvoksi (Advice), muodostavat yhdessä aspektin (Aspect). Aspektit liitetään koodin erityisellä aspektipunojalla (Aspect weaver). Aspektipunoja liittää aspektit osaksi varsinaista kääntäjälle annettavaa ohjelmakoodia. Tämän jälkeen koodi voidaan kääntää kielen omalla kääntäjällä, minkä jälkeen ohjelma on valmis suoritettavaksi.

2 Läpileikkaava ongelma 3 Aspektiohjelmointi pyrkii helpottamaan ohjelmistokehitystä ratkaisemalla läpileikkaavien ongelmien aiheuttaman koodin pirstaloitumisen [Kic97, s. 9]. Läpileikkaavalla ongelmalla tarkoitetaan haastetta, jota ei voi perinteisillä ohjelmointiparadigmoilla eriyttää selvästi omaksi komponentikseen, vaan sen toteutus hajautuu toisteisena eri puolille ohjelman lähdekoodia. Luokkaan joudutaan usein toteuttamaan sen perustoiminnallisuuden lisäksi huomattavasti muutakin logiikkaa kuten metodikutsujen synkronointia, lokikirjausten pito tai esimerkiksi tietoturvaominaisuuksia [Påh02, s. 4]. Nämä ominaisuudet toteutetaan siis luokkaan tai vaihtoehtoisesti luokka kutsuu näitä ominaisuuksia toteuttavia komponentteja. Koodin on usein toisteista ja sitä syntyy huomattavia määriä, mikä tekee ohjelman rakenteesta sotkuista (Tangled code) [Kic97, s. 8]. Kuva 1 havainnollistaa läpileikkaavan ongelman hajautumista järjestelmän eri komponentteihin. Kuva 1. Läpileikkaavat ongelmat koskettavat useita järjestelmän komponentteja. Aspektiohjelmointi jakaa ohjelmointiongelmat kahteen kategoriaan [Kic97, s. 8]. Ominaisuus on peruskomponentti (Component), jos se on puhtaasti kapseloitavissa

4 yleisestetyksi toiminnallisuudeksi (Procedure). Toiminnallisuudella tarkoitetaan tässä esimerkiksi oliota, metodia, proseduuria tai API:a. Ominaisuus on aspekti, jos sitä ei voi puhtaasti kapseloida yleistetyksi proseduuriksi. Aspektit eivät tyypillisesti ole selkeitä järjestelmän yksittäisiä osia vaan ne ovat enemmänkin peruskomponenttien ominaisuuksia. Tämä kategorisointi tuo esiin aspektiohjelmoinnin tavoitteen. Järjestelmä voidaan abstrahoida selkeästi eri luonteisiksi osiksi, joista voidaan lopulta koota valmis järjestelmä. 2.1 Ratkaisun modularisointi Johdannossa annettiin esimerkkejä tyypillisistä läpileikkaavista ongelmista. Seuraavaksi esitellään yksinkertainen läpileikkaava ongelma ja sen ratkaisu esimerkkilistauksineen. Ohjelmistokehittäjä on kehittänyt pelin, jossa ohjataan ruudulla näkyviä esineitä. Jokainen ruudulla näkyvä esine toteuttaa MovableObject -rajapinnan, joka tarjoaa setterin x- ja y-koordinaateille. Jokaisen setterikutsun jälkeen näyttöluokkaa täytyy tiedottaa tapahtuneesta muutoksesta, joten setteri hoitaa myös tämän. Erilaisia liikuteltavia objekteja voi olla suuri määrä, mutta kaikissa näissä toistuu listauksessa 1 esitetty rakenne. public class Ship implements MovableObject { private int x; private int y;... @Override public void setxy(int x, int y) { this.x = x; this.y = y; Display.notify(); // Tiedota näyttöä muutoksesta } } Listaus 1. Luokka Ship toteuttaa rajapinnan MovableObject.

5 Tiedottamisesta syntyy ongelma, jos esimerkiksi pelin grafiikkakehys täytyy vaihtaa ja Display.notify() -kutsun sijaan joudutaan jatkossa tekemään jokin toinen rutiini. Tällöin kehittäjä joutuu toteuttamaan muutoksen jokaiseen MovableObject - rajapinnan toteuttavaan luokkaan, mikä on työlästä ja virhealtista. Aspektiohjelmointi mahdollistaa tiedotusongelman siirtämisen pois MovableObject - rajapinnasta ja vastuun antamisen kokonaan luokan ulkopuolelle. Aspektiohjelmoinnilla voidaan määritellä oma komponentti, aspekti, joka suoritetaan aina MovableObject - luokan ilmentymien setxy -metodin suorituksen jälkeen. Listauksessa 2 on esimerkki aspektista, joka ratkaisee tiedotusongelman. Listauksessa on toteutettuna aspekti, joka kutsuu näyttöluokan notify -metodia aina MovableObject -luokan ilmentymien setxy -metodin suorituksen jälkeen. Liitoskohtamäärityksen (Pointcut) kohta MovableObject+. sitoo neuvon suorituksen kaikkiin MovableObject -luokan aliluokkiin. Aspektin toteuttamisen jälkeen MovableObject -rajapinnan toteutuksista voidaan jättää kutsu Display.notify(); pois. public aspect MovableOperations { pointcut notifydisplay(): execution( * spacewar.model.movableobject+.setxy(..)); after() : notifydisplay() { Display.notify(); // Tiedota näyttöä muutoksesta } } Listaus 2. Aspekti, joka ratkaisee tiedotusongelman. Aspekti koostuu neuvosta ja siihen liittyvästä liitoskohtamäärityksestä. Neuvolla (Advice) tarkoitetaan varsinaista aspektin toteuttavaa komponenttia. Se on luonteeltaan tavallinen metodi ja voi kutsua muita komponentteja kuten mikä tahansa muukin metodi. Neuvoja voi olla eri tyyppisiä. Esimerkiksi suositussa aspektitoteutuksessa AspectJ:ssä [Asp05] neuvoja on viittä eri tyyppiä. Ne ovat before, after,

6 after returning, after throwing ja around. Before -tyyppinen neuvo suoritetaan ennen varsinaista peruskomponenttia. After suoritetaan peruskomponentin suorituksen päätyttyä. After return saa parametrinaan liitoskohdasta palautuneen paluuarvon, jolloin voidaan esimerkiksi kirjoittaa lokiin saatu laskentatulos. After throwing saa parametrinaan heitetyn poikkeuksen, jolloin voidaan hoitaa poikkeuksenkäsittelyä. Around -tyyppinen neuvo suoritetaan siten, että osa siitä suoritetaan ennen peruskomponenttia ja osa siitä suoritetaan komponentin suorituksen jälkeen. Aspektit liitetään muuhun ohjelmakoodiin liitoskohtamäärityksellä. Liitoskohtamääritys on joukko liitoskohtia (Join point), joissa aspekti liitetään ohjelmakoodiin (Kuva 2). Liitoskohta voi olla esimerkiksi jonkin metodin kutsuminen tai poikkeuksen heitto [Påh02, s. 8]. Liitoskohtamääritykseen käytetään siihen erityisesti kehitettyä kieltä ja kullakin aspektitoteutuksella voi olla oma liitoskohtakielensä. Jotkin toteutukset antavat ohjelmoijalle mahdollisuuden valita eri liitoskohtamäärityskielistä [Joh12, s. 233]. Kuva 2. Neuvot liitetään liitoskohtamäärityksen mukaisiin liitoskohtiin.

7 Aspektipunoja on ohjelma, joka suoritetaan ennen varsinaista ohjelman lähdekoodin kääntämistä. Se liittää ohjelmoijan määrittelemät neuvot näille määriteltyihin liittymäkohtiin. Aspektipunoja siis generoi ohjelmoijan tekemien liitoskohtamääritysten avulla sotkuista koodia, jota ohjelmoija olisi ohjelmoinut, jos ei olisi käyttänyt aspektiohjelmointia. Ohjelmoijan ei tarvitse nyt kuitenkaan nähdä tätä välivaihetta [Kic97, s. 13]. Modernit aspektitoteutukset pystyvät hoitamaan aspektien punomisen vasta luokan latauksen aikana (Load-time weaving) tai vasta ohjelman suorituksen aikana (Runtime weaving) [Ecl09]. 3 Aspektiohjelmointikieli Mikä tekee kielestä aspektikielen? Aspektiohjelmointi ei ole sidoksissa olio-ohjelmointiin, vaikka tunnetuimmat toteutukset kuten AspectJ [Ecl12], Spring AOP [Joh12, s. 198] ja PostSharp [Sha12] perustuvat kaikki oliokieliin. Kiczales et al. käyttivät ensimmäinen aspektiohjelmointia käsittelevässä artikkelissaan [Kic97, s. 4] osaan esimerkeistä Lispiä, joka on proseduraalinen kieli. Filmanin ja Friedmanin [Fil01, s. 8] mukaan olioparadigman tarjoama luokkahierarkia on vain miellyttävä ympäristö aspektiohjelmoinnille. 3.1 Määrällistäminen ja tietämättömyys Filmanin ja Friedmanin mukaan aspektiohjelmoinnille olennaista ovat termit määrällistäminen (Quantification) ja tietämättömyys (Obliviousness) [Fil01, s. 3]. Niillä voidaan osoittaa, onko kieli aspektikieli. Määrällistämisellä tarkoitetaan peruskomponenttien tarkkailua ja tutkimista sekä kannanottoa niiden toteutukseen [Fil01, s. 5]. Aspektiohjelmoijana siis tutkimme ensin kuinka peruskomponentti toimii ja tämän jälkeen teemme komponentin, joka jollain tapaa paikkaa mahdollisia perus-

8 komponentin puutteita. Tietämättömyydellä tarkoitetaan sitä, että perusohjelman ei tarvitse tietää, että sen toimintaan vaikutetaan aspektiohjelmoinnilla. Sama pätee ohjelmoijiin. Ohjelmoijien ei tarvitse tietää, että heidän luomansa ohjelman toimintaan tullaan vaikuttamaan aspektiohjelmoinnilla. Filmanin ja Friedmanin mukaan aspektiohjelmointi perustuu kykyyn tehdä määrällistettyjä kannanottoja tietämättömien ohjelmoijien luomista ohjelmista [Fil01, s. 4]. He haluavat, että voisimme sanoa Tämä koodi toteuttaa tämän haasteen (Concern). Suorita se, kun nämä ehdot pitävät. Voimme siis tehdä kannanottoja muotoa Ohjelmassa P, kun ehto C pitää, suorita tehtävä A. perinteisesti ohjelmoidusta ohjelmasta P [Fil01, s. 5]. Steimannin [Ste06, s. 484] mukaan äskeisessä määritelmässä näkyy AspectJ:n suuri vaikutus aspektiohjelmoinnin määritelmän kehittymiseen. Pari (C, A) voidaan nähdä aspektin määritelmänä. C on liitoskohtamääritys ja A tässä kohdassa suoritettava neuvo. P on ohjelman suoritus, joka sisältää neuvojen suorituksen. Määrällistämisen suorittaa AspectJ:n kääntäjä. Ohjelmaa voidaan määrällistää joko sen staattisen rakenteen perusteella tai dynaamisesti sen käyttäytymisen perusteella. Ohjelman staattinen määrällistys on sen ohjelmakoodi tai siitä jäsennelty abstrakti syntaksipuu [Fil01, s. 5]. Aspektijärjestelmät voivat olla staattiselta määrällistämiskyvyltään kahta eri luokkaa [Fil01, s. 5-6]. Ne voivat olla joko musta laatikko -järjestelmiä (Black-box) tai läpinäkyviä -järjestelmiä (Clear-box). Musta laatikko -järjestelmät eivät pysty tutkimaan peruskomponenttien sisältöä ja eivät siten voi muuttaa esimerkiksi näiden kenttiä. Ne ovat luonteeltaan kääreitä, jotka ympäröivät peruskomponenttia. Esimerkiksi metodikutsujen synkronointi on tällaiselle järjestelmälle sopiva ongelma, sillä synkronoinnissa tarkoituksena on ajoittaa komponentin suoritus oikea-

9 aikaiseksi. Synkronoinnin tapauksessa aspektin ei siis tarvitse varsinaisesti käsitellä peruskomponenttia, mutta aspekti hoitaa komponentin kutsumisen oikeaan aikaan. Läpinäkyvät järjestelmät kykenevät tarkastelemaan ja myös muuttamaan peruskomponenttien sisältöä. Niillä pystytään määrittelemään hyvin tarkkoja ehtoja ja muokkaamaan esimerkiksi ohjelman tulostusta, jos tietyt ehdot täyttyvät. Tällaiset tekniikat ovat omiaan esimerkiksi lokikirjoitukseen [Fil01, s. 6]. Dynaaminen määrällistäminen tapahtuu ohjelman suoritusaikana [Fil01, s. 6]. Siinä voidaan määritellä ehtoja, jotka voivat liittyä esimerkiksi poikkeusten heittoon, aliohjelmakutsuihin tai ohjelman käyttöhistoriaan. Dynaamisesti voidaan tarkistaa esimerkiksi funktion parametrien oikeellisuus tai toteuttaa tietoturvaominaisuuksia kuten tarkistaa käyttäjän oikeus suorittaa kutsuttu metodi. 3.2 AspectJ AspectJ [Ecl12] on suosittu Javaan perustuva aspektiohjelmointitoteutus. AspectJ sai alkunsa Xeroxin Palo Alton tutkimuskeskuksessa, josta myös aspektiohjelmointi on lähtöisin. AspectJ-projektissa on työskennellyt esimerkiksi aspektiohjelmoinnin lanseeranneen artikkelin [Kic97] kirjoittanutta tutkimusryhmää johtanut Gregor Kiczales. Vuonna 2003 AspectJ annettiin osaksi Eclipse-projektia, joka kehittää avoimen lähdekoodin ohjelmistokehistystyökaluja [Pal03]. Uusin versio AspectJ:stä on tekstin kirjoitushetkellä Java 1.7 -yhteensopiva AspectJ 1.7.1. AspectJ laajentaa Java-kieltä aspektin käsitteellä. Kaikki Java-ohjelmat ovat siis yhteensopivia AspectJ:n kanssa, mutta AspectJ:n laajennokset eivät käänny tavallisella Java-kääntäjällä. AspectJ käyttää omaa kääntäjäänsä, joka sisältää myös aspektipunojan [Ecl09]. Se tuottaa standardia Javan tavukoodia, joten AspectJ:llä toteutetut ohjelmat toimivat tavallisella Javan virtuaalikoneella. Aspekti määritellään AspectJ:ssä kuten mikä tahansa luokka, mutta sen luonnissa

10 käytetään termiä aspect termin class sijaan [Asp03]. Aspekti voi AspectJ:ssä sisältää liitoskohtia ja neuvoja. Se voi sisältää myös tyypinsisäisiä määrityksiä (Intertype declarations), joilla voidaan lisätä valmiisiin luokkiin kenttiä, metodeja sekä rajapintoja. Listauksessa 3 on esimerkki AspectJ:llä toteutetusta aspektista, joka tulostaa getauthor-luokan kutsun palauttaman kirjailijan nimen. Tätä tekniikkaa, jossa metodin paluuarvo kierrätetään aspektin läpi, voidaan käyttää esimerkiksi lokikirjoituksen toteuttamiseen. 1. public aspect LogAuthorName { 2. pointcut log() : execution( * fi.bachelor.fall.document.getauthor(..)); 3. after() returning (Author author): log() { 4. System.out.println("Author was: " + author.getname()); 5. } 6. } Listaus 3. AspectJ:llä toteutettu metodin getauthor suorituksen jälkeen suoritettava aspekti. Rivi 1 määrittelee aspektin nimen, joka on listauksessa LogAuthorName. Rivi 2 tekee liitoskohtamäärityksen. Aspekti liitetään paketin fi.bachelor.fall luokan Document metodin getauthor suoritukseen. Rivi 3 määrittelee after return -tyyppisen neuvon nimeltä log. After return - tyyppinen neuvo suoritetaan liitoskohdan suorittamisen jälkeen. Se saa parametrinaan liitoskohdassa määritellyn metodin paluuarvon. AspectJ tarjoaa monipuolisen syntaksin liitoskohtien määrittelemiseen [Asp03]. Listauksessa 3 käytettiin metodin suoritukseen kytkeytyvää liitoskohtaa. Muita liitoskohtatyyppejä ovat esimerkiksi poikkeuskäsittelijän suoritus, joka määritellään esimerkiksi: handler(arrayoutofboundsexception) sekä kohdeobjektin tyypin mukaan aktivoituva target(sometype). Liitoskohtamääritysten parametreissa voi-

11 daan käyttää tähtioperaattoria ("*"), joka hyväksyy kaikki arvot. Liitoskohtamääritys voidaan myös koostaa useasta liitoskohtatyypistä käyttäen operaattoreita OR (" "), AND ("&&") ja NOT ("!"), jolloin saadaan aikaan hyvin tarkkoja määrityksiä. 4 Toteutustekniikat Aspektiparadigma voidaan toteuttaa kahdella hyvin erilaisella tekniikalla [Don11]: Ensin esitelty tekniikka on Xeroxin Palo Alton tutkimuskeskuksessa kehitty tapa punoa aspektikoodi peruskomponenttien ympärille erillisellä aspektipunojalla joko käännösaikana tai vasta dynaamisesti ohjelman suoritusaikana [Kic97, s. 11-12]. Toinen tapa on polymorfismia hyväkseen käyttävät välitysluokat [Don11, s. 458]. 4.1 Koodin generointi Koodin generointiin perustuvassa menetelmässä määritellään ensin neuvot, minkä jälkeen ne liitetään koodiin erillisellä liitoskohtamäärityksellä. Liitoskohtamääritys tehdään erityisellä tarkoitusta varten kehitetyllä kielellä. Varsinainen aspektien punonta voidaan suorittaa kahdella tapaa: Vanhempi [Kic97, s. 12] tapa on punoa aspektit ohjelmakoodiin ennen kääntämistä ja luovuttaa kääntäjälle valmis lähdekooditiedosto, jossa aspektit ovat valmiiksi koodiin sidottuina, jolloin kääntäjän ei tarvitse erikseen osata käsitellä aspekteja. Tästä hieman pidemmälle viedyssä versiossa kääntäjä osaa hoitaa sekä aspektien punomisen, että koodin kääntämisen. Näin toimii esimerkiksi jo aiemmin esitelty AspectJ [Ecl09]. AspectJ liittää ensin aspektit varsinaiseen ohjelmakoodiin, minkä jälkeen se kääntää koodin Javan tavukoodiksi. Toinen tapa on punoa aspektit ohjelmaan, on liittää ne vasta suoritusaikana käyttäen hyväksi dynaamisesti tavukoodia generoivaa kirjastoa kuten CGLIB (Code Ge-

12 neration Library) [Cod12]. CGLIB mahdollistaa ohjelman suoritusaikana luokkien luonnin dynaamisesti sekä jo olemassaolevien luokkien muokkaamisen. Tätä tekniikkaa (ja kirjastoa) käyttävät hyväkseen monet suositut ohjelmakehykset kuten Hibernate [Hib12] ja Spring [Joh12, s. 199]. Seuraavassa listauksessa esitetään AspectJ:n vaihtoehtoisella @AspectJ-syntaksilla [Asp05] toteutettu, aiemman listauksessa 3 AspectJ:n standardisyntaksilla toteutetun aspektin kanssa toiminnaltaan identtinen aspekti. Erona listaukseen 2 on se, että nyt aspektin määrittelyyn on käytetty AspectJ:n tarjoamia kääntäjälle tarkoitettuja kommentteja. Tämä tuo selvästi ilmi sen, kuinka aspektit ovat luonteeltaan tavallisia luokkia, jotka aspektipunoja sitoo muuhun ohjelmaan. @Aspect public class LogAuthorName { @AfterReturning(pointcut="execution( * fi.bachelor.fall.document.getauthor(..))", returning= author ) public void log(author author) { System.out.println("Author was: " + author.getname()); } } Listaus 4. Yksinkertainen aspekti toteutettuna AspectJ:n @Aspect-syntaksilla. Aspektiluokka on kommentoitu @Aspect ja neuvo on määritelty kommentilla @AfterReturning, joka saa parametrinaan liitoskohtamäärityksen. Esimerkissä liitämme luokan LogAuthorName metodin log kutsun edeltämään pakkauksessa fi.bachelor.fall olevan luokan Document metodin getauthor kutsua. @ - alkuiset kommentit ovat kääntäjälle tarkoitettua tietoa, minkä avulla se kykenee punomaan aspektit osaksi varsinaista tavukoodia.

13 4.2 Suoritusaikainen punonta Suoritusaikainen punonta perustuu dynaamisten välitysluokkien (dynamic proxies) käyttöön [Don11, s. 458]. Välitysluokkia käyttävä strategia perustuu Javan tapauksessa reflektioon. Reflektiolla tarkoitetaan ohjelman rakenteen tarkastelua sekä muuttamista ohjelman suoritusaikana [Ora12]. Tehdas-suunnittelumallia mukaileva välitysluokkatehdas voidaan toteuttaa seuraavasti [Don11, s. 458]: Luodaan staattinen välistysluokkatehdas. Tehdas-luokan ei tarvitse toteuttaa mitään erityistä rajapintaa. Tehtaan välitysluokan luonnista vastaavalle metodille annetaan parametreina sopivan rajapinnan tarjoavat before - ja after -neuvot sekä peruskomponentin toteuttava olio. Tehtaalta saadaan paluuarvona Object -muotoinen olio, joka voidaan pakottaa sopivan tyyppiseksi (Cast). Tämän jälkeen peruskomponentin suorittavaa metodia voidaan kutsua välitysluokan kautta. Kutsu suorittaa nyt kuitenkin ensin before -neuvon, ja vasta tämän jälkeen suoritetaan peruskomponentti, eli alkuperäinen kutsuttu metodi. Tämän jälkeen suoritetaan vielä after -neuvo. Tehtaan toteutuksesta on esimerkki listauksessa 5. Listaus on hyvin vaikeaselkoinen ja sen ymmärtäminen ei ole välttämätöntä. public class AopProxy { public static Object createproxy(final Object obj, final BeforeAdvice beforeadvice, final AfterAdvice afteradvice) { return Proxy.newProxyInstance( obj.getclass().getclassloader(), obj.getclass().getinterfaces(), new InvocationHandler() { public Object invoke(object proxy, Method method, Object[] args) throws Throwable { beforeadvice.before(); Object object = method.invoke(obj, args); afteradvice.after();

14 } } }); return object; } Listaus 5 [Don11, s. 458]. Dynaamisten välitysluokkien kirjoittaminen on hyvin sotkuista. Tällä tekniikalla aspektiohjelmointi on mahdollista toteuttaa täysin Javan standardikirjastolla ilman erillistä aspektipunojaa. Tekniikka on kuitenkin ohjelmoijalle hidas ja vaikeasti hahmotettava, kuten listauksesta 5 voi todeta, joten suoritusaikainen punonta tehdään käytännössä ohjelmistokehyksen tarjoamien palveluiden avulla. Esimerkiksi yrityssovelluksissa paljon käytetyssä Spring-sovelluskehyksessä on oma suoritusaikaiseen punontaan perustuva aspektiohjelmointitoteutus [Joh12, s. 235]. 5 Hyödyt Ohjelmiston laatua voidaan mitata esimerkiksi arvioimalla sen tehokkuutta, monimutkaisuutta, ymmärrettävyyttä, uudelleenkäytettävyyttä, testattavuutta ja ylläpidettävyyttä [Ros97, s. 1-2]. Aspektiohjelmointi pyrkii parantamaan ohjelmiston laatua modularisoimalla läpileikkaavat ongelmat omiksi komponenteikseen. Tämä voi esimerkiksi vähentää tarvittavaa koodimäärää [Lip00], tehostaa laskentaa [Kic97] ja lisätä ohjelmoijan tuottavuutta [Han09]. 5.1 Koodin laatu Monet ohjelmointikielet tarjoavat jonkinlaisen rakenteen poikkeusten käsittelyyn. Poikkeuskäsittely tuottaa kuitenkin huomattavia määriä komponentin perusongel-

15 man kannalta toissijaista koodia. Poikkeuskäsittely tuottaa myös huomattavia määriä toisteista koodia, kun samaa poikkeusta joudutaan käsittelemään useassa järjestelmän komponentissa. Aspektiohjelmoinnilla tämä voidaan välttää ympäröimällä poikkeuksia heittävä komponentti poikkeuskäsittelyyn erikoistuneilla neuvoilla. Lippert ja Lopes tutkivat aspektiohjelmoinnin käyttöä poikkeuskäsittelyyn [Lip00]. He kirjoittivat JWAM-nimisen interaktiivisiin yrityssovelluksiin (interactive business applications) tarkoitetun sovelluskehyksen [Bre99] uusiksi käyttäen AspectJ:tä ja saavuttivat huomattavia parannuksia koodin laatuun [Lip00, s. 424]. Alkuperäisessä JWAM-kehyksen versiossa, joka ei käyttänyt aspektiohjelmointia, poikkeusten havaitsemiseen käytettiin 2120 riviä esiehtoja ja 666 riviä jälkiehtoja. Lisäksi poikkeuksien hoitamiseen käytettiin 414 catch-lausetta (2070 koodiriviä). Yhteensä poikkeuskäsittelyyn käytettiin 10,9% koodista. Identtisen toiminnallisuuden tarjoavassa AspectJ:tä käyttävässä versiossa esiehtoja käsitteli 660 riviä koodia ja jälkiehtoja 300 riviä koodia. Catch-lauseita oli vain 31 kappaletta (200 koodiriviä). Yhteensä poikkeuskäsittelyä oli vain 2,9% ohjelmakoodista. Gregor Kiczales et al., tutkivat aspektiohjelmoinnin esitelleessä artikkelissaan aspektiohjelmoinnin hyötyjä käyttäen tutkimuksessaan kuvankäsittelyohjelmaa, jossa kuva kulkee läpi erilaisten suodattimien [Kic97, s. 4]. Optimoimaton versio ohjelmasta oli kooltaan 768 riviä. Optimoimattoman version suorituskyky oli kuitenkin huomattavan hidas verrattuna siihen, mitä saataisiin, jos suodatinketjuja optimoitaisiin käsin. Käsin optimoidussa versiossa rivejä oli 35213. Aspekteilla pyrittiin tässä tutkimuksessa hoitamaan suodattimien optimointi. Se onnistui huomattavan hyvin, sillä aspekteilla toteutetussa versiossa rivejä oli enää 1039 ja suorituskyky oli verrattavissa käsin optimoituun versioon ollen yli 100 kertaa nopeampi kuin optimoimaton versio [Kic97, s. 13]. Koodirivien määrää ei voi pitää yksiselitteisenä ohjelmiston laadun mittarina. Lippert ja Lopes saivat kuitenkin tuloksia myös aspektiohjelmoinnin ohjelmiston laatua

16 parantavista mahdollisuuksista [Lip00, s. 424]. Spagettikoodin määrää saatiin karsittua huomattavasti, kun ohjelman perustoiminnallisuus oli kuvattu omissa komponenteissaan ja virheenkäsittely omissaan. Ohjelmiston tuki eri konfiguraatioille parani [Lip00, s. 425]. Vasta käännösaikana tapahtuva aspektien liittäminen ohjelmistoon antoi mahdollisuuden määritellä vaihtoehtoisia tapoja hoitaa poikkeukset esimerkiksi ohjelmiston kehitysvaiheen mukaan. Tuki järjestelmän vaatimusmuutoksille parani myös huomattavasti. Kun yksi poikkeustyyppi on käsitelty vain yhdessä komponentissa, voidaan koko järjestelmää koskeva muutos hoitaa yhdessä paikassa. Ilman aspekteja poikkeuskäsittelyn muutos voitaisiin huonossa tapauksessa joutua toteuttamaan jopa satoihin eri komponentteihin. Aspektit osaltaan helpottavat ohjelmistokehitystä sillä ne mahdollistavat esimerkiksi geneerisen virheenkäsittelyn, jolloin peruskomponenttien kehityksen aikana voidaan käyttää yleiskäyttöisiä virheenkäsittelykomponentteja, jotka voidaan myöhemmin korvata paremmin virhetyypille soveltuvilla [Lip00, s. 425]. Tällöin voidaan keskittyä varsinaisen perustoiminnallisuuden nopeaan prototyyppitestaamiseen. Lisäksi ohjelmistokomponenttien uudelleenkäytettävyys paranee, kun kerran toteutettu aspekti voidaan kytkeä moniin eri ohjelmistoihin. 5.2 Koodin tehokkuus Kuten jo edellisessä kappaleessa mainitussa kuvankäsittelyohjelman tutkimuksessa [Kic97] todettiin, on aspektiohjelmoinnilla mahdollista saavuttaa huomattavia hyötyjä optimoimalla koodia ennen sen antamista kääntäjälle. Tällainen optimointi hidastaa ohjelman kääntämistä, sillä aspektit tulee punoa ohjelmaan ennen sen luovuttamista kääntäjälle. Koodia optimoivien aspektien käyttö kuitenkin nopeuttaa ohjelman suoritusta merkittävästi [Kic97, s. 13]. Aspektiohjelmoinnin käytöllä voi olla suuria vaikutuksia ohjelman suorituskykyyn ja ohjelmoijan tulee ymmärtää

17 kuinka hänen käyttämänsä aspektitoteutus toimii, jotta hän voisi käyttää sitä tehokkaasti. Aspektien punonta voi tapahtua myös dynaamisesti ohjelman suorituksen aikana. AspectWerkz-projekti [Bon05], joka työsti [Pal03] omaa aspektiohjelmointitoteutustaan, testasi eri aspektiohjelmointitoteutusten suorituskykyä [Asp04]. Mittauksissa havaittiin, että ennen käännöstä tapahtuvaan punontaan perustuvat ratkaisut eivät juurikaan hidasta ohjelman suoritusta; metodin kutsumiseen kuluva aika nousi testijärjestelmässä viidestä nanosekunnista kymmeneen nanosekuntiin. Tällä ei juuri ole vaikutusta ohjelman suorituskykyyn, jollei aspektillisia metodeja kutsuta huomattavan tiheään. Dynaamiset toteutukset olivat huomattavasti hitaampia. Springin aspektitoteutuksella metodin kutsumiseen kului 390 nanosekuntia ja JBossin toteutuksella [Jbo12] 220 nanosekuntia. Tällainen viive saattaa vaikuttaa jo huomattavasti ohjelman suorituskykyyn. Dynaamiset toteutukset testattiin suorittamalla niitä ilman optimointeja. Dynaamiset toteutukset ovat kuitenkin käyttäjän optimoitavissa, jolloin voitaisiin saavuttaa parempia tuloksia. Esimerkiksi Spring tarjoaa mahdollisuuden estää neuvojen muokkaaminen ohjelman suoritusaikana [Joh12, s. 266]. Tämä vähentää metodin kutsumiseen tarvittavaa logiikkaa ja nopeuttaa näin kutsua. Aspektiohjelmoinnin käytöllä näyttäisi siis voivan olla suuria vaikutuksia ohjelman suorituskykyyn. Ohjelmoijan tulee ymmärtää kuinka hänen käyttämänsä aspektitoteutus toimii, jotta hän voisi käyttää sitä tehokkaasti. 5.3 Ohjelmoijan tuottavuus Hanenberg, Kleinschmager ja Josupeit-Walter tutkivat aspektiohjelmoinnin vaikutusta ohjelmoijan tuottavuuteen [Han09]. He opettivat ohjelmoijille aspektiohjelmointia ja mittasivat tämän jälkeen kuinka nopeasti ohjelmoija ratkaisee ongelman aspektiohjelmoinnilla käyttäen AspectJ:tä verrattuna olio-ohjelmointiin Javalla. He

18 havaitsivat, että aspektilla on oltava vähintään 36 liitoskohtaa, jotta läpileikkaavien ongelmien erottaminen aspekteina peruskomponenteista olisi tuottavampaa kuin perinteisen olio-ohjelmoinnin käyttäminen [Han09, s. 166]. Aspektiohjelmointi ei siis välttämättä sovellu kovin pieniin projekteihin, sillä tuottavuushyötyä saavutetaan vasta, kun saman läpileikkaavan ongelman kohtaa suurehko määrä komponentteja. Testiin osallistuneet ohjelmoijat olivat kuitenkin saaneet vain 1,5 tunnin opetuksen aspektiohjelmointiin, joten on mahdollista, että todellinen tuottavuus aspektiohjelmoinnin hyvin sisäistäneellä ohjelmoijalla olisi parempi. Walker et al. [Wal99] puolestaan tutkivat ohjelmoijan kykyä ylläpitää AspectJ:llä tuotettua koodia. He käyttivät tutkimuksessa hajautettua kirjastojärjestelmää [Wal99, s. 122]. Tutkijat havaitsivat, että ohjelmoijan on helppo löytää virheitä aspektikoodista, jos läpileikkaava ongelma on tarpeeksi selkeä. Kuitenkin vain yhdessä kolmesta synkronointiin liittyvistä ongelmista ratkaisuaika oli AspectJ:tä käyttäen huomattavasti nopeampi kuin puhtaalla Javalla [Wal99, s. 124]. Ohjelman jatkokehitystä mittaavissa testeissä AspectJ-koodin kehitettävyyttä verrattiin Emerald-kielisen koodin kehitettävyyteen [Wal99, s. 122]. Emerald valittiin vertailukieleksi, koska siinä on sisäänrakennettuna tuki hajautetulle ja synkronoidulle ohjelmoinnille. Aspektiohjelmoijat olivat kaikissa testeissä hieman Emeraldohjelmoijia hitaampia [Wal99, s. 126]. Tutkimuksessa havaittiin, että aspektiohjelmointi on nopeaa ja tuottavaa, jos aspektin ja peruskomponentin välinen rajapinta on tarpeeksi selkeä [Wal99, s. 126]. Esimerkiksi yksinkertainen metodikutsujen synkronointi onnistuu hyvin aspekteilla, sillä tällöin peruskomponentissa ei tarvitse tehdä minkäänlaisia olettamuksia aspekteista. Ongelmia syntyy, kun esimerkiksi ohjelman suoritusnopeutta pyritään optimoimaan luomalla aspekti, joka jollain tapaa vaikuttaa peruskomponentille saapuvan tiedon muotoon. Tällöin peruskomponentti joutuu tekemään perustoiminnalli-

19 suuden kannalta ylimääräisiä oletuksia saamansa tiedon laadusta, mikä lisää komponentin ohjelmoinnin haastavuutta. Tällöin myös osaltaan rikkoutuu Filmanin ja Friedmanin [Fil01, s. 3] määritelmä, jonka mukaan aspektiohjelmoinnissa on kyse määrällistettyjen kannanottojen tekemisestä tietämättömistä komponenteista. 6 Yhteenveto Aspektiohjelmointi pyrkii ratkaisemaan läpileikkaavat ongelmat eriyttämällä kunkin läpileikkaavan ongelman ratkaisun omaksi komponentikseen. Läpileikkaavia ongelmia ovat ongelmat, joiden toteutus hajautuu helposti toisteisena järjestelmän eri komponentteihin. Tällaisia ongelmia ovat esimerkiksi monet tietoturvaominaisuudet, lokikirjausten teko sekä transaktioiden hallinta. Aspektit, koostuvat neuvosta, jolla tarkoitetaan varsinaista ongelman toteuttavaa koodia sekä liitoskohtamäärityksestä, jonka avulla määritellään aspektien liitospisteet muuhun ohjelmakoodiin. Aspektit liitetään usein koodiin erityisellä aspektipunojalla. Aspektien punonta voi tapahtua jo ennen koodin kääntämistä tai vasta dynaamisesti ohjelman suoritusaikana. Aspektiparadigman mukaista koodia on mahdollista toteuttaa myös ilman erillistä aspektipunojaa käyttämällä välitysluokkia. Aspektiohjelmoinnin tuoma koodin modulaarisuus parantaa koodin laatua. Se vähentää huomattavasti esimerkiksi poikkeuskäsittelyyn tarvitta vaa koodimäärää. Aspektiohjelmointi ei ole aina tehokas tapa ratkaista ongelmaa, sillä läpileikkaavan ongelman löytäminen ja sen modularisointi yleiskäyttöiseksi komponentiksi voi olla haastavaa. Koodin ylläpidettävyyden parantumisesta ei ole konkreettisia todisteita ja aspektiohjelmoinnilla toteutetun ohjelmiston ylläpito oli joissain tapauksissa jopa hitaampaa kuin aspektittoman ohjelmiston. On huomattava, että aspektiohjelmointi ei poista tarvetta ratkaista läpileikkaavia

20 ongelmia. Se antaa vain työkalun läpileikkaavien ongelmien modularisointiin. Aspektiohjelmointi ei myöskään syrjäytä olio-ohjelmointia tai muita ohjelmointiparadigmoja. Se on luonteeltaan enemmänkin laajennos nykyisiin ohjelmointiparadigmoihin.

Lähteet 21 Asp03 AspectJ Team, the, The aspectj programming guide, chapter 2. the aspectj language, 2003. http: //eclipse.org/aspectj/doc/released/progguide/language.html. [10.12.2012] Asp05 AspectJ Team, the, Pointcuts and advice, 2005. http://www.eclipse.org/aspectj/doc/next/adk15notebook/. [8.12.2012] Asp04 AspectWerkz ja Vasseur, A., Aop benchmark, 2004. http://docs.codehaus.org/display/aw/aop+benchmark. [8.12.2012] Bre99 Breitling, W., Lilienthal, C., Lippert, M. ja Züllighoven, H., The jwam framework: Inspired by research, reality-tested by commercial utilization. Proceedings of OOPSLA 2000 Workshop: Methods and Tools for Object-Oriented Framework Development and Specialization, 1999. Bon05 Bonér, J. ja Vasseur, A., Aspectwerkz - plain java aop, 2005. http://aspectwerkz.codehaus.org/. [8.12.2012] Cod12 Dij82 Don11 Code generation library, 2012. http://cglib.sourceforge.net/. [8.12.2012] Dijkstra, E. W., On the role of scientific thought. Selected writings on Computing: A Personal Perspective. Springer-Verlag, 1982, sivut 60 66. Dong, Z., Aspect oriented programming technology and the strategy of its implementation. International Conference on Intelligence Science and Information Engineering. IEEE, 2011, sivut 457 460. Ecl09 Eclipse Foundation, the, Understanding aspectj technology, 2009. http: //www.eclipse.org/aspectj/doc/released/faq.php#technology. [8.12.2012]

22 Ecl12 Eclipse Foundation, the, Aspectj project, the, 2012. http://www.eclipse.org/aspectj/. [8.12.2012] Fil01 Hib12 Han09 Filman, R. ja Friedman, D., Aspect-oriented programming is quantification and obliviousness. RIACS Technical Report 01.12. IEEE, 2001. Hibernate - jboss community, 2012. http://www.hibernate.org/. [8.12.2012] Hanenberg, S., Kleinschmager, S. ja Josupeit-Walter, M., Does aspect-oriented programming increase the development speed for crosscutting code? an empirical study. Third International Symposium on Empirical Software Engineering and Measurement. IEEE, 2009, sivut 156 167. Jbo12 Jboss aop, 2012. http://www.jboss.org/jbossaop. [10.12.2012] Joh12 Johnson, R. et al., Spring framework reference documentation, 2012. http://static.springsource.org/spring/docs/3.1.3.release/ spring-framework-reference/pdf/spring-framework-reference. pdf. [8.12.2012] Kic97 Lip00 Kiczales, G., Lamping, J., Mendhekar, A., Maeda, C., Lopes, C., Loingtier, J.-M. ja Irwing, J., Aspect-oriented programming. Proceedings of the European Conference on Object-Oriented Programming, ECOOP 97. Springer-Verlag, 1997, sivut 220 242. Lippert, M. ja Videira, L., A study on exception detection and handling using aspect-oriented programming. Proceedings of the 22nd international conference on Software engineering. ACM, 2000, sivut 418 427. Ora12 Oracle, The java tutorials, trail: The reflection api, 2012. http://docs.oracle.com/javase/tutorial/reflect/index.html. [8.12.2012] Pal03 Palo Alto Research Center Incorporated, Palo alto research center and eclipse announce release of aspectj to the open source community, 2003. http://www.parc.com/news-release/27. [8.12.2012]

23 Pok89 Påh02 Ros97 Sha12 Ste06 Wal99 Pokkonuri, B. P., Object oriented programming. ACM SIGPLAN Notices Volume 24 Issue 11, Nov. 1989. ACM, 1989, sivut 96 101. Påhlsson, N., An introduction to aspect-oriented programming and aspectj. Topic Report for Software Engineering, 2002. Rosenberg, L. ja Hyatt, L., Software quality metrics for object-oriented environments. Crosstalk Journal, 1997. SharpCrafters, Postsharp, 2012. http://www.sharpcrafters.com/. [8.12.2012] Steimann, F., The paradoxical success of aspect-oriented programming. OOPSLA 06 Proceedings of the 21st annual ACM SIGPLAN conference on Object-oriented programming systems, languages, and applications. ACM, 2006, sivut 481 497. Walker, R., Baniassad, E. ja Murphy, G., An initial assessment of aspect-oriented programming. Proceedings of the 1999 International Conference on Software Engineering. ACM, 1999, sivut 120 130.