(C) Jussi Koskinen, 2000-
1. Ohjelmistotyön ongelmat
Ohjelmistoteknisillä menetelmillä pyritään
aikaansaamaan luotettavia ohjelmistoja taloudellisesti. Frederick P. Brooks Jr.
on klassisessa, vuonna 1987 julkaistussa artikkelissaan ‘No silver bullet -
essence and accidents of software engineering’ [1], eritellyt
ohjelmistotuotannon oleellisia ongelmia. Eräs ongelmista on se, että ohjelmisto
on ns. näkymätön (invisible).
Lähdekoodista ei voida suoraan nähdä kaikkia ohjelmistojen kehittämisessä ja
ylläpidossa oleellisia seikkoja. Ohjelmiston kaikkia oleellisia aspekteja ei
myöskään yleisesti ottaen voida esittää ohjelmoijille, suunnittelijoille, ja
ylläpitäjille käyttäen yhtä ainoaa havainnollista esitystapaa, mikä on
mahdollista useilla muilla teknisillä aloilla. Toisin kuin muiden teknisten
alojen tuotteet, ohjelmistot yleensä myös koostuvat suurimmaksi osaksi ei-standardinomaisista komponenteista,
mikä hankaloittaa ylläpitoa ja uusiokäyttöä. Pyrittäessä muodostamaan käsitys
ohjelmiston toiminnasta ja sen rakenteesta, ylläpitoon liittyen, ohjelma
joudutaan yleensä käsitteellisesti osittamaan monilla eri tavoilla. Sitä voi
myös olla hyödyllistä tarkastella eri karkeustasoilla ja tarkastelun kohteeksi
kannattaa tilanteesta riippuen ottaa erilaisia riippuvuuksia, joita ohjelmiston
osien välillä vallitsee.
2. Ohjelmien ylläpito
Ohjelmistojen
kehitystä on perinteisesti vaiheistettu käyttäen ns. vesiputousmallia. Ohjelmistoja kehitettäessä lähtökohtana ovat
järjestelmälle asetettavat vaatimukset. Ohjelmiston kehitys etenee
vesiputousmallin mukaisesti suoraviivaisesti analyysi- ja suunnitteluvaiheiden
kautta varsinaiseen toteutukseen, joka sisältää lähdekoodin kirjoittamisen.
Tätä seuraa ylläpitovaihe.
Ohjelmien ylläpito on perinteisesti määritelty muutosten teoksi ohjelmistoon
sen jälkeen, kun se on luovutettu asiakkaille. Toisaalta, iteraation ja
prototyypityksen merkitys tunnustetaan nykyään yleisesti. Tällöin ohjelmiston
kehittäminen ei ole suoraviivainen prosessi, vaan etenee vaatimuksia asteittain
tarkentaen. Tällaista tarkastelutapaa edustaa Barry Boehmin vuonna 1988
esittämä ns. ohjelmistotuotannon spiraalimalli
[2]. Mallin mukaisesti järjestelmän kehitykseen liittyy kiinteä vuorovaikutus
asiakkaiden kanssa. Ohjelmistoon tehdään muutoksia paitsi välttämättömien
muutostarpeiden, myös tarkentuvien asiakasvaatimusten seurauksena. Ylläpidon
problematiikan kannalta oleellista on se, että ohjelmiston muuttamista ei voida
välttää.
Ohjelmien ylläpito on perinteisesti tapana
jakaa neljään laajaan tehtäväluokkaan. Ensinnäkin, korjaava ylläpito käsittää tietokoneohjelmissa olevien virheiden
diagnosoinnin, paikantamisen ja korjaamisen. Toiseksi, sopeuttava ylläpito sisältää ohjelmiston liittämisen muuttuvaan
ympäristöön. Kolmanneksi, parantava
ylläpito käsittää lisäyksien ja muutosten tekemisen perustuen muuttuviin
käyttäjien tarpeisiin. Neljänneksi, ennaltaestävä
ylläpito sisältää ohjelmiston kehittämisen, s.e. sitä on jatkossa helpompi
ylläpitää. Tämä luokitus on peräisin 80-luvun alusta ja on esiintynyt mm. Roger
S. Pressmanin ohjelmistotekniikan perusteoksessa [3]. Vastaavankaltaista
luokittelua on käyttänyt myös mm. Ian Sommerville omassa ohjelmistotekniikan
kirjassaan [4].
Ohjelmien ylläpito on merkittävä osa
tietojärjestelmien kehittämisestä. Ian Sommervillen mukaan [4] on arvioitu,
että ylläpitoon kuluu n. 65-75% ohjelmiston elinkaaren aikaisista
kustannuksista. Ohjelmien ylläpito on myös vaativaa työtä. Vaativuutta lisääviä
tekijöitä ovat mm.: ylläpidettävien ohjelmistojen ja tehtävien muutosten
laajuus, muutosten tekeminen koodiin, joka ei ole muutoksien tekijälle ennestään
tuttua, sekä puutteellinen dokumentointi. Esimerkki ylläpidon ongelmista ja
siihen liittyvistä kustannusvaikutuksista on ns. vuosi 2000 (Y2K) ongelma. Vaikka vuosi 2000 ongelma onnistuttiinkin
ratkaisemaan ennakoitua paremmin [5], vaati ongelman ratkaiseminen paljon
työtä. Esimerkiksi IT Viikon mukaan Nokia käytti vuosi 2000 ongelmaan, mm.
ennaltaehkäisevään ylläpitoon, n. 450 Mmk [6].
3. Ohjelmien ymmärtäminen
Ohjelmien ymmärtämisprosessin tavoitteena on
lisätä ylläpitäjän tietotasoa liittyen seikkoihin, jotka ovat tärkeitä
ohjelmointi- tai ylläpitotehtävien suorittamiselle. Riittävä ohjelmien
rakenteen ja toiminnan ymmärtäminen on välttämätöntä, jotta ohjelmistoon
voidaan tehdä muutoksia ilman, että niistä seuraa ei-toivottuja sivuvaikutuksia. Periaatteessa,
muutokset tulisi suunnitella ja niiden seuraukset selvittää. Muutosten teko
perustuen riittämättömään ymmärrykseen aiheuttaa ohjelmiston laadun
rapautumista (ripple-effect). Hyvä ymmärrys myös edesauttaa muutosten tekoa
s.e. ohjelmiston ylläpidettävyys ei tarpeettomasti heikkene.
Ohjelmien ymmärtämisprosessille on esitetty
lukuisia teoreettisia malleja [7,8]. Ymmärtämiseen vaikuttavia tekijöitä ovat
mm. käytettävät ymmärtämisstrategiat, ymmärtämisen tuloksena muodostettavat
mentaaliset mallit, sekä käsitteelliset rakenteet, joita vastaavat lähdekoodin
tietyt ohjelmarivit.
Ymmärtämisstrategiat
kuvaavat niitä tapoja, joilla ylläpitäjä pyrkii ymmärtämään ohjelmaa.
Tyypillisesti ymmärtämispyrkimyksiin liittyy lähdekoodin edestakainen selaus,
pyrkimyksenä löytää rakenteita, jotka auttavat hahmottamaan ohjelman
tarkoituksen ja toimintalogiikan. Ohjelmaa voidaan selata noudattaen systemaattisia tai opportunistisia
strategioita. Esimerkiksi, noudatettaessa ylhäältä-alaspäin
etenevää (ns. top-down) strategiaa, ylläpitäjä pyrkii ensin ymmärtämään
kutsuhierarkian ylimmän tason - pääohjelman. Vastaavasti noudatettaessa alhaalta-ylöspäin etenevää (ns.
bottom-up) strategiaa, ylläpitäjä kiinnittää ensin huomionsa perustason
“rakennuspalikoihin”, esimerkiksi aliohjelmiin, joita mahdollisesti kutsutaan
montaa eri kautta ohjelmassa. Käytännössä strategioita sovelletaan ottaen
huomioon tilannekohtaiset tekijät, eli toimitaan joustavasti ja opportunistisesti. Näin muodostuvissa mentaalisissa malleissa on kyse ylläpitäjän
“sisäisistä” näkemyksistä koskien ohjelmiston oleellisia aspekteja.
Lähdekoodin tietyt selkeästi havaittavat
osat tai ohjelmarivit (beacons) voivat toimia lähtökohtina laajempien
kokonaisuuksien ymmärtämiselle, kuten esimerkiksi C-kielisten ohjelmien
pääfunktio, jota vastaa merkkijono ‘main’. Tietyt ohjelmarivit yhdessä
tuottavat tietyn toiminnallisuuden vastaten ohjelmoijien alkuperäisiä, ns. ohjelmasuunnitelmia (program plan).
Kyseessä voi olla esimerkiksi vakiintunut tapa toteuttaa tietoalkioiden lajittelu,
eli järjestykseen asettaminen, käyttäen esimerkiksi yleisesti tunnettua ‘quick
sort’ algoritmia. Ymmärtäminen on erityisen hankalaa silloin jos tietyn
toiminnallisuuden toteuttavat ohjelmarivit ovat hajautuneet s.e. ymmärtämisen
kannalta oleellisten ohjelmarivien välissä on tässä suhteessa epäoleellisia
ohjelmarivejä. Tällöin on kyseessä ns. hajautunut
ohjelmasuunnitelma (delocalized program plan) [9]. Käsitteellisesti
yhteenkuuluvien rakenteiden ymmärtämistä voidaan pyrkiä tukemaan tarjoamalla ylläpitäjälle
esitysmuotoja, jotka tuovat esiin mielekkäät kokonaisuudet ja niiden väliset
oleelliset riippuvuudet.
Ohjelmien ylläpitotehtäviin ja ohjelmien
ymmärtämiseen liittyen ylläpitäjillä on tietotarpeita.
Nämä tietotarpeet voidaan tyydyttää perustuen tietoon, jota saadaan joko
tutkimalla lähdekoodia, dokumentaatiota tai alan kirjallisuutta tai
kommunikoimalla kolleegojen kanssa. Lähdekoodin analyysi voi olla manuaalista
tai automatisoitua. Esimerkki dokumentaatioon kohdistuvasta tietotarpeesta on kohdealueen,
eli sovellusalueen, käsitteiden määrittelyt. Lähdekoodista tarvitaan usein
tietoa ohjelman sisältämien tunnisteiden määrittely- ja käyttökohteista,
ohjelman sisältämien aliohjelmien, proseduurien tai funktioiden välisistä
kutsusuhteista sekä siitä miten ohjelman suoritus etenee ja tieto siirtyy
muuttujalta toiselle. Tämän kaltainen tieto on yleishyödyllistä, liittyen
moniin ylläpitotehtävätyyppeihin.
4. Käänteistekniikat
Käänteistekniikalla (reverse
engineering) tarkoitetaan ohjelmiston sisältämien komponenttien ja niiden
välisten suhteiden tunnistamista ja vaihtoehtoisten - usein abstrahoitujen - esitysmuotojen luomista
[10]. Tämä on erityisen tärkeää, jos ohjelmistoa ei ole dokumentoitu lainkaan,
tai sen dokumentointi on puutteellista tai epäajantasalla. Käänteistekniikassa
pyrkimyksenä on luoda lähdekoodi syötteenä esitysmuotoja, jotka tuovat esiin
järjestelmän oleelliset piirteet. Täten prosessi etenee käänteisesti suhteessa
perinteisen ohjelmiston kehityksen vesiputousmallin mukaiseen järjestykseen.
Parhaimmassa tapauksessa voidaan automaattisesti tuottaa edeltävien vaiheiden
keskeisten dokumenttien runkoja. Käänteistekniikoita voidaan soveltaa useilla
eri tasoilla. Usein ohjelmistojen esittämiseen käytettyjä tapoja ovat mm.
kutsukaaviot ja (kontrolli)vuokaaviot. Kutsukaavio
koostaa tiedon siitä, miten ohjelman sisältämät aliohjelmat, proseduurit tai
funktiot kutsuvat toisiaan, eli miten ne käynnistävät toistensa toiminnan. Vuokaavio taas kuvaa ohjelman
suorituksen etenemistä ja etenemisen vaihtoehtoisia reittejä.
Jotta ylläpidon tuki olisi asianmukaisesti
kohdennettua, tulisi ylläpitäjälle tarjota välineistö, jolla hän voi saada
tietoa kullakin hetkellä oleellisista tietoalkioista. Näitä voivat olla
ohjelmanosat tai dokumentit tai niiden osat. Käänteistekniikat perustuvat
ohjelmien automaattiseen analyysiin. Automaattinen ohjelma-analyysi voi olla
staattista, jolloin käytetään ainoastaan tietoa, joka on saatavilla ohjelman
käännösaikana tai dynaamista, jolloin hyödynnetään myös ohjelman suoritukseen
liittyvää tietoa. Ohjelmien automaattiseen analyysiin on käytettävissä lukuisia
tekniikoita.
Lähdekoodin analyysissä eräs tekniikka,
jolla voidaan edesauttaa tietyssä tilanteessa relevanttien näkymien
muodostamista on ns. ohjelmien
siivuttaminen (jota myös joskus viipaloinniksi kutsutaan). Siivutus on
alunalkaen Mark Weiserin vuonna 1982 esittämä tekniikka [11]. Epäformaalisti
ilmaisten, siivuun sisällytetään ne ohjelmanosat, joilla on merkitystä
suhteessa valittuun lähtökriteeriin. Lähtökriteeri
on tyypillisesti muuttujan esiintymä tietyssä kohtaa ohjelmaa. Käytännössä,
siivuun sisällytettävät ohjelmanosat saadaan määriteltyä suorittamalla
ohjelmalle tietovirta- ja kontrollivirta-analyysi. Esimerkiksi, korjaavan
ylläpidon tapauksessa, ylläpitäjän tehtävänä voi olla ohjelmointivirheen
jäljittäminen. Virheen olemassaolo havaitaan yleisesti sitä kautta, että
ohjelma tuottaa tietyssä kohtaa virheellisen tulosteen. Tuloste määrittyy
muuttujien arvojen kautta. Seuraamalla ohjelman suorituksen vaihtoehtoisia reittejä
taaksepäin saadaan virheelliseen tulokseen vaikuttavat tekijät selville.
Automatisoitu siivutus auttaa tätä prosessia esittämällä ylläpitäjälle näkymän,
jossa vain ko. tehtävään liittyen oleelliset ohjelmanosat ovat mukana.
Edellisen kaltaiset, virheenjäljitykseen
liittyvät apuvälineohjelmistot on usein integroitu esim. kääntäjäympäristöön.
Yleisempi integroitu ratkaisu on ns. CASE
(Computer Assisted/Aided Software/System Engineering) ympäristö tai
työkalupaketti (tietokoneavusteinen systeemi- tai ohjelmistotyöpaketti), joka
sisältää monia ohjelmien kehittämisen tai ylläpidon kannalta hyödyllisiä
apuvälineitä. Integroinnin ja apuvälineiden yhteistoiminnan perustana on usein tietointegraatio, joka perustuu usein
siihen, että apuvälineet käyttävät yhteistä tietomallia.
Tämän tietomallin perustana on usein erityisesti ylläpidon tukeen soveltuvien
ns. lower-CASE -työkalujen osalta
ohjelman jäsennyspuu ja symbolitaulu. Jäsennyspuu sisältää
tiedon ohjelman hierarkkisesta, syntaktisesta rakenteesta ja symbolitaulu mm.
tiedon ohjelman sisältämien nimettyjen symbolien, kuten muuttujien, määrittely-
ja käyttökohteista.
Nykyaikaisiin apuvälineisiin liittyy
oleellisena osana tiedon esittäminen
käyttäjälle havainnollisessa ja käyttökelpoisessa muodossa. Esimerkiksi
Borlandin C/C++ kääntäjäympäristössä käytetään värejä erottamaan lähdekoodin
erilaiset osat. Esimerkiksi kielen varatuilla sanoilla, operaattoreilla,
vakioilla, makroilla ja kommenteilla on oma korostustapansa. Usein
CASE-välineissä käytetään graafisia
näkymiä täydentämään tekstuaalista esitystä. Tyypillisesti graafiset
näkymät edesauttavat kokonaiskuvan muodostamisessa. Esimerkiksi nykyaikaisessa
Imagix -työkalussa [12] voidaan ohjelmakoodin osien välisiä suhteita
tarkastella haluttaessa myös käyttäen kolmiulotteista esitysmuotoa sekä valita
tarkastelun karkeustaso, esimerkiksi se näytetäänkö moduulit, aliohjelmat,
muuttujat, makrot jne. Eräs graafisiin esitysmuotoihin liittyvä ongelma on se,
että laajojen ohjelmien ollessa kyseessä, myös tarvittavat graafiset näkymät
ovat laajoja. Näitä ongelmia on omalta osaltaan helpottanut se, että näytöt
ovat kehittyneet sekä kooltaan, että laadultaan. Valintojen tekomahdollisuudet
ja abstrahointi ovat tärkeitä, jotta graafisia näkymiä voidaan hyödyntää
täysipainoisesti. Koska ohjelman eri aspektien esittämiseen joudutaan
käyttämään erilaisia esitystapoja, mm. erilaisia kaavioita, hyödyllistä on myös
näissä kaavioesityksissä esiintyvien vastinparien väliset ristiinviittaukset, jotka mahdollistavat nopean siirtymisen esitysmuodosta
toiseen.
5. Hypertekstiesitysmuodot
Ohjelmistotyön
tukivälineissä on viime vuosikymmenellä yleistynyt myös ns.
hypertekstiesitysmuoto. Hyperteksti
koostuu solmuista, jotka sisältävät tekstiä sekä solmujen välisistä linkeistä, jotka
mahdollistavat tekstin toisiinsa liittyvien osien nopean epälineaarisen läpikäynnin. Hypertekstin idean esitti aikoinaan
Vannevar Bush jo vuonna 1945 [13]. Tämän jälkeen hypertekstiä on tutkinut mm.
Theodore Holm Nelson 1960-luvulta lähtien. Yleisemmin hypertekstiä on alettu
soveltaa 1980-luvun puolivälin jälkeen ja erityisesti World Wide Webin kasvun
seurauksena. Hypertekstiesitysmuoto täydentää tekstihakujen ja kyselyjen
käyttöä tarjoamiensa navigointimahdollisuuksien kautta.
Ohjelmistotyön tukivälineissä
hypertekstiesitysmuotoa on lähinnä käytetty dokumenttien (ja myös niiden osien)
välisessä linkityksessä [14,15,16]. Automaattinen hypertekstin muodostus on
lähinnä perustunut tilastollisiin ja dokumenttien ryhmittely (clustering)
tekniikoihin [17]. Lähdekoodin sisältämiä osia ja niiden välisiä riippuvuuksia
voidaan myös tarkastella hypertekstinä [18,19]. Tällaista hypertekstiä voidaan
muodostaa automaattisesti, jolloin hyperteksti on eräs lähdekoodin esitysmuoto,
jota voidaan käyttää mm. käänteistekniikkatyökaluissa täydentämään perinteistä
lineaarista esitystapaa sekä graafisia esitysmuotoja. Systemaattiseen
tiedonhakuun soveltuva, abstraktien syntaksipuiden ja ohjelmariippuvuuksien
relaatio-ominaisuuksien käyttöön perustuva, lähestymistapa on esitetty
väitöskirjassani [20].
[1] Brooks, F.P. Jr. 1987. No
silver bullet - essence and accidents of software engineering. Computer 20 (4), 10-19.
[2] Boehm, B. 1988. A spiral
model of software development and enhancement. Computer 21 (5), 61-72.
[3] Pressman, R. 1997. Software Engineering - A Practitioner's
Approach (4th ed.). McGraw-Hill.
[4] Sommerville, I. 1996. Software Engineering (5th ed.).
Addison-Wesley.
[5] ITV. 2000a. Suomalaiset
välttivät Y2K-ongelmat. Vuosituhat vaihtui ilman suuria ongelmia. IT Viikko 5.1.2000.
[6] ITV. 2000b. Y2K maksoi Nokialle
450 miljoonaa. IT Viikko, 10.2.2000.
[7] Brooks, R. 1983. Towards a
theory of the comprehension of computer programs. International Journal of Man-Machine Studies 18 (6), 543-554.
[8] von Mayrhauser, A. &
Vans, A.M. 1995. Industrial experience with an integrated code comprehension
model. Software Engineering Journal 10 (5), 171-182.
[9] Letovsky, S. & Soloway,
E. 1986. Delocalized plans and program comprehension. IEEE Software 3 (3),
41-49.
[10] Chikofsky, E. & Cross, J.
H. II. 1990. Reverse engineering and design recovery: a taxonomy. IEEE Software 7 (1), 13-17.
[11] Weiser, M. 1982. Programmers
use slices when debugging. Communications
of the ACM 25 (7), 446-452.
[12] Imagix. 2000. Imagix 4D. Product
information available (10-Mar-00) in www-form at <URL:
http://www.imagix.com>. Company: Imagix. Description: a reverse engineering
tool for C and C++.
[13] Bush, Vannevar. 1945. As we
may think. Atlantic Monthly 176 (1), 101-108.
[14] Bigelow, J. 1988. Hypertext
and CASE. IEEE Software 5 (2), 23-27.
[15] Garg, P. 1989. Information Management in Software
Engineering: A Hypertext Based Approach. Los Angeles: University of
Southern California (Diss.).
[16] Oinas-Kukkonen, H. 1997. Improving the Functionality of Software Design
Environments by Using Hypertext. Univ. of Oulu, Finland. Acta
Univ. Ouluensis, A 296 (Diss.).
[17] Allan, J. 1995. Automatic Hypertext Construction.
Ithaca, NY: Department of Computer Science, Cornell University (Diss.).
[18] Brade, K., Guzdial, M., Steckel,
M. & Soloway, E. 1994. Whorf: a hypertext tool for software maintenance. International Journal of Software
Engineering and Knowledge Engineering 4
(1), 1-16.
[19] Nørmark, K. & Østerbye,
K. 1994. Representing programs as hypertext. In B. Magnusson, G. Hedin & S.
Minör (Eds.) Proceedings of the Nordic
Workshop on Programming Environment Research (NWPER'94). LU-CS-TR: 94-127. Lund, Sweden: Lund Univ., 11-24.
[20] Koskinen, J. 2000. Automated Transient Hypertext Support for
Software Maintenance. Univ. of Jyväskylä, Finland. Jyväskylä Studies in
Computing 4 (Diss.).
Abstract
of the related Ph.D. thesis (in English)
Updated: June
11, 2000, Sept. 28, 2004, Aug. 3, 2010 by Jussi Koskinen.