Tartu Ülikool
Matemaatikateaduskond
Arvutiteaduse instituut
Tarkvarasüsteemide õppetool
Targo Tennisberg
Objekt-orienteeritud süsteemianalüüs ja selle metoodikad
Semestritöö
Sissejuhatus *
1. Ülevaade objekt-orienteeritusest (OO) *
1.1 Objekt-orienteerituse mõiste *
1.2 Objekt-orienteeritud tarkvaraarendus *
1.3 Objekt-orienteerituse põhijooned *
1.4 OMT metoodika *
2. OO modelleerimine *
2.1 Modelleerimise mõiste *
2.2 Objektimudel *
2.3 Objektid ja klassid *
2.4 Seosed objektide ja klasside vahel *
2.5 Üldistamine ja pärimine *
2.6 Praktiline näide – sularahaautomaat *
3. Dünaamiline modelleerimine *
3.1 Sündmused *
3.2 Olekud *
3.3 Olekudiagrammid *
3.4 Operatsioonid *
3.5 Keerukamad konstruktsioonid *
3.5 Praktiline näide – sularahaautomaat *
4. Funktsionaalne modelleerimine *
4.1 Funktsionaalsed mudelid *
4.2 Andmevoodiagrammid *
4.3 Praktiline näide – sularahaautomaat *
5. UML ja selle rakendamine *
5.1 UML-i ülevaade *
5.2 Kasutussituatsioonidiagrammid (use case diagrams) *
5.3 Klassidiagrammid *
5.4 Objektisuhtlusdiagrammid (object interaction diagrams) *
5.5 Mooduldiagrammid (package diagrams) *
5.6 Olekudiagrammid *
5.7 Tegevusdiagrammid (activity diagrams) *
5.8 Paigaldusdiagrammid (deployment diagrams) *
5.9 UML-i ja tema vahendite kasutamisest *
Summary *
Viited *
Käesolevas töös kirjeldatakse objekt-orienteeritud lähenemist süsteemianalüüsile kui tarkvaratootmise seisukohalt tähtsaimale etapile, samuti vaadeldakse hetkel enamkasutatavaid objekt-orienteeritud süsteemianalüüsi metoodikaid, OMT-d (Object Modeling Technique) ja UML-i (Unified Modeling Language). Töö esimene peatükk, “Ülevaade objekt-orienteeritusest”, annab lühikese sissejuhatava ülevaate objekt-orienteerituse mõistest kui sellisest, kirjeldatakse olulisemaid objekt-orienteeritusega seotud mõisteid ja põhijooni ning selle kasutamist tarkvaratootmisel. Üldiselt eeldatakse lugejalt siiski, et ta on üldjoontes tuttav objekt-orienteerituse peamiste mõistetega ja omab selles valdkonnas elementaarseid teadmisi ja kogemusi. Teine peatükk, “OO modelleerimine”, annab alguses ülevaate modelleerimisest, selle ideedest ja võimalustest, seejärel peatutakse lähemalt objektimudeli koostamisel. Kolmas peatükk, “Dünaamiline modelleerimine”, kirjeldab süsteemi olekute kujutamist ja dünaamilise mudeli koostamist. Neljandas peatükis, “Funktsionaalne mudel”, kirjeldatakse andmevooge, andmevoodiagrammide koostamist ja funktsionaalset mudelit ning selle mõtet üldse. Viies peatükk, “UML ja selle rakendamine” tutvustab lühidalt UML-i (Unified Modeling Language) kui tänapäeval levivat standardit objekt-orienteeritud lähenemisviisi rakendamisel.
Töö on iseloomult referatiivne, selle põhiline, OMT tehnoloogiat puudutav osa baseerub raamatul “Object-Oriented Modeling and Design” [1], teise peatüki puhul on kasutatud ka allikat [2]. Sellest raamatust on saadud ka ideid peatükkide lõpus olevate praktiliste näidete jaoks. Viienda peatüki materjal on võetud põhiliselt raamatust “UML Distilled” [3]. Üldise ideoloogia ning konkreetsete sammude järjestuse kirjeldamisel on kasutatud CASE-vahendiga SELECT kaasaskäivat juhendmaterjali “SELECT Perspective Mentor” [4]. Punkt 1.4, “OMT metoodika”, on kirjutatud, lähtudes allikast [5]. Kõiki vaadeldavaid mõisteid ja meetodeid on püütud illustreerida selgitavate näidetega. Tekstis esinevad näited on osalt minu enda loodud, osalt võetud allikast [1] ning osalt mitmetest WWW kaudu kättesaadavatest artiklitest.
Kuna enamiku reaalse elu projektide materjale on vastavate lepingutega keelatud levitada, siis kahjuks polnud võimalik tuua näiteid otse tegelikust elust. Antud töös kirjeldatud tehnoloogiaid olen isiklikult kasutanud Eesti Kodakondsus- ja Migratsiooniameti infosüsteemi loomise projektis, Airbus Industries’i uue lennukitüübi elektrisüsteemi konfigureerimise programmi kirjutamisel ning Eesti Maapanga telepangandussüsteemi “Teele” väljatöötamisel.
Terminite tõlkimisel on eelkõige kasutatud Vello Hansoni “Arvutisõnastikku”.
Töös esinevate näidete läbitöötamisel
ja jooniste koostamisel on kasutatud CASE-vahendeid SELECT Enterprise
Modeler (SELECT Software Tools) ja Visio (Visio Corporation).
1. Ülevaade objekt-orienteeritusest (OO)
(Rumbaugh 1)
Objekt-orienteeritud modelleerimine ja tarkvaraloomine on eelkõige
eripärane mõtteviis mudelite kasutamiseks reaalse maailma kujutamisel,
kus põhiliseks konstruktsiooniks on mõiste objekt,
mis kombineerib endas nii andmestruktuuri kui ka konkreetse üksuse
käitumisviisi. Objekt-orienteeritud mudelid on kasulikud probleemide
mõistmisel, konkreetse eriala spetsialistidega suhtlemisel, süsteemide
modelleerimisel, dokumentatsiooni ettevalmistamisel ja programmide ning
andmebaaside kavandamisel.
1.1 Objekt-orienteerituse mõiste
(Rumbaugh 1.1)
Pealiskaudse definitsiooni kohaselt tähendab “objekt-orienteeritus”, et me korraldame tarkvara diskreetsete objektide kogumina, milles sisalduvad nii andmestruktuur kui ka selle objekti käitumine. See on kontrastiks tavapärasele programmeerimisele, kus andmestruktuur ja meetodid nende haldamiseks on võrdlemisi lõdvalt seotud. Objekt-orienteeritud lähenemise täpsete nõuete üle on palju vaieldud; üldiselt sisaldavad nad endas nelja aspekti: eristatavus, klassifitseerimine, polümorfism ja pärimine.
Eristatavus tähendab, et andmed on jagatud diskreetseteks, eristatavateks üksusteks, mida nimetatakse objektideks. Objektideks võivad olla näiteks kirje andmebaasis, programmiaken ekraanil, malenupp malelaual, topeltseotud ahel mingite andmete hoidmiseks jne. Objektid võivad olla konkreetsed (nt. fail failisüsteemis või tabel andmebaasis) ja kontseptuaalsed (nt. kasutajaõiguste poliitika mitmekasutajasüsteemis). Igal objektil on omaenese eristatav identiteet, see tähendab, et kaks objekti jäävad eristatavateks ka siis, kui kõik nende atribuudid (näiteks nimi ja suurus) omavad samu väärtusi.
Tõelises elus iga objekt lihtsalt eksisteerib, kuid programmeerimises on igal objektil unikaalne pide, mille järgi sellele viidata saab. Pide võib olla realiseeritud mitmel erineval moel, nagu aadressi, massiivi indeksi või mingi kindla atribuudi unikaalse väärtusena. Viited objektidele on kindla kujuga ja ei sõltu objektide sisust, lubades sel moel luua mitmesuguseid objektikollektsioone, nt. kataloog failisüsteemid võib sisaldada nii faile kui ka teisi katalooge.
Klassifitseerimine tähendab, et objektid, millel on sama andmestruktuur (atribuudid) ja käitumisviis (operatsioonid), grupeeritakse klassidesse. Näiteks Dokument, Aken või Malenupp võivad olla klassid. Klass on abstraktsioon, mis kirjeldab rakenduse tähtsaid omadusi ja jätab kõrvale ülejäänud. Klasside valik on suvaline ja sõltub konkreetsest rakendusest.
Iga klass kirjeldab piiramatu suurusega objektihulga. Iga üksikut objekti nimetatakse vastava klassi esindajaks. Igal esindajal on oma väärtused iga atribuudi jaoks, aga ühised atribuudinimed ja operatsioonid teiste selle klassi esindajatega. Näiteks klassil Inimene võivad olla atribuudid nimi, pikkus, sugu, perekonnaseis jne., operatsioonid sünd, surm, abielu, laste saamine, igal sellesse klassi kuuluval objektil on operatsioonide jaoks sama realisatsioon, kuid erinevad atribuudiväärtused. Iga objekt omab viidet oma klassile, st “teab, mis ta on”.
Polümorfism tähendab, et sama operatsioon võib erinevate klasside korral erinevalt käituda. Klassidel Malenupp ja Aken võib mõlemal olla operatsioon liiguta, kuid loomulikult peavad need operatsioonid olema teostatud erinevalt. Operatsioon on tegevus või transformatsioon, mida objekt sooritab või mida objektile võib rakendada. Operatsiooni konkreetset teostust nimetatakse meetodiks. Kuna objekt-orienteeritud operaator on polümorfne, võib talle vastata rohkem kui üks meetod, mis seda operatsiooni teostab.
Reaalses elus on operatsioon lihtsalt erinevate objektide sarnaste käitumiste abstraktsioon. Iga objekt “teab”, kuidas sooritada omaenese operatsioone. Objekt-orienteeritud programmeerimiskeeles valib keel ise operatsiooni nime ja objektiklassi põhjal õige meetodi, et sooritada antud polümorfset operatsiooni.
Pärimine on hierarhilisel struktuuril baseeruv klassidevaheline
atribuutide ja operatsioonide jagamine. Klass võib olla defineeritud
küllaltki laialivalguvalt ja seejärel täiendatud järjest
spetsiifilisemateks alamklassideks. Iga alamklass sisaldab endas
(pärib) kõik ülemklassi omadused ja lisab
neile iseenda unikaalsed omadused. Alamklassis ei tule kõiki ülemklassi
omadusi üle korrata. Näiteks kui meil on klass Ahel mistahes
andmete hoidmiseks, võime me luua alamklassid Stringiahel
või Punktiahel vastavate spetsiifiliste andmete hoidmiseks;
klassist Dialoog saab pärida näiteks klassid Failidialoog,
Fondivahetusdialoog
ja Printimisdialoog, millel on kõik
Dialoogi omadused
ja lisaks veel mitmed spetsifitseerivad omadused. Erinevate klasside ühiste
omaduste leidmine ja nende ühisesse ülemklassi koondamine võimaldab
suuresti vähendada kordamist projekteerimisel ja programmeerimisel
ning on üks objekt-orienteeritud süsteemi peamisi eeliseid.
1.2 Objekt-orienteeritud tarkvaraarendus
(Rumbaugh 1.2)
Nagu objekt-orienteeritus üldse, on ka objekt-orienteeritud tarkvaratootmine üks mõtteviis, mida rakendada reaalses elus esinevate abstraktsioonide puhul. Antud kontekstis arendus viitab tarkvara elutsükli esimestele osadele – need on analüüs, projekteerimine ja teostus. Objekt-orienteeritud arendustöö põhiolemuseks on peamiselt rakendusvaldkonna mõistete ja kontseptsioonide identifitseerimine ja organiseerimine, mitte niivõrd nende lõplik esitus programmeerimiskeeles, olgu see siis objekt-orienteeritud või ei. On täheldatud (Brooks-87), et peamine raskus tarkvarategemisel pole mitte probleemi ülekandmine konkreetsesse programmeerimiskeelde, vaid just probleemi olemuse käsitlemine selle suure keerukuse tõttu. Käesolevas töös ei süüvitagi eriti süsteemi praktilisse teostusse ja juurutamisse, vaid antakse ülevaade analüüsifaasi disainist ja sellega seotud reeglitest ning notatsioonist.
Enamik praeguseni toimunud pingutusist objekt-orienteerituse vallas on olnud suunatud programmeerimiskeeltele. Kirjanduses on rõhk olnud pigem teostusel, mitte analüüsil ja projekteerimisel. Objekt-orienteeritud programmeerimiskeeled on kasulikud vanade paindumatute keelte piirangute kaotamisel, kuid samas on see tarkvaratootmise jaoks ka samm tagasi, sest tähelepanu koondatakse liialt teostusmehhanismidele nende taga olevate protsesside asemel. Teatavasti on märksa kallim parandada realiseerimisel ilmnevaid vigu, kui neid, mis tulevad välja varem. Liiga varane teostusega arvestamine piirab valikuvõimalusi projekteerimisel ja viib tihti halvema produktini. Objekt-orienteeritud lähenemine arendustööle sunnib tarkvarategijat läbi kogu tarkvara elutsükli töötama ja mõtlema oma rakendusvaldkonna termineis. Andmestruktuuride ja funktsioonide detaile on võimalik rahuldavalt paika panna ainult siis, kui on põhjalikult identifitseeritud ja korrastatud konkreetsele rakendusele omased kontseptsioonid.
Objekt-orienteeritud tarkvaraarendus on kontseptuaalne protsess, mis ei sõltu kuni viimase etapini programmeerimiskeelest ja lõpliku teostuse vahenditest. Tegu pole programmeerimistehnikaga, vaid täiesti teistlaadse mõtteviisiga. Suurim kasu selle rakendamisest tuleb sellest, et aidatakse spetsifitseerijatel, tarkvarategijatel ja klientidel selgelt väljendada abstraktseid mõisteid ja neid üksteisele vahendada. Objekt-orienteeritus võib peale programmeerimise olla aluseks ka spetsifitseerimisele, analüüsile, dokumenteerimisele ja liideste loomisele.
Käesolevas töös kirjeldatakse objekt-orienteeritud tarkvaratootmise metoodikaid ja objekt-orienteeritud mõistete graafilist esitusviisi. Metoodika koosneb rakendusvaldkonna mudeli ehitamisest ja seejärel realisatsiooniks vajalike detailide lisamisest projekteerimise käigus. Peamised sammud sel teel on:
Mõned klassid ei ole analüüsi osad, kuid nad osutuvad kasulikeks hilisemates etappides. Näiteks andmestruktuurid, nagu puud, paisktabelid ja ahelad esinevad üliharva tegelikus elus, aga väga sageli programmeerimises. Need tuuakse sisse projekteerimise käigus toetamaks spetsiifilisi algoritme. Selliseid andmestruktuure kasutatakse ainult reaalse elu objektide kujutamiseks arvutis ja nad ei päri oma omadusi otse tegelikust elust.
Objekt-orienteeritud tarkvaratootmises enimlevinud OMT metoodika kasutab süsteemi kirjeldamiseks kolme liiki mudeleid, need on objektimudel, mis kirjeldab süsteemis esinevate objekte ja nende seoseid; dünaamiline mudel, mis kirjeldab süsteemi komponentidega toimuvaid muutusi; ja funktsionaalne mudel, mis kirjeldab andmete liikumist süsteemis.
Objektimudel kirjeldab süsteemi objektide staatilist struktuuri ja nende seoseid. Objektimudel koosneb objektidiagrammidest. Objektidiagramm on graaf, mille tippudeks on klassid ja kaarteks suhted klasside vahel.
Dünaamiline mudel kirjeldab süsteemi neid aspekte, mis aja jooksul muutuvad. Dünaamilist mudelit kasutatakse süsteemi kontrolli seisukohalt oluliste aspektide spetsifitseerimiseks ja teostamiseks. Dünaamilise mudeli koostisosadeks on olekudiagrammid. Olekudiagramm on oma olemuselt graaf, mille tippudeks on olekud ja kaarteks üleminekud ühest olekust teise, mida põhjustavad sün dmused.
Funktsionaalne mudel kirjeldab andmete liikumist süsteemis. Funktsionaalne mudel koosneb andmevoodiagrammidest, mis esitavad mingit andmetöötlust. Andmevoodiagramm on graaf, mille tippudeks on protsessid ja kaarteks andmevood.
Need kolm mudelit on kogu s&ml;steemi esituse kolm külge ja nad on kõik omavahel seotud. Peamine neist on objektimudel, sest alati on vaja kindlaks teha, mis muutub, enne kui selgitada millal ja kuidas see toimub.
Objekt-orienteeritud tarkvaraarendus pöörab ümber varemlevinud funktsiooni-orienteeritud metoodika (Yourdon-89), (DeMarco-79). Eelmistes metoodikates oli põhirõhk süsteemi funktsionaalsuse spetsifitseerimisel ja osadeks lahutamisel. Selline lähenemine võib soovitud eesmärgi saavutamisel paista kõige otsesemana, kuid saadud süsteem võib olla habras. Kui nõudmised muutuvad, võib funktsionaalsuse analüüsimise teel saadud süsteem vajada põhjalikku restruktureerimist.
Objekt-orienteeritud lähenemine seevastu teeb kõigepealt kindlaks rakendusvaldkonna objektid ja sobitab alles siis protseduurid nende ümber. Kuigi see meetod võib tunduda kaudsena, peab objekt-orienteeritud tarkvara paremini vastu muutvatele nõudmistele, sest ta baseerub rakendusvalla struktuuril enesel, mitte üksiku probleemi funktsionaalsetel vajadustel.
1.3 Objekt-orienteerituse põhijooned
Objekt-orienteeritud tehnoloogiat iseloomustavad mitmed põhijooned. Kuigi need jooned esinevad ka mujal peale objekt-orienteeritud süsteemide, on nad viimastes eriti hästi esile toodud. Peatumegi järgnevalt neil eripäradel.
Abstraheerimine tähendab fokuseerumist ainult terviku vajalikele, lahutamatutele osadele ja juhuslike omaduste ignoreerimist. Süsteemianalüüsil tähendab see, et tähelepanu pööratakse sellele, mis objekt on ja mida ta teeb, enne kui otsustatakse, kuidas tema esitust realiseerida. Abstraktsioonide kasutamine annab meile vabaduse teha otsustusi nii kaua kui võimalik, vältides enneaegseid kohustusi spetsiifiliste detailide ees. Enamik tänapäeva programmeerimiskeeli võimaldavad abstraktseid andmetüüpe, kuid võimalus kasutada pärimist ja polümorfismi annab objekt-orienteeritud keeltele erilise võimsuse. Abstraktsioonide kasutamine analüüsifaasi ajal tähendab tegelemist ainult vastava rakenduse mõistetega ja disaini ning realiseerimise alaste otsuste mittevastuvõtmist enne, kui probleem on põhjalikult selgeks tehtud. Abstraktsioonide õige kasutamine võimaldab sama mudeli kasutamist analüüsil, kõrgtaseme projekteerimisel, programmi ja andmebaasi struktureerimisel ning dokumenteerimisel. Keelest sõltumatu projekteerimine lükkab kodeerimise detailide üle otsustamise edasi kuni viimase, võrdlemisi mehaanilise arendusstaadiumini.
Kapseldamine (või ka informatsiooni peitmine) tähendab objekti väliste aspektide, mida ka teised objektid saavad kasutada, eraldamist sisemistest, objekti omaduste realisatsiooniks vajalikest detailidest. Kapseldamine väldib programmi osade teineteisest sellisesse sõltuvusse langemist, et väikegi muudatus sunnib peale suuremahulisi parandusi. Objekti sisemist realisatsiooni võib muuta, ilma et oleks vaja muuta seda objekti kasutavaid rakendusi. Realisatsiooni võib muuta, soovides parandada käideldavust, parandada viga või portida koodi teisele platvormile. Kapseldamine pole ainult objekt-orienteeritud keelte omadus, kuid võimalus kombineerida andmestruktuur ja objekti käitumine üheks üksuseks muudab kapseldamise muude keeltega võrreldes puhtamaks ja võimalusterohkemaks.
Objekt-orienteeritud süsteemi puhul ei pea operatsiooni väljakutsuja muretsema selle pärast, kui palju realisatsioone sellel operatsioonil on. Operaatorite polümorfism tõstab selle otsustuse väljakutsuvast koodist ümber klassihierarhiasse. Kui meil on näiteks aken, mis sisaldab mitut tüüpi objekte, ja on vaja need objektid üle joonistada, ei pea me programmis kindlaks tegema, kuidas see erinevate objektide puhul käib, vaid võime lihtsalt välja kutsuda iga objekti meetodit Joonista ning objekt teab ise, mida edasi teha.
Objekt-orienteeritud tehnikad võimaldavad mitmel tasandil koodi jagamist. Nii andmestruktuuri kui ka operatsioonide pärimine võimaldab struktuuri ühiste joonte jagamist alamklasside vahel ilma ressursse raiskamata. Ühise koodi jagamine pärimist kasutades ongi üks objekt-orienteeritud keelte peamisi eeliseid. Ressursside kokkuhoidmisest koodi kirjutamisel on tegelikult veelgi tähtsam kontseptuaalne selgus, et erinevad operatsioonid tähendavad tegelikult ühte ja sedasama asja. See vähendab oluliselt erinevate juhtumite arvu, mida uurida ja analüüsida. Objekt-orienteeritud arendus ei võimalda mitte ainult informatsiooni jagamist rakenduse sees, vaid ka projekteerimistulemuste ja koodi taaskasutamist tuleviku projektides. Kuigi seda võimalust on objekt-orienteeritud tehnoloogia õigustamisel üle tähtsustatud, pakub objekt-orienteeritud tarkvaratootmine vahendeid nagu abstraheerimine, kapseldamine ja pärimine, mis võimaldavad meil luua taaskasutatavate komponentide teeke. Objekt-orienteeritus pole siiski imerohi, mis kindlustaks meile taaskasutamise võimalikkuse. Taaskasutatavus ei teki juhuslikult, vaid peab olema korralikult ette planeeritud, mõeldes kaugemale praeguse konkreetse rakenduse vajadustest ja kulutades lisajõudu üldisema disaini saavutamiseks.
Objekt-orienteeritud tehnoloogia rõhub sellele, mis objekt on, mitte sellele, kuidas seda kasutatakse. Objekti kasutusviisid sõltuvad suuresti rakenduse detailidest ja muutuvad sageli arenduse käigus. Kui vajadused muutuvad, jäävad objekti poolt pakutavad võimalused märksa stabiilsemaks, kui see on tavalise protseduuristruktuuri puhul, seega on objektistruktuuril põhinevad süsteemid pikemas perspektiivis püsivamad. Objekt-orienteeritud tarkvaratootmisel pööratakse suurt tähelepanu andmestruktuurile ja väiksemat tähelepanu protseduuristruktuurile, võrreldes funktsioonide dekompositsioonil baseeruvate metoodikatega. Sellelt seisukohalt sarnaneb objekt-orienteeritud arendustöö informatsiooni modelleerimise tehnikatega, mida kasutatakse andmebaaside disainil, kuigi objekt-orienteeritud arendus lisab sinna klassist sõltuvuse mõiste.
Eristatavus, klassifitseerimine, polümorfism ja pärimine iseloomustavad
kõiki peamisi objekt-orienteeritud programmeerimiskeeli. Igat neist
mõistetest saab kasutada ka eraldiseisvana, aga koos nad täiendavad
teineteist. Objekt-orienteeritud lähenemise eelised on suuremad, kui
nad esimesel pilgul paistavad. Suurem tähelepanu objekti olulistele
omadustele sunnib tarkvarategijat mõtlema hoolikamalt ja sügavamalt
sellest, mis on objekt ja mida ta teeb, andes tulemuseks üldjuhul
puhtama, üldisema ja kindlama süsteemi, võrreldes sellega,
kui pöörata tähelepanu ainult andmete ja operatsioonide
kasutamisele. Ülaltoodud võimalused kokku annavad täiesti
erineva programmeerimisstiili.
Tarkvaratehnika metoodika on tarkvara loomise organiseeritud protsess, kasutades eelnevalt defineeritud tehnikate ja notatsioonireeglite kogumit. Metoodika esitatakse tavaliselt konkreetsete sammude jadana, kus iga sammuga on seotud vastavad tehnikad ja notatsioon. Need sammud on korraldatud elutsükliks, mis sisaldab arendustöö erinevaid faase. Täielik tarkvara elutsükkel ulatub algsest probleemipüstitusest läbi tarkvara analüüsi, projekteerimise realiseerimise ja testimise kuni tööfaasini, kus teostatakse hooldust ja täiendusi.
OMT tehnoloogia toetab kogu tarkvara elutsüklit. Antud töös on kirjeldatud peamiselt analüüsifaasi, kuid objekt-orienteeritud lähenemine on ennast tõestanud ka projekteerimise ja kodeerimise faasis. Samuti muudab see lihtsamaks testimise ja hoolduse, kus tavapäraseid meetodeid on märgatavalt muudetud. Objekt-orienteeritud lähenemine loob puhta, kergestimõistetava disaini, mida on lihtsam testida, hooldada ja laiendada, sest objektiklassid loovad loomuliku modulaarsuse.
OMT tarkvaraprojekteerimise metoodika koosneb järgmistest osadest:
Analüüs tegeleb rakenduse mõistmise ja analüüsimisega, kasutades vastava rakendusvaldkonna mõisteid. Analüüsifaasi sisendiks on probleemipüstitus, mis kirjeldab lahendust vajavat probleemi ning annab vajatava süsteemi kontseptuaalse ülevaate. Lisasisenditeks on pidev dialoog kliendiga ning teadmiste kogumine vastava rakenduse alal. Analüüsifaasi väljundiks on formaalne mudel, mis hõlmab süsteemi kolm peamist aspekti: objektid ja nendevahelised seosed, dünaamiline süsteemi kontroll ning funktsionaalne andmete teisendamine.
Süsteemi üldine arhitektuur pannakse paika süsteemidisaini käigus. Kasutades juhisena objektimudelit, jagatakse süsteem alamsüsteemideks. Tehakse otsustused protsessidevahelise kommunikatsiooni, andmete hoidmise ning dünaamilise mudeli realisatsiooni kohta. Seatakse prioriteedid selle kohta, mida edasise projekteerimise käigus optimiseerida.
Objektidisaini käigus vaadatakse üle ja viimistletakse analüüsifaasis saadud mudelid ning optimiseeritakse neid, et saada praktilist disaini. Objektidisaini ajal toimub ka nihe rakenduskesksetelt mõistetelt arvutikesksetele. Kõigepealt valitakse algoritmid süsteemi peamiste funktsioonide jaoks. Nende algoritmide põhjal optimiseeritakse objektimudeli struktuuri, et saada võimalikult efektiivset realisatsiooni. Edasi määratakse kindlaks iga assotsiatsiooni ja atribuudi realisatsioon ja lõpuks jagatakse alamsüsteemid mooduliteks.
OMT metoodikale vastavaid täpsemaid samme on kirjeldatud järgmiste
peatükkide lõpus olevais praktilistes näidetes.
(Rumbaugh 2.1-2.2)
Mudel on abstraktsioon, mis peaks võimaldama millestki arusaamist enne selle tegelikku loomist. Kuna mudel jätab kõrvale mittehädavajalikud detailid, on temaga lihtsam ümber käia kui tegeliku objektiga. Abstraktsioonide loomine on üks inimese iseloomulikumaid võimeid, mis laseb tal tegeleda keerukate süsteemidega. Mudeleid on loodud paljudel elualadel tuhandeid aastaid, erandiks pole ka tarkvaratootmine. Keerukate süsteemide rajamiseks tuleb abstraheerida mitmeid vaateid süsteemile, ehitada mudeleid spetsiaalset kokkulepitud notatsiooni kasutades, kontrollida, kas mudelid rahuldavad süsteemile esitatavaid nõudmisi ning lisada neile järk-järgult detaile kuni tegeliku realisatsiooniga vastavusse jõudmiseni.
Modelleerimise peamised ülesanded on:
Erinevad mudelid ei ole teineteisest täiesti sõltumatud – süsteem on midagi enamat kui sõltumatute osade kogum, aga iga mudelit saab suures ulatuses uurida ja mõista ka eraldiseisvana. Sidemed eri mudelite vahel on piiratud ja täpsed. Muidugi on võimalik luua ka halbu mudeleid, kus kolm mudelit on nii põimunud, et neid ei saa eraldada, kuid hea stiil on süsteemi eri aspektid teineteisest isoleerida ja nendevahelist suhtlust piirata.
Kõik kolm mudelit arenevad arendustsükli käigus. Analüüsifaasis
konstrueeritakse rakendusvalla mudel, pööramata tähelepanu
realiseerimiseks vajalikele küsimustele. Projekteerimisel lisatakse
mudelile probleemi lahenduseks vajalikud konstruktsioonid. Realiseerimise
käigus kodeeritakse mõlema valdkonna struktuurid.
(Rumbaugh 2.2.1)
Objektimudel kirjeldab süsteemi objektide struktuuri – nende identiteeti, seoseid teiste objektidega, nende atribuute ja operatsioone. Objektimudel annab meile raamistiku, millele rajada dünaamiline ja funktsionaalne mudel. Muutused ja transformatsioonid ei saa omada mõtet, kui pole midagi, mis muutuks või transformeeruks. Objektid on ühikud, milleks me oma maailma jagame.
Meie eesmärgiks on konstrueerida objektimudel, mis hõlmaks eneses päris elu mõisted, mis on olulised meie rakenduse jaoks. Modelleerides tehnilist probleemi, peaks me kasutama mõisteid, mis on tuttavad tehnikutele, majandusprobleemi puhul ärimeestele tuntud mõisteid, kasutajaliidese loomisel üldisi tavakasutajale arusaadavaid mõisteid. Analüüsil saadav mudel tohiks sisaldada arvutivalla mõisteid ainult siis, kui tegu on konkreetselt arvutiala probleemiga, nagu näiteks kompilaatori või operatsioonisüsteemi loomine. Projekteerimisjärgne mudel kirjeldab, kuidas probleemi lahendada ning võib sisaldada ka arvutispetsiifilisi konstruktsioone.
Objektimudel esitatakse graafiliselt, objektidiagrammidena, mis sisaldavad
objektiklasse. Klassid on korraldatud hierarhiana, vastavalt sellele, kuidas
nad jagavad ühist struktuuri ja käitumuslikkust. Klassid defineerivad
atribuudid, millele igas esindajas väärtused omistatakse ning
operatsioonid, mida iga objekt sooritab või mille parameetriks ta
on.
Objektimudeli koostamise eesmärk on objektide kirjeldamine. Näiteks Tartu Ülikool, kataloog C:\TEMP, Targo Tennisberg, protsess number 2342 või pealmine aken võivad olla objektid. Objekt on lihtsalt miski, millel on antud kontekstis mõte. Me defineerime objekti kui abstraktsiooni või mõiste, millel on antud probleemi jaoks olemas selge piiritlus. Objektidel on kaks eesmärki: nad aitavad mõista tegelikku maailma ja samas varustavad meid praktilise baasiga, millest lähtudes ehitada üles valdkonnale vastavat programmi. Probleemi lahutus objektideks sõltub konkreetsest analüütikust ja probleemi olemusest, pole olemas üheselt määratud korrektset esitust.
Kõik objektid on eristatavad. Kaks protsessorit võivad olla sama valmistaja, tüübi ja taktsagedusega, kuid nad on endiselt erinevad protsessorid, me võime nad mõlemad eri arvutite sisse panna. Ka identsed kaksikud on endiselt kaks eristatavat isikut, kuigi nad näevad sarnased välja.
Objektiklass kirjeldab objektigruppi, millel on sarnased omadused (atribuudid), ühine käitumine (operatsioonid), ühised seosed teiste objektidega ja ühine semantika. Ülikool, Kataloog, Üliõpilane, Protsess ja Aken on objektiklassid. Objektide ja objektiklasside märkimisel probleemikirjelduses kasutatakse tavaliselt nimisõnu. Sama klassi objektid erinevad üksteisest atribuutide väärtuste ja seoste poolest teiste objektidega, kuid võib esineda ka atribuutide ja seoste poolest identseid objekte.
Ühe klassi objektid jagavad sama semantilist tähendust, mis seisab kõrgemal atribuutidest ja sõltub konkreetsetest vajadustest. Näiteks võib hobusel ja tallil mõlemal olla vanus ja hind, kuid nad kuuluvad eri klassidesse. Samas, kui meil on vaja vaadelda neid ainult eelarve koostamisel, võime nad paigutada ka ühte klassi.
Iga objekt “teab” oma klassi. Enamik objekt-orienteeritud programmeerimiskeeli suudavad objekti klassi programmi töö ajal kindlaks teha, mingit liiki viide objektiklassile on seega objekti kohustuslik koostisosa.
Selleks, et objekte ja klasse korralikult kirjeldada, ei piisa ainult sõnadest ja näidetest, vaja läheb formalisatsiooni, et luua objektimudelit, mis oleks järjekindel, täpne ja selgesti mõistetav.
Objektidiagrammid annavad meile graafilise notatsiooni objektide, klasside ja nendevaheliste suhete kujutamiseks. Objektidiagrammid on kasulikud nii abstraktsel modelleerimisel kui ka tegelike programmide disainil. Objektidiagramme on kahte liiki – klassidiagrammid ja esindajadiagrammid.
Klassidiagramm on skeem või muster, mis kirjeldab palju võimalikke andmete esindajaid. Klassidiagramm kirjeldab objektiklasse. Esindajadiagramm kirjeldab, kuidas on omavahel seotud konkreetne hulk objekte. Esindajadiagramm on kasulik testjuhtumite (stsenaariumide) dokumenteerimisel ja näidete puhul. Klassidiagramm vastab lõpmatule hulgale esindajadiagrammidele.
Joonisel on näidatud klasside ja objektide esitus OMT notatsiooni kasutades:
Joonis 2-1 Klass ja objekt
Atribuudid on andmete konkreetsed väärtused, mida mingi klassi objektid eneses hoiavad. Nimi, vanus ja matriklinumber on klassi Üliõpilane objektide atribuudid. Värv, kaal ja väljalaskeaasta on klassi Auto objektide atribuudid Igal atribuudil on väärtus iga esindaja jaoks. Erinevatel esindajatel võivad olla samad või erinevad atribuudiväärtused. Iga atribuudi nimi on klassisiseselt unikaalne (aga teistes klassides võib selline atribuut olemas olla). Seega nii klassil Üliõpilane kui ka klassil Ülikool võib mõlemal olla atribuut aadress. Atribuut peaks olema lihtsalt väärtus, mitte objekt. Erinevalt objektidest pole väärtused eristatavad. Näiteks pole võimalik eristada kõiki arvu “24” esinemisi tekstis. Kui meil on objekt klassist Üliõpilane, siis 24 võib olla tema atribuudi vanus väärtuseks, aga eraldiseisvana ta mõtet ei oma. Kui meil on klass Riik ja klass Linn, siis riigi pealinn ei peaks olema esitatud atribuudina klassis Riik, vaid seda tuleks kujutada assotsiatsioonina nende kahe klassi vahel.
Atribuute kirjeldatakse diagrammil nii:
Joonis 2-2 Klassi atribuudid
Reaalse elu atribuute ei tohi segi ajada realisatsiooni sisemiste identifikaatoritega. Sisemised identifikaatorid on ainult realisatsioonietapi probleem ja neil pole vastavas rakenduses mingit tähendust. Analüüsi käigus tuleb kasutada ainult tegeliku elu mõisteid.
Operatsioon on funktsioon või transformatsioon, mida võib rakendada klassi objektidele või mida objektid saavad kasutada. Näiteks võivad klassil Aken olla operatsioonid ava, sule, peida, näita, liiguta, muuda suurust jne. Kõigil mingi klassi objektidel on samad operatsioonid. Igal operatsioonil on kohustusliku argumendina olemas tema sihtobjekt. Operatsiooni realisatsioon sõltub sellest sihtobjektist. Kuna iga objekt “teab” oma klassi, siis saab alati valida õige realisatsiooni.
Sama operatsiooni võib kasutada mitmete klasside puhul, siis nimetatakse seda operatsiooni polümorfseks, see tähendab, et sama operatsioon esineb erinevate klasside puhul erineval kujul. Operatsiooni teostus konkreetse klassi puhul on meetod. Näiteks võib klassil Fail olla operatsioon trüki, kuid olenevalt faili sisust (tekst, graafika, eritähendusega konstruktsioonid) võib trükkimine toimuda erinevalt.
Peale sihtobjekti võib operatsioonil olla ka teisi argumente. Sellised argumendid parametriseerivad operatsiooni, kuid ei mõjuta meetodi valikut. Meetod sõltub ainult sihtobjekti klassist.
Kui operatsioonil on meetodid mitmetes klassides, peab kõigil meetoditel olema sama signatuur – argumentide arv ja tüüp ning tagastatava väärtuse tüüp. Seega operatsioonil trüki ei tohiks olla ühel juhul argumendiks failinimi ja teisel juhul failipide. Samuti on mõttekas mitte anda samu nimesid kahele operatsioonile, mis on semantiliselt erinevad, kuigi nad kuuluvad eri klassidesse. Näiteks pole kuigi hea kasutada samas programmis operatsiooni liiguta nii akna kui ka malenupu liigutamise puhul.
Operatsioone kujutatakse diagrammil järgmiselt:
Joonis 2-3 Operatsioonid
Kokkuvõttes kujutatakse klasse ristkülikuna, mis on jagatud kuni kolmeks osaks: ülemises osas klassi nimi, keskmises atribuudid ja alumises operatsioonid.
Joonis 2-4 Klassi üldine esitus
2.4 Seosed objektide ja klasside vahel
(Rumbaugh 3.2)
Seos vastava mõistena on füüsiline või kontseptuaalne ühendus klassi esindajate vahel. Näiteks Targo Tennisberg õpib Tartu Ülikoolis. Matemaatiliselt on seos defineeritud kui esindajate järjestatud hulk. Seos on assotsiatsiooni esindaja.
Assotsiatsioon kirjeldab seoste hulka ja ühist semantikat. Näiteks üliõpilane Õpib ülikoolis. Kõik seosed assotsiatsioonis ühendavad samade klasside objekte. Assotsiatsioonid ja seosed esinevad probleemiesituses tavaliselt tegusõnadena. Assotsiatsioon kirjeldab võimalike seoste hulga samamoodi, nagu klass kirjeldab võimalike objektide hulga.
Programmeerimiskeeltes on assotsiatsioonid üldjuhul realiseeritud viitadena ühelt objektilt teisele. Viit on antud kontekstis atribuut ühes objektis, mis sisaldab täpset viidet teisele objektile. Näiteks võib klassi Üliõpilane andmestruktuur sisaldada atribuuti õppeasutus, mis viitab objektile klassist Ülikool, ja Ülikooli objekt atribuuti üliõpilased, mis viitab üliõpilaste hulgale. Assotsiatsioonide sel viisil realiseerimine on täiesti vastuvõetav, aga neid ei tohiks sel viisil modelleerida.
Seos näitab kahe (või enama) objekti omavahelist seotust. Seose modelleerimine viidana varjaks ära asjaolu, et seos pole mitte osa kummastki objektist, vaid sõltub neist mõlemast korraga. Ülikool ei ole osa üliõpilasest ja üliõpilane ei ole osa ülikoolist. Samuti, kui me kasutame vastastikuste viitade paari, Ülikoolilt Üliõpilaste hulgale ja Üliõpilaselt Ülikoolile, peidab see ära fakti, et need mõlemad viidad sõltuvad teineteisest. Seega tuleks kõik klassidevahelised sidemed kujutada assotsiatsioonidena, isegi programmidisainides. Tuleb rõhutada, et assotsiatsioonid pole mitte ainult andmebaasikonstruktsioonid, kuigi ka relatsioonilised andmebaasid on üles ehitatud assotsiatsioonide mõisteid kasutades.
Assotsiatsiooni notatsioon OMT-s on joon klasside vahel ja seose notatsioon joon objektide vahel (vt. joonist).
Joonis 2-5 Üksühene assotsiatsioon ja seos
Assotsiatsioon võib olla ka rohkem kui kahe erineva klassi vahel,
sel juhul kujutatakse seda rombina klasside vahel.
Joonis 2-6 Seos mitme
klassi vahel
Assotsiatsioonidele saab peale panna mitmeid kitsendavaid tingimusi, üldjuhul näitavad need seda, mitu objekti vastavatest klassidest omavahel seotud on.
Joonis 2-7 Mitu-mitmele seos
Joonis 2-8 Null või
üks seotud objekti
Täidetud ring tähistab üks-mitmele või mitu-mitmele seost, tühi ring seda, et seotud objekt võib ka puududa. Täidetud ringile võib olla juurde kirjutatud mitut laadi piirajaid stiilis “3”, “1-3, 5” jne.
Üldiselt kujutab atribuut endast objekti mingit omadust. Samamoodi võivad ka seosel olla atribuudid, mis kujutavad selle seose mingit omadust. Kui meil on näiteks seos õpib klasside Üliõpilane ja Ülikool vahel, siis on mõttekas siduda atribuudid nagu kursus ja keskmine hinne vastava seosega, mitte üliõpilasega, sest üliõpilane võib käia ka mitmes ülikoolis.
Vahel ongi kasulik kujutada assotsiatsiooni omaette klassina, sel juhul oleks seos selle klassi esindaja.
Joonis 2-9 Assotsiatsiooni
atribuudid
Assotsiatsioon võib olla kvalifitseeritud, see tähendab, et meil on seotud kaks klassi ja kvalifitseerija. Kvalifitseerija on spetsiaalne atribuut, mis vähendab tegelikku mitmesust assotsiatsioonis. Kvalifitseerida võib üks-mitmele ja mitu-mitmele assotsiatsioone. Kui ühele objektile vastab hulk teise klassi objekte, siis kvalifitseerija eristab sellest hulgast konkreetseid objekte. Kvalifitseerija kasutamist illustreerib järgmine joonis:
Joonis 2-10 Kvalifitseeritud assotsiatsioon
Palju parem on joonisel näidata, et kataloog ja failinimi määravad ära ka faili, kui kasutada ilma kvalifitseerijata assotsiatsiooni, mis ütleb ainult, et kataloogis võib olla palju faile.
Agregeerimine on “osa-tervik” või “osa millestki” suhe, kus objektid, mis tähistavad komponente, on seotud objektiga, mis esindab nende kogumit. Agregeerimist kujutatakse nii:
Joonis 2-11 Agregeerimine
Agregeerimise tähtsaimad omadused on transitiivsus ja antisümmeetria. Peale selle levivad mitmed terviku omadused ka osadele, näiteks võib instituutidel olla teaduskonnalt saadud atribuut dekaani nimi. Agregeerimine omab olulist mõtet ainult siis, kui osadel on ühiseid omadusi, mida saab omistada ka kogu tervikule. Kui on tegu mitte nii väga selgete juhtumitega, tuleks kasutada tavalist assotsieerimist. Agregeerimine on assotsieerimise tugev vorm, kus agregaatobjekt on valmistatud komponentidest ja komponendid on agregaadi osad. Semantiliselt on agregaat laiendatud objekt, mida käsitletakse paljude operatsioonide puhul ühe objektina, kuigi ta füüsiliselt koosneb mitmetest väiksematest üksustest. Üksikul agregaatobjektil võib olla mitut eri liiki osi – iga osa-tervik suhet võetakse eraldi agregatsioonina, et rõhutada sarnasust assotsieerimisega.
Modelleerimisel defineeritakse agregeerimine kui terviku klassi vastavusse viimine ühe komponentklassiga. Tervik, mis koosneb mitut liiki osadest, vastab mitmele agregeerimissuhtele. Seega on agregeerimine assotsieerimise spetsiifiline vorm.
Komponendi eksisteerimine võib sõltuda agregeeritud terviku
olemasolust. Näiteks ei saa olemas olla tekstilõiku, ilma et
oleks olemas teksti, millesse ta kuulub, kuid mikroprotsessor võib
eksisteerida ka ilma arvutita. Samuti võivad (aga ei pruugi) osad
esineda mitmes agregaadis. Mitmed agregaadi operatsioonid rakenduvad kogu
antud agregaadis esinevate agregeerimisseostega saadud transitiivsele sulundile
ja opereerivad nii otseste kui ka kaudsete osadega. Näiteks kui meil
on dokument, mis koosneb mitut eri liiki osadest, ja me tahame seda salvestada,
tuleb meil kasutada vastava dokumendiklassi salvestamismeetodit, mis omakorda
ei pruugi üldse midagi teada oma osade salvestamisest, vaid kutsub
lihtsalt välja nende osade vastavad meetodid, mis omakorda võivad
teha sedasama oma alamosadega jne. Iga elementaarne osa sealjuures “teab”
ise, kuidas ennast salvestada. Sellist protsessi nimetatakse propageerimiseks.
Tihti kasutatakse ka rekursiivset agregeerimist.
Üldistamine ja pärimine on võimsad abstraktsioonid jagamaks klasside sarnasusi, säilitades samas erinevused nende vahel. Näiteks võime me tahta modelleerida järgmist situatsiooni: Meil on veevärgivarustuse ladu, kus igal objektil on tootja, kaal ja maksumus. Pumpadel on lisaks näitajad surve ja läbilaskevõime kohta. Veepaakidel on näitajad ruumala ja surve kohta. Nüüd võimegi defineerida ainult üks kord kogu varustusele ühised jooned ja siis lisada detailid pumpade, paakide ja muude kategooriate jaoks. Üldistamine on seos klassi ning ühe või enama täpsustatud variandi vahel sellest. Antud juhul oleks siis klass Varustus klasside Pump ja Paak ülemklassiks ja vastavad täpsustatud variandid on alamklassid. Mingile alamklasside grupile omased atribuudid ja operatsioonid võtame kokku ülemklassis ja samas hakkab iga alamklass neid endiselt sisaldama.
Üldistamine ja pärimine on transitiivsed üle kuitahes paljude tasemete. Iga alamklassi esindaja on ühtlasi ka ülemklassi esindaja. Terminid eellane ja järglane viitavad klasside mitmetasemelisele üldistamisele. Klassi esindaja olek sisaldab endas väärtust iga atribuudi jaoks igast eellasklassist. Samuti võib järglasklassi esindajale rakendada suvalist eellasklassi operatsiooni. Alamklass mitte ainult ei päri kõiki oma eellaste omadusi, vaid lisab neile ka omaenda spetsiaalsed atribuudid ja operatsioonid. Näiteks lisatakse klassis Pump atribuut läbilaskevõime, mida muude varustuskategooriate puhul ei esine.
Üldistamise notatsioon on näha järgnevalt jooniselt (siin on ära toodud väike osa Microsoft Foundation Classes’i klassihierarhiast):
Joonis 2-12 Üldistamine
Üldistamine on kasulik konstruktsioon nii kontseptuaalsel modelleerimisel kui ka realiseerimisel. Üldistamine kergendab modelleerimist, struktureerides klasse ja efektiivselt kokku võttes, mida on klassides ühist ja erinevat. Operatsioonide pärimine on kasulik realiseerimise käigus, sama koodi taaskasutamisel.
Objekt-orienteeritud keeled toetavad pärimist tugevalt. (Pärimise kontseptsioon mõeldi tegelikult välja juba ammu, kuid alles objekt-orienteeritud programmeerimine tegi selle populaarseks). Samas ei toeta näiteks praegu kasutatavad andmebaasisüsteemid seda peaaegu üldse. Objekt-orienteeritud tarkvaratootmisega tegelejate seas on pärimine saanud peaaegu koodi taaskasutamise sünonüümiks. Pärast süsteemi modelleerimist vaadatakse saadud klassid tavaliselt üle selle mõttega, et leida võimalusi sarnaste klasside grupeerimiseks ja sama programmiteksti uuesti kasutamiseks. Tihti tekivad sellise töö käigus klassiteegid, mis on kättesaadavad läbi mitme projekti ning mida on alati võimalik konkreetses projektis uuesti kasutada ja modifitseerida, et saada täpselt vajalikku tulemust. Sellegipoolest jääb peamiseks kasutoojaks päritavuse puhul süsteemi kontseptuaalne lihtsustumine, mis tuleneb teineteisest sõltumatute detailide arvu vähenemisest.
Terminid päritavus, üldistamine ja spetsialiseerimine viitavad kõik ühe ja sama idee eri aspektidele ja neid kasutatakse vahelduvalt. Antud kontekstis tähendab üldistamine teatud klassidevaheliste seoste loomist, pärimine viitab seda suhet kasutades saadavale atribuutide ja operatsioonide jagamise mehhanismile ning spetsialiseerimine osutab faktile, et alamklassid kitsendavad ja täpsustavad ülemklassis defineeritud mõistet.
Alamklass võib oma eellase omadusi ümber defineerida, kirjeldades uuesti sama nimega omaduse. Sellisel juhul alamklassi omadus asendab vastava ülemklassi omaduse. Ümberdefineerimist võib kasutada mitmel põhjusel – täpsustamaks konkreetsest alamklassist sõltuvat käitumist, omaduse spetsifikatsiooni parandamiseks ja tihendamiseks või parema jõudluse saavutamiseks.
Näiteks võib meil olla klass Funktsioon ja meetod joonista tema graafiku joonistamiseks. Samas, kui meil läheb tarvis palju ringjooni, võime defineerida vastava klassi Ringjoon. Ringi puhul pole aga mõtet iga tema punkti otse vastava võrrandi põhjal arvutada, vaid võime kasutada näiteks märksa efektiivsemat Bresenhami algoritmi. Siis kirjutamegi uue meetodi spetsiaalselt ringide joonistamiseks.
Ümber võib defineerida atribuutide vaikeväärtusi või operatsioonidele vastavaid meetodeid, kuid ei tohi muuta nende signatuuri. Uus definitsioon peab säilitama atribuuditüübi, operatsiooni argumentide arvu ja tüübi ning tagastatava väärtuse tüübi. Atribuudi või operatsiooni argumendi tüüpi võib piirata, kuid seda tuleb teha ettevaatusega. Üsna tavaline on programmi jõudluse parandamine defineerides üldise meetodi ümber ja asendades ta spetsiaalse meetodiga, mis kasutab mingit erilist lisainformatsiooni, kuid ei muuda operatsiooni semantikat.
Ühtegi omadust ei tohiks ümber defineerida selliselt, et ta jääb ülemklassi omaga signatuuri või semantika poolest mitteühilduvaks. Alamklass on ülemklassi erijuht ja peaks olema igas mõttes ülemklassiga ühilduv. Levinud, kuid mitte eriti hea tava objekt-orienteeritud programmeerimises on soovitud klassiga sarnase klassi “laenamine” ning seejärel selle modifitseerimine mõningaid omadusi muutes või ignoreerides, seda isegi juhul, kui uus klass ei ole enam vana klassi erijuht. Selline toimimine võib viia mõistelise segaduse ning programmidesse sisseehitatud peidetud eeldusteni.
Vahel võib meil vaja minna abstraktseid klasse, s.o. klasse, millel endal pole otseseid esindajaid, kuid mille järglastel on. Vastupidine mõiste on konkreetne klass, millel võivad olla esindajad. Pärimispuu lehtedeks võivad olla ainult konkreetsed klassid.
Abstraktsed klassid organiseerivad eri klasside omadusi. Tihti on kasulik tekitada abstraktne ülemklass, et kapseldada klasse, mis kuuluvad sama assotsiatsiooni või agregatsiooni koosseisu. Üldjuhul kasutatakse abstraktseid klasse meetodite defineerimiseks, mida alamklassid pärida saavad. Samas võib klass aga jätta operatsiooni üldse meetodiga varustamata, seda nimetatakse siis abstraktseks operatsiooniks.
Näiteks võib meil olla abstraktne klass Fail, millest
saame pärida klassid Tekstifail, Rastergraafikafail ja Vektorgraafikafail.
Sellel klassil on abstraktsed operatsioonid salvesta ja trüki,
kuid pole meetodit nende operatsioonide realiseerimiseks, kuna eri tüüpi
faile salvestatakse ja trükitakse erinevalt. Need meetodid on aga
olemas vastavates järglasklassides, s.t. kitsendatud tüüpi
faile me saame juba trükkida ja salvestada.
2.6 Praktiline näide – sularahaautomaat
Vaatleme näitena järgmist ülesannet: Meil on vaja projekteerida tarkvara, mis toetaks sularahaautomaatide (edaspidi ATM – automated teller machine) võrku, mida kasutab mitu panka. Igal pangal on oma keskarvuti oma kontode haldamiseks ja nendel tehingute sooritamiseks. Siis on veel olemas tellerid oma arvutitega, mis on ühendatud otse vastava panga keskarvutiga. Tellerid sisestavad kontode ja tehingute andmeid, sularahaautomaadid suhtlevad keskarvutiga, mis seejärel sooritab vastavaid tehinguid. ATM võtab vastu kaardi, suhtleb kasutaja ja kesksüsteemiga, et toimetada tehinguid, annab välja sularaha ja trükib kviitungeid. Süsteem vajab korralikku arvepidamist ja turvalisuse kontrolli. Samuti on vaja korrektselt korraldada üheaegseid juurdepääsusoove samale kontole. Pankadel on oma tarkvara omaenese arvutite jaoks, meil on vaja luua tarkvara automaatide ja võrgu jaoks. Jagatud süsteemi maksumus läheb jagamisele pankade vahel, vastavalt seda kasutanud klientide arvule.
Tegeliku elu objektimudeli koostamisel võib OMT metoodika kohaselt eristada järgmisi samme:
Sõnadel ilma kontekstita võib olla palju tõlgendusi, seetõttu tuleb meil luua andmesõnastik kõigi üksuste jaoks, mida me kavatseme modelleerida. Tuleb luua kirjeldus iga üksuse jaoks, lähtudes konkreetsest probleemist ja kirjeldades ühtlasi ära kõik eeldused ja piirangud nende kasutamisel. Andmesõnastik kirjeldab ka assotsiatsioone, atribuute ja operatsioone. Antud juhul tuleb andmesõnastik järgmine:
Joonis 2-13 Sularahaautomaatide
süsteemi objektimudel
(Rumbaugh 5)
Ajast sõltuvatest objektidevahelistest seostest on tihti raske aru saada. Süsteem on kõige paremini mõistetav, kui kõigepealt uurida selle staatilist struktuuri, s.t. objektide ja nende suhete struktuuri konkreetsel fikseeritud ajamomendil, ning seejärel objektides ja nende seostes aja möödudes esinevaid muutusi. Süsteemi ajast sõltuvad aspektid võetakse kokku dünaamilises mudelis. Siin vaadeldakse välistele mõjutajatele vastusena toimuvate operatsioonide rida, pööramata tähelepanu sellele, mis operatsioonid need on, milliste objektidega nad tegelevad või kuidas nad realiseeritud on. Dünaamilise modelleerimise peamised mõisted on sündmused, mis vastavad välistele mõjutajatele, ja olekud, mis väljendavad objektide väärtusi. Olekudiagramm on tavaline arvutiteaduse mõiste, mida kasutatakse lõplike automaatide graafilisel kujutamisel. Olenevalt konkreetsest kasutusalast on seda kirjanduses käsitletud eri viisidel, antud töös pööratakseähelepanu sündmuste ja olekute kasutamisele süsteemi kontrolli seisukohalt, mitte niivõrd algebralistele konstruktsioonidele.
Objektimudel kirjeldab süsteemi kõiki võimalikke
objekte, atribuute ja seoseid. Objekti konkreetset atribuutide väärtuste
ja seoste kogumit nimetatakse olekuks. Aja jooksul mõjutavad
objektid teineteist, põhjustades muutusi nende olekutes. Ühte
konkreetset juhtumit, kus üks objekt mõjutab teist, nimetatakse
sündmuseks. Reaktsioon sündmusele sõltub objekti olekust
ja võib tähendada oleku muutumist või uue sündmuse
saatmist mõnele muule objektile.
Sündmus on miski, mis leiab aset kindlal ajahetkel, näiteks kasutaja vajutas klahvi ‘A’ alla. Sündmusel pole ideaaljuhul kestust, võrreldes antud abstraktsiooni ajaskaalaga on see kaduvväike. Üks sündmus võib loogiliselt eelneda või järgneda teisele või võivad nad olla seostamata. Kasutaja saab klahvi ‘A’ lahti lasta alles siis, kui ta on eelnevalt alla vajutatud, need sündmused on omavahel seotud. Samas võib kasutaja alla vajutada või lahti lasta klahvi ‘B’, need sündmused ei oma eelmistega seost.
Sündmus on ühesuunaline informatsiooni liikumine ühest objektist teise. See pole nagu alamprogramm, mis võib väljakutsujale mingi väärtuse tagastada. Objekt, mis teisele sündmuse saadab, võib oodata vastust, kuid sel juhul peab see olema teine sündmus ja selle saatmine on teise objekti otsustada.
Iga sündmus on unikaalne,
kuid need grupeeritakse sündmusklassidesse, andes igale klassile
nime, mis näitab nende ühist struktuuri ja esinemisviisi. Nende
klasside struktuur on hierarhiline nagu tavaliste objektiklasside struktuurgi.
Näiteks sündmused kasutaja vajutas klahvi ‘A’ alla ja
kasutaja
vajutas klahvi ‘B’ alla kuuluvad klassi klahvi allavajutus.
Sündmus edastab infot ühelt objektilt teisele. Mõned sündmused
on lihtsalt signaalid, mõnedel on aga atribuudid, mis hoiavad nende
poolt edastatavat informatsiooni. Näiteks meie klahvivajutuse sündmus
võib sisaldada vastava klahvi koodi, samuti ka klahvide Shift,
Ctrl ja Alt asendit vajutamise hetkel. Vaikimisi on iga sündmuse
atribuudiks tema toimumise aeg. Atribuute näidatakse sulgudes sündmuse
nime järel.
Joonis 3-1 Näiteid sündmusklassidest
Olek on objekti atribuutide väärtuste ja seoste abstraktsioon. Väärtuste hulgad grupeeritakse olekuteks vastavalt omadustele, mis oluliselt mõjutavad objekti olemust. Näiteks võib üliõpilane olla päevases või kaugõppes või üleüldse ülikoolist eksmatrikuleeritud. Olek määrab ära objekti reaktsiooni sündmustele. Reaktsioon võib kvantitatiivselt sõltuda atribuutide konkreetsetest väärtustest, kuid kvalitatiivselt jääb ta sama oleku piires alati samaks ning võib kvalitatiivselt erineda vaid objekti erinevate olekute puhul. Sündmusele reageerimine võib tähendada mingit tegevust või objekti oleku muutumist.
Olgu meil näiteks objekt Telefon, me võtame toru ja hakkame numbrit valima. Üksikute numbrite valimine viib telefoni olekust pidev toon olekusse valimine, kusjuures pole tähtis, milliseid numbreid konkreetselt valiti.
Olek vastab kahe sündmuse vahelisele intervallile. Näiteks võib meil olla objekt Lamp, mis võtab vastu sündmusi lülitamine, nende sündmuste vahepeal on ta vastavalt olekutes põleb ja ei põle.
Olek on tihti seotud sellega, et objekti atribuutide väärtused rahuldavad teatud tingimust. Näiteks kui rõhk veepaagis ületab 50 atm, läheb paak olekust normaalne rõhk olekusse ohtlik rõhk ja kontrollsüsteem peab hakkama sündmustele teisiti reageerima. Lihtsamal juhul on meil tegu ka reaalses elus diskreetselt eristatavate väärtustega, näiteks võib üliõpilase olek olla esimesel kursusel, teisel kursusel, kolmandal kursusel, neljandal kursusel või magistrantuuris.
Olekuid defineerides jäetakse kõrvale need atribuudid, mis
ei puuduta otseselt objekti olemust ja me koondame kokku ühte olekusse
kõik need atribuudiväärtuste ja seoste kombinatsioonid,
mis reageerivad sündmustele samamoodi. Loomulikult mõjutab
iga atribuut mingil määral objekti käitumist, muidu poleks
tal mõtet, kuid tihti ei mõjuta paljud atribuudid iseenesest
sündmuste järjekorda ning neist võib mõelda lihtsalt
kui mingitest olekusisestest parameetriväärtustest. Meenutame
siinkohal, et modelleerimise eesmärk üleüldse on pöörata
tähelepanu süsteemi nendele detailidele, mis on tähtsad
probleemi lahenduse seisukohalt ja ülejäänud kõrvale
jätta. Kolm OMT mudelit (objekti-, dünaamiline ja funktsionaalne)
esitavad süsteemi erinevaid vaateid, atribuutide konkreetne valik
ei pruugi eri vaadetes sama olla. Kui näiteks üliõpilane
on teisel kursusel, ei oma tähtsust, milliseid aineid ta just konkreetselt
kuulab ja milliseid hindeid nende eest saab, need iseenesest ei mõjuta
tema akadeemilist staatust, seega võime selle kõik kokku
võtta olekuna teisel kursusel. Mõnikord on olulised
ka kõik atribuudiväärtused, kuid sel juhul on nende hulk
tavaliselt suhteliselt väike. Nii sündmused kui ka olekud sõltuvad
abstraheerimise tasemest, ei ole mingit kindlat reeglit, mille alusel konkreetset
süsteemi kujutada.
Olekudiagramm käsitleb sündmusi ja olekuid. Kui sündmus saabub, sõltub järgmine olek nii senisest olekust kui ka sündmusest, sündmuse poolt esile kutsutud olekumuutust nimetatakse üleminekuks. Olekudiagramm on suunatud graaf, mille tippudeks on olekud ja kaarteks üleminekud, millele on kirjutatud vastava sündmuse nimi.
Olekudiagramm määrab ära olekute järjestuse, mille määrab sündmuste järjestus. Kui objekt on ühes olekus ja leiab aset sündmus, mis vastab ühele tema üleminekutest, siis läheb objekt üleminekut tähistava noole otsas asuvasse olekusse – st sündmus vallandab ülemineku. Kui olekust lahkuvaid üleminekuid on mitu, siis esimene saabuv sündmus vallandab vastava ülemineku. Kui toimub sündmus, millele vastavat üleminekut ei ole, siis seda sündmust lihtsalt ignoreeritakse. Sündmuste jada vastab teele graafis.
Toome siinkohal klassikalise näite telefoniga helistamisest:
Joonis 3-2 Telefoniga
helistamise olekudiagramm
Olek ei määra täielikult ära objekti kõiki väärtusi, näiteks pole olekus ühendamine üheselt määratud, milline number tegelikult valiti.
Olekudiagramm kirjeldab ühe konkreetse klassi objektide käitumist. Kuna klassi kõigil esindajatel on definitsiooni kohaselt sama käitumisviis, jagavad nad kõik ühte ja sedasama olekudiagrammi, nagu nad jagavad ka muid selle klassi omadusi. Aga kuna igal objektil on omaenda atribuudiväärtused, on tal ka oma olek ning oma sündmuste järjekord, mis temani jõuab. Iga objekt on teistest sõltumatu. Olekudiagramm võib kujutada objekti elutsüklit või siis lõpmatut tsüklit. Esimesel juhul kirjeldatakse lõpliku elueaga objekte – see tähendab, et neil on olemas algolekud, mis tähistavad objekti loomist, neid tähistatakse täidetud ringina, ning lõppolekud, mis tähistavad objekti hävitamist, neid tähistatakse rõngaga ümbritsetud samasuguse ringina.
Joonis 3-3 Malemängu
lihtsustatud olekudiagramm
Dünaamiline mudel on olekudiagrammide kogumik, mis suhtlevad
teineteisega jagatud sündmuste abil. Olekudiagramm, nagu objektiklasski,
võib kirjeldada palju võimalikke sündmuste ahelaid.
Stsenaarium on dünaamilise mudeli jaoks umbes sama, mis esindajadiagramm
objektimudeli jaoks.
Olekudiagrammidest oleks vähe kasu, kui nad kirjeldaksid ainult sündmuste mustreid. Objekti käitumise kirjeldus peab määrama ära ka selle, mida objekt sündmuse saabudes teeb. Olekute või üleminekutega võivad seotud olla operatsioonid, mida vastavasse olekusse jõudmise või ülemineku toimumise puhul sooritatakse.
Aktsioon on hetkeliselt toimuv operatsioon. Aktsioonid on seotud sündmustega, ta esitab operatsiooni, mille kestus on antud olekudiagrammi mõõtkavas tähtsusetu.
Aktsioonid võivad esitada ka sisemisi kontrolloperatsioone nagu atribuutide väärtuste seadmist või uute sündmuste genereerimist. Sellistel aktsioonidel pole vastet tegelikus elus, need on mehhanismid realisatsiooniaegse programmi juhtimise struktureerimiseks. Näiteks võime me suurendada mingi sisemise loenduri väärtust iga kord, kui teatud konkreetne sündmus aset leiab. Arvutis võtab iga operatsioon siiski teatud hulga aega, kuid tõelisi sündmusi eraldavate ajavahemikega võrreldes võime nad lugeda hetkelisteks.
Aktsiooni notatsioon üleminekus on kaldkriips (‘/’) sündmuse
nime järel ja sellele järgnev aktsiooni nimi.
Joonis 3-4 Aktsioonid
hiire parempoolse nupu vajutamisel
Toiming on operatsioon, mille sooritamine võtab aega.
Toiming on seotud olekutega, nad sisaldavad enestes kestvaid operatsioone,
nagu näiteks animatsiooni näitamine ekraanil või operatsioone,
mis teatud aja möödudes ise ära lõppevad, näiteks
mingite arvutuste sooritamine. Toimingu notatsioon on “do: Toimingunimi”
olekut tähistavas kastis oleku nime all.
Joonis 3-5 Toimingu
notatsioon
3.5 Keerukamad konstruktsioonid
Olekudiagramme võib struktureerida, et võimaldada suurte ja keerukate süsteemide kirjeldamist. Olekudiagrammid struktureerimise põhimehhanismid on samad, mis objektide struktureerimiselgi: üldistamine ja agregeerimine. Üldistamine on samaväärne teineteises sisalduvate toimingutega. See võimaldab kirjeldada toimingut kõrgel tasemel ning siis minna allapoole, et lisada detaile, sarnaselt hierarhiliste alamprogrammide väljakutsetega. Lisaks võimaldab üldistamine olekute ja sündmuste korraldamist hierarhiatesse, kasutades ühise struktuuri ja käitumisviisi puhul pärimist, sarnaselt pärimisega klasside puhul. Agregeerimine võimaldab oleku lõhkumist komponentideks, mille omavaheline suhtlus on piiratud, sarnaselt objektide agregeerimishierarhiaga. Agregeerimine on samaväärne olekute kokkulangemisega.
Tavalise olekudiagrammi puhul tekib probleem, et tal on väidetavalt
vähe võimsust ja suurte probleemide puhul on ta ebapraktiline.
Need probleemid kehtivad struktureerimata olekudiagrammi puhul. Tõepoolest,
olgu meil n sõltumatut tõeväärtusatribuuti,
mis süsteemi juhtimist mõjutavad. Tavalise olekudiagrammi puhul
läheks sellise olukorra jaoks vaja 2n olekut. Eraldades
süsteemi aga n sõltumatuks olekumasinaks, läheb
vaja ainult 2n olekut. Või vaatame joonisel olevat olekudiagrammi,
kus on vaja n 2 üleminekut, et ühendada kõik
olekud omavahel.
Joonis 3-6 Üleminekute
arvu kasv olekute arvu kasvades
Kui seda mudelit struktureerida, võib üleminekute arvu vähendada n-ni. Kõigis keerulistes süsteemides on suur hulk liiasust, mida võib ära kasutada olekudiagrammide lihtsustamiseks, kui meil on olemas vajalikud struktureerimismehhanismid.
Oleku sees oleva tegevuse võime muuta omaette madalama tasemega olekudiagrammiks, kus iga olek tähistab tegevuse üht sammu. Teineteises sisalduvad tegevused sarnanevad alamprogrammidele, nende hulk moodustab võre. (Kui me eristame teineteisest sama diagrammi erinevad koopiad, siis saame puu).
Teineteises sisalduvad olekudiagrammid tähistavad üldjuhul olekute üldistamist. Üldistamine on “või-seos”. Objekt, mis on kõrgema taseme diagrammil mingis olekus, peab madalama taseme diagrammil olema täpselt ühes olekus, kas siis esimeses või teises või mõnes teistest olekutest. Madalama taseme olekud on kõrgema taseme olekute täpsustused.
Olekutel võivad olla alamolekud, mis pärivad üleminekud oma ülemolekutelt. Iga üleminek või aktsioon, mis rakendub mingile olekule, rakendub ka kõigile tema alamolekutele.
Nagu olekute puhul, võib ka sündmusi üldistamist kasutades
hierarhiasse korraldada, pärides sündmuste atribuute.
3.5 Praktiline näide – sularahaautomaat
Jätkame eelmises peatükis alustatud sularahaautomaatide võrgu näite vaatlemist. Dünaamilise mudeli loomisel tuleb kõigepealt valmistada ette stsenaariumid tüüpdialoogide jaoks. Kuigi need stsenaariumid ei pruugi katta kõiki juhtumeid, on vähemalt kindel, et tähtsamad interaktsioonid pole kahe silm vahele jäänud. Stsenaariumid tuleb luua nii tavapäraste dialoogide jaoks kui ka sellisteks juhtumiteks, kus tekivad eriolukorrad (antud juhtumil näiteks vale PIN-koodi sisestamine). Samuti tuleb mõelda piirjuhtumite peale (sisendandmete minimaalsed ja maksimaalsed väärtused jne). Kasutajal peaks võimalikult paljudes kohtades olema võimalus töö katkestada. Veel peab iga sündmuse juures olema kirja pandud, kes on selle algatajaks.
Vaatleme üht sellist dialoogi antud näite puhul. Esimesena on toodud stsenaarium, kus kõik on korras.
Järgmiseks tuleb luua mingi ligikaudne pilt süsteemi kasutajaliidesest,
et kindlaks teha, kuidas informatsioon täpselt liigub ja siis kindlaks
teha kõik süsteemis liikuvad sündmused. Korralikult koostatud
stsenaariumide puhul on sündmuste leidmine suhteliselt lihtne. Enne
olekudiagrammi tegemist tuleb kasuks stsenaariumide ja leitud sündmust
põhjal järgnevusdiagrammide koostamine, neid on käsitletud
kuuenda peatüki neljandas punktis. Lõpuks saame joonistada
olekudiagrammid. Olekudiagrammid tuleks teha iga klassi jaoks, mille dünaamiline
(ajast sõltuv) käitumine pole triviaalne. Antud juhul saame
järgmised diagrammid:
Joonis 3-7 Sularahaautomaadi
objektimudel
Joonis 3-8 Klassi
Pankade
grupp olekudiagramm
Joonis 3-9 Klassi
Pank
olekudiagramm
4. Funktsionaalne modelleerimine
Funktsionaalne mudel kirjeldab süsteemis toimuvaid arvutuslikke
protsesse, näidates ära, mis juhtub, kui dünaamiline
mudel näitab seda, millal juhtub ja objektimudel näitab,
millega
juhtub. Funktsionaalne mudel näitab, kuidas arvutusel saadakse
sisendandmetest väljundandmed, kujutades endast andmevoodiagrammide
kogumit, mis näitavad andmete sisestamist ja liikumist läbi sisemiste
operatsioonide ja andmehoidlate kuni väljastamiseni. Andmevoodiagrammid
ei näita juhtsüsteemi või objektide struktuuri, see kuulub
dünaamilise ja objektimudeli juurde.
Funktsionaalne mudel määratleb arvutuse tulemused, näitamata täpsemalt, kuidas ja millal neid leitakse. Funktsionaalne mudel annab objektimudeli igale operatsioonile ja dünaamilise mudeli tegevusele tähenduse. Mitteinteraktiivsetel programmidel nagu näiteks kompilaatorid, on triviaalne funktsionaalne mudel, nende ülesandeks on mingi funktsiooni arvutamine. Sellisel juhtumil on funktsionaalne mudel nende programmide põhiline mudel, kuigi ka objektimudel on tähtis iga mittetriviaalsete andmestruktuuridega programmi jaoks. Kontrastina on andmebaasidel tihti vastupidises mõttes triviaalne funktsionaalne mudel, kuna nende eesmärgiks on andmeid säilitada ja korrastada, mitte neid teisendada.
Teatud tüüpi funktsionaalne mudel on näiteks tabelarvutusprogrammi tabel. Üldjuhul on tabelis olevad väärtused triviaalsed ja neid ei saa rohkem struktureerida, ainus huvitav objektistruktuur on tabel ise. Sellise tabeli eesmärgiks on esitada väärtusi teiste väärtuste mõistetes.
Kompilaatori töö on peaaegu puhas arvutamine. Selle sisend on mingis keeles kirjutatud programmi tekst, väljund on objektifail, mis seda programmi teises keeles realiseerib, tavaliselt siis antud arvuti masinkeeles. Kompileerimise mehaanika iseenesest ei oma rakenduse seisukohalt tähtsust.
Maksumaksmisele saab samas koostada mahukama funktsionaalse kirjelduse,
mis sisaldab valemeid maksumäära arvutamiseks, arvestades sissetulekut,
kulutusi, annetusi, perekonnaseisu jne. Siin tuleb meil ka defineerida
objektid (sissetulek, mahaarvamised) ja see sisaldab dünaamilist informatsiooni
(millal makse maksta, millal arvutada oodatavaid sissetulekuid, millal
saata sissetulekutõendid töötajatele). Maksuankeedid,
nendel olevad andmed ja nende struktuur annavad meile maksumäärade
arvutamise algoritmi, määratledes, kuidas saada tulemust sisendandmetest
nagu sissetulek, kulutused, mahaarvamised ja muud. Märgime, et ankeet
annab meile vaid algoritmi, mitte tegeliku funktsiooni, kus oleks täpselt
määratletud, milliseid operatsioone millises järjekorras
sooritada. Kontrastina on meil programmis tavaliselt antud arvutamise funktsioon,
mitte algoritm. Võrdluseks, maksumaksja ei pea ankeeti täitma
mingis konkreetses järjekorras, et tulemust saada.
Funktsionaalne mudel koosneb andmevoodiagrammidest, mis määratlevad operatsioonide ja andmetel olevate piirangute tähendused. Andmevoodiagramm näitab süsteemis arvutatavate väärtuste funktsionaalset suhet, sisaldades sisend- ja väljundandmeid ning andmehoidlaid. Andmevoodiagramm on graaf, mis näitab andmete voogu lähetest läbi protsesside, mis neid modifitseerivad, kuni sihtideni. Andmevoodiagramm ei sisalda juhtinformatsiooni nagu aeg, millal protsessid käivitatakse või otsustused erinevate võimaluste vahel, see informatsioon kuulub dünaamilise mudeli juurde. Samuti ei näita andmevoodiagramm andmete organiseerimist objektideks, seda tehakse objektimudelis.
Andmevoodiagramm sisaldab protsesse, mis andmeid teisendavad,
andmevooge,
mis andmeid teisaldavad, tegelased, mis andmeid toodavad ja tarbivad
ning andmehoidlad, kus andmeid passiivselt säilitatakse.
Joonis 4-1 Andmevoodiagramm
ikooni näitamisest akendatud graafika puhul
Vaatleme nüüd lähemalt andmevoodiagrammi elemente:
Protsess teisendab andmeid. Madalaima taseme protsessid on tavalised funktsioonid, millel puuduvad kõrvalefektid. Tüüpilised funktsioonid on näiteks kahe arvu summeerimine, teenustasu arvutamine krediitkaardiga sooritatud tehingutelt ja läbi punktihulga kulgeva splaini arvutamine. Andmevoodiagramm tervikuna on kõrgtaseme protsess. Protsessil võib olla kõrvalefekte, kui ta sisaldab ka mittefunktsionaalseid komponente nagu andmehoidlad või välised objektid. Kõrvalefektidega protsesside puhul ei määra funktsionaalne mudel üheselt süsteemi käitumist. Funktsionaalne mudel ainult näitab kõiki võimalikke teid, mitte seda, milline variant tegelikult aset leiab. Sellise protsessi tulemus sõltub süsteemi käitumisest, mille määrab ära dünaamiline mudel. Mittefunktsionaalsete protsesside näited on failide lugemine ja kirjutamine, iseõppiv hääletuvastusalgoritm, piltide näitamine tööjaama akendussüsteemis.
Protsessi kujutatakse ellipsina, millesse on kirjutatud teisenduse kirjeldus, tavaliselt selle nimi. Igal protsessil on fikseeritud arv sisend- ja väljundandmete nooli, millest igaüks kannab kindlat tüüpi väärtust. Sisenditele ja väljunditele võib juurde kirjutada täpsustava nime, mis näitab nende rolli arvutuses, kuid tavaliselt piisab andmetüübist. Protsessil võib olla ka mitu väljundit. Joonisel on näidatud üks madaltaseme protsess ja eelmisel joonisel toodud diagramm, mis on koondatud üheks kõrgtaseme protsessiks.
Joonis 4-2 Protsessid
Diagramm näitab ainult sisendi ja väljundi teid, kuid tuleb näidata ka väljundi arvutamist sisendist. Kõrgtaseme protsessi saab jagada eraldi andmevoodiagrammiks, täpselt nagu alamprogrammi on võimalik jagada madalama taseme alamprogrammideks. Mingil hetkel jõuame sel viisil atomaarsete protsessideni, mida saab kirjeldada loomulikus keeles, matemaatilise valemi abil või muul moel. Atomaarsed protsessid on üldjuhul triviaalsed, nad võivad näiteks lihtsalt pärida mingilt objektilt teatud atribuudi väärtuse.
Andmevoog ühendab ühe objekti või protsessi
väljundi teise objekti või protsessi sisendiga. See esitab
andmete vahepealset väärtust, voo jooksul andmete väärtus
ei muutu. Andmevoogu tähistatakse noolena, millele on kirjutatud andmete
kirjeldus, tavaliselt andmetüüp. Samu andmeid võib kasutada
erinevates kohtades, samuti võib jagada andmed osadeks, mis kõik
lähevad erinevatesse protsessidesse. Vastavalt sellele lahutatakse
andmevoogu kujutav nool siis osadeks, nagu joonisel näidatud.
Joonis 4-3 Andmevoo
jagamine osadeks
Iga andmevoog tähistab üht väärtust arvutuste mingis faasis. Diagrammisiseselt võivad need olla mingid vaheväärtused, mis tegelikus elus ei pruugi mingit tähendust omada. Diagrammi piiril olevad vood tähistavad sisendit ja väljundit. Need vood võivad olla ühendamata (kui meie diagramm on osa mingist suuremast süsteemist) või olla ühendatud objektidega. Joonisel 4-1 on sisenditeks ikooni nimi ja asukoht, see, kust nad tulevad, peab olema määratud laiemas kontekstis, milles seda diagrammi kasutatakse. Väljundid sellel joonisel on pikselioperatsioonid, mis saadetakse ekraanipuhvri objektile. Samad sisendid ja väljundid esinevad joonisel 4-2, kus kogu eelmine diagramm on abstraheeritud üheksainsaks protsessiks.
Tegelane on aktiivne objekt, mis juhib andmevoodiagrammi, kas siis andmeid tootes või tarbides. Tegelased on ühendatud diagrammi sisendite ja väljunditega. Tegelasteks võivad olla näiteks programmi kasutaja, arvuti poolt kontrollitav treipink vms. Tegelaste konkreetsed tegevused jäävad andmevoodiagrammist välja, neid vaadeldakse dünaamilises mudelis.
Tegelasi tähistatakse ristkülikutena, mis näitavad, et tegu on objektiga. Näiteks ekraanipuhver joonisel 4-1 on tegelane, mis tarbib pikselioperatsioone.
Andmehoidla on passiivne objekt andmevoodiagrammis, mis säilitab andmeid hilisema juurdepääsu tarvis. Erinevalt tegelasest, ei genereeri andmehoidla mingeid operatsioone, vaid ainult vastab soovidele andmeid hoiule panna ja välja anda. Andmehoidla võimaldab andmetele ligipääsu erinevas järjekorras, võrreldes järjekorraga, milles nad on tekitatud. Andmehoidlateks võivad olla näiteks lennuliini piletireserveeringute andmebaas, pangakonto või eelmise päeva õhutemperatuuride vaatlusandmete kogum.
Andmehoidlat kujutatakse kahe paralleelse joonena, mille vahele on kirjutatud hoidla nimi. Hoidlasse sisenevad nooled tähistavad informatsiooni või operatsioone, mis modifitseerivad säilitatavaid andmeid, see tähendab nii andmete lisamist, kustutamist kui ka muutmist. Väljuvad nooled tähistavad andmete võtmist andmehoidlast. See võib tähendada nii mingi terve objekti kui ka selle atribuudi võtmist. Objekti tegelik struktuur on ära määratud objektimudeliga, seal on näidatud ka atribuutidele ligipääsu ja nende modifitseerimise lubatavad operatsioonid.
Järgmises näites on kujutatud müügiga tegeleva firma
hinnakirja. Hinnakirja sisestatakse kaubaartiklite nimed ja hinnad. Hiljem
leitakse etteantud kauba nimetuse põhjal tema hind. Andmehoidlast
väljuv kirjata nool tähendab, et kogu hinnakiri on vastava protsessi
sisendiks, nii et on võimalik korraldada valikut sellest.
Joonis 4-4 Andmehoidla
näide
Nii tegelased kui ka andmehoidlad on objektid. Me saame neid eristada seetõttu, et nende käitumine ja kasutamine on üldiselt erinevad, kuigi objekt-orienteeritud keeles võivad nad mõlemad olla realiseeritud objektidena. Teisest küljest võib andmehoidla olla realiseeritud failina ja tegelane välisseadmena. Mõned andmevood on samuti objektid, kuigi paljudel juhtudel on nad lihtsalt väärtused nagu näiteks arvud, millel puudub oma identiteet. (Objekt-orienteeritud keeltes on objektid ja puhtad väärtused siiski tihti sarnaselt realiseeritud.)
On olemas erinevus objekti kui üksikväärtuse ja andmehoidla
vahel, mis sisaldab palju väärtusi. Järgmises näites
valib klient pangas välja ühe konto. Valimise operatsiooni tulemuseks
ongi konto objekt, mida hiljem kasutatakse andmehoidlana. Andmevoogu, mis
tekitab uue objekti, tähistatakse tühje kolmnurgaga voo lõpus.
Joonis 4-5 Andmehoidla
saamine protsessi tulemusena
4.3 Praktiline näide – sularahaautomaat
Funktsionaalne mudel näitab, kuidas on väärtused arvutatud, pööramata tähelepanu nende arvutuste järjekorrale, seal tehtavatele otsustustele või objektistruktuurile. Funktsionaalne mudel näitab, millised väärtused sõltuvad millistest. Funktsionaalsete sõltuvuste näitamiseks on hea kasutada andmevoodiagramme. Funktsioone endid võib kujutada mitmel moel, sealhulgas loomulikus keeles, matemaatiliste valemite abil või pseudokoodina.
Funktsionaalse mudeli loomise põhilised sammud OMT metoodika järgi on:
Joonis 4-6 Sisend-
ja väljundandmed sularahaautomaatide süsteemis
Järgmiseks konstrueerime andmevoodiagrammi, kus on näidatud,
kuidas sisendandmetest väljundandmed saadakse. Andmevoodiagramm on
tavaliselt mitmekihiline, järgmisel joonisel on toodud meie süsteemi
ülemine kiht.
Joonis 4-7 ATM-süsteemi
andmevoodiagrammide ülemine kiht
Järgnevalt tuleks iga mittetriviaalse protsessi kohta kõrgema
taseme diagrammil luua oma madalama taseme diagramm ja jätkata seda
tegevust rekursiivselt nii kaua kui vaja. Antud juhul vaatleme lähemalt
protsessi sooritada tehing, punktiirjoonega toodud andmevood tähistava
andmete liikumist negatiivse stsenaariumi korral.
Joonis 4-8 Tehingu
sooritamise andmevoodiagramm
Selles peatükis antakse lühike ülevaade UML-ist kui tarkvaratootmise
vahendist ning selle võimalustest. Töö piiratud mahu tõttu
pole võimalik süveneda pakutud meetoditega seotud ideoloogilistesse
küsimustesse, neid on küllaltki põhjalikult käsitletud
allikas [2]. Vaadeldud on UML-i põhilisi konstruktsioone ja toodud
näiteid nendest.
UMLi nimetatakse tavaliselt modelleerimise keeleks, mitte meetodiks. Enamik tarkvara tootmise metoodikaid koosnevad (vähemalt põhimõtteliselt) modelleerimise keelest ja protsessist. Modelleerimise keel on (tavaliselt graafiline) notatsioon, mida kasutatakse disaini väljendamiseks. Protsess on tavaliselt nõuannete kogum, milliseid samme töö käigus astuda. Selles peatükis vaatlemegi peamiselt seda notatsiooni, modelleerimise keele süntaksit. Näiteks määrab klassidiagrammi notatsioon ära mõisted nagu näiteks klass või assotsiatsioon.
Järgnevalt vaatlemegi UML-is võimalusi, lähtudes selles
kasutatavatest eri liiki diagrammidest ja notatsioonivõimalustest.
Joonis 5-1 Järgnevusdiagramm
Struktuursed meetodid kasutasid tarkvara projekteerimisel funktsionaalset
dekompositsiooni, milles kogu süsteem pandi kirja funktsioonina
ning jagati seejärel alamfunktsioonideks jne. Funktsioonid olid nagu
kasutussituatsioonid objekt-orienteeritud süsteemis, nad väljendasid
midagi, mida terve süsteem tervikuna tegi. Sel ajal olid andmed ja
operatsioonid teineteisest eraldatud, lisaks funktsioonide osadeks lahutamisele
tuli eraldi struktureerida andmeid. Objekt-orienteeritud tehnikad tõid
sellesse lähenemisviisi pöörde, ei ole enam funktsionaalset
dekompositsiooni, kuid küsimus süsteemi osadeks jagamisest on
alles jäänud. Suure süsteemi jagamiseks kasutatakse UML-is
mooduldiagramme. Olgu meil tegemist mingit laadi haldussüsteemiga,
mis peab koosnema mitmest eristatavast tarkvaralisest osast, mis sõltuvad
teineteisest. Sel juhul ongi hea kujutada kõiki neid osi diagrammina,
kus nooled moodulite vahel näitavad sõltuvust (noole alguses
olev moodul sõltub lõpus olevast moodulist). Antud näites
on meil tegemist mingi abstraktse firmaga, kellel on kliendid, klientide
jaoks on mingi omaette tarkvaramoodul, neile saab edastada mitmesuguseid
korraldusi, mille sisestamiseks on olemas graafiline kasutajaliides, mis
baseerub AWT-l (Abstract Window Toolkit). Samuti on klientidel olemas
postiloend, mille kasutajaliides samuti AWT-i kasutab. Kõigi nende
komponentide jaoks on olemas või tuleb luua suhteliselt sõltumatud
tarkvaralised moodulid. Selliste moodulite omavahelise sõltuvuse
näitamiseks kasutataksegi mooduldiagrammi.
Joonis 5-2 Mooduldiagramm
Olekudiagramme kasutatakse süsteemi käitumise uurimiseks,
nad kirjeldavad kõiki olekuid, milles vaadeldav objekt võib
olla, ning kuidas objekti oleks muutub temani jõudvate sündmuste
tulemustena. Enamikus objekt-orienteeritud tehnikates joonistatakse olekudiagrammid
parajasti iga klassi jaoks, et näidata üksiku objekti elutsüklit.
Kuna ka olekudiagramme oleme ülalpool juba põhjalikumalt vaadelnud,
siis siinkohal lisanäiteid enam tooma ei hakka.
Tegevusdiagrammid kombineerivad eneses ideid, mis on võetud mitmetest eri tehnikatest, sealhulgas Jim Odelli loodud sündmusdiagrammid, SDL-i (Specification and Description Language) olekute modelleerimise tehnikad ja Petri võrgud. Peamiseks mõisteks on siin tegevus, selle mõiste sisu sõltub diagrammi joonistaja vaatekohast. Üldiselt on tegevus miski, mingi ülesanne, mis tuleb sooritada, kas siis inimese või arvuti poolt. Tegevus on tihti realiseeritud mingi klassi meetodina. Tegevused järgnevad teineteisele, tegemist on suunatud graafiga. Samamoodi nagu olekudiagrammilgi, on ka siin olemas algolek ja lõppolekud.
Joonisel on toodud näide inimesest, kes tahab juua, ja tema tegevustest
sellises situatsioonis. Vaatleme näiteks tegevust Leida jook.
Sellel tegevusel on kaks väljuvat noolt, millele on vastavusse seatud
mingi loogiline avaldis, mis näitab, milline suund valida, täpselt
nagu olekudiagrammilgi. Juhtumil, kui kohvi ei olnud, tuleb läbida
otsuspunkt,
kus tehakse kindlaks, kas limonaadi on. Seda otsustuspunkti ei vaadelda
eraldi tegevusena, sest jookide olemasolu tehti kindlaks juba eelmise tegevuse
juures. Kui kohvi oli, tuleb järgmiseks sünkronisatsiooniriba,
mis eraldab teineteisest või ühendab erinevaid sõltumatuid
tegevusliine.
Joonis 5-3 Tegevusdiagramm
Joonis 5-4 Paigaldusdiagramm
5.9 UML-i ja tema vahendite kasutamisest
Loetleme nüüd veel kokkuvõtteks situatsioone, kus erinevaid kirjeldatud vahendeid ja diagramme vaja läheb.
Object-oriented systems analysis and its methodologies
Targo Tennisberg
Summary
This paper describes object-oriented methods of systems analysis, especially OMT (Object Modeling Technique) and UML (Unified Modeling Language). The main purpose of the paper is giving a summary of those methods to people who are new to systems analysis and object-oriented modeling; some knowledge of basic object-oriented concepts is nevertheless required. More attention is paid to the modeling process and the ideas of it, main steps of OMT are discussed more thoroughly. In the last chapter various notation concepts are briefly introduced.
The main books where I found data when writing the paper, were “Object-Oriented Modeling and Design” [1] and “UML Distilled” [3]. Whenever possible, I have tried to illustrate the text with examples and drawings. When creating the examples, I used the CASE tools SELECT Enterprise Modeler (SELECT Software Tools) and Visio (Visio Corporation).
I have used the methods described here in various real life projects,
e.g. Estonian Citizenship and Immigration Board information system
project, creating a configuring program of the electricity system of the
new airplane of Airbus Industries and designing a telebanking system
of Estonian Land Bank.