A felhasználói felület a program azon része, amely segítségével a felhasználó a számítógéppel kommunikál. A felhasználói felület a mai napig az egyik legjobban kutatott és fejlesztett terület a számítástechnikában, ám ennek ellenére a mai napig nem alakultak ki a fejlesztés közben vakon követhetô szabályok. Az idôk folyamán természetesen kikristályosodtak bizonyos, sokak által követett szokások, módszerek. Ebben a leckében ezekkel az inkább csak irányelveknek tekintendô technikákról fogunk tanulni, amelyek elôsegíthetik a problémamentes kapcsolattartást a felhasználóval.
Súgás
A legtöbb felhasználó esetében igen sokat nyom a latban, ha a futtatott program konzekvensen ellátja használóját világosan fogalmazott, tömör üzenetekkel és információval mûködése során. A felhasználóval való kapcsolattartás egyik legfontosabb eleme a súgás, amikor is arról tájékoztatjuk a felhasználót, hogy most éppen milyen tevékenységet vagy adatot várunk tôle. A legtöbb ember egyszerûen átugorja a hosszú üzeneteket, ezért fogalmazzunk röviden és világosan. Ha mégiscsak terjedelmes információt kell közölnünk, akkor osszuk fel részekre, a legfontosabb részét jelenítsük meg és tegyük opcionálissá a maradék információ megtekintését. A ló másik oldalára esünk át, amikor a közölt információ túlságosan szûkszavú és a felhasználó nem igazán tudja eldönteni, hogy mit is akarunk. A legjobb módszer az arany középút megtalálására, ha valakit megkérünk, hogy tesztelje programunkat. Ügyeljünk az üzenetek megfogalmazására is. Kutatások bebizonyították, hogy a felhasználók kevésbé szeretik, ha úgy teszünk, mintha a számítógép emberi lény lenne. Sokkal jobb, ha például a "Szia! Azért vagyok itt, hogy elkészítsem az adóbevallásodat." üzenet helyett az "Ezzel a programmal az adóbevallást lehet elkészíteni." bejelentkezô üzenet jelenik meg adóbevallás készítésére alkalmas programunk indításakor. Amikor hiba történik, akkor pedig nem szabad a felhasználóval azt éreztetni, hogy a hiba miatta történt, hanem el kell neki magyarázni, hogy hogyan kerülheti el a jövôben a hasonló problémákat.
Segítségrendszer kiépítése
A REXX programok egyik fô jellemzôje, hogy többségük viszonylag rövid. Ez azt is jelenti, hogy a legtöbb esetben elég egy, a program használatát elmagyarázó üzenet és nincs szükség beépített segítségrendszerre. Természetesen elôfordulhatnak olyan esetek is, amikor érdemes a segítségek számára egy külön alrendszert tervezni. Az alábbiakban bemutatott példa kibôvítése az esetek többségében bôven elegendô. A példaprogram futtatásakor pótlólagos információt kapunk, ha a kérdôjelet viszünk be.
/* Minimális segítségrendszer */ DO FOREVER SAY 'Vezetéknév:' PARSE PULL nev SELECT WHEN nev = '?' THEN SAY 'Gépelje be a vezetéknevét!' WHEN nev = '' THEN SAY 'A vezetéknév szükséges információ!' OTHERWISE LEAVE END END EXIT
Hangeffektusok használata
A legeredményesebben talán a programokba beépített hangeffektusokkal vonhatjuk magunkra a felhasználók figyelmét. Jó dolog hangjelzést adni hosszabb futási idôt igénylô folyamatok végén, hibajelzések nyomatékosításaként, vagy egyéb figyelmeztetô üzenetek megjelenítésekor. A REXX-ben természetesen erre is van lehetôség, mivel a Beep függvény segítségével megszólaltathatjuk a PC hangszóróját, s a Beep paraméterei révén azt is megadhatjuk, hogy a jel frekvenciája (Hz) és idôtartama (ms) mekkora legyen. Az alábbi kétsoros kód például egy két tónusú hangjelzést ad:
Beep(250, 250) /* 250Hz, 250ms */ Beep(150, 500) /* 150Hz, 500ms */
Természetesen nem jó itt sem átesni a ló másik oldalára! Hacsak nem akarjuk valamilyen fontos dologra felhívni a figyelmet, akkor inkább ne használjunk hangokat. A "zajos" programokat nem szeretik a felhasználók, és elôbb utóbb megpróbálják majd programunkat elcsendesíteni.
Színek használata
A hangok mellett színekkel is "feldobhatjuk" programunkat. Az értelmetlen csicsázáson túlmenôen valódi többletértéket jelent, amennyiben a színeket konzekvensen használjuk. Ha például a hibaüzeneteket mindig piros színnel jelenítjük meg, akkor a felhasználó már tudni fogja, hogy valami rossz történt, mielôtt még elolvasná az aktuális hibaüzenetet. A színek kezelésére nincsenek külön REXX függvények, ugyanis a feladat tökéletesen megoldható az OS/2 parancssora által nyújtott eszközökkel. Alapesetben az OS/2-es ablak ANSI terminálemulációt nyújt. Az emuláció speciális ANSI vezérlôkarakterek segítségével befolyásolható. Ez azt jelenti, hogy speciális karakterláncok "megjelenítésével" letörölhetô például az ablak, vagy beállítható a háttér vagy a szöveg színe. Minden ANSI karakterlánc az escape karakterrel kezdôdik, amelynek 27, vagy pedig 1B a kódja hexadecimális számrendszerben. Az escape karaktert követô egyéb karakterek határozzák meg, hogy a parancs mit is csinálj. A [2J megadásával például töröljük a képernyôt:
SAY '1B'x || '[2J'
Mivel a vezérlôkarakterek észben tartása nem nagy élvezettel, ezért érdemes ôket megfelelôen elnevezett változókban tárolni és a kódok helyett ezeket a változókat használni.
A színek megadása már egy kicsit bonyolultabb:
SAY '1B'x || '[35;44m'
A [ után álló szám a szöveg, a ; után álló szám pedig a háttér színének a kódját jelenti. Az alábbi táblázatban összefoglaltuk az ANSI színek kódjait:
| Szín: | Szövegszín: | Háttérszín: |
| fekete | 30 | 40 |
| piros | 31 | 41 |
| zöld | 32 | 42 |
| sárga | 33 | 43 |
| kék | 34 | 44 |
| magenta | 35 | 45 |
| cián | 36 | 46 |
| fehér | 37 | 47 |
Gondolom nem lep meg senkit, hogy az alapértelmezés szerinti szövegszín a fehér, a háttérszín pedig a fekete. Ha valamelyik számot nem adjuk meg, akkor az alapértelmezett érték lesz továbbra is az érvényes. Ha a kódokat kombináljuk (amit a karakterláncok összefûzésével tehetünk meg), akkor hatásuk összeadódik. Amikor az elsô paraméternek 1-et adunk meg, az abban a pillanatban beállított szövegszín világosabb lesz. A 0-val visszatérhetünk az alapértelmezés szerinti szövegszínhez.
Több ANSI vezérlôkarakter is létezik a kurzor mozgatására, mi azonban csak egyet fogunk tárgyalni, ami a SAY utasítás mellékhatásnak köszönhetô. A SAY ugyanis mindig a sor elejére pozícionálja a kurzort, s ez bizonyos vezérlô karakterek esetében zavart okoz. A kurzor pozícionálására mi az '1B'x || [sor;oszlopH formátumú karakterláncot fogjuk használni. A színeket beállító karakterláncoktól eltérôen ebben az esetben H-ra végzôdik a parancs. A két paraméter adja meg a kurzor kívánt pozícióját. A képernyô bal felsô sarka az 1;1 koordinátájú pont, a többi pozíció az ehhez a ponthoz viszonyított eltérést adja meg. Most pedig lássunk egy példát a most tanultak használatára, amibôl minden egy csapásra világos lesz!
/* ANSI vezérlôkarakterek használata */
konyv. = ''
torles = '1B'x || '[2J' /* képernyôtörlés */
feher_a_keken = '1B'x || '[37;44m' /* fehér kék háttérrel */
piros_a_keken = '1B'x || '[31;44m' /* piros kék háttérrel */
vilagos = '1B'x || '[1m' /* világosabb elôszín */
normalis = '1B'x || '[0m' || feher_a_keken /* a normál szín */
segitseg_hely = '1B'x || '[3;1H' /* a segítségsor helye */
vezeteknev_hely = '1B'x || '[5;1H' /* a vezetéknév helye */
keresztnev_hely = '1B'x || '[7;1H' /* a keresztnév helye */
utca_hely = '1B'x || '[9;1H' /* az utca helye */
varos_hely = '1B'x || '[11;1H' /* a város helyes */
segitseg_torles = segitseg_hely || Copies(' ', 80) || segitseg_hely
i = 0
DO FOREVER
SAY feher_a_keken || torles
SAY vilagos || Center('Hozzáadás a címjegyzékhez', 80) || normalis
SAY segitseg_torles || Center('(Vezetéknév, vagy "kész", ha kész)', 80)
SAY vezeteknev_hely || vilagos || 'Vezetéknév:' || normalis
PARSE PULL valasz
IF valasz = 'kész' THEN
LEAVE
i = i + 1
konyv.i.vezeteknev = valasz
SAY segitseg_torles || Center('(Keresztnév)', 80)
SAY keresztnev_hely || vilagos || 'Keresztnév:' || normalis
PARSE PULL konyv.i.keresztnev
nev = konyv.i.vezeteknev konyv.i.keresztnev
SAY segitseg_torles || Center('(Utca, házszám)', 80)
SAY utca_hely || vilagos || 'Utca, házszám:' || normalis
PARSE PULL konyv.i.utca
SAY segitseg_torles || Center('(Város, irányítószám)', 80)
SAY varos_hely || vilagos || 'Város, irányítószám:' || normalis
PARSE PULL konyv.i.varos
END
konyv.0 = i
SAY normalis || torles
DO i = 1 TO konyv.0
SAY ''
SAY konyv.i.vezeteknev konyv.i.keresztnev
SAY konyv.i.utca
SAY konyv.i.varos
END
EXIT
A fenti program felhasználói adatokat kér be, s tárolja azokat. Minden egyes rekord bevitele után törli a képernyôt és kéri a következô személy adatait. Ha már nincs több adat, akkor a "kész" szó begépelésével léphetünk ki. A képernyô tetején minden esetben egy segítségsort is láthatunk, amelynek tartalma dinamikusan változik az éppen kitöltés alatt álló mezô jellegétôl függôen. A futás végén a program kilistázza az eltárolt adatokat. A segítségsort a képernyô alján is megjeleníthetjük, ekkor azonban ügyelni kell arra, hogy az információ megjelenítése után mindig újrapozícionáljuk a kurzort, különben a SAY utasítás a következô sor elejére pozícionál, ami a képernyô legördüléséhez vezet. Ha igazán biztosak akarunk lenni a dolgunkban, akkor programunkat a MODE utasítással kell kezdeni, hogy mi határozzuk meg a képernyô sorainak számát:
'mode 80,25' infopos = '1B'x || '[25;1H' curspos = '1B'x || '[5;1H' info = 'Kérem a személy vezetéknevét!' SAY infopos || info || curspos || 'Vezetéknév:'
Parancssorban megadható paraméterek használata
A programok egy része elfogad parancssorban megadott paramétereket is. Egy paraméter elvileg bármilyen adat lehet; az egyetlen korlátozás a parancsértelmezô által meghatározott maximális adathossz. Speciális paraméterek a kapcsolók (switch), amelyekkel a program viselkedését lehet befolyásolni. Az OS/2 dir parancsa például másképpen listázza ki a fájlokat és könyvtárakat, ha megadjuk a /w kapcsolót, mint anélkül. A kapcsolók elsô karaktere általában "/", vagy pedig "-", mivel így könnyen meg lehet különböztetni ôket a többi paramétertôl. A legjobb megközelítés az, ha mindkét fajtát támogatjuk programunkban. A kezdôkarakter után álló karakter vagy karakterek adják meg a kapcsoló jelentését. A legtöbb program nem tesz különbség a kis és nagybetûk között, bár erre nem érdemes alapozni, mivel vannak olyan alkalmazások, amelyek kénytelenek ezt a lehetôséget is kihasználni a megadható kapcsolók nagy száma miatt. Az alábbiakban egy olyan kódrészletet mutatunk be, amely alapjául szolgálhat a kapcsolók és paraméterek helyes kezelésének:
/* Kapcsolók és egyéb paraméterek feldolgozása */ PARSE ARG input kapcsolok.0 = 0 parameterek.0 = 0 DO WHILE input <> '' PARSE VAR input szo input IF Left(szo, 1) = '/' | Left(szo, 1) = '-' THEN DO j = kapcsolok.0 + 1 kapcsolok.j = Substr(szo, 2) SELECT WHEN kapcsolok.j = '?' | kapcsolok.j = 'h' THEN SAY 'Ez egy példaprogram!' OTHERWISE NOP END kapcsolok.0 = j END ELSE DO j = parameterek.0 + 1 IF Left(szo, 1) = '"' THEN DO input = szo input PARSE VAR input '"' szo '"' input END parameterek.j = szo parameterek.0 = j END END SAY 'Kapcsolók:' IF kapcsolok.0 = 0 THEN SAY 'Nem volt megadva!' ELSE DO i = 1 TO kapcsolok.0 SAY 'Kapcsoló'i': 'kapcsolok.i END SAY 'Paraméterek:' IF parameterek.0 = 0 THEN SAY 'Nem volt megadva!' ELSE DO i = 1 TO parameterek.0 SAY 'Paraméter'i': 'parameterek.i END EXIT
A fô munkát a DO-WHILE hurok végzi, amely feldarabolja a parancssorban megadott adatot és minden egyes darabot megvizsgál, hogy nem egy kapcsolóról van-e szó. A SELECT utasítás ellenôrzi, hogy nem segítséget kért-e a felhasználó. Az idézôjelek közé tett paraméterekre is figyel a program, mivel elôfordulhat, hogy a megadni kívánt paraméterben szóköz is szerepel. A futás végén a program megjeleníti a megadott kapcsolókat és az egyéb paramétereket.
A bekért adatok ellenôrzése
A programozás egyik alapvetô szabálya a következôképpen hangzik: szemét be, szemét ki. Gyakori programozói hiba ugyanis azt feltételezni, hogy a felhasználó mindig korrekt adatokat visz be. Sajnos ez nem így van, ezért programunknak gondoskodni kell arról. hogy megvédje magát a szándékosan vagy esetleg csak véletlenül megadott rossz adatoktól, különben a program által generált kimenet nem az lesz, amire számítunk, vagy rosszabb esetben egyszerûen csak összeomlik az alkalmazás. Gyakori eset, hogy numerikus adatok bevitelekor nem ellenôrizzük, hogy valóban számokat kaptunk-e bemenetként. Ez szerencsére nagyon könnyen megoldható a már korábban ismertetett DATATYPE függvénnyel. Amikor egész számokra várunk, akkor ezt is ellenôrizni illik. Persze mint minden mást, az ellenôrzést sem kell túlzásba vinni. Ha például személyneveket várunk, akkor elég csak azt ellenôrizni, hogy a megadott adat legalább egy karakterbôl áll. Amikor összehasonlítjuk a bevitt adatot valamilyen, a programban tárolt adattal, akkor ne feledkezzünk meg arról sem, hogy meg akarjuk-e különböztetni a kis és nagybetûs eseteket. Ha nem, akkor érdemes az adatokat az összehasonlítás elôtt nagybetûs alakra hozni a TRANSLATE függvénnyel. Bizonyos esetekben elfogadhatunk rövidítéseket is a felhasználótól. Tipikus eset, amikor igen vagy nem választ várunk. Ilyenkor ahhoz vannak az emberek szokva, hogy elég az i vagy az n betûket megadni, és nem kell az egész szót begépelni. A rövidítések ellenôrzésére szolgál az Abbrev függvény:
Abbrev(információ, info [, hossz])
Ez a függvény egyszerûen összehasonlítja az info karakterláncot az információ karakterlánc elsô, vagy a hossz paraméter által megadott darabszámú karakterével, és ha ezek megegyeznek, akkor 1-et ad vissza, ellenkezô esetben pedig 0-át. Az Abbrev függvény különbséget tesz a kis és nagybetûk között is.
Defenzív programozás
A legtöbb helyzetben az a kívánatos, ha defenzíven programozunk. Ez azt jelenti, hogy programunknak számolni kell olyan esetekkel is, amelyek elvileg nem, vagy csak nagyon ritkán fordulhatnak elô. A bemeneti paraméterek ellenôrzése szükséges, azonban nem elégséges feltétele a defenzív programozásnak. Kívánatos például, hogy programunk CTRL-BREAK-kel történô megszakítására figyeljük, mivel ekkor programunkat ilyen esetben is kultúrált módon tudjuk befejezni. A megszakítás figyeléséhez be kell kapcsolni a már tanult SIGNAL ON HALT mechanizmust. Egy másik fontos dolog, hogy ellenôrizzük a futás során végrehajtott parancsok visszatérési értékeit. A parancsok végrehajtása ugyanis nem minden esetben sikerül, és ennek akár katasztrofális következményei is lehetnek:
'copy 'nagyon_fontos_adatfajl backupdir 'del 'nagyon_fontos_adatfajl
Ilyen esetben például nagyon fontos ellenôrizni a törlés elôtt, hogy a fontos fájl másolata valóban elkészült-e:
'copy 'nagyon_fontos_adatfajl backupdir IF rc = 0 THEN 'del 'nagyon_fontos_adatfajl
Bizonyos esetekben nem tudunk mit csinálni, ha egy parancs végrehajtása nem sikerül. Ilyenkor közölni kell a felhasználóval a rossz hírt, és ha van értelme, fel kell neki kínálni a lehetôséget, hogy a parancsot megismételtethesse.
REXX GYÍK:
K1. Hogyan kapcsolhatom be az ANSI terminálemulációt, ha az éppen ki van kapcsolva?
V1. Az ANSI ON illetve OFF paranccsal lehet az emulációt ki illetve bekapcsolni. Ha paraméter nélkül gépeljük be az ANSI parancsot, akkor válaszul megkapjuk az emuláció pillanatnyi állapotát.
Gyakorlatok:
1. Készítsen egy programot, amely összeadja a bevitt számokat és kijelzi az eredményt. A számok bevitelét az "=" begépelésével zárja le. Ellenôrizze, hogy a bevitt számok egész számok-e és ha nem, akkor adja meg a felhasználónak a hiba korrigálásának a lehetôségét!
| Kádár Zsolt 1998. 06. 14. | [ Elôzô lecke | Következô lecke | Tartalom ] |