Ohjelmistoarkkitehtuurit kehysarkkitehtuurit Kevät 2014 Samuel Lahtinen (Johannes Koskinen) http://www.cs.tut.fi/~ohar/ 1
Yleistä Arkkitehtuuriarvioinneista Vierailuluentojen korvaava tehtävä löytyy kotisivuilta Muunneltavuudesta ja myöhäisestä asioiden kiinnittämisestä: Peruspäätökset jne. heti, jotain jonka päälle rakentaa Variaatiopisteet, auki jätettävät asiat: määritellään tarkasti, mietitään miten asiat voivat varioitua Sitomisesta: määrittely ajoaikaisuus, vaatii kuitenkin päätöksiä arkkitehtuurissa!= ei olla otettu mitään kantaa 2
12. Kehysarkkitehtuurit Johdanto Kehystyypit Kehysten osittaminen Kehykset ja suunnittelumallit Kehysten etuja ja ongelmia Yhteenvetoa 3
Mikä on (ohjelmisto)kehys? Ohjelmistokehys on olioparadigman tapa toteuttaa tuotealusta. Kehys muodostuu kokoelmasta luokkia, jotka toteuttavat tuoteperheen yhteisen arkkitehtuurin ja toiminnallisuuden. Kehys erikoistetaan tuotteeksi. 4
Kehys erikoistetaan toimivaksi tuotteeksi Kehys Sovelluskohtainen koodi kontrolli Erikoistamisrajapinta 5
Sovelluskehys vs. perinteinen ohjelmakirjasto: Hollywoodperiaate Aliluokkia, komponentteja Sovelluskohtainen Sovellus Uudelleenkäytettävä Sovelluskehys Aliohjelmia, luokkia, moduuleita Hollywood-periaate: Älä soita meille, me soitetaan teille 6
Missä ohjelmistokehyksiä käytetään/mitä ohjelmistokehyksiä tunnet? 7
Erikoistamistekniikat kehyksissä rajapinnan toteutus (~takaisinkutsu) periytyminen (~takaisinkutsu) olioiden/komponenttien luonti, alustus ja konfigurointi geneeristen luokkien (template) instantiointi refleksiivisyys 8
Kehystyypit Erikoistamisen tulos Sovelluskehys: erikoistamisen tulos on sovellus Komponenttikehys (framelet): erikoistamisen tulos on komponentti Hierarkkinen kehys: erikoistamisen tulos on uusi kehys Erikoistamismekanismi Muunneltava kehys: erikoistaminen tehdään lähinnä periytymisellä (ja metodin ylimäärittelyllä) Koottava kehys: erikoistaminen tehdään lähinnä instantioinnilla (+ parametroinnilla) ja alustuskonfiguroinnilla Plugin-kehys: erikoistaminen tehdään lähinnä rajapintojen toteutuksella 9
Muunneltavat kehykset A B 10
Koottavat kehykset A <<create>> B 11
Plugin-kehykset rajapintoja komponentteja 12
Kehysten osittaminen Käsitemallipohjainen lähestymistapa Komponenttipohjainen lähestymistapa Kerrostaminen: hierarkkiset kehykset 13
Käsitemallipohjainen lähestymistapa OO-arkkitehtuurityyli : 1. Tee sovellusalueen käsitemalli 2. Hae ja lisää käsitemalliin yleistykset (kantaluokat) 3. Muunna käsitemalli luokkamalliksi, lisää oletustoteutukset, rajapinnat 4. Tunnista variaatiopisteet luokkamallista 5. Suunnittele variaatiopisteiden toteutus (esim. suunnittelumalleja soveltamalla) 14
Esimerkki: Simulointikehys 15
<<framework>> SimulationFW Muunneltava kehys <<interface>> Creature setmyworld(world) show() getx(): int gety(): int move() interact(creature) growold() die() * World getsize(): int add(creature) remove(creature) show() simulate(int, CreatureFactory) <<interface>> CreatureFactory 1 createcreature(): Creature DefaultCreature <<create>> DefaultCreatureFactory xcoord ycoord age setmyworld(world)... die() <<create>> createcreature(): Creature EatingCreature energy interact(creature) SimulationApp main() <<create>> <<create>> EatingCreatureFactory createcreature(): Creature 16
<<framework>> SimulationFW Koottava kehys <<interface>> Creature setmyworld(world) show() getx(): int gety(): int move() interact(creature) growold() die() * World getsize(): int add(creature) remove(creature) show() simulate(int,creaturefactory) <<create>> <<interface>> CreatureFactory 1 createcreature(): Creature DefaultCreatureFactory DefaultCreature xcoord ycoord age setmyworld(world)... die() EatingCreature energy interact(creature) <<create>> <<create>> createcreature(): Creature EatingCreatureFactory createcreature(): Creature SimulationApp <<create>> main() 17
<<framework>> SimulationFW <<interface>> Creature setmyworld(world) show() getx(): int gety(): int move() interact(creature) growold() die() * Plug-in kehys World getsize(): int add(creature) remove(creature) show() simulate(int,creaturefactory) 1 PluginLoader <<interface>> CreatureFactory createcreature(): Creature load() <<load>> <<plugin>> EatingApplication EatingCreature SimulationApp EatingCreatureFactory energy interact(creature) main() createcreature(): Creature <<create>> 18
Komponenttipohjainen lähestymistapa: Monoliittiset kehykset vs. frameletit Monoliittinen kehys Sovellus Kehys Framelet Framelet Komponentti Komponentti Erikoistus Erikoistus Erikoistus 19
Hierarkkinen kehys 20
Hierarkkinen kehys: yleinen simulointikehys Punamuurahaisten simulointisovellus Muurahaisten simulointikehys Hyönteisten simulointikehys Eläinpopulaatioiden simulointikehys Yleinen simulointikehys 21
Hierarkkinen kehys: esimerkkikehys EatingCraeture, EatingCreatureFactory, SimulationApp DefaultCreature, DefaultCreatureFactory World, Creature 22
Hierarkkinen kehys: liiketoimintakehys Varastonhallintasovellus Varastonhallintasovelluskehys Spring 23
Strategy Game Framework http://lurgee.net 24
Cont. 25
Esimerkkejä kehyksistä Javascript-kehykset, vähemmän erikoistamista, enemmän omien instanssien luomista ja kehyksen tarjoamiin palveluihin luottamista http://en.wikipedia.org/wiki/comparison_of_javascript_frameworks Verkkokehykset (web app frameworks), Struts, Django, Ruby on rails, Vaadin Pelit, pelimoottorit, fysiikka, jne. GUI-kehykset: Qt, Eclipse 26
Kysyttävää?
Kehykset ja suunnittelumallit Suunnittelumalleilla (GoF) voidaan lisätä järjestelmän joustavuutta sekä tavallisissa sovelluksissa (ylläpidettävyys, siirrettävyys) että kehyksissä (uudelleenkäytettävyys) Hyvin suunniteltu oliosovellus voidaan ymmärtää usein (implisiittisen) kehyksen erikoistuksena. 28
Suunnittelumallit kehyksen erikoistamisrajapintana Sovelluskohtainen koodi Kehys Suunnittelumallin ilmentymä 29
Suunnittelumallit ja kehykset Graphicaltem draw * children Kuuluu kehykseen Rectangle Circle FigGroup draw draw draw for all children c: c.draw; 30
Tyypillisiä kehyksissä käytettyjä GoF-suunnittelumalleja Operaatiorunko (Template Method) Strategia (Strategy) Kuorruttaja (Decorator) Tehtaat (Abstract Factory, Factory Method) Tarkkailija (Observer)... 31
Operaatiorunko (Template Method) Ongelma: Metodin sovelluskohtainen staattinen variointi 32
Kehyksessä Kehys Creature draw() move(dx, dy) setcolor(backgr) draw() x = x + dx y = y + dy setcolor(color) draw() Sovellus MyCreature draw() piirretään oma eliö 33
Strategia (Strategy) Ongelma: Metodin dynaaminen sovelluskohtainen variointi (isäntäolion olemassaolon aikana) 34
Kehyksessä Kehys setcolor(backgr) drawer.draw() x = x + dx y = y + dy setcolor(color) drawer.draw() Creature setdrawer(drawer) move(dx, dy) Drawer draw Sovellus dd = new DeadDrawer(); c.setdrawer(dd); piirretään oma eliö elävänä AliveDrawer draw() DeadDrawer draw() 35
Kuorruttaja (Decorator) Ongelma: Miten antaa mahdollisuus liittää sovelluskohtaista toiminnallisuutta tiettyyn kehyksen komponentiin dynaamisesti? 36
Esimerkki 37
basic interaction ; BasicBehavior Kehys SpecialBehavior interaction() next.interaction(); interaction() Behavior interaction() next behav DefCreature interaction() append(behavior) DefWorld Creature Sovellus Behavior::interaction(); if energy < min { host.die(); } Behavior::interaction(); makesound(); MyBehavior2 MyBehavior1 interaction() interaction() Main: c = new DefCreature(); b1 = new MyBehavior1(); c.append(b1); d = new DefCreature(); b2 = new MyBehavior2(); d.append(b2); DefCreature::interaction: behav.interaction(); Kehys liittää automaattisesti BasicBehavior:in DefCreature-olioon 38 38
Abstrakti tehdas (Abstract Factory) Ongelma: Miten luoda yhdenmukaisesti tietyn sovelluskohtaisen luokkakokoelman olioita kehyksessä? 39
Kehyksessä Kehys Obstacle Creature World simulate() ElemFactory makecreature(): Creature makeobstacle(): Obstacle Sovellus MyObstacle MyCreature MyFactory Main: f = new MyFactory() world = new World(f); world.simulate(); return new MyCreature(); return new MyObstacle(); makecreature() makeobstacle() 40
Tarkkailija (Observer) Ongelma: Miten antaa sovelluskohtaisille komponenteille mahdollisuus reagoida jonkin kehyksen komponentin tilan muutoksiin? 41
if meteorhit { for all obs: obs.notifymeteor(); } Kehyksessä Kehys MeteorSource DefWorld MeteorObserver notifymeteor() Creature register( ) simulate() register(meteorobserver) Sovellus MyCreature notifymeteor() 42
Kahden kehyksen yhdistäminen säikeillä GUI-kehys Simulointikehys MainWindow Controller Manager EventLoop säie säie 43
Kehyksien kehittämisestä Luettavuus, kehyksen koodi luettavaa, kehyksen käyttö ja luettavan koodin tuottaminen Koodin lukeminen vs. kirjoittaminen Käytön helppous, yksinkertaisuus Älä pakota käyttäjiä toistamaan samaa asiaa (ensin kali-kuvaus, sitten sama koodissa, jne.) Mieti myös koodintäydennystä (ei getelementname, getelementtype ) Virheiden etsintä ajoaikana joku ei toimi vs. käännösvirhe (jos staattisesti tyypitetty) 44
Kehyksien kehittämisestä Piilomerkitykset ja abstraktioiden särkyminen Dokumentoi piilomerkitykset Pyri tekemään abstraktiot niin, etteivät ne vuoda osassa tilanteista = yhteneväisyys Laajennettavuus Yksinkertaisuus, dependency injection, helppo alkuun pääsy 45
Kehyksen ominaisuuksia (vielä) Käänteinen kontrolli, Inversion of control: kehys vastaa yleisestä ohjelman suorituksesta (ei kehystä käyttävän koodin tekijä/kehystä käyttävä koodi) Laajennettavuus, muokattavuus: muokataan luomalla uusia osia, erikoistamalla kehyksen peruspalveluita, parametrien avulla Kehyksellä oletustoiminnallisuutta: kehys tekee jotakin jo valmiiksi, ei pelkästään kokoelma tyhjiä rajapintoja Kehyksen omaa koodia ei muokata, kuten ei yleensä kirjastonkaan 46
Kehykset etuja? 47
Kehyksen ongelmat? 48
Kehysten etuja Kehysten etuja tuotealustojen toteutustekniikkana: Paljon kokemusta (esim. GUI-kehykset) Soveltaa yleistä, tunnettua OO teknologiaa (vrt. DSL) Tukee avoimia variaatiopisteitä (vrt. DSL) Tukee hyvin kerroksittaisia/hierarkkisia tuotealustoja Kovat osaajat tekevät kehyksen, sisällöntuottamisen jne. taitajat tuotteen 49
Kehysten ongelmia Teknisesti vaativa tapa tehdä ohjelmistoja, prosessi usein hyvin iteratiivinen Kehyksistä tulee helposti suuria, mutkikkaita ja vaikeasti hallittavia ohjelmistoja Ajankäyttö, kustannukset, jos ollaan tekemässä vain yksittäistä sovellusta Sovellusten testaaminen voi olla vaikeaa ilman kehyksen koodia Sovelluksen tekeminen kehyksen päälle: opettelu, joustavuus?, riippuvuus 50
Yhteenvetoa Kehys on OO tapa toteuttaa tuotealusta Kehysarkkitehtuureja käytetään paljon yrityksissä, kokemukset valtaosalta positiivisia Kehyksen tekeminen on huomattavasti vaativampaa kuin yksittäisen sovelluksen Vältä suurien muunneltavien (white-box) kehysten tekemistä Kehys voi olla hoikahko suhteessa itse sovellukseen: toiminnallinen runko ja sisältö 51
Kysyttävää?