Transcript Blue Border
Komponenttipohjainen ohjelmistotekniikka (TJTSS56) Osa 10 Kevätlukukausi 2010 Jyväskylän yliopisto Tietojenkäsittelytieteiden laitos Markku Sakkinen Suunnittelumallit, ohjelmistokehykset ja arkkitehtuurit Szyperski, luku 9 Aiempien lukujen opetus: olio-ohjelmointi ja komponenttien ohjelmointi on monimutkaista. • Kaikkia, varsinkin isoissa järjestelmissä merkittäviä ongelmia ei vielä hallita eikä edes ymmärretä täydellisesti. • Miksi olio- ja komponenttitekniikka kuitenkin tuntuu toimivan yleensä varsin hyvin? Ohjelmistojen rakentajat noudattavat hyviä yleisiä ohjeita ja käyttävät onnistuneita arkkitehtuureja ja suunnitelmia esikuvinaan. • Ei yritetäkään tuottaa ratkaisuja pelkän teorian avulla. • Paljon kokemusta ja jonkin verran teoriaa. • Arkkitehtuuri- ja suunnittelukokemuksen uudelleenkäyttö on ehkä kaikkein hyödyllisintä uudelleenkäyttöä. • Kaikki tekniikan alat noudattavat samaa periaatetta. • Tarvitaan hyviä tapoja, joilla välitetään tietoa onnistuneista esimerkeistä. Ohjelmistoissa käsiteltävät asiat ovat hyvin laajalla kokoskaalalla: yhdestä bitistä jättiläismäisiin järjestelmiin. • Tuskin mikään muu tekniikan ala on samanlainen. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 25. 3. 2010 2 Suunnittelumallit, ohjelmistokehykset ja arkkitehtuurit (jatkoa) Komponenttipohjaisten järjestelmien arkkitehtuuri on paljon vaativampi suunniteltava kuin perinteisten monoliittisten järjestelmien. • Siksi arkkitehtuuri- ja suunnittelutason uudellenkäyttö on erityisen tärkeää. • Tässä luvussa ei käsitellä yksittäisten algoritmien ja tietorakenteiden suunnittelua, koska ne eivät ole tärkeitä komponenttien tasolla. • Seuraavassa esitetään uudelleenkäyttöä eli lähestymistavan jakamista yhdeksällä eri tasolla. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 25. 3. 2010 3 Suunnittelumallit, ohjelmistokehykset ja arkkitehtuurit (jatkoa) Ristiriidattomuuden (consistency) jakaminen - ohjelmointikielet Jokaisessa ohjelmointikielessä on pienempi tai suurempi määrä valmiita mekanismeja ja toimintoja. • Nämä ovat yhteisiä kaikille ohjelmille ja ohjelmoijille. • Lisäksi kussakin kielessä jotkin muut asiat ovat helppoja toteuttaa, jotkin vaikeita tai mahdottomia. • Kielen ympärille kehittyy suosittuja idiomeja ja laajempikin ohjelmointikulttuuri. • Jotkin kielet pakottavat vahvasti tiettyyn ohjelmointityyliin, jotkin ovat hyvin sallivia. • Mikään kieli ei voi pakottaa hyvään ohjelmointiin, mutta kielessä voidaan estää monia vaarallisia asioita. Komponenttien ohjelmoinnissa suosituimpia ovat oliokielet (ml. hybridikielet). • Tässä(kin) luvussa keskitytään niihin. • Muilla ohjelmointimalleilla, varsinkin funktio- ja logiikkaohjelmoinnilla on omat etunsa. • Mikään ei estä käyttämästä niitä komponenttien sisäisessä toteutuksessa. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 25. 3. 2010 4 Konkreettien toteutusosasten (solution fragments) jakaminen – kirjastot Aliohjelmakirjastot ovat kaikkein vanhin uudelleenkäytön väline. • Jo ennen korkean tason ohjelmointikieliä. • Edelleenkin tärkeä ja hyödyllinen. • Kirjastoissa voi olla myös makroja (jos kielessä on makromahdollisuus). • Samoja aliohjelmia (ei makroja) voidaan tavallisesti kutsua useista eri kielistä. • Modulaarisisten ja oliokeskeisten kielien kirjastoissa on tietysti (myös) moduuleja ja luokkia. Vanhoissa ohjelmointikielissä (Cobol, Fortran, Algol, PL/1, Pascal ym.) yleisesti tarvittavat mekanismit ja toiminnot määriteltiin itse kielen syntaktisina ja semanttisina osina. Uudemmissa kielissä (jo C:ssä) esim. syöttö- ja tulostustoiminnot toteutetaan tavallisesti standardikirjaston aliohjelmina (tms.). • Yleensä jotkin standardialiohjelmat ovat välttämättä ”maagisia”: niitä ei voitaisi kirjoittaa itse ao. kielellä. • Jotkin varsinaisen kielen konstruktit voivat vaatia tiettyjä standardialiohjelmia. • Ohjelmoijan kannalta ero ei ole kovin oleellinen. • Esim. Lispissä ja Smalltalkissa ”varsinainen” kieli on hyvin suppea ja melkein kaikki toiminnot standardikirjaston funktioissa / luokissa. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 7. 4. 2010 5 Yksittäisten sopimusten jakaminen – rajapinnat Kun jonkin palvelun käyttäjiä (asiakkaita) ja tarjoajia (palvelimia) voidaan kytkeä vapaasti yhteen, niiden välinen sitova sopimus on itsessään merkittävä. • Kukin sopimus liitetään johonkin nimettyyn rajapintaan. • Sopimus voi olla osittain formaali ja osittain epäformaali. • Sopimus aiheuttaa sekä palvelimelle että asiakkaalle todennusvelvollisuuksia (verification obligations). • Tarpeeksi huolellisesti laaditun sopimuksen perusteella myös täysin riippumattomista lähteistä tulevat asiakkaat ja palvelimet voivat toimia oikein yhdessä. Rajapinnat ja niihin liittyvät sopimukset ovat järjestelmän pienimpiä sopimuksellisia kokonaisuuksia. • Rajapinnan määrittelemät operaatiot eivät ole mielekkäitä erillisinä (tai rajapinta on huonosti suunniteltu). • Rajapinnat ja sopimukset eivät vielä kerro mitään suuremmista kokonaisuuksista, siis järjestelmän arkkitehtuurista. Kukin komponentti liittyy joihinkin sopimuksiin palvelimena (tarjotut rajapinnat) ja joihinkin asiakkaana (vaaditut rajapinnat). Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 7. 4. 2010 6 Yksittäisten sopimusten jakaminen – rajapinnat (jatkoa) • Vaikka jollakin rajapinnalla voi olla useita tarjoajia, jokaiseen rajapinnan (ja sopimuksen) ilmentymään liittyy vain yksi looginen tarjoaja. • Yleensä suoran rajapinnan looginen tarjoaja on moduuli tai komponentti ja epäsuoran rajapinnan tarjoaja on olio. • Vastaavasti rajapinnalla voi olla useita käyttäjiä, mutta jokaiseen rajapinnan ilmentymään liittyy vain yksi looginen käyttäjä. Joukko rajapintoja (sopimuksineen) voidaan määritellä koostetuksi sopimukseksi. • Koostettu sopimus määrittelee yleensä useiden osapuolten yhteistoimintaa (Richard Helm, Ian Holland ja Dipayan Gangopadhyay, OOPSLA/ECOOP’90). • Sama komponentti voi toimia koostetun sopimuksen joidenkin rajapintojen tarjoajana ja joidenkin käyttäjänä. • Tätä ajatusta on kehitetty edelleen rajapintoihin perustuvaksi ohjelmistoarkkitehtuuriksi (Hans Jonkers, WICSA 2001). Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 7. 4. 2010 7 Yksittäisten vuorovaikutuksen palasten (interaction fragments) jakaminen – viestit ja protokollat (käytännöt) Rajapintojen kautta tapahtuvaa vuorovaikutusta voidaan kuvata viesteinä (kuten usein olioohjelmoinnin kirjallisuudessakin). • Operaation kutsu ja paluu siitä (mahdollisine tuloksineen) katsotaan eri viesteiksi (kuten sekvenssikaavioissa). • Viesti kulkee lähettäjältä vastaanottajalle loogista ”linjaa” pitkin. • Samalla loogisella linjalla voi olla toisessa tai molemmissa päissä useitakin osapuolia – esim. joukkolevityksessä (multicast). • Sama linja liittyy tavallisesti useampaan kuin yhteen rajapintaan. • Kaksisuuntaiseen liikenteeseen tarvitaan vähintään kaksi rajapintaa, ellei toiseen suuntaan välitetä vain kutsujen tuloksia. Tietyllä linjalla sallittuja viestejä kuvataan protokollilla. • Szyperski käyttää myös termiä ”viestikaava” (message schema). • Protokolla määrittelee viestien syntaksin ja yleensä ainakin jonkin verran niiden semantiikkaa. • Viestin voidaan vaatia sisältävän vastaanottajan ja/tai lähettäjän tunnisteen. • Protokolla määrittelee myös sallitut viestien järjestykset. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 8. 4. 2010 8 Yksittäisten vuorovaikutuksen palasten jakaminen (jatkoa) Viestit voidaan määritellä itsensä kuvaaviksi (self-describing). • Tämä vastaa monien oliokielten reflektiomahdollisuuksia, joiden avulla oliot ovat käytännössä itsensä kuvaavia. • Viestien ja rajapintojen välillä on mielenkiintoinen suhde. • Esim. HTTP:ssä viestit ovat täysin itsensä kuvaavia ja rajapinnassa on käytännössä vain yksi operaatio: käsittele viesti. • Perinteisissä sovellusliittymissä (API) taas jokaisen operaation kutsun muoto (parametrit) on täysin määrätty eikä siinä ole mitään itsensäkuvausta. • Välimuotojakin on, esim. telnet- ja FTP-protokollat. Samat (useidenkin osapuolten väliset) vuorovaikutukset voidaan määritellä joko koostetuilla sopimuksilla tai protokollilla. • Perinteisesti tietoliikenneyhteisö suosii protokollia ja viestejä, ohjelmointiyhteisö rajapintoja. • Protokollat korostavat viestejä, rajapinnat operaatioita. • Asynkronisia vuorovaikutuksia voidaan kuvata luontevammin protokollilla, synkronisia rajapinnoilla. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 8. 4. 2010 9 Yksittäisen vuorovaikutuksen arkkitehtuurin jakaminen – (suunnittelu)mallit (patterns) Oletan, että (suunnittelu)mallin käsite on kuulijoille jotenkin tuttu. • Niitä voidaan kutsua mikroarkkitehtuureiksi. Gamman ym. (”Gang of Four” – GOF) kirjassa (1995) kuvataan mallien ja (ohjelmistokehysten) eroja seuraavasti: • Suunnittelumallit ovat abstraktimpia ja vähemmän erikoistuneita kuin kehykset. Kehykset ovat alijärjestelmien osittaisia toteutuksia, kun taas malleilla ei ole välittömiä toteutuksia: toteutukset sisältävät vain esimerkkejä malleista. • Suunnittelumallit ovat pienempiä arkkitehtuurin elementtejä kuin kehykset. Jotkin mallit toimivat jopa yksittäisen metodin tasolla (esim. TemplateMethod ja FactoryMethod); useimmat kehykset hyödyntävät useita malleja. Suunnittelumallit ja rajapinnat ovat keskenään ortogonaalisia. • Melkein kaikissa malleissa on mukana useita rajapintoja. • Tietyssä yhteydessä sama rajapinta voi osallistua useiden mallien toteutukseen. • Operaatioiden ryhmittely rajapintoihin perustuu operaatioiden välisistä riippuvuuksiin (sopimussuhteisiin). • Operaatioiden ilmeneminen malleissa perustuu niiden vuorovaikutusrooleihin. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 8. 4. 2010 10 Yksittäisten vuorovaikutuksen arkkitehtuurin jakaminen – (suunnittelu)mallit (jatkoa) Myös suunnittelumallit ja protokollat ovat keskenään ortogonaalisia. • Malli voi käyttää osaa viesteistä vastaavasti, kuin se voi käyttää osaa rajapinnan operaatioista. Suunnittelumallit, rajapinnat ja protokollat kuvaavat ohjelmiston ”viipaleita” eri näkökulmista (aspekteista), ja niitä on hyödyllistä käyttää yhdessä. • Rajapinta määrittelee osittaisen näkymän loogiseen palveluntarjoajaan, jota tyypillisesti käyttää avoin joukko asiakkaita. • Protokolla määrittelee komponenttien tai olioiden välisen loogisen kommunikaatiolinjan. • Suunnittelumalli erottaa arkkitehtuurista yhden vuorovaikutuskokonaisuuden. On mahdollista, vaikka vaikeaa, tunnistaa sellaisten suunnittelumallien perheitä, jotka sopivat hyvin käytettäviksi yhdessä. • Lisäämällä tällaiseen perheeseen heuristiikat, joiden avulla malleja yhdistellään, saadaan mallikieli (pattern language). • Monia tällaisia mallikieliä on jo kehitetty. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 8. 4. 2010 11 Arkkitehtuurin jakaminen – (ohjelmisto)kehykset (frameworks) Kehyksiä on tutkittu ensimmäiseksi Smalltalkin standardikirjastosta (Peter Deutsch 1989). Ohjelmistokehys on joukko yhteistyössä toimivia luokkia, joista yleensä osa on abstrakteja ja jotka muodostavat uudelleenkäytettävän suunnitelman tietynlaisille ohjelmistoille. • Kehys on usein suunnattu jollekin sovellusalalle, mutta ei välttämättä. • Voidaan laatia kehys esim. .NETin web-lomakkeiden käyttöliittymäolioiden rakentamista varten. Osa kehyksen luokissa on käytettävissä toteutuksen perimiseen. • Yleensä jotkin näistä ovat abstrakteja, niin että niistä täytyy johtaa konkreetteja aliluokkia. • Usein perittäviksi tarkoitetuissa luokissa on kuitenkin joka metodille ainakin oletustoteutus, niin että aliluokkien määrittely ei ole välttämätöntä. • Metodeille voi olla myös ”osittaistoteutuksia”, jotka on tarkoitettu täydennettäviksi aliluokissa. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 8. 4. 2010 12 Arkkitehtuurin jakaminen – kehykset (jatkoa) Perinteiset kehykset keskittyvät luokkiin ja perintään. • Koska kehyksen soveltamiseksi tarvitaan tietoa yliluokkien toteutuksesta, puhutaan valkolaatikkouudelleenkäytöstä. Kehys voidaan vaihtoehtoisesti suunnitella koostamista hyödyntäväksi. • Koska tällöin tarvitsee tuntea vain kehyksen luokkien tarjoamat ja vaatimat rajapinnat, puhutaan mustalaatikkouudelleenkäytöstä. • Mielivaltaiset välimuodot (harmaalaatikkokehykset) ovat mahdollisia (ja luultavasti nykyään yleisiä). Kehyksen tärkeimpiä merkityksiä on sen osien välillä sallittujen vuorovaikutusten määrittely. • Tämä voi nopeuttaa tuntuvasti yksittäisten toteutusten rakentamista. Kuuluisin ja luultavasti vanhin oliokeskeinen ohjelmistokehys on Smalltalkin standardikirjastoon sisältyvä Model – View – Controller (MVC). • Siitä voidaan havaita runsaasti GOF:n suunnittelumallien esimerkkejä (erityisesti Observer, Composite ja Strategy). • Kirjassa on hieman lisää MVC:stä. • Kehyksiä on edelleenkin tarjolla eniten graafisten käyttöliittymien rakentamiseen. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 8. 4. 2010 13 Arkkitehtuurin jakaminen – kehykset (jatkoa) Kehys yhdistää ja konkretisoi joukon suunnittelumalleja, niin että eri mallien osanottajien lomitus ja vuorovaikutukset toimivat järkevästi. • Kehys voidaan selittää käyttämiensä mallien avulla (Ralph Johnson, OOPSLA’92). • Kehys ei lisää malleihin vain ylempää arkkitehtuuritasoa vaan myös niiden tarvitseman infrastruktuurin. Käytetystä teknologiasta riippuu, kuinka vahvasti kehys voi säännellä hyödyntämistään. • Esim. Smalltalkissa kehystä soveltava ohjelmoija pystyy rikkomaan mitä rajoitteita tahansa. • Esim. Javassa (ja joissakin muissa kielissä vielä paremmin) sääntely saadaan tiukaksi pakkausten tai moduulien sekä luokkien suojausmahdollisuuksien avulla. Hyvän ohjelmistokehyksen suunnittelu ja rakentaminen on haastava tehtävä, jossa tarvitaan useita iteraatioita. • Ei kannata, ellei sille uskota olevan useita konkreetteja sovelluskohteita. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 8. 4. 2010 14 Arkkitehtuurin jakaminen – kehykset (jatkoa) Kehyksen suunnittelu voi edetä joko kokoavasti eli alhaalta ylös (bottom up) tai osittavasti eli ylhäältä alas (top down). • Kokoava suunnittelu lähtee kehyksen maailmasta (domain) ja on suunnittelumalleihin perustuvaa (pattern-driven). • Osittava suunnittelu lähtee kohdemaailmasta (sovelluksen käsitteistä) ja on kohteisiin perustuvaa (target-driven). Kokoava suunnittelu: • Soveltuu silloin, kun kehyksen maailma on jo kohtalaisen hyvin tunnettu, esim. suunnittelun muutamien iteraatiokierrosten jälkeen. • Estää huonoja ratkaisuja alatasolla. • Voi johtaa ”ostoskeskusten” tapaisiin alempien tasojen moduuleihin, joissa on tarpeettomiakin toimintoja. Osittava suunnittelu: • Soveltuu silloin, kun kohdemaailma ymmärretään hyvin mutta kehyksen maailma ei ole kunnolla hahmottunut. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 9. 4. 2010 15 Arkkitehtuurin jakaminen – kehykset (jatkoa) Esimerkki: oletetaan, että MVC-periaate ei olisi vielä tunnettu ja haluttaisiin suunnitella kehys ohjelmille, joilla voidaan muokata ja näyttää monenlaisia dokumentteja ikkunoissa. • Koska on useita dokumenttilajeja ja ne vaativat erilaista visualisointia ja käsittelyä, yleisen kehyksen laatiminen vaikuttaa kannattavalta. • Peruskysymys: miten kohdemaailman oliot ja niiden vuorovaikutukset voidaan esittää kehyksen maailmassa? • Vastauksen löytäminen ei ole helppoa. • Ensin kannattaa suunnitella ainakin karkeasti yksittäistä toteutusta muutamalle eri dokumenttilajille ja vasta sitten ruveta yleistämään niistä kehystä. • Liian rajoitettu ja jäykkä kehys ei sovi kaikille kiinnostaville dokumenttilajeille tai ei tarjoa riittäviä palveluja. • Liian laaja ja joustava kehys aiheuttaa tehottomuutta ja/tai liikaa monimutkaisuutta. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 9. 4. 2010 16 Kokonaisrakenteen jakaminen – järjestelmän arkkitehtuuri Tässä keskitytään tarkastelemaan ohjelmiston kerroksellisuutta (layering). • Tiukka (strict) kerroksellisuus: kukin ohjelmiston osa saa käyttää vain itseään lähinnä alimman kerroksen palveluja. • Väljä (non-strict) kerroksellisuus: kukin ohjelmiston osa saa käyttää kaikkien itseään alempien kerroksen palveluja. • Kumpikin estää takaisinkutsut. • Mahdollisesti sallitaan saman kerroksen komponenttien kutsua toisiaan. • Jos tässä ei ole rajoitteita, takaisinkutsutkin ovat mahdollisia. • Joissakin ohjelmointikielissä (esim. Component Pascalissa) kielletään moduulien väliset riippuvuussyklit, siis mm. takaisinkutsut. Tiukka kerroksellisuus on vanha periaate, jota on pyritty noudattamaan varsin paljon perinteisissä ohjelmistoissa. • Käyttöjärjestelmä THE (Technische Hogeschool Eindhoven) – viisi kerrosta (Edsger Dijkstra, CACM 1968). • Helpottaa huomattavasti järjestelmän ymmärtämistä. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 9. 4. 2010 17 Kokonaisrakenteen jakaminen – järjestelmän arkkitehtuuri (jatkoa) • Kunkin kerroksen täydelliseksi ymmärtämiseksi tarvitsee ymmärtää vain sen oma toteutus sekä sen käyttämät lähinnä alemman kerroksen rajapinnat ja sen lähinnä ylemmälle kerrokselle tarjoamat rajapinnat. • Toisaalta periaate vaikeuttaa usein laajennettavuutta. • Jokin ylemmän kerroksen lisätoiminto tai –komponentti voi tarvita palvelua, jota ei ole saatavissa lähimmältä alakerrokselta, vaikka se onkin olemassa jossakin vielä alemmalla kerroksessa. • Tehokkuus kärsii, jos palvelupyynnöt (varsinkin pienet) joutuvat kulkemaan monen välikäden kautta. Väljällä kerroksellisuudella voidaan välttää tiukan kerroksellisuuden haittapuolia. • Silloin menetetään myös sen ensisijainen etu. Suuren järjestelmän arkkitehtuurin ymmärrettävyyteen ei riitä pelkkä kerroksellisuus. • Ainakin joissakin kerroksissa osia voi olla liikaa. • Tarvitaan lisäksi kaksi tai useampia rakeisuusasteita. Mutkikas arkkitehtuuri tekee ohjelmiston rakentamisen, ymmärtämisen ja ylläpitämisen vaikeaksi. • Lisäksi se rapautuu nopeammin kuin yksinkertainen arkkitehtuuri. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 9. 4. 2010 18 Kokonaisrakenteen jakaminen – järjestelmän arkkitehtuuri (jatkoa) Entä komponentit – Szyperski sivuuttaa ne tässä kohdassa? • Komponentti on yleensä paljon pienempi kokonaisuus kun kokonainen perinteinen sovellus. • Komponentin sisäisessä arkkitehtuurissa tiukan kerroksellisuuden haitat voivat jäädä mitättömiksi. • Toisaalta hyvin yksinkertaisissa komponenteissa kerroksellisuus voi olla tarpeetonta. • Komponenttiohjelmoinnissa rajapintoja pidetään ensisijaisina ja komponentteja toissijaisina. • Koska rajapinnat eivät vielä määrittele arkkitehtuuria, niitä ei tunnu mielekkäältä jakaa kerroksiin. • Jos komponenttien välinen arkkitehtuuri halutaan kerrokselliseksi, voidaanko ja täytyykö järjestelmään liittää useita saman rajapinnan tarjoavia komponentteja, jos rajapinnan asiakkaita on useissa kerroksissa? Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 9. 4. 2010 19 Alijärjestelmistä koostuvat järjestelmät – kehyshierarkiat Arkkitehtuuria on useilla tasoilla. • Suunnittelumallit ovat mikroarkkitehtuureja. • Ohjelmistokehykset ovat alijärjestelmien arkkitehtuureja. • Isoissa järjestelmissä on useimmiten useita eri kehyksiä. • Kokonaisjärjestelmän arkkitehtuuri määrittelee kehysten välisen integroinnin. • Jo hyvien kehysten laatiminen on vaikeaa, mutta hyvän ylemmän arkkitehtuurin suunnittelu vielä vaikeampaa. • Tärkeä vaikeuttava tekijä on se, että kukin kehys pyrkii määräämään toimintojen kontrollin. Suuret järjestelmät rakennetaan yleensä hierarkkisesti alijärjestelmistä. • Voidaan ajatella ohjelmistokehyksen periaatteen viemistä korkeammalla tasolle: luokkakehyksistä alijärjestelmäkehyksiin. • Alijärjestelmäkehys sisältää abstrakteja, täydennettäviä alijärjestelmiä. • Käytännössä tällainen laajennus ei ole helppoa, varsinkaan jos halutaan mahdollistaa useita hierarkiatasoja. • Kirjan luvussa 21 yleistetään MVC-kehys hierarkkiseksi; se aiheuttaa tuntuvasti lisää mutkikkuutta. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 12. 4. 2010 20 Alijärjestelmistä koostuvat järjestelmät – kehyshierarkiat (jatkoa) Tietylle abstraktio- ja rakeisuustasolla sopivien abstrahointivälineiden käyttäminen ylemmällä tasolla ei ylipäänsä ole onnistunut. • Proseduuri tai metodi ei ole lause. • Luokka ei ole proseduurin tai funktion sulkeuma. • Moduuli tai pakkaus ei ole luokka. • Alijärjestelmä ei ole moduuli. • Alemman tason abstraktiossa tarvitaan sellaisia komkreetteja yksityiskohtia, jotka ovat ylemmällä tasolla turha rasite. • Ylemmällä tasolla täytyy puolestaan ottaa huomioon sellaisia asioita, joita alemmalla ei tarvita. • Esim. tuonti- ja vientimääreitä ei tarvita luokkaa tai ainakaan metodia alemmilla tasoilla. • Nämä asiat voivat vaatia myös tuottavaan organisaatioon uusia rooleja (laajempien näkökulmien huomioonottamista). Alalla ei ole (tai ollut ainakaan 2002) vielä tarpeeksi tietämystä ja kokemusta yleisten kehyshierarkioiden suunnitteluun. • Komponentti- ja alijärjestelmäkehyksiä on jo olemassa. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 12. 4. 2010 21 Yhteentoimivuus (interoperability), perinnejärjestelmät (legacy systems) ja uudelleenrakentaminen (?) (re-engineering) Melkein kaikissa organisaatioissa on toiminnassa vanhoja ohjelmistoja, jotka on toteutettu menneiden aikojen välineillä ja menetelmillä. • Yleensä niiden täydellinen korvaaminen uusilla ei ole mahdollista tai ainakaan kannattavaa. • Tarvitaan hyviä liittymiä uusiin järjestelmiin sekä asteittaista korvaamista. • Usein keskeinen ongelma on selkeän kokonaisarkkitehtuurin puuttuminen. • Hyväkin alkuperäinen arkkitehtuuri on voinut rapautua, jos sen ylläpidosta ei huolehdittu ohjelmiston evoluution yhteydessä. Arkkitehtuurin pitämiseksi kunnossa tarvitaan aika ajoin uudelleenorganisointia (?) (refactoring) eri tasoilla. • Komponenttipohjaisen arkkitehtuurin yksi etu on se, että tämä on suhteellisen helppoa komponentin tasolla. • Ylimmät tasot ovat vaativimpia. Yhteentoimivuus ajassa ja paikassa: • Versioiden välinen yhteensopivuus taakse- ja eteenpäin. • Eri paikoissa toisistaan riippumatta kehitettävien järjestelmien ja osasten yhteentoimivuus. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 12. 4. 2010 22 Yhteentoimivuus, perinnejärjestelmät ja uudelleenrakentaminen (jatkoa) Uusien tekniikkojen käyttöönotto voi aiheuttaa pahoja seurauksia, jos samalla ei oteta huomioon arkkitehtuurin näkökohtia kaikilla tarpeellisilla tasoilla. • Varhaisessa oliotekniikkojen hyödyntämisessä unohdettiin usein korkean tason arkkitehtuuri. • Luokkien väliset kytkennät olivat mielivaltaisia ja sotkuisia. • Kerroksellisuutta ei pyritty noudattamaan. • Perusjärjestelmiä ja niiden laajennoksia ei erotettu toisistaan. Kuten erityisesti kirjan luvussa 7 esitettiin, arkkitehtuurin puute aiheuttaa pahempia ongelmia oliopohjaisissa kuin perinteisissä (rakenteisissa ja proseduraalisissa) järjestelmissä. • Ohjelmiston siirto käyttämään toista aliohjelmakirjastoa on vaikeaa, mutta siirto luokkakehyksestä toiseen on paljon vaikeampaa. • Jo saman kehyksen evoluutio aiheuttaa ongelmia (”särkyvä yliluokka”). Globaalin yhteentoimivuuden tarve Internetissä (erityisesti web-palveluissa) ovat uusi haaste. • Nyt vielä pilvipalvelut taivaanrannalla. Komponenttipohjainen ohjelmistotekniikka (Markku Sakkinen) – Osa 10 12. 4. 2010 23