Magazín KPI
Časopis Katedry počítačov a informatiky FEI TUKE
kpi

Parkovací systém budovy Business Center Košice – časť 1.

Úlohou tejto práce bol návrh, implementácia a testovanie parkovacej mobilnej aplikácie v Andro-ide. Je určená pre zamestnancov firmy Wirecard, ktorým by mala aplikácia pomôcť pri parkovaní a ušetriť tak ich čas aj peniaze. Motiváciou bola hlavne náhrada zastaralého, minimálne využí-vaného parkovacieho systému, postaveného na zdieľanej Google tabuľke. V aplikácií sme použili najnovšie funkcie Androidu. Zamerali sme sa hlavne na funkcionálne a reaktívne programovanie pomocou lambda výrazov a knižnicou Rx Java. Chceli sme týmto dosiahnuť čo najlepší použí-vateľský zážitok. Počas implementácie sme dbali na dodržiavanie materiálneho dizajnu, čo má tiež vplyv na používateľa. V samom závere sme vytvorili dva rovnaké projekty, kde jeden bol napro-gramovaný v jazyku Java a ten druhý v jazyku Kotlin. Oba projekty sme navzájom porovnali a odvodili ich klady aj zápory.

Úvod

Parkovísk, kde sme doteraz dokázali bez problémov zaparkovať auto stále ubúda. Problém sa týka hlavne väčších miest, kde počet ľudí každým dňom rastie. To platí aj pre autá, ktorých je už tak mnoho, že podľa mňa ich čoskoro začneme kupovať aj svojim domácim miláčikom. Problém parko-vania nenastáva len pri nakupovaní, ale aj po príchode domov či do práce. Firma Wirecard v Košiciach, ktorá sídli v budove známej ako „Biznis Centrum Košice“ na Štúrovej ulici sa nachádza takmer v priamom centre Košíc, kde je hustá premávka a šanca zaparkovať pre zamestnancov je veľmi nízka. Budova obsahuje podzemné parkovisko, pričom firma má v podnájme len niekoľko miest (závisí od veľkosti prenajímaných priestorov). Každé miesto má priradené práve jedného zamestnanca (nazvime vlastníka). Získanie takého miesta zahŕňa čakanie v dlhom poradovníku. Keďže dopyt je väčší ako ponuka, zamestnanci museli parkovať na platených alebo na vzdialenej-ších verejných parkoviskách. Tu si položme otázky, kto tento systém riadi? Kto určuje priradenie nových parkovísk? Ako vyriešiť absenciu vlastníka parkoviska, keď voľné miesto môže zatiaľ vyu-žiť niekto iný? Môže ho využiť ktokoľvek? Pri uvoľnení parkoviska mimo sídla budovy, ako sa k nemu dostať? Doposiaľ existujúce riešenia, neposkytovali odpoveď na všetky tieto otázky, keďže firma má špeciálne požiadavky ako napr. viacero rozhraní (admin, user), navigácia priamo k parko-vaciemu miestu, či sledovanie voľných miest pomocou notifikácií.

V poslednom čase sa do popredia dostal momentálne už oficiálny jazyk určený na programovanie Android aplikácií s názvom Kotlin. Je to pomerne mladý jazyk. Rýchlo naberá na popularite vývo-járov, preto sme sa rozhodli naprogramovať aplikáciu aj v tomto jazyku. Koniec koncov, použiť spomínaný jazyk bola jedna z požiadaviek zákazníka. Pri programovaní tejto aplikácie sme sa roz-hodli sledovať rozdiely medzi programovacími jazykmi Java a Kotlin. Porovnanie sa nám zdalo ako veľmi dobrý nápad, keďže Kotlin je čerstvý oficiálny programovací jazyk pre Android a pomaly nahrádza Javu, ktorá si držala oficiálny status po dlhé roky. Našim cieľom bolo vytvoriť dve rov-naké aplikácie, kde jedna bude naprogramovaná v Jave a druhá v Kotline. Našou úlohou bolo in-tegrovať serverovú časť dodanú zákazníkom spolu s našou aplikáciou. Serverová časť je implemen-tovaná v softvérovom rámci Spring a obsahuje databázu všetkých zamestnancov s ich vzťahmi k parkovacím miestam. Vo firme Wirecard momentálne používajú zdieľanú webovú tabuľku, kde si každý zamestnanec osobne mení status parkoviska. K parkovisku vie pristupovať ktorýkoľvek pou-žívateľ bez autentifikácie, tiež ju vie kedykoľvek celú zmazať. Veľkou nevýhodou je, že tabuľku dokáže súčasne editovať len jedna osoba, pričom zmeny musí uložiť, aby ich videli ostatní za-mestnanci. Keď vlastník parkoviska nebude v práci, musí to zaevidovať v tabuľke zbytočne zdĺha-vým procesom. Veríme, že s našou aplikáciou sa problém vyrieši a vlastník ochotnejšie uvoľní svoje miesto iným kolegom. Časom, keď aplikáciu prispôsobíme tak, že si v nej budú zamestnanci žiadať dovolenku, proces sa ešte zjednoduší, lebo sa takto vlastníkove parkovacie miesto pri jeho absencii automaticky uvoľní. Našim hlavným cieľom bude zjednodušiť a zrýchliť prácu s parkovacím systémom, tiež zaistiť jeho bezpečnosť registráciou a bezpečným prihlásením používateľa. V projekte budeme manažovať všetky procesy, ktoré vývoj reálnej produkčnej aplikácie zahŕňa. Patrí sem návrh (prehodnotiť, čo musí aplikácia obsahovať), dizajn (vonkajšia grafická vizualizácia), samotná implementácia (reali-zácia návrhu), testovanie použiteľnosti (zistenie, či aplikácia interaguje tak, ako sme plánovali) a na-koniec samotná publikácia aplikácie (vypustenie aplikácie do produkčného prostredia). O spra-vova-nie databázy sa bude starať administrátor pomocou webovej aplikácie, ktorý by vedel mana-žovať používateľov a ich vzťahy ku konkrétnym parkoviskám. Používateľ by mal prístup len k svojmu vlastnému parkovisku alebo iným prázdnym parkoviskám. Naraz je možné obsadiť len jedno parkovisko. Vlastník parkoviska vie svoje parkovacie miesto uvoľniť inému kolegovi a to tak, že svoje miesto označí na konkrétne dni ako prázdne a iní kolegovia si ho vedia rezervovať. Žiadateľ o miesto si určí, koľko dní tam chce parkovať a po schválení vlastníkom je parkovacie miesto rezervované na jeho meno.

Kotlin vs Java

Na začiatku môže byť ťažké zanechať jazyk, ktorý programátor detailne ovláda a začať s iným, úplne novým. Najmä keď berieme na vedomie, že náš kód bude testovaný reálnymi používateľmi. Porovnanie Kotlin a Java môžeme stotožniť s porovnaním Swift a Objektové C. Rovnako ako Swift, je Kotlin ľahko použiteľný. Jednoznačne sa dá jeho použitím ušetriť veľa riadkov kódu. Vývojári so znalosťou C# a Java sa ho naučia pomerne rýchlo, lebo má s týmito jazykmi veľa spo-ločného. Výhodou je možnosť použitia Javy a Kotlinu v jednom projekte, kde dokážu bez problé-mov spolupracovať. Jednoduché je aj použitie knižníc, ktoré už začínajú ponúkať rozšírenia pre Kotlin. Jedným z dobrých príkladov je Rx Kotlin, postavený na základe knižnice Rx Java. Kotlin má v porovnaní s Javou aj pár nevýhod, akými sú veľký počet balíkov a dlhšia kompilácia Gradle. Najdôležitejšou výhodou technológie Kotlin je súbor nových funkcií, ktoré Java neobsahuje. V nasledujúcej časti si vyberieme niektoré z obľúbených a bližšie ich vysvetlíme [1].

Bezpečnosť null pomocou nulových typov Kotlin chráni program pred nulovými referenciami tým, že všetky typy sú štandardne „nie null“. To znamená, že kompilátor nám nepovolí použiť neinicializovanú premennú. Ak chceme, aby pre-menná obsahovala hodnotu null, tak jej priradíme nulovú hodnotu a hneď za typom pridáme otáz-nik ako v ukážke nižšie.

var nonNullable: String = "My string" // needs to be initialized 
var nullable: String? 

Kdekoľvek programátor pristupuje k nulovej premennej, prekladač vykoná nulovú kontrolu. Tým je kód prehľadnejší a vieme určiť čo je null a čo nie, čiže kód je kvalitnejší a menej chybový [1].

Rozšírené funkcie Sú odvodené z jazyka C#. Pomocou rozšírených funkcií dokážeme meniť správanie triedy bez pou-žitia dedičnosti. Vieme zavolať funkciu z objektu tak, ako keby bola súčasťou triedy. V ukážke sme vytvorili rozšírenú funkciu pre objekt String s názvom makePretty(). Môžeme si všimnúť, že táto funkcia nie je funkcia z objektu String, ale syntakticky tak pôsobí [1].

StringMakePretty.kt 
fun String.makePretty(): String { 
// make the string pretty and return it 
}

Funkcie vyššieho rádu a lambdy Funkcie vyššieho rádu (známe z jazyka JavaScript alebo C#) dokážu funkciu prijať ako parameter alebo ju vrátiť. Tieto funkcie môžu byť uložené v premenných na neskôr. Ak nie je funkcia deklaro-vaná ale vyhodnocuje sa ako výraz, tak ju nazývame lambda alebo anonymná funkcia. Nižšie uve-dený príklad reprezentuje anonymnú funkciu, ktorá pošle požiadavku na server a očakáva až dva rôzne odpovede (úspešné volanie alebo chybu) [1]. V Jave by si to vyžadovalo vytvorenie nových inštancií a oveľa viac napísaného kódu.

fun networkCall(onSuccess: (ResultType) -> Unit, 
onError: (Throwable) -> Unit) { 
try { 
// create and execute network request 
onSuccess(myResult) 
} catch(e: Throwable) { onError(e)}}

Dátové triedy Sú obrovským šetričom času. Vzhľadom k tomu, že väčšina aplikácií je riadená údajmi, často len vytvárame triedy s poľami na uchovávanie údajov, čo môže byť v Jave veľmi zdĺhavé (použitie metód get/set) [1]. Kotlin to všetko zvládne v jednom riadku, pričom o generovanie potrebných metód sa postará kompilátor, čo opäť ušetrí mnoho miesta v kóde. V ukážke vytvárame dátovú triedu s názvom Pouzivatel, ktorá obsahuje polia na zadanie mena a veku.

data class Pouzivatel(var meno: String, var vek: Int)

Nemeniteľnosť Pri viacvláknovom programovaní sa musí programátor zaoberať synchronizáciou vlákien a týmto predísť neriadenej modifikácii premenných. Kotlin môže deklarovať premennú ako nemeniteľnú a týmto ju ochráni pred nežiadúcimi zmenami. Deklarovať premenné môže pomocou var, čo robí premennú meniteľnou alebo val, čo robí premennú nemeniteľnou (statickou).

Funkcionálne programovanie

Prvým a dôležitým krokom je funkcionálne programovanie pochopiť a porozumieť mu. Je to para-digma programovania, fungujúca na vyhodnocovaní matematických funkcií. Považujme ho za zmes podmienených výrazov a rekurzie, čiže niečo ako lepidlo, ktoré spája riadky kódu dohromady. Kód vyzerá ako postupnosť matematických funkcií, ktoré sú napísané vo veľmi redukovanom tva-re [2]. Takýto kód pozitívne ovplyvňuje výkonnosť aplikácie. Funkcionálne programovanie ponúka uži-točné nástroje na písanie dobrého, krátkeho a zrozumiteľného kódu, čo je vlastne cieľom kaž-dého vývojára. Programátori, ktorí sa začínajú učiť FP a majú predošlú znalosť OOP (Objektovo orientované programovanie), môžu mať problémy s niektorými vlastnosťami jazyka, pretože sa líšia. Pro-gramátori OOP tvrdia, že koncept dedičnosti a zapuzdrenia uľahčujú prácu s údajmi [2]. Programátori FP tvrdia, že separovanie údajov a metód uľahčujú vývoj kódu a vytvárajú menej priestoru na chyby. Nasledujúca ukážka kódu znázorňuje rozdiel pri zápise funkcií v OOP (prvá ukážka) a FP (druhá ukážka).

public List<Integer> increment(List<Integer> numbers) {
    List<Integer> addOne = new LinkedList<>();

    for(Integer number : numbers) {
        addOne.add(number++);
    }

    return addOne;
}
public List<Integer> increment(List<Integer> numbers) {
    return numbers
            .stream()
            .map(number -> number++)
            .collect(Collectors.toList());
}

Môžeme si všimnúť, že ukážka OOP (prvá) obsahuje dva zoznamy. Jeden je tam zbytočne a môže spôsobovať nechcenú zmenu hodnôt. V ukážke FP každej položke zoznamu priradíme hodnotu a následne vrátime nový zoznam. V tomto prípade máme menej premenných a menší priestor na chybu ako v OOP. Týmto nepoukazujeme na to, že OOP je horšie ako FP. Obe metódy majú svoje výhody, záleží od problému. V našom prípade použijeme FP, tu sú dôvody:

Nemeniteľnosť: Ako už bolo spomenuté, premenné svoju hodnotu po inicializácií už nemenia. Ak ju chceme zmeniť, musíme si vytvoriť novú alebo ju inicializovať nanovo. Vývojár sa teda nemusí báť vedľajších účinkov a sústrediť sa na ostatné problémy.

Čisté funkcie: Celé funkcionálne programovanie je postavené na pojme funkcia. Nie je to myslené ako funkcia či metóda v programátorskom poňatí, ale ako matematická funkcia. Funkcia je pravá vtedy, ak je jej výsledok závislý len na vstupných hodnotách a nemá žiadne vedľajšie účinky. Funkcia f (x) = x + 1 vždy vráti 2, keď x je rovné 1, bez ohľadu na to v akom stave sa ap-likácia nachádza a ako často je funkcia volaná. Skrátka získajú hodnoty a vrátia výsledok. Sú rýchle, jednoduché a spoľahlivé [2].

Reaktívne programovanie

Celé reaktívne programovanie funguje na funkcionálnom a asynchrónnom programovaní. Tiež ho skrátene nazývame FRP (Funkcionálno-reaktívne programovanie). FRP programuje asynchrónne dátové toky. Veľký prínos ma pre mobilné a webové aplikácie, ktoré sú reaktívne s množstvom uda-lostí používateľského rozhrania. Asynchrónne dátové toky chápme ako typické interakcie pou-žíva-teľa, ako sú kliknutie na tlačidlo, vyplnenie formulára, prijatie telefónneho hovoru, získanie kon-krétnej chyby, signál o ukončení udalosti a iné. Vývojár ich môže vytvárať prakticky kdekoľ-vek, čo robí celú aplikáciu asynchrónnou. Môže zložité a dlhé výpočty poslať na server alebo na iné vlákna, aby to používateľa vôbec neobmedzilo. Celé reaktívne programovanie funguje na ved-ľajších vlák-nach aplikácie a tým nezaťažuje hlavné vlákno, ktoré priamo komunikuje s používate-ľom. Pred pár rokmi tieto aplikácie fungovali tak, že používateľ vyplnil dlhé formuláre a potom ich naraz odoslal na serverovú časť, kde následne čakal na odpoveď. FRP umožňuje túto komunikáciu v reálnom čase, čo znamená, že úprava jednotlivých formulárov sa hneď automaticky odosiela na serverovú časť. Dokonca v tom okamihu už dokážu iní používatelia zaznamenať zmeny na ich zariadeniach. Takéto správanie aplikácie vytvára pozitívny používateľský zážitok [3]. Charakteristické vlastnosti reaktívneho programovania sú:

Jednoduchá správa vlákien: dôležitou úlohou je vlákna správne manažovať, aby sme vedeli ľahko prepínať medzi vláknami. Často je treba aktualizovať UI (používateľské rozhranie), čo znamená, že vedľajšie vlákno musí odovzdať svoje informácie hlavnému vláknu. Čiže jedno vlák-no naruší chod iného, odovzdá mu informácie a pokračuje ďalej.

Ľahká kompilácia: ideálne je odovzdať väčšinu práce na vedľajšie vlákna a nezasahovať tak do hlavného UI vlákna, pokiaľ nedokončia svoje úlohy. Keď že vedľajšie vlákna často zasahujú do toho hlavného (aktualizácia UI, výpis DB a iné), museli sme mať istotu, že takéto zásahy budú bez vedľajších účinkov. O tieto zásahy sa musí postarať knižnica, ktorá by mala byť ľahko kompilova-teľná, aby nevznikal priestor na chyby.

Vedľajšie účinky: počas komunikácie viacerých vlákien, by mali mať medzi sebou čo naj-menšie vzájomné prepojenia, aby nenastali chyby. Vlákna by nemali byť od seba nijako závislé, čo spôso-buje zrozumiteľnosť programu a ľahší prístup k prípadným chybám.

Na vytvorenie reaktívnej asynchrónnej aplikácie potrebujeme implementovať knižnicu Rx (Reacti-ve extensions), ktorá obsahuje radu nástrojov a programových princípov na zostavenie asynchrón-neho kódu [3].

RxJava

V programových dátových tokoch Rx knižnice sú dáta resp. signály vysielané z jedného kompo-nentu do druhého. Druhý element musí však byť zaregistrovaný na prijímanie týchto zmien. RxJava je Java VM (Virtual Machine) implementácia reaktívneho programovania, chápme ako Rx knižnica po-užitá v Jave. Je to horúca novinka v Androide. Nie je jednoduché ju pochopiť, pretože je ešte málo odskúšaná a je o nej primálo dostupných zdrojov. Taktiež je problém prejsť priamo z OOP kvôli pár zásadným rozdielom ako sme už spomínali. Rx pozostáva z týchto troch vzorov:

RX = OBSERVABLE + OBSERVER + SCHEDULERS

Observable: sú to toky dát. Je to zhluk údajov, ktoré Rx knižnica prenáša medzi vláknami perio-dicky alebo raz za čas, záleží od toho ako je nastavený. Observable slúži ako dodávateľ, spracováva a odosiela údaje ostatným častiam (Observer). Môžeme sa ešte stretnúť so vzorom Flowable, ktorý je takmer rovnaký ako Observable s malým rozdielom. Flowable obsahuje pomôcku BackPressure, ktorá pomáha spracovať veľmi intenzívny príchod údajov tým, že niektoré podľa stratégie vyne-cháva [4]. Obsahuje tri základné metódy: • onNext(): ktorá je zavolaná ak prídu na vyhodnotenie nové údaje, • onError(): ak sa vyskytne akákoľvek chyba, • onComplete(): je zavolaná ak boli vyhodnotené posledné údaje.

Observer: slúži ako pozorovateľ, čaká na signál a po jeho prijatí získa dáta z Observable pomocou metódy subscribeOn(). Po získaní dát rozhodne, čo sa má ďalej stať. Môže spracovať odpoveď zo servera alebo aktualizovať UI. Ak dostane od Observable chybu, zavolá sa metóda onError(), ktorú už musí vývojár správne vyhodnotiť. Tento vzor urýchľuje operácie, lebo reaguje na každú prijatú požiadavku osobitne, takže sa navzájom neblokujú [4].

Obrázok 1 Vzťahy a volanie metód medzi Observable a Subscriber [4].

Schedulers: v preklade plánovači, sú časťou knižnice Rx, ktorá hovorí predošlým spomínaným dvom častiam na ktorých vláknach sa majú vykonávať. Robí to pomocou metódy observeOn(). Tiež určuje na ktorom vlákne sa má spustiť pomocou funkcie scheduleOn(). Rx má v sebe zabudo-vané vlákna, na ktorých tieto toky dát riadi. Rx ponúka ohromnú sadu nástrojov, ktoré dokážu prichádzajúce dáta akokoľvek spracovať. Dovo-ľuje dáta filtrovať, zlučovať, preradiť pomocou operátorov. Operátory sú zábavnou častou Rx, pre-tože dovoľujú programátorovi meniť dáta prakticky akokoľvek. Rx používa na vysvetlenie operáto-rov guľôčkový diagram, pretože takto znázornené sú zrozumiteľné a ľahšie pochopiteľné.

Obrázok 2 Guľôčkový diagram znázorňujúci funkcionalitu operátora startWith() [5].

Horná čiara reprezentuje nespracované údaje, tieto dáta sú posielané vzorom Obervable. Text v strednej časti hovorí o tom, aký typ operátora práve používame. Riadok pod rámčekom znázorňuje už spracované údaje. Rôzne typy objektov sú odlíšené rôznymi tvarmi (písmena a čísla).

V tomto prípade sú objekty rovnakého typu, ale ak sa pozrieme na obrázok (Obrázok 3), vidíme ukážku zložitejšieho pretypovania objektov.

Obrázok 3 Guľôčkový diagram znázorňujúci funkcionalitu operátora switchMap() [5].

Aplikácia

Našim cieľom bolo navrhnúť a implementovať modernú mobilnú parkovaciu aplikáciu pre firmu Wirecard. Aplikácia má za úlohu zamestnancom uľahčiť parkovať a týmto šetriť ich čas. Po stiah-nutí aplikácie je potrebné sa zaregistrovať a následne autentifikovať pomocou prihlasovacieho mena a hesla. Po prihlásení má používateľ k dispozícií prístup k voľným parkovacím miestam, ktoré si môže na konkrétny deň rezervovať. Ak už má miesto rezervované, alebo je vlastníkom niektorého miesta, aplikácia mu o ňom poskytne detailne údaje, ako sú poloha, dátum rezervácie či kontakt na prípadného vlastníka. Na poslednej obrazovke sa môže používateľ bezpečne odhlásiť alebo si zme-niť heslo. Celá aplikácia sa delí na tieto základné časti:

  1. Registrácia používateľa.
  2. Autentifikácia (prihlásenie) používateľa.
  3. Načítanie hlavných obrazoviek.
  4. Zmena osobných údajov.
  5. Rezervácia voľného miesta na konkrétny deň.
  6. Uvoľnenie miesta na konkrétny deň.

Registrácia používateľa Aplikáciu nie je možné používať bez registrácie, čiže ju považujeme za základný prvý krok. Regis-trácia zaručuje jednotlivým používateľov jedinečnosť a bezpečnosť. Registračná logika by mala byť čo najjednoduchšia a mala by vyžadovať len tie údaje, ktoré naozaj potrebuje. Ak je údajov predsa veľké množstvo, je lepšie to rozdeliť na viacero obrazoviek, aby to bolo prehľadnejšie a zro-zumiteľ-nejšie. Priveľa požadovaných údajov na jednej obrazovke používateľa nemotivuje dokončiť registrá-ciu. V našom prípade si registrácia vyžaduje priveľa povinných údajov, tak sme sa rozhodli rozdeliť ich na menšie časti na viacerých obrazovkách. Spomínané údaje sú:

Telefónne číslo: Je to jeden z najdôležitejších údajov. Používa sa pri autentifikácií ako pri-hlasovacie meno.

Heslo: Rovnako ako telefónne číslo, používa sa pri autentifikácií.

Meno a priezvisko: Vypisujeme pri zobrazení detailu parkoviska.

Adresa elektronickej pošty: Slúži ako overenie zabudnutého hesla. V budúcnosti bude slúžiť ako overenie používateľa počas registrácie.

Bezpečnostná otázka/odpoveď: Používa sa pri zabudnutí hesla.

Obrázok 4 Jednotlivé za sebou nasledujúce obrazovky registrácie.

Na obrázku (Obrázok 4) vidíme jednotlivé obrazovky, ktorých polia potrebujeme pre úspešnú regis-tráciu správne vyplniť. Každá obrazovka je navrhnutá tak, aby používateľ rýchlo pochopil, aké údaje sú od neho požadované. Najprv každé pole overíme, či nie je prázdne a následne ho validu-jeme podľa typu vstupu. Každý typ má osobitnú validáciu, podľa vopred dohodnutých vzorov. Používateľ sa nedostane na ďalšiu obrazovku, pokiaľ nie je validácia úspešná.

Obrázok 5 Validácie telefónneho čísla a email z prvej obrazovky.

Na poslednej obrazovke je poslaná žiadosť o registráciu na server, kde sa požiadavka vyhodnotí. Po úspešnom vyhodnotení sa zobrazí upozornenie o zaznamenaní novej registrácie. Následne je pou-žívateľ presmerovaný na prihlasovaciu obrazovku, kde hneď môže svoje nové konto verifikovať. V budúcnosti plánujeme registráciu ešte viac zrýchliť registráciou pomocou Gmail účtu. Naša apli-kácia z účtu vytiahne potrebné údaje a tie, ktoré sa jej získať nepodaria, dodatočne vypýtame.

Autentifikácia (prihlásenie používateľa) Je to najčastejšie používaná časť aplikácie. Kedykoľvek sa používateľ vráti k aplikácií, zobrazí sa mu prihlasovacia obrazovka a je nútený sa verifikovať. Táto obrazovka obsahuje zmysluplné logo a farby reprezentujúce danú aplikáciu. Tiež by mala obsahovať 3 základné východiská a tými sú prihlásenie, registrácia a obnova zabudnutého hesla. Väčšinou autentifikácia prebieha pomocou prihlasovacieho mena a hesla, ktoré sú uložené v databáze na servery. V našom prípade použijeme ako prihlasovacie meno telefónne číslo, ktoré má každý zamestnanec samozrejme jedinečné. Pri zadávaní hesla overujeme jeho dĺžku, ktorá je štandardne 8 znakov. Tiež zisťujeme, či obe prihla-sovacie polia nie sú prázdne. Nasledujúci obrázok (Obrázok 6) je znázornenie našej prihlasovacej obrazovky.

Obrázok 6 Prihlasovacia obrazovka aplikácie.

Po vyplnení prihlasovacích údajov a stlačení tlačidla „LOGIN“ nasleduje validácia jednotlivých polí. Ukážka vzoru, podľa ktorého validujeme vstup telefónneho čísla:

String regex = "^\\+(?:[0-9] ?){6,14}[0-9]$";

Ak je validácia úspešná, pošleme na server požiadavku na verifikáciu používateľa. Server obsahu-je databázu registrovaných používateľov a tak si overí, či v nej existuje niekto s týmto číslom. Ak existuje, tak overí aj jeho heslo. Keď je overenie hesla neúspešné a zopakuje sa po sebe 3-krát, tak telefónne číslo zablokuje. Ak náhodou používateľ neexistuje, zobrazí sa upozornenie, ktoré vyzý-va používateľa najprv k registrácií. V prípade, že používateľ je úspešne autentifikovaný, server vráti okrem úspešnej správy aj token používateľa. Token je v reťazec 36 znakov v tvare písmen a čísel. Ten si uložíme do SharedPreferences, ktoré slúžia ako úložisko niektorých primitívnych typov v aplikácií.

SharedPreferences settings = getContext().getSharedPreferences(TO-KEN, MODE_PRIVATE); // Zapíš dáta do SharedPreferences 
SharedPreferences.Editor editor = settings.edit(); 
editor.putString("token", receivedToken); editor.apply();

Vyššie znázornený príklad ukazuje ako token zapísať do SharedPreferences. Prvý riadok definuje id, pod ktorým bude token v SharedPreferences uložený. Nasledujúce riadky konkrétny token uložia. Naopak, príklad znázornený nižšie, nám konkrétny token podľa jeho id vytiahne a uloží do premennej value.

SharedPreferences settings = getContext()
.getSharedPreferences(TO-KEN, MODE_PRIVATE); // Čítanie z SharedPreferences 
String value = "Bearer " + settings.getString("token", "");

Ukladať si token hneď po autentifikácií je dôležité, lebo odvtedy všetky požiadavky smerované na server vyžadujú v jej tele token používateľa. Získať token spôsobom, ako to robíme my, nám umožní získať ho v ktorejkoľvek časti aplikácie. Jedinou nevýhodu je, že token ukladáme v rov-nakej podobe ako ho získame. Takto je jednoduché zneužiť ho po jeho získaní. Získať ho nie je jednoduché, keďže existuje priamo len v konkrétnom zariadení, ale opatrnosti nie je nikdy dosť. Do budúcna odporúčame implementovať metódy na zašifrovanie a dešifrovanie citlivých infor-mácií v aplikácií.

Načítanie hlavných obrazoviek Už z názvu dokážeme zistiť, že súčasťou hlavných obrazoviek je hlavná funkcionalita aplikácie. Ostatné obrazovky nám slúžia na pomoc pri autentifikácií, autorizácií či uľahčení používania, ale logika hlavnej obrazovky je ten dôvod, prečo sme si aplikáciu stiahli a chceme ju používať. V našom prípade delíme hlavnú obrazovku na 3 časti pomocou zobrazenia ViewPager.

Obrázok 7 Zobrazenie hlavných obrazoviek pomocou ViewPager.

Pohybovať sa medzi obrazovkami môžeme potiahnutím prsta. Na hlavnú obrazovku je používateľ presmerovaný hneď po autentifikácií. Zobrazíme mu najprv obrazovku s názvom „MY SPOT“ alebo „FREE SPOT“. Záleží od toho, či používateľ má k sebe priradené niektoré parkovisko alebo nie. V prípade, že parkovisko priradené má, môže byť jeho vlastníkom alebo ho môže mať na určitý deň rezervované. Odpoveď získame od servera, ktorý vyhodnotíme a zobrazíme správnu obrazovku.

Obrázok 8 Dva typy hlavným obrazoviek s názvom „MY SPOT“ vľavo a „FREE SPOT“ vpravo.

Ak používateľ nemá žiadne pridelené miesto, pošleme na server požiadavku, ktorá vráti všetky par-kovacie miesta, ktoré majú aspoň jeden voľný deň určený na rezerváciu a zobrazíme obrazov-ku z obrázka (Obrázok 8) s názvom „FREE SPOT“ vpravo. Na druhej strane, ak už používateľ parkovacie miesto pridelené má, získame zo servera detailne údaje o parkovisku a zobrazíme ich. Sú to:

• Názov parkovacieho domu, kde sa parkovisko nachádza. • Číslo parkovacieho miesta, prípade aj číslo podlažia. • Meno vlastníka parkoviska (ak som to ja tak moje meno). • Telefónne číslo vlastníka, ak ho potrebujem kontaktovať. • Deň, ktorý mám miesto rezervované (len ak nie som vlastník).

Posledná, tretia obrazovka, slúži používateľovi udržiavať jeho konto v bezpečí. Nachádzajú sa na nej používateľské nastavenia, ktorými používateľ udržiavať bezpečnosť používania aplikácie.

Obrázok 9 Tretí typ hlavnej obrazovky, obsahujúci nastavenia.

Tlačidlo „Change password“ umožňuje používateľovi zmeniť heslo. Podrobnejšie si to predstaví-me v nasledujúcej kapitole. Tlačidlo „Logout“ používateľa z aplikácie bezpečne odhlási a presme-ruje ho na prihlasovaciu obrazovku. Hneď po stlačení tohto tlačila odstránime používateľov to-ken, ktorý je uložený v SharedPreferences. Takto zaistíme bezpečnosť. Ukážke kódu, ktorá od-stráni používateľov token, sme sa venovali v časti Autentifikácia (prihlásenie používateľa). V budúcnosti chceme pridať ešte ďalšie tlačilo, určené na prijímanie notifikácií. Tlačidlo by malo obsahovať prepínať, ktorým používateľ povolí alebo zamietne prijímanie notifikácií. Ak ich pou-žívateľ povolí, bude upozornený vždy ak sa uvoľní nejaké miesto a hneď si ho bude môcť rezer-vovať.

Obrázok 10 Tlačilo umožňujúce prijímanie notifikácií o voľných miestach.

Zmena osobných údajov Túto časť by mala byť samozrejmosťou každej aplikácie, ktorá pracuje s autentifikovaním a auto-ri-zovaním používateľov. Je predsa bežná vec, že si chceme zmeniť svoje heslo alebo ho časom zabudneme. Vývojár sa musí postarať o to, aby nám túto možnosť umožnil. Pomocou nich zni-žujeme šancu odhalenia používateľovho hesla. Všetky požiadavky sú hneď posielané na server, kde sú sa-mozrejme overené pomocou tokenu. Obrázok (Obrázok 11) obsahuje dve základné ob-razovky na modifikáciu hesla. Prvá obrazovka (na obrázku vľavo) umožňuje prihlásenému použí-vateľovi zmeniť si aktuálne heslo. Potrebuje zadať správne svoje heslo a 2-krát správne zadať nové heslo. Nové heslo je kontrolované na zhodu, dĺžku, povolené znaky či overenie prázdneho poľa. Druhá obra-zovka (na obrázku vpravo) slúži neprihlásenému, ale existujúcemu používateľovi na získanie zabudnutého hesla pomocou emailovej adresy. Musí správne zvoliť jednu z bezpečnostných otá-zok a tiež správne vyplniť bezpečnostnú odpoveď. Následne bude presunutý na vytvorenie nové-ho hesla (obrazovka vľavo). Táto možnosť ešte nie je úplná, keďže server nemá podporu posiela-nia správ na emailovú adresu.

Obrázok 11 Obrazovky určené na zmenu osobných údajov (zmena hesla vpravo) a (zabudnutie hesla vľavo)

Rezervácia voľného miesta na konkrétny deň Táto časť patrí k hlavným účelom aplikácie. Predpokladáme, že práve kvôli tejto možnosti si bu-dú zamestnanci sťahovať túto aplikáciu. Ak si používateľ, ktorý nemá pridelené žiadne parkova-cie miesto, vyberie zo zoznamu jedno z voľných miest (Obrázok 8 vpravo), zobrazí sa mu kalen-dárové dialógové okno na aktuálny mesiac. Všetky dni v mesiaci sú štandardne zosivené, čiže nie je možné si ich zvoliť. Medzi tým na serveri zistíme, ktoré dni v tomto mesiaci je vybrané parko-vacie miesto dostupné a len tieto dni dovolíme používateľovi si vybrať. Po kliknutí na jeden z voľných dní, sa voľba odošle na server, kde sa údaje zaznamenajú a parkovacie miesto sa používa-teľovi priradí. Nasledujúci formát je požiadavka na server pri rezervácií miesta.

{ "parking-place-identifier": "6f35275c-a0b5-440c-8752-9eb654312653", 
"days": [ 
"2018-05-24", 
"2018-05-28" 
], 
"login-alias": "+421901111240", 
"login-alias-type": "msisdn"}

Požiadavka je v JSON formáte. V tomto prípade neočakávame zo servera žiadnu pozitívnu odpo-veď. Ak je miesto úspešne zarezervované, server vráti prázdnu požiadavku. Zmysluplnú odpoveď vráti len pri chybe. Požiadavka si vyžaduje id parkovacieho miesta, dni, ktoré používateľ zvolil, jeho telefónne číslo a typ prihlasovacieho mena, pod ktorým je verifikovaný. Netreba zabudnúť na token, ktorý je potrebný poslať v hlavičke požiadavky. Každá požiadavka predstavuje objekt. Pomáha nám pri tom knižnica Retrofit, ktorá takéto objekty vytvára a posiela na server ako po-žiadavku.

Takto vyskladáme vyššie spomenutú požiadavku priamo v kóde pomocou knižnice Retrofit. Po-ložka @Header znamená, že ide o hlavičku požiadavky. V nej posielame token spolu s informáci-ou, že naša požiadavka bude vo formáte JSON a tiež, že očakávame odpoveď rovnakého formátu. Položka @PUT, za ktorým nasleduje adresa servera hovorí, že sa snažíme na server niečo uložiť. Funkcia je typu Completable, čo značí prítomnosť Rx Javy. @Body je spomínaný objekt požia-davky, ktorý Retrofit transformuje do formátu JSON. @Path je dynamická časť adresy servera, ktorú môžeme meniť.

Obrázok 12 Na vybranom parkovacom mieste vidíme dva voľné dni.

Uvoľnenie miesta na konkrétny deň Hneď po rezervácií je druhou najpoužívanejšou funkcionalitou uvoľnenie parkovacieho miesta pre ostatných zamestnancov. Uvoľniť miesto môže len vlastník parkoviska, ktorý svoje miesto sprístupní na deň, ktorý určí on. V aktuálnom riešení, kde museli vlastníci uvoľňovať miesta v zdieľanom súbore, bola táto funkcionalita využívaná veľmi málo. Posielajú sa na server len odliš-né žiadosti. Ak zistíme, že používateľ je vlastník parkoviska, presmerujeme ho priamo na obrazovku s detai-lom parkoviska (Obrázok 8 vľavo). Po stlačení tlačidla s textom „RELEASE SPOT“ zobrazíme opäť kalendárové dialógové okno. Zo servera zistíme, ktoré dni už používateľ uvoľnil. Uvoľnené budú zobrazené zosivenou farbou, čiže už ich znova uvoľniť nemôže. Naopak, dni, ktoré vlastník môže uvoľniť budú zvýraznené. Toto správanie aplikácie vidíme na obrázku (Obrázok 13).

Obrázok 13 Kalendár obsahuje jedno uvoľnené miesto a ostatné prístupné na rezerváciu.

Akonáhle vlastník zvolí, ktorý deň miesto bude voľné, opäť pošleme požiadavku na server, ktorá vráti prázdnu odpoveď, ak je všetko v poriadku. Všetky požiadavky a odpovede v aplikácií spraco-vávame pomocou Rx Java. Ukážka požiadavky a spracovanie odpovede na uvoľnenie miesta:

Názov funkcie, ktorú voláme je setAvailableDays(String token, AvailableDaysRequest setAvai-lable-DaysRequest, String mobile_number). Táto funkcia má rovnakú podobu ako funkcia as-signPar-kingPlace(String token, AssignParkingPlace assignParkingPlace, String userNumber), uvedenú v časti Rezervácia voľného miesta na konkrétny deň. Líšia sa len v adrese, na ktorú žia-dosť odosielajú a tiež v objekte požiadavky, ktorý je v tomto prípade AssignParkingPlace namies-to Avai-lableDaysRequest. Ako už bolo spomenuté, ak je požiadavka vyhodnotená ako úspešná, príde prázdna odpoveď. Po jej prijatí zavoláme príkaz, ktorý nanovo načíta údaje na hlavných obrazov-kách. V opačnom prípade si musíme v metóde handleError() poradiť s chybovou hláškou.

Záver Našou úlohou bolo navrhnúť, implementovať a následne otestovať mobilnú aplikáciu určenú na uľahčenie parkovania pre zamestnancov firmy Wirecard. Aplikácia má za úlohu nahradiť zastaralý systém uvoľňovania parkovacích miest pomocou zdieľaného webového dokumentu, ktoré obsaho-valo množstvo nevýhod. Hlavným cieľom bolo motivovať vlastníkov parkovísk, aby v ich neprítomnosti uvoľnili miesto iným zamestnancom a tak im ušetrili čas i peniaze, keďže v aktuálnom riešení žiaden vlastník miesto neuvoľňuje.

Z existujúcich riešení sme zistili, že dobrá aplikácia má dizajn a funkcionalitu navrhnutú tak, aby používateľa zaujala. Android aplikácií je na trhu príliš veľa, čiže väčšinou si používateľ vyberie tú, z ktorej má najlepší prvý dojem. Dosiahli sme ho pomocou materiálneho dizajnu, ktorý nám ponúkol základné návrhové vzory, pomocou ktorých dokážeme používateľa zaujať.

Server aplikácie bol dodaný firmou Wirecard. Našou úlohou bolo nájsť správne prostriedky na ko-munikáciu s ním. Zvolili sme na to knižnicu Retrofit, ktorá umožňuje odosielanie žiadostí a prijímanie odpovedí zo servera. Celá komunikácia je postavená na asynchrónnej komunikácií. Na jej implementáciu sme použili knižnicu Rx Java, ktorá je aktuálne horúcou novinkou v reak-tívnom programovaní. Reaktívne programovanie sme použili v každej interakcií s používateľom, aby sme zachovali nepretržitú asynchrónnu komunikáciu a skrášlili používateľov zážitok z použí-vania.

Tú istú aplikáciu sme vytvorili dva krát, v dvoch odlišných programovacích jazykoch, Java a Ko-tlin. Oba projekty sme navzájom porovnali. Pri práci s ním sme ocenili dynamickosť jazyka a odporúčame nekonvertovať kód z projektu Java do Kotlinu, ale začať rovno od začiatku s jazy-kom Kotlin.

V budúcnosti je plánovaný vývoj iOS aplikácie a webového rozhrania, ktoré už bude obsahovať admin rozhranie. Server dodaný firmou má stále pár nedostatkov, ako overenie používateľského konta pomocou emailovej adresy či posielanie notifikácií priamo do zariadenia. Konkrétne našu aplikáciu chceme rozšíriť o funkciu Google máp, ktoré budú používateľa navigovať priamo na rezervované miesto a tiež implementovať spracovanie notifikácií.

Zoznam použitej literatúry

[1]. ArcTouch. “Kotlin vs. Java: First Impressions Using Kotlin | ArcTouch.” ArcTouch. n.d. Web. 12 Apr. 2018. https://arctouch.com/blog/kotlin-vs-java/

[2]. Lucidchart. “Functional Programming Principles Every Imperative Programmer Should Use - Lucidchart.” Lucidchart. 29 Nov. 2017. Web. 30 Mar. 2018. https://www.lucidchart.com/techblog/2017/11/29/functional-programming-principles-every-imperative-programmer-should-use/

[3]. Keval Patel. “What is Reactive Programming? – Keval Patel – Medium.” Medium. 12 Dec. 2016. Web. 30 Mar. 2018. https://medium.com/@kevalpatel2106/what-is-reactive-programming-da37c1611382

[4]. 1488456777928876. “Be Reactive: Develop your next app with RxJava – Andro-idPub.” AndroidPub. 25 Jan. 2018. Web. 30 Mar. 2018. https://android.jlelse.eu/be-reactive-develop-your-next-app-with-rxjava-4f00bfde0020

[5]. N.a. “RxMarbles: Interactive diagrams of Rx Observables.” Rxmarbles.com. 28 Jul. 2017. Web. 30 Mar. 2018. http://rxmarbles.com/#switchMap

Linkovať