Könyvhöz tartozó online melléklet
Könyv: UML földi halandóknak (Robert A. Maksimchuk, Eric J. Naiburg)
Melléklet: Olvasson bele!
Alkalmazásmodellezés
A fejezetben
tárgyalt témák
• Miért szükséges az alkalmazások modellezése?
– A
másik válasz
– A
kérdés háttere
• A teljes alkalmazást modellezni kell?
• Mi a helyzet a programozási nyelvekkel?
• Milyen részletességgel kell modellezni az alkalmazásokat?
• Hogyan modellezi az alkalmazásokat az UML?
– Az
osztálydiagramok alapjainak áttekintése
• Osztályok
• Műveletek
• Társítások
• Egyéb társításjelzések
– Az
osztálydiagramokról bővebben
• Halmaz és összetétel
• Általánosítás
• Társításosztályok
• Megszorítások
– A
sorrenddiagramokról bővebben
• Haladóknak
• Kifejezések
• Összefoglalás
• Ellenőrző kérdések
Miért szükséges az alkalmazások
modellezése?
Meglepő módon erre
a kérdésre először azt a választ adhatjuk, hogy vannak esetek, amikor
az alkalmazás modellezése valószínűleg indokolatlan. Nem
feltétlenül szükséges például, ha hétköznapi alkalmazásról van
szó, vagy ha a fejlesztőeszközök elég hatékonyak az alkalmazás
egy jelentős részének „összeállításához”, illetve ha a fejlesztők
korábban már készítettek hasonló alkalmazásokat, ezért pontosan
tudják, hogyan valósítsák meg az adott megoldást.
Az üzlet szempontjából
nélkülözhetetlen, komoly alkalmazások létrehozásakor azonban elengedhetetlen
az alkalmazásmodellezés. A 2. fejezetben felsoroltunk néhány
okot, amiért fontos a vállalkozások modellezése, és ezen okok jó része
igaz az alkalmazások modellezésére is. Először is, rendkívül
fontos átlátni, hogy mi az, ami már rendelkezésre áll, hiszen a legtöbb
fejlesztés nem érintetlen területen történik. Általában adott valamilyen
meglévő rendszer, illetve szoftver, amelyet a csapat esetleg nem
ismer, és amelyet módosítani vagy bővíteni kell. A meglévő
alkalmazásokat könnyebb egy modell áttekintésével megérteni, mint
a kódjukat olvasgatva.
Stafétabot (ismét)
A 2. fejezetben tárgyaltuk
azt az esetet, amikor egy olyan, rendkívül fontos alkalmazást örököltem,
ami nem rendelkezett leírással, a kód és az adatállományok egy része
hiányzott, és senki nem értette (számos fejlesztő került már
ilyen helyzetbe). Emlékezhetünk, hogy két hétbe telt megismerni az alkalmazást,
és még több időre volt szükség a mögötte húzódó elképzelések megértéséhez
és az alkalmazás újból működőképessé tételéhez. További
elvesztegetett időt és felmerülő költséget jelentett az
olyan felhasználókkal foglalkozni, akik nem értették, hogy az alkalmazás
hogyan, illetve miért működik úgy, ahogy működik. Ha rendelkezésre
állt volna az alkalmazás modellje, a problémák és az azokkal járó kiadások
elkerülhetőek lettek volna.
Lássuk azonban a történet
többi részét. Az alkalmazás némi „felújítás” után nagyon jó állapotba
került, mindene működött, minden részének szerepe tisztázódott,
és változatkövető rendszer felügyelte. Még előzetes dokumentáció
is készült hozzá. Minden sínen volt tehát, viszont az alkalmazásnak
nem volt modellje (a szervezet, ahol dolgoztam, nem foglalkozott alkalmazásmodellezéssel).
Volt néhány kisebb, nem
jelentős hiba, amelyeknek még a nyomára kellett bukkanni, de
ezek nem gátolták a működést, és nem akadályozták volna az átadást.
Ilyenkor kell szabadságra menni. Meg is tettem, és felfrissülten tértem
vissza, készen arra, hogy folytassam az alkalmazás felújítását. Munka
közben felfigyeltem néhány különös eseményre, amit korábban nem tapasztaltam.
Az alkalmazás továbbra is elég jól működött, de olyan dolgokat
csinált, amiket nem kellett volna, például időnként két üzenetet
küldött a kezelőnek. Vajon szándékosan, mondjuk az alkalmazás
egy olyan eldugott része miatt működött így, amelyet nem vizsgáltam
meg, vagy hibás viselkedésről van szó? Biztos voltam benne, hogy
az alkalmazás nem így működött, mielőtt elmentem.
Miután pár napig böngésztem a kódot, észrevettem, hogy néhány
apróbb változtatás történt benne. További nyomozás után kiderült,
hogy az egyik új felhasználó a felettesemnél panaszkodott a program
működésére, és a főnök valamiért úgy döntött, hogy „rendbe
hozza” a kódot anélkül, hogy bárkinek is szólna. Igen, megváltoztatta
az alkalmazás működését csupán azért, hogy ennek az egy felhasználónak
a kedvében járjon. Eközben számos új, valódi hibát idézett elő. Ha
rendelkezésre állt volna a program modellje, képes lett volna megfelelő
változtatást végezni, de csakúgy, mint sok programozó, aki valamilyen
szoftvert örökölt, nem rendelkezett modellel. Gyorsan felmérte a kódot,
és módosításokat végzett, amivel anélkül „oldotta meg” a „problémát”,
hogy felismerte volna az ezzel létrehozott mellékhatásokat (hibákat).
1. ‑Az alkalmazások modelljeit – különösen
a bonyolultabb, kényesebb programokét – időbe telik létrehozni,
de még több időt takaríthatnak meg, amikor változtatásokat kell
végezni a szoftveren.
4. ‑Ha szabadságra
megyünk, zárjuk le a kódot. A beállításkezelés létfontosságú a sikeres
fejlesztéshez.
Az is indokolja az alkalmazások
modellezését, hogy új alkalmazások tervezésekor a változások
gyakran a tervezési szakasz közben
történnek. Ha rendelkezésre áll egy modell, sokkal könnyebben felmérhetjük
a módosítások hatását, mivel látjuk
az alkalmazás azon részeit, amelyeket befolyásolnak. Ahogy a Stafétabot (ismét) részben leírtak
mutatják, ha meg kell változtatni a kódot, a tervezési modellek vizsgálatával
megállapítható, hogy a javasolt változások nem tesznek-e kárt az alkalmazásban
egy másik helyen.
Az alkalmazás grafikus
modellje segítségével sokkal könnyebben eldönthetjük, hogy a felépítés
megfelel-e az üzlet követelményeinek. A szó szoros értelmében rámutatha-tunk
az adott követelményt kielégítő elemre, ahelyett, hogy egy szöveges
leíráscsoportra mutatnánk.
Végül, ahogy korábban
is említettük, a modellek „gyújtópontként” szolgálnak, ami lehetővé
teszi, hogy az érdekeltek megtárgyalják és megoldják a felépítéssel
kapcsolatos kérdéseket. Ahogy az Egyesült Államok egykori elnöke,
Dwight Eisenhower mondta: „A terv semmi – a tervezés minden”. Nem csak magukról
a modellekről van szó, hanem arról a folyamatról, illetve elmélkedésről,
amelyet a rendkívüli jelentőségű modellek létrehozásához
végeznünk kell. A modellezés gondolkodásra késztet bennünket, és az
átgondolás eredményeként jobb felépítést alakíthatunk ki.
A másik válasz
Azok számára, akik azt
kérdezik, hogy miért kell modellezni az alkalmazásokat, van még egy
válaszunk, ami elég egyszerű: már amúgy is modellezünk, csak nem nevezzük
a nevén.
Emlékezzünk a modelleknek
az 1. fejezetben leírt meghatározásaira: a modell egy elkészítendő
dolog ábrázolása. A legtöbb szoftverfejlesztő részlegnél, ha
végigmegyünk a fülkék között, különféle modelleket látunk a táblákra
firkálva: A programok és azok alprogramjainak szerkezetét modellező
blokkvázlatokat, a programok vezérlő folyamatát modellező
folyamatábrákat, hosszú, osztott téglalapokat, amelyek a mezők
szerkezetét, és egymáshoz kapcsolódó négyzetek hálózatát, amelyek
egy webhely hivatkozásait modellezik – és igen, még egy-két UML diagramot
is. Ezek mind modellezési módszerek. A modellezés csupán a rendszerek
elemzésének, illetve tervezésének részeként használt eljárás, amelyet
az olvasók többsége már minden bizonnyal alkalmaz, csak nem szabványos
módon. Az UML mindössze szabványos megközelítést, jelrendszert és jelentést
ad a modellezési tevékenységekhez.
A kérdés háttere
Gyakran valójában más
kérdések (vagy félelmek) rejlenek a mögött a kérdés mögött, hogy miért
szükséges az alkalmazások modellezése. A legtöbben, akik azt kérdezik,
hogy miért kell modellezni az alkalmazásokat, már tudják a választ.
A valódi kérdés más tényezőkre vonatkozik. A vezetők például
gyakran azért teszik fel ezt a kérdést, mert valójában amiatt aggódnak,
hogy a modellezés túl sok időt vesz igénybe. Nem ismerik fel, hogy a
kódolás gyakran a befejezetlen tervezésből eredő okok miatt
emészti fel a fejlesztés erőforrásainak java részét. A felépítés
meghatározásának feladata a programozókra hárul, és a kód írása
közben kell elvégezniük azt. Ahogy korábban mondtuk, valójában modellezünk
(azaz tervezünk), csak másként nevezzük.
Vannak olyan vezetők
is, akik a megírt kódsorok számával mérik a haladást; ők általában
a szoftverfejlesztés „Vigyázz, kész, kódolás!” iskolájának követői.
Ez helytelen (de sajnos elterjedt) hozzáállás az iparban. Aki magára
ismer, olyan jelentősebb szempontokra is gondoljon, mint a vállalkozás
igényeinek kiszolgálása, rugalmas felépítés létrehozása, jó minőségű
termék készítése és a modellezés sok más előnye, amit ebben és a korábbi
fejezetekben említettünk.
A költségek is szerepet
játszanak annak eldöntésében, hogy modellezzünk-e vagy sem. Nem maga
a modellezés jelent költséget (ahogy a fejezet egy korábbi részében
kifejtettük, ezt a feladatot egyébként is elvégezzük majd, akár szabványosan
modellezünk, akár nem). Az az előzetes befektetés a valódi költség,
amelyet vagy szakképzett munkaerőre fordítunk, vagy arra, hogy a jelenlegi
személyzetet megtanítsuk a helyes modellezésre. Ez az „egyszeri”
költség azonban minden későbbi munkánál megtérül, elsősorban
a kevesebb újratervezés és hibajavítás által (emlékezzünk a 3.1.
ábra táblázatára). A szándékunk szerint működő alkalmazás
létrehozására kell összpontosítani (ha nem azt csinálja, amit a megrendelő
szeretne, az összes idő és pénz kárba vész), illetve az alkalmazás
teljes élettartamára számított kiadásokra. Elvégre a vezetők
feladatának része a munkaerő fejlesztése is, igaz?
Hasonlóképpen, azoknak
a programozóknak, akik ezt a kérdést felteszik – és akiket az előző
fejtegetések egyike sem érint –, érdemes elgondolkodniuk: miért ne
akarnának új szaktudásra szert tenni? Hiszen a programozó alkalmazhatósága
a szaktudásában rejlik. Továbbá, miért akarna valaki csak kódoló
lenni ahelyett, hogy megdolgozna a „programtervező mérnök” címért?
Megelégszünk azzal, hogy szögeket verünk be, vagy katedrálisépítővé
akarunk válni? Az UML maradandó, ezért érdemes bővítenünk vele
a képességeinket.
A teljes alkalmazást modellezni
kell?
Amikor csak lehet, érdemes
a teljes alkalmazást (vagy rendszert) modellezni, így tudatos irányítás
alatt tarthatjuk az alkalmazás szerkezetét és felépítését. Néhány
esetben például, amikor nem az egész rendszert felügyeljük, nem tudjuk
teljes egészében modellezni azt, mégis nagyon hasznos lehet, ha modellezzük
az irányításunk alatt álló részeket.
Lyukasabb, mint egy svájci
sajt
Rendszerintegrátorként
egy igen nagy projekten dolgoztam (és így a rendszer megvalósításának
egyetlen elemét sem befolyásolhattam közvetlenül), és egy mások által
a rendszerkövetelményekben meghatározott, meglehetősen
összetett gyártási forgatókönyv került elém. Még csak akkoriban kezdtem
megismerkedni az objektumközpontú megoldásokkal, és úgy döntöttem,
hogy elkészítem a forgatókönyv állapotdiagramját. (Egy későbbi
fejezetben megtudjuk majd, hogy az állapotdiagramok általában egy
meghatározott objektum állapotát ábrázolják. Úgy döntöttem, hogy
a teljes forgatókönyvön kipróbálom ezt a módszert.)
Nagy meglepetésemre kiderült, hogy számos hézag van a gyártási
forgatókönyvben. Sok esetben ugyanis nem határozta meg, hogy mi történjen
bizonyos, gyakran fennálló körülmények között. Más szóval, ha ez a forgatókönyv
megvalósul, csúfos kudarcot vallott volna. A rendszernek ez a része
nem az „enyém” volt, a modellezés által mégis sok mindent megtudhattam
róla, és megtalálhattam a hibáit, ami lehetővé tette, hogy
fontos változtatásokat javasoljak.
1. ‑Ne féljünk kreatív módon alkalmazni
a modellezési eljárásokat (például nem objektumokról, hanem egy
egész rendszerről készítünk állapotdiagramot)! Ha megfelelő
módon használjuk azokat (azaz nem hagyjuk figyelmen kívül a diagram
vagy a módszer alapelveit), új lehetőségeket fedezhetünk fel,
amelyekkel remekül hasznosíthatjuk ezeket az eljárásokat. Az UML-rendőrség
nem fogja ránk törni az ajtót, ha így teszünk.
Ha meglévő rendszerrel
van dolgunk (esetleg bővítenünk kell azt, vagy javítani, illetve
cserélni kell egy részt úgy, hogy közben működőképes maradjon),
dönthetünk a „beburkolás” mellett. Ilyenkor külső felületréteggel
„vesszük körül”, amely ugyanazokat a meglévő felületeket biztosítja
a külső alkalmazásoknak, de lehetővé teszi a benne rejlő
technológia megváltoztatását. Modellezéskor csak a rendszer vagy
az alkalmazás felületét modellezzük, a belső részekét nem (a
fejezet egy későbbi részében, az osztályok tárgyalásakor
visszatérünk a felületek modellezésére). Ez azt is lehetővé
teszi, hogy új felületeket adjunk a rendszerhez, a meglévők megbontása
nélkül. (Igaz, hogy az új felületek használhatják a régieket, de ezt
a csomagolás elrejti.) Így megváltoztathatjuk a belső megvalósítást,
úgy, hogy a felület változatlan marad.
Amennyiben a költségvetés,
az idő vagy a személyzet szakképzettségének hiánya (vagyis ha
nincs sok olyan emberünk, aki képes megoldani a modellezést) korlátoz
bennünket, csak a rendszer legfontosabb részeit modellezzük. Megtehetjük
például, hogy csak az elsődleges feladatokat modellezzük részletesen.
Az alkalmazás vagy a rendszer minden kockázatos elemét modellezni
kell. Ha az alkalmazás valósidejű, akkor modellezni kell; ebben
az esetben nem kockáztathatunk meg egy rossz, kevéssé ismert felépítésen
alapuló fejlesztést. Elvégre ha nem tudjuk elérni, hogy az alapvető
elemek működjenek, miért foglalkozzunk egyáltalán a kevésbé
fontos részekkel?
Mi a helyzet a programozási
nyelvekkel?
A programozási nyelvek
sokat fejlődtek az újrahasznosítható összetevőkönyvtárak,
hatékony programozási keretrendszerek és hasonlók megjelenésével.
Viszont az, hogy egy nyelvet „objektumorientált”-nak (objektumközpontúnak)
neveznek, még nem jelenti azt, hogy helyettesítheti a megfelelő
objektumközpontú elemzést és tervezést.
Egy programozási nyelv
– még ha felhasználható szerkezeti elemeket is tartalmaz – nem biztosíthatja
a megfelelő felépítést, és azt sem, hogy az alkalmazás megfelel
a megrendelő igényeinek. Ez olyan, mintha azt mondanánk, hogy ha
egy gyártónak sikerül előre összeszerelt kerekeket beszereznie,
és kisteherautókban alkalmaznia azokat, akkor az elkészült jármű
megfelel majd a megbízhatósági szabványoknak, és jól irányítható
lesz. A nyelvek és az eszközök nem helyettesíthetik a megfelelő
elemzést és tervezést.
Milyen részletességgel
kell modellezni az alkalmazásokat?
Azok, akik készek modellezni
az alkalmazásaikat, gyakran megkérdezik, mikor kell áttérni a modellezésről
a megvalósításra, vagy hogy mennyi részletet tartalmazzanak a modellek.
Bizonyos esetekben a lehető legrészletesebb modell készítése
a legjobb: például ha rendkívül fontos, illetve érzékeny rendszereket
modellezünk, amilyen egy beültetett orvosi eszköz (ilyenkor életek
forognak kockán), vagy amikor a rendszer hibája rendkívüli gazdasági
következményekkel jár. Az ilyen nagy horderejű végeredmény indokolja,
hogy a lehető legrészletesebben modellezzük az alkalmazást.
Szintén részletes modellezést
igényelnek az olyan helyzetek, amikor a teljesítmény vagy a megbízhatóság
rendkívül fontos, csakúgy, mint amikor külsősöket bízunk meg a fejlesztéssel.
Miben hasonlítanak ezek a helyzetek? Olyan esetek, amikor az alkalmazás
teljes körű meghatározásával (vagyis modellezésével) csökkenteni
kell a tervezési kompromisszumokat. Senki sem szeretne kezdő
programozókra bízni olyan kulcsfontosságú tervezési döntéseket,
amelyek befolyásolhatják az elsődleges tényezőket, mondjuk
a teljesítményt vagy a biztonságot. A kezdő programozó például
esetleg úgy valósítja meg a kódot, hogy csökkentse a memóriafelhasználást.
Ez ugyan ártalmatlannak tűnhet, de lehet, hogy számunkra nem a memóriakihasználás
fontos, hanem hogy kiemelkedő sebességű rendszert kapjunk.
Ezeket a fontos felépítésbeli kompromisszumokat nem szabad a megvalósításig
halogatni. Az ilyen létfontosságú rendszerek teljes és részletes modelljét
el kell készíteni, hogy azt kapjuk, amire valóban szükségünk van.
A kevésbé kényes munkáknál
általában az időbeosztás, a költségvetés és a személyzet
szakképzettsége határozza meg, hogy milyen részletes modellt készítünk.
Általában jobb, ha a modell minél több részletet tartalmaz, de sokszor
gyakorlatiasan egyensúlyba kell hozni a tényezőket. Az egyik
jelzés, amire érdemes figyelni, a változás gyorsasága. Ha a modell
részletei folyamatosan változnak, például ha a leírt műveletek
gyakran módosulnak, valószínűleg még nincs itt az ideje, hogy a modellek
a fejlesztés megvalósítási szakaszába lépjenek, mert a felépítés
még nyilvánvalóan kiforratlan. Mielőtt továbblépnénk, meg kell
várnunk, amíg beáll egy elfogadható mértékű állandóság (mivel
a változás soha nem szűnik meg). Természetesen az „elfogadható”
meghatározása az adott cégtől függ, amikor azonban a változás
aránya alacsony, állandó szintre kerül, valószínűleg készen állunk
rá, hogy hozzáfogjunk a felépítésmodellek megvalósításához.
Hogyan modellezi az alkalmazásokat
az UML?
Az üzleti modell meghatározza,
hogy miért építjük a rendszert (azaz, hogy miként támogatja a vállalkozást),
a feladatmodellek megmutatják, hogy a szereplők hogyan használják
majd a rendszert, a felépítésmodellek pedig meghatározzák a rendszer
kezdeti szerkezetét. Ezzel a tudással felszerelkezve készen állunk
az alkalmazás modellezésére. Ezek az előzetes modellek korlátozzák
az alkalmazás „formáját”. Az üzleti- és a feladatmodellek határt
szabnak a felépítési térnek (ami jó, mert a megoldások összességét
egy megoldástérre korlátozza). A felépítésmodellek határozzák meg
a megoldás átfogó szerkezetét. Ily módon a modellek fejlesztésével
szabályozhatjuk a munka időbeosztását és költségeit.
Az osztálydiagramok alapjai
– ismétlés
A korlátok meghatározását
követően leggyakrabban az osztálydiagram szolgál az alkalmazás
statikus szerkezetének ábrázolására. Az osztálydiagramokkal korábban,
a 4. fejezetben ismerkedtünk meg, ahol láttuk a felépítésmodellezés céljából
történő alkalmazásukat. Azok kedvéért, akik átugrották azt a részt,
újra áttekintjük az osztálydiagramok néhány alapelvét – mivel ezek
az alkalmazásmodellezés velejárói –, majd megvizsgálunk néhány további
modellezési elemet, amelyek ezekben a diagramokban szerepelnek.
Osztályok
Az osztálydiagram az alkalmazás fontos osztályait
és azok más osztályokhoz fűződő kapcsolatait mutatja.
Az osztályok elsősorban a rendszerben szereplő „dolgokat”
ábrázolják. A kezdeti modellek (üzleti követelmények, felépítés)
fejlesztése során már számos fontos osztályra bukkanunk. A többi modell
nélkül sokkal nehezebb megtalálni ezeket az osztályokat, de nem lehetetlen.
Ha nem rendelkezünk kezdeti modellekkel, tekintsük az alkalmazás
problémamegfogalmazását, és válasszuk ki a valós dolgokat: könyvelés,
repülőgép, megrendelő, termék, közvetítő, jelentés
és így tovább (lásd az 5.1. ábrát). Ezek lesznek a területi osztályok vagy tartományosztályok,
amelyeknek szerepelniük kell a diagramokban. A modell fejlődése
során a nem valós dolgok is osztályokként jelennek meg: ilyenek többek
között a feldolgozást irányító vezérlő osztályok.
5.1. ábra
Osztály, amely egy bolygót
ábrázol
De mik az osztályok a szoftver
megvalósításának szempontjából? Az osztályok hasonló objektumok egy csoportját írják
le, olyan sablonok, amelyek az objektumok létrehozására szolgálnak
az alkalmazásban.
A szabályok megszegése
Az UML modellek tárgyalásakor gyakran egyenértékűként
használják az „osztály” és az „objektum” kifejezést. Ez szigorúan véve
nem helyes, de ha észben tartjuk, hogy az osztály a leírás, és az objektum
a megvalósítás, nem lehet gond. Nem kell amiatt izgulni, hogy a modellezés
„Hatalmas Varázslói” megtudják, mit tettünk.
Ahogy egy süteményformával
sok egyforma süteményt készíthetünk, ugyanúgy, ha rendelkezésre áll
egy „Bolygó” nevű osztály, akkor a Bolygó osztály segítségével
is több bolygó objektumot hozhatunk
létre az alkalmazásban. Egy csomó egyforma bolygó talán nem túl érdekes,
ahogy azonban az egyforma süteményeket változatossá tehetjük reszelékkel,
cukormázzal vagy ételszínezékkel, a többalakúság
(polimorfizmus) alkalmazásával az osztályokat is egyedivé tehetjük
(erről a fejezet későbbi részében lesz bővebben szó).
Rögzítenünk kell az osztályok
fontos adatait. Ezt a jellemzők
(attribútumok) – ezek a 4. fejezet szerkezetre vonatkozó leírásaihoz
hasonlóak, de itt az alkalmazás felépítését jellemzik – alkalmazásával
tehetjük meg. A jellemzők határozzák meg az alkalmazáshoz szükséges
osztályok lényeges tulajdonságait – nem az összes tulajdonságot,
csak azokat, amelyek alkalmazhatók az adott problémára. Ha például
az alkalmazás a bolygóknak a Naprendszerben elfoglalt helyét modellezi,
a Bolygó osztály valószínűleg rögzíti a bolygónak a Naptól mért
távolságát és a pályáját (lásd az 5.2. ábrát), de a magösszetételét
nem.
5.2. ábra
Jellemzőkkel ellátott
Bolygó osztály
Kedves lakó!
Az osztályokban szereplő jellemzők határozzák meg az
osztály által rögzíteni kívánt elvont fogalom természetét. Ez kulcsfontosságú
lehet a projekt sikere szempontjából. Egyszer részt vettem egy olyan
munka záróértékelésen, amely „komoly gondokkal” küszködött. Az egyik
probléma forrása a „Cím” osztály volt. A csoportnak az volt az elképzelése
a „cím”-ről, hogy az otthonunk helyét jelöli. Ugyan a cím ezen felfogása
nem helytelen, az adott alkalmazás szempontjából azonban mégsem volt
a legszerencsésebb, mert az alkalmazás nem házak elhelyezkedésével
foglalkozott, hanem levelezőprogram volt. Ebben a környezetben
a cím megfelelőbb leírása az lett volna, hogy „az a hely, ahová levelet
küldünk” (ami lehet az otthonunk, utazás során egy szálloda, betegség
esetén kórház, hétvégi ház és így tovább).
1. ‑Ügyeljünk, hogy az osztályok és
azok jellemzői az alkalmazás szempontjából megfelelő fogalmat
rögzítsék!
A jellemzőket az
adatok összefüggésében is vizsgálhatjuk. Az objektumközpontú elemzés
és tervezés egy egységbe zárja
(betokozza) az adatokat és a feldolgozást. A jellemzők az osztály
belsejébe ágyazott adatok. Az osztályban szereplő adatok (jellemzők)
a jellemzők láthatóságától függően más osztályok számára
is elérhetők lehetnek. A jellemzők nyilvános, védett, privát
vagy csomag láthatósággal rendelkezhetnek (lásd az 5.1. táblázatot).
5.1.
táblázat Láthatóságfajták
Láthatóság Jelölés Jelentés
Privát - Ezeket a jellemzőket csak maga az
osztály érheti el.
Védett # Ezeket a jellemzőket az osztály
minden gyermekosztálya elérheti.
Nyilvános + Ezeket a jellemzőket bármelyik
osztály elérheti.
Csomag ~ Ezeket a jellemzőket az adott csomag
összes osztálya elérheti.
Elméletben az osztályok
összes jellemzőjének privátnak kell lennie, hogy biztosítsuk az
erős betokozást (ami megakadályozza, hogy a jellemzőket más objektumok
elérjék vagy megváltoztassák, kivéve ha a tulajdonos objektum lehetővé
teszi ezt). Ennek ellenére kerülhetünk olyan helyzetbe, például
részletes tervezés vagy megvalósítás során, amikor „enyhíteni”
kell a betokozás mértékét. Ilyen esetekben eltérő láthatósági
szintek alkalmazásával nagyobb hozzáférést biztosíthatunk az osztályok
jellemzőihez. Ha azonban nincs kifejezetten szükség más láthatóságra,
a jellemzőknek privátnak kell maradniuk.
Mit csinálnak tehát az
osztályok? Ezt az osztály műveletei határozzák meg.
Műveletek
A műveletek az osztályok
által biztosított szolgáltatások. A műveletek az osztályszimbólum
harmadik rekeszében láthatók. Azok a műveletek, amelyek hozzáférést
biztosítanak a jellemzőkhöz, általában az osztály többi végrehajtó
függvényével azonos helyen tárolódnak (lásd az 5.3. ábrát). A külső
objektumok így kapnak hozzáférést a tulajdonos objektum privát jellemzőihez.
Lehet, hogy nem maga az osztály hajtja végre az összes műveletet,
de az osztály felelős azért, hogy valami
elvégezze a műveleteket (például egy másik objektum, amely
ténylegesen teljesíti a feladatot). Ilyenkor az osztály vezérlő
osztályként működik, az alkalmazás egészét vagy egy részét irányítva.
5.3. ábra
A Bolygó osztály a hozzáadott
műveletekkel
A rendelkezésre álló
diagram kiforrottságától függően lehet, hogy csak a művelet
neve látható. Ahogy egy művelet fejlődik, kialakul a teljes aláírása, amelyben megjelenik a neve,
a paraméterei, az alapértelmezett értékei, a visszatérési típusa
és így tovább (lásd 5.4. ábra). Az, hogy mennyi részletet írunk le, attól
függ, hogy az adott szervezet hogyan alkalmazza a modellezést, azaz
hogy mennyi részletre van szükség, mielőtt átadhatjuk a felépítést
a programozóknak a megvalósításhoz.
5.4. ábra
A Bolygó osztály a művelet-aláírásokkal
A szabályok megszegése
II.
Ahhoz hasonlóan, ahogy az „osztály” és az „objektum” kifejezést
rokon értelműként használjuk, amikor UML modellekről van szó
(ahogy a fejezet korábbi részében taglaltuk), a „művelet” és a „függvény”
szó is azonos jelentéssel fordul majd elő, ami elvileg szintén helytelen.
A művelet egy olyan szolgáltatást ír le, amelyet az osztálya biztosít,
a (tag)függvény viszont az adott művelet megvalósítása. Számos
függvény (megvalósítás) teljesíthet egy műveletet. Ha például
adott egy Rendezés művelet, a függvény buborékos rendezéssel,
hasító rendezéssel vagy más rendezési algoritmussal is megvalósíthatja
a műveletet.
Találkozhatunk {abstract} (elvont)
jelölésű műveletekkel is. Ez azt jelzi, hogy nem az adott osztály
valósítja meg a műveletet, hanem az egy gyermekosztályban valósul
meg, ahol ugyanaz a művelet a gyermek műveletrekeszében is
szerepel. Ez az egyik lehetőség, hogy egy művelet egyedi megvalósításokkal
rendelkezzen. A „tölt” művelet például teljesen más módon valósulna
meg a „Puska” és a „Fúvócső” osztályban. Ez a többalakúság fogalmának központi gondolata (lásd az 5.5.
ábrát): ha a gyermek olyan műveletet ír le, amely a szülőosztályban
is szerepel, akkor a gyermek művelete felülbírálja a szülő műveletét. Ily módon a gyermek
működése módosíthatja vagy felválthatja a szülő viselkedését.
5.5 ábra
Többalakúság
Az osztályok műveletei
lehetnek olyan függvények, amelyeket az osztály saját akaratából,
vagy olyanok, amelyeket más objektumok utasítására hajt végre. A mások
által kérhető műveleteket befolyásolhatja a láthatóság
(lásd a korábbi 5.1. táblázatot), ami a műveletekre ugyanúgy érvényes,
mint a jellemzőkre.
Egy másik UML elem, amely
korlátozhatja, hogy más osztályok milyen szolgáltatásokat kérhetnek,
a felület. A felület csupán egy műveletcsoport, amelyet egy külső
elem láthat, és ezáltal meghívhat (lásd az 5.6. ábrát). Az osztály tervezője
határozza meg, hogy a felület milyen
műveleteket tesz láthatóvá.
5.6. ábra
Felülettel rendelkező
osztály
Társítások
Ahogy a 4. fejezetben
kifejtettük, a társítások a rendszerobjektumok közötti kapcsolatot
mutatják. Jellemzően az objektumok közötti adatátviteli csatornákat
ábrázolják, amelyek a korábban tárgyaltaknak megfelelően lehetnek
kétirányúak vagy egyirányúak. Az irányítottságot (más szóval vezérelhetőséget)
általában a tervezési szakasz későbbi részében kell meghatározni,
amikor már többet tudunk arról, hogy a feldolgozás hogyan keresztezi
a társításokat. Így kiderül, miként kell optimalizálni a társítások
megvalósítását.
Egyéb társításjelzések
A társítások végén megjelenő
jelzésekről (például mennyiség, rombusz) szintén szó esett a 4. fejezetben.
Gyakran találkozunk majd néhány másikkal is.
5.7. ábra
Szerepnevek
A szerepnevek a társítás végén jelenhetnek meg. Ezek a társítás
szerepnevekkel megegyező végén található osztályokat írják
le. A szerepnév azt jelöli, hogy az osztály az adott kapcsolatban hogyan
viselkedik majd a hozzá társított osztállyal. Ez hasonlít ahhoz,
ahogy az életben is több szerepet játszunk. A szerző másként viselkedik
mérnökként és befektetőként (noha előfordulhatnak azonos
viselkedésformák). Egy mérnök olvashat, elemezhet, tervezhet, építhet
és így tovább. Egy befektető olvashat, elemezhet, eladhat, vásárolhat,
könyvelést vezethet és hasonló tevékenységeket végezhet (lásd az
5.7. ábrát). Ilyen módon a szerepnevek elkülönítik az osztályaik viselkedését.
A szerepnevek különválasztják az egy osztály és egy másik osztály
közötti társításban megfigyelhető viselkedéseket, a minősítők viszont azokat
az objektumcsoportokat különítik el, amelyek társításban vehetnek
részt. Lássunk néhány példát a Bérlista és az Egyén osztály alkalmazásával.
5.8. ábra
Jelzés nélküli társítás
Az 5.8. ábrán azt láthatjuk, hogy a Bérlista
részleg fizet az Egyénnek. Az 5.9. ábra azt mutatja, hogy a szerepnév
hozzáadásával hogyan lehet egyértelműbbé tenni a dolgokat: a Bérlista
fizet az Egyénnek, aki alkalmazottként (és nem vállalkozóként vagy
gyártóként) viselkedik. Egyik diagram sem igazán pontosan körülírt.
5.9. ábra
Szerepnévvel ellátott
társítás
Amikor az 5.10. ábrán látható módon minősítőt
(az alkalmazott számát) adunk a diagramhoz, tudjuk, hogy csak az adott
Egyén objektum vesz részt a társításban (azaz csak a meghatározott
alkalmazottszámmal rendelkező Egyén kap fizetést). Ha ehhez hozzáteszünk
egy mennyiséget, további információval bővítjük a modellt. Az 5.11.
ábrán láthatjuk, hogy a 0..1 mennyiség miatt a Bérlista vagy senkinek
nem fizet (ami azt jelenti, hogy az alkalmazottszám nem tartozik alkalmazotthoz),
vagy egy adott alkalmazottnak fizet.
5.10. ábra
Szerepnévvel és minősítővel
ellátott társítás
5.11. ábra
Szerepnévvel, minősítővel
és mennyiséggel ellátott társítás
A minősítő és a mennyiség megváltoztatásával
az 5.12. ábrán is látható új jelentést kapunk, ahol a Bérlista több teljes
munkaidős alkalmazottnak fizet (a részmunkaidős alkalmazottakat
a „teljes munkaidős” minősítő kizárja).
5.12. ábra
Szerepnévvel és egy objektumcsoportot
kijelölő minősítővel ellátott társítás
Az osztálydiagramokról
bővebben
Halmaz és összetétel
A 4. fejezetben említettünk
két rokon társítást: a halmazt
(aggregation) és az összetételt
(composition). (Az UML 2.0-ban az összetétel társítást összetett halmaznak
is nevezik.) Az 5.13. ábrán láthatjuk a két társítást.
5.13. ábra
A halmaz és az összetétel
társítás
A halmazt üres (vagy lyukas),
az összetételt kitöltött rombusz jelöli. A rombusz mindkét esetben a társítás
„Teljes” végén jelenik meg. Ezeket a társításokat a következőképpen
kell értelmezni: „a Rész az Egész része” illetve „az Egésznek van egy Része”
(az adott részek számát a társítás rész végénél szereplő mennyiség
határozza meg).
Ezek a társítások azt a
különleges jelentést hordozzák, hogy a társítás egyik eleme a másik
„része”. A halmaz és az összetétel között az jelenti a különbséget,
hogy milyen szoros a részt vevő elemek közötti kapcsolat. A halmaz
lazább társítás, míg az összetétel sokkal szorosabb összetartozást
jelöl. Az összetételben a Részek csak egy Egész részei lehetnek, továbbá
az Egész megszűnésekor az összes része is megsemmisül (sőt az
Egész feladata gondoskodni arról, hogy a részei megszűnjenek).
Az 5.14. ábra egy zseblámpa példáján mutatja be ezeket a kapcsolatokat.
5.14. ábra
Egy zseblámpa halmaza és
összetétele
A zseblámpának van egy
kapcsolója. Ez összetétel, mivel a kapcsoló annak az egy zseblámpának
a része. Ha eldobjuk (megsemmisítjük) a zseblámpát, a kapcsoló is követi.
Az elemet viszont eltávolíthatjuk a zseblámpából, és egy másikban
alkalmazhatjuk, ezért ez a kapcsolat halmazként jelenik meg.
Ügyeljünk azonban, hogy
ezek a „rész–egész” kapcsolatok nem csak kézzel fogható (fizikai) elemekre
érvényesek. Egy Egyénnek például lehet Hite, Márkaneve vagy Piaci
értéke is.
Általánosítás
A fejezet egy korábbi
részében felbukkant az általánosítás kapcsolat (lapozzunk vissza
az 5.5. ábrához). A társítás nyílhegyénél szereplő osztályok a fölérendelt
osztályok, a társítás másik végén szereplő osztályok pedig az alárendelt
osztályok. A fölé- és alárendelt osztályok kapcsolata a gyermek–szülő
kapcsolathoz hasonlítható. A gyermek- (alárendelt) osztályok öröklik
a szülő- (fölérendelt) osztályok jellemzőit, műveleteit
és kapcsolatait.
5.15. ábra
Általánosítás
Az 5.15. ábra egy ilyen
kapcsolatot szemléltet. A szülő (Fegyver) a súly, a hossz és a hatótávolság
jellemzővel rendelkezik. A gyermekek (a Puska és a Fúvócső)
öröklés révén átveszik ezeket a tulajdonságokat,
vagyis ezeknek is lesz súlyuk, hosszuk és hatótávolságuk, annak ellenére,
hogy az alosztályokban ez nem feltétlenül jelenik meg külön. Ugyanez
igaz a műveletekre is – a gyermekek a szülőktől öröklik
azokat. Ebben a példában – ahogy korábban is kifejtettük – a gyermekosztályok
felülbírálják (vagyis átformálják) a „tölt” műveletet.
Társításosztályok
Előfordul, hogy amikor
elkezdjük összekapcsolni az osztályokat (társításokon keresztül),
olyan helyzetbe kerülünk, amikor nem maguk az osztályok, hanem a közöttük
lévő kapcsolat a lényeg. Az 5.16. ábra például egy olyan befektetőt
jelenít meg, aki különböző részvényekbe fektet be.
5.16. ábra
Alaptársítás
Ha az alkalmazásnak ki
kell számítania a befektetés adóvonzatát, akkor ismernie kell olyan
adatokat, hogy mikor vásárolták és adták el a részvényt, az árfolyamokat
és így tovább. A vásárlás dátuma tehát a befektető jellemzője?
Egyértelműen nem. A részvényé? Nem igazán, mivel a vásárlás
időpontja nem a részvény belső tulajdonsága. Ez az információ
a befektető és a részvény kapcsolatát
írja le, és nem az osztályokét. Ebben a helyzetben a kapcsolat a lényeg.
5.17. ábra
Társításosztály
Hol rögzítjük tehát ezt
az információt? Társításosztályokban.
(Amikor már azt gondoltuk, hogy biztonságban vagyunk, és megértettük
az összes osztályokkal és társításokkal kapcsolatos dolgot, akkor
jön a csavar.) A társításosztályok olyan társítások, amelyek rendelkeznek
az osztályok bizonyos tulajdonságaival. A következő példában
a kulcsfontosságú információ, amire szükség van, a részvény és a befektető
birtokviszonyával kapcsolatos
(lásd az 5.17. ábrát).
A Birtokviszony
társításosztály tartalmazza a két másik osztály közötti kapcsolat fontos adatait. (A társításosztályokat
gyakran látjuk még a több elem közötti társításoknál.) A befektető
nélkül nincs vásárlás, a részvény nélkül viszont nincs mit megvenni:
együtt van szükség a befektetőre és a részvényre. A kapcsolat nem
létezhet a két társított osztály létezése nélkül, így a társításosztály
sem.
Megszorítások
Az UML által biztosított
megszorítások lehetővé teszik,
hogy érthetőbbé és kifejezőbbé tegyük a tervet. A megszorítások
olyan jelölések, amelyek tovább korlátozzák vagy pontosítják a modellelemeket.
Az 5.18. ábránál visszatérünk a bérlista példájához. Ha a vállalatnál
minden héten fizetést osztanak, hozzáadhatunk egy olyan megszorítást,
amely kifejezi ezt (a kapcsos zárójelben látható).
A megszorítások lehetnek
időbeli, sorrendbeli megszorítások, egyedi tulajdonságok,
vagy bármi, ami az adott helyzetben szükséges.
5.18. ábra
Megszorítás
A sorrenddiagramokról
bővebben
Ahogy az osztálydiagramok
az alkalmazás statikus szerkezetét ábrázolják, a sorrenddiagramok
képesek az alkalmazás dinamikus viselkedésbeli jellegének megjelenítésére.
Mint azt a 2. és a 3. fejezetben elmondtuk, azt mutatják, hogy az alkalmazás
objektumai miként működnek együtt, hogy üzenetek alkalmazásával
elérjék a kívánt végeredményt. A diagramok másik felhasználási területe
(vagyis az alkalmazásmodellezés) további bizonyíték a sokoldalúságukra.
Az állapotdiagramot – amely szintén viselkedésdiagram – a 8. fejezetben
tárgyaljuk.
A következő diagramok
példával szemléltetik a sorrenddiagramok használatát az alkalmazásmodellezésben.
Az 5.19. ábra egy orvosi feljegyzéseket kezelő rendszer együttműködés-szabályozó
alrendszerét mutatja.
5.19. ábra
Együttműködési feladatdiagram
Ebben a példában a „LACS átadása” feladatra
összpontosítunk. Ahhoz, hogy megfeleljenek a szabályozási követelményeknek,
az egészségügyi intézményeknek adatokat kell szolgáltatniuk a kormánynak
a gondozásukban álló betegekről. Ezt az egészségügyi feljegyzéscsoportot
Legkisebb Adatcsoportnak (LACS) nevezik. A sorrenddiagram a rendszer
dinamikus működését rögzíti (lásd 5.20. ábra).
5.20. ábra
Együttműködési sorrenddiagram
A diagram üzenetfolyamát
követve láthatjuk, hogy az Ügyintéző létrehoz egy „Köteget”,
ahová a LACS-ok kerülnek. A kiválasztott LACS-ok a Köteghez adódnak,
majd az Adatközvetítőhöz kerülnek, és így tovább, ahogy a műveletsor
folytatódik.
Ez a sorrenddiagram bemutatja
a rendszer elemei közötti dinamikus kölcsönhatásokat. Ez biztosítja
az alapot az elemek szerkezetének meghatározásához, ami az 5.21. ábrán
– ez a „LACS átadása” feladat osztálydiagramja – látható.
Az objektumközpontú
rendszertervezés meglehetősen sok ismétléssel jár. Az osztályfelépítés
fejlesztésekor a tervező rájött, hogy új rendszerelem kell a Kötegek
létrehozásához és átadásához. Így láthatjuk, hogy a diagramban megjelenik
egy Kötegkezelő. Egy szigorú rendszerben frissítenék a sorrenddiagramot,
hogy az tartalmazza a Kötegkezelőt. Az alkalmazástervezés
előrehaladtával gyakran fordulnak elő ismétlések és változások
a különböző diagramok között. (Ha valaki meg szeretné érteni
az itt szereplő példa folyamatát és fejlődését az üzleti
modellezéstől az alkalmazásig, a szerzők UML for Database Design [NAIB3] című
könyvében megtalálja a tanulmány részletes kidolgozását.)
5.21. ábra
Együttműködési osztálydiagram
Haladóknak
A következő témákat
érdemes tanulmányozni:
• Az osztályokban a név, a jellemzők és a műveletek
rekeszén kívül további rekeszek szerepelhetnek. Keressünk példát
az alkalmazásukra.
• Vizsgáljuk meg a származtatott
jellemzők gyakran alkalmazott elvét.
• Tanulmányozzuk a függőség
viszonyt.
• Derítsük ki a megvalósításosztályok, a típusok és a paraméterezett
osztályok (más néven sablonosztályok) közötti különbséget.
• Az ebben a fejezetben szereplő társítások mindig
két osztályt kapcsolnak össze. Vannak helyzetek, amikor kettőnél
több osztály vesz részt egyetlen kapcsolatban. Tanulmányozzuk az „n-es
kapcsolatokat”.
• Hasonlítsuk össze és állítsuk szembe
egymással a sorrenddiagramokat és az együttműködési diagramokat.
Kifejezések
Felület Beburkolás
Osztály Objektum
Többalakúság Fogalom
UML-rendőrség Betokozás
Láthatóság Művelet
Aláírás Elvont
Felülbírálás Társítás
Jelzés Szerepnév
Minősítő Mennyiség
Halmaz Összetétel
Összetartozás Társításosztály
Megszorítások Jellemző
Általánosítás Öröklés
Összefoglalás
A fejezet elején felsoroltuk
az alkalmazások modellezése mellett szóló érveket. Rámutattunk,
hogy az átlagos rendszertervező blokkvázlatok, folyamatábrák
és hasonló módszerek segítségével már eleve modellezi az alkalmazásokat.
Megtudtuk, hogy a szabványos (UML alkalmazásával történő) modellezés
egyaránt hasznos az új és az öröklött alkalmazásoknál, különösen, ha
a program rendkívül fontos, bonyolult, illetve folyamatosan változik.
Megvizsgáltuk az alkalmazásmodellezés személyes és szakmai indokait
is.
Ez után körüljártuk azt
a kérdést, hogy milyen szélességben és mélységben kell modellezni az
alkalmazásokat. Ugyan az a legjobb, ha a teljes alkalmazást modellezzük,
de az alkalmazás vagy a rendszer egyes részeinek modellezéséhez
szükséges különböző követelményeket és megoldásokat is megismertük.
Azt is megtanultuk, hogy nem szabad azt hinni, hogy a programozási
nyelvek helyettesíthetik a megfelelő elemzést és tervezést.
Végül megismertük az
osztálydiagramokban található fő elemeket: a jellemzőkkel
és műveletekkel rendelkező osztályokat és az azok közötti
társításokat. Bevezettük a többalakúság, a betokozás, a láthatóság
és a megszorítások fogalmát. Elsajátítottuk a szerepnevek, a minősítők
és a mennyiségjelzések használatát. Ezen kívül összehasonlítottunk
két különleges társítást: a halmazt és az összetételt. Végül az általánosítást
és az öröklést is tárgyaltuk.
Ellenőrző kérdések
1. Igaz vagy hamis? „A többalakúság elve azt mondja, hogy az osztályok
adatai rejtettek a külső egységek számára, és csak belső egységek
érhetik el azokat, az osztály által biztosított műveleteken keresztül.”
2. Milyen korlátozást alkalmaznak a szerepnevek egy osztályra?
3. A minősítők azon osztályok meghatározott objektumait
jelölik ki, amelyek...
a. a társítás
minősítőhöz közelebbi végén találhatók.
b. a társítás
távolabbi végén találhatók.
4. Igaz vagy hamis? „Egy halmazban az Egész megsemmisülésekor
nem feltétlenül semmisül meg az összes Rész.”
5. Az alábbiak közül melyik nem láthatóságfajta?
a. Privát
b. Részleges
c. Látszólagos
d. Nyilvános
e. Elvont
f. Csomag
g. Védett
[NAIB3]
Naiburg, Eric J. és Robert A. Maksimchuk. 2001. UML for Database Design. Boston, MA: Addison-Wesley.