Alkalmazások fejlesztése

3. előadás

Horváth Győző
Egyetemi adjunktus
1117 Budapest, Pázmány Péter sétány 1/c., 2.420-as szoba
Tel: (1) 372-2500/1816
horvath.gyozo@inf.elte.hu

Tartalomjegyzék

  • Mintafeladat
  • Tervezési lépések
  • Statikus oldalak kiszolgálása
  • Dinamikus oldalak kiszolgálása
  • Űrlapadatok feldolgozása

Mintafeladat

Feladat

Hibabejelentő oldal készítése laborokba.

Tervezés

Tervezés lépései

  • követelmények összegyűjtése, követelmény-analízis
  • szerepkörök, használati esetek, folyamatok meghatározása
  • (oldalfunkciók)
  • oldalvázlatok készítése
  • site struktúra (oldaltérkép)
  • architektúra terv
  • adatbázis tervezése
  • designtervek készítése

Elméleti és gyakorlati példa

Követelmények összegyűjtése

  • Funkcionális elvárások
    • nyújtandó szolgáltatások ismertetése
  • Nem funkcionális követelmények
    • használhatóság
    • teljesítmény
    • rendelkezésre állás
    • skálázhatóság
    • biztonság
    • karbantarthatóság

Hibabejelentő

Funkcionális követelmények

  • Felhasználóként szeretnék bejelenteni egy gépterembeli hibát, hogy minél előbb javíthassák. --> Hiba bejelentése
  • Felhasználóként szeretnék visszajelzést kapni, hogy a bejelentett hiba milyen státuszban van. --> Hibák listázása
  • Felhasználóként szeretnék kérdést vagy megjegyzést fűzni egy hibához azután is, hogy felvettem. --> Hiba history, chat, forum.

Hibabejelentő

Funkcionális követelmények

  • Operátorként szeretném látni a hibalistát.
  • Operátorként szeretnék egy hibát megtekinteni és státuszát váltani. Státuszváltáskor kötelező üzenetet megadni.
  • A felhasználók és operátorok bejelentkezés után használhatják a funkciókat. Ezeket egy előre megadott listából, vagy LDAP authentikációval kell elvégezni.
  • A főoldalon az alkalmazás ismertetése, esetleg statisztikák jelenik meg.

Hibabejelentő

Nem funkcionális követelmények

  • Felhasználóbarát, ergonomikus elrendezés és kinézet.
  • Gyors működés.
  • Biztonságos működés: jelszavak tárolása, funkciókhoz való hozzáférés.

Szerepkörök

  • jogosultsági csoportok
  • elérhető funkciók
  • folyamatok pontos menete

Szerepkörök (Hibabejelentő)

  • vendég: a főoldal tartalmához fér hozzá, rögzíteni nem tud.
  • bejelentő: a vendég szerepkörén túl hibát tud bejelenteni, és bejelentett hibáit megtekinteni.
  • operátor: a bejelentő szerepkörén túl az összes hibát meg tudja tekinteni, és annak státuszát állítani tudja.

Használati esetek

Szerepkörökhöz tartozó használati esetek.

Használati eset diagram.

nomnoml/ArgoUML

Használati esetek (Hibabejelentő)

Használati eset diagram
Használati eset diagram

Folyamatok meghatározása

Az egyes használati esetek részletes folyamatai.

UML Activity Diagram.

nomnoml/ArgoUML

Folyamatok meghatározása (Hibabejelentő)

  • bejelentő
    • hiba bejelentésének folyamata
    • megjegyzés fűzésének folyamata
  • operátor
    • hiba státuszának állítása

Folyamatok meghatározása (Hibabejelentő)

Hiba bejelentésének folyamata (Activity Diagram)
Hiba bejelentésének folyamata (Activity Diagram)

Oldaltérkép

Az egyes oldalak egymáshoz viszonyított kapcsolatai.

Tipikusan hierarchikus, ritkán topografikus kapcsolati rendszer.

Szöveges/Grafikus megadás

Oldaltérkép (Hibabejelentő)

Publikus:

- Főoldal
- Help
- Login

Bejelentő

- Főoldal
- Help
- Login/Logout
- Hibalista
    + új hiba
    + hiba megtekintése
        * megjegyzés hozzáfűzése

Operátor

- Főoldal
- Help
- Login/Logout
- Hibalista
    + hiba megtekintése
        * hiba módosítása
        * megjegyzés hozzáfűzése

Végpontok

Az egyes oldalak elérhetősége.

Szemantikus URI-k.

Végpontok (Hibabejelentő)

  • GET /: főoldal
  • GET /help: leírás a használatról
  • GET /login: bejelentkező oldal
  • POST /login: bejelentkezési adatok felküldése
  • GET /errors/list: saját hibalista oldal
  • GET /errors/new: új hiba felvitele
  • POST /errors/new: új hiba felvitele, adatok küldése
  • GET /errors/:id: hiba adatai
  • POST /errors/:id/comment: új megjegyzés
  • GET /operator/list: operátor felület, hibalista
  • GET /operator/errors/:id: operátor felület,
  • POST /operator/errors/:id/status: státuszállítás

Oldalvázlatok

Az egyes oldalak körülbelüli elrendezése.

Kölcsönös hatással az adattartalomra és funkciókra.

Drótvázkészítés, mockup.

Lumzy/Táblázatkezelő/Prezentációkészítő/Befotózott szabadkézi rajz

Oldalvázlatok (Hibabejelentő)

Főoldal drótvázterve
Főoldal drótvázterve

Adatmodell

Az alkalmazásban használatos adatok struktúrája.

Osztály- vagy objektumdiagram

nomnoml/ArgoUML

Adatmodell (Hibabejelentő)

Adatmodell
Adatmodell

Adatbázisterv

Az adatok tárolásához szükséges struktúra.

Táblaleírások, mezőnkénti kifejtéssel.

Függ a választott adatbázis-kezelő rendszertől.

nomnoml/ArgoUML

Adatbázisterv (Hibabejelentő)

Adatbázisterv
Adatbázisterv

Állapotdiagram

Az alkalmazásban használt állapotátmenetek definiálása.

nomnoml/ArgoUML

Állapotdiagram (Hibabejelentő)

Hiba állapotdiagramja
Hiba állapotdiagramja

Designtervek

Drótvázrajzok alapján.

Háttérképek, elrendezések, színek, stb.

Kép (GIMP, Photoshop)

--> Statikus oldalvázak, sablonok.

Designtervek (Hibabejelentő)

Kihagyható

CSS keretrendszer megfelelő kinézetet biztosít.

Designterv: főoldal

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

    <title>Hibabejelentő</title>

    <!-- Stylesheets -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.5/sandstone/bootstrap.min.css">
</head>
<body>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-12">

                <nav class="navbar navbar-default">
                  <div class="container-fluid">
                    <!-- Brand and toggle get grouped for better mobile display -->
                    <div class="navbar-header">
                      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                        <span class="sr-only">Toggle navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                      </button>
                      <a class="navbar-brand" href="#">Hibabejelentő</a>
                    </div>

                    <!-- Collect the nav links, forms, and other content for toggling -->
                    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                      <!-- <ul class="nav navbar-nav">
                        <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
                        <li><a href="#">Link</a></li>
                        <li class="dropdown">
                          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
                          <ul class="dropdown-menu">
                            <li><a href="#">Action</a></li>
                            <li><a href="#">Another action</a></li>
                            <li><a href="#">Something else here</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="#">Separated link</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="#">One more separated link</a></li>
                          </ul>
                        </li>
                      </ul> -->
                      <ul class="nav navbar-nav navbar-right">
                        <li><a href="#">Login</a></li>
                        <li><a href="#">About</a></li>
                      </ul>
                    </div><!-- /.navbar-collapse -->
                  </div><!-- /.container-fluid -->
                </nav>

                <div class="page-header">
                    <h1>Hibabejelentés az IK-n</h1>
                </div>

                <p>
                    Blabla blabla blabla
                </p>

            </div>
        </div>
    </div>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</body>
</html>

Designterv: hibalista

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

    <title>Hibabejelentő</title>

    <!-- Stylesheets -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.5/sandstone/bootstrap.min.css">
</head>
<body>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-12">

                <nav class="navbar navbar-default">
                  <div class="container-fluid">
                    <!-- Brand and toggle get grouped for better mobile display -->
                    <div class="navbar-header">
                      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                        <span class="sr-only">Toggle navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                      </button>
                      <a class="navbar-brand" href="#">Hibabejelentő</a>
                    </div>

                    <!-- Collect the nav links, forms, and other content for toggling -->
                    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                      <!-- <ul class="nav navbar-nav">
                        <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
                        <li><a href="#">Link</a></li>
                        <li class="dropdown">
                          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
                          <ul class="dropdown-menu">
                            <li><a href="#">Action</a></li>
                            <li><a href="#">Another action</a></li>
                            <li><a href="#">Something else here</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="#">Separated link</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="#">One more separated link</a></li>
                          </ul>
                        </li>
                      </ul> -->

                      <ul class="nav navbar-nav navbar-right">
                        <li><a href="#">Kilépés</a></li>
                        <li><a href="#">About</a></li>
                      </ul>

                      <p class="navbar-text navbar-right">Üdv, XY!</p>
                      
                    </div><!-- /.navbar-collapse -->
                  </div><!-- /.container-fluid -->
                </nav>

                <div class="alert alert-dismissible alert-success">
                    <button type="button" class="close" data-dismiss="alert">×</button>
                    Sikeres hibafelvitel!
                </div>

                <div class="page-header">
                    <h1>Bejelentett hibáim</h1>
                </div>

                <table class="table table-striped table-hover ">
                    <thead>
                        <tr>
                            <th>Időpont</th>
                            <th>Státusz</th>
                            <th>Helyszín</th>
                            <th>Leírás</th>
                        </tr>   
                    </thead>
                    <tbody>
                        <tr>
                            <td>2015.09.16. 13:58</td>
                            <td><span class="label label-danger">Új</span></td>
                            <td>PC6 15. gép</td>
                            <td>Rossz billentyűzet <span class="badge">4</span></td>
                        </tr>
                        <tr>
                            <td>2015.09.16. 13:58</td>
                            <td><span class="label label-info">Folyamatban</span></td>
                            <td>PC6 15. gép</td>
                            <td>Rossz billentyűzet <span class="badge">4</span></td>
                        </tr>
                        <tr>
                            <td>2015.09.16. 13:58</td>
                            <td><span class="label label-success">Megoldva</span></td>
                            <td>PC6 15. gép</td>
                            <td>Rossz billentyűzet <span class="badge">4</span></td>
                        </tr>
                    </tbody>
                </table>

                <p><a href="#" class="btn btn-default">Új hiba felvitele</a></p>
            </div>
        </div>
    </div>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</body>
</html>

Designterv: új hiba

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">

    <title>Hibabejelentő</title>

    <!-- Stylesheets -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.5/sandstone/bootstrap.min.css">
</head>
<body>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-12">

                <nav class="navbar navbar-default">
                  <div class="container-fluid">
                    <!-- Brand and toggle get grouped for better mobile display -->
                    <div class="navbar-header">
                      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                        <span class="sr-only">Toggle navigation</span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                      </button>
                      <a class="navbar-brand" href="#">Hibabejelentő</a>
                    </div>

                    <!-- Collect the nav links, forms, and other content for toggling -->
                    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                      <!-- <ul class="nav navbar-nav">
                        <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
                        <li><a href="#">Link</a></li>
                        <li class="dropdown">
                          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
                          <ul class="dropdown-menu">
                            <li><a href="#">Action</a></li>
                            <li><a href="#">Another action</a></li>
                            <li><a href="#">Something else here</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="#">Separated link</a></li>
                            <li role="separator" class="divider"></li>
                            <li><a href="#">One more separated link</a></li>
                          </ul>
                        </li>
                      </ul> -->

                      <ul class="nav navbar-nav navbar-right">
                        <li><a href="#">Login</a></li>
                        <li><a href="#">About</a></li>
                      </ul>

                      <p class="navbar-text navbar-right">Üdv, XY!</p>

                    </div><!-- /.navbar-collapse -->
                  </div><!-- /.container-fluid -->
                </nav>

                <div class="page-header">
                    <h1>Új hiba bejelentése</h1>
                </div>

                <form class="form-horizontal">
                    <fieldset>
                        <div class="form-group has-error">
                            <label for="helyszin" class="col-lg-2 control-label">Helyszín</label>
                            <div class="col-lg-10">
                                <input class="form-control" id="helyszin" placeholder="pl. PC6, Lovarda, 2. emeleti folyosó..." type="text">
                                <span class="help-block">Kötelező</span>
                            </div>
                        </div>
                        <div class="form-group">
                            <label for="leiras" class="col-lg-2 control-label">Leírás</label>
                            <div class="col-lg-10">
                                <textarea class="form-control" rows="3" id="leiras"></textarea>
                                <span class="help-block">Meg kell adni a helyszínt, ha pedig konkrét géppel van probléma, akkor azt is.</span>
                            </div>
                        </div>
                        <div class="form-group">
                            <div class="col-lg-10 col-lg-offset-2">
                                <button type="reset" class="btn btn-default">Cancel</button>
                                <button type="submit" class="btn btn-primary">Submit</button>
                            </div>
                        </div>
                    </fieldset>
                </form>             

            </div>
        </div>
    </div>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
</body>
</html>

Kliensoldali függőségek kezelése

Kliensoldali függőségek

  • Böngésző
  • JavaScript állományok
  • CSS állományok
  • Képek
  • Statikus tartalmak

Kliensoldali függőségek kezelése

  • CDN használata
  • Lokálisan
    • kézzel letölteni
    • Cloud9: wget https://maxcdn.bootstrapcdn.com/bootswatch/3.3.5/sandstone/bootstrap.min.css
    • Csomagkezelőre bízni: bower

Bower

  • Kliensoldali csomagkezelő
  • npm install bower -g
  • Cloud9-on telepítve van
  • bower parancs
  • bower install packagename
  • bower init --> bower.json
  • .bowerrc
{
    "directory": "lib/"
}

Input adatok feldolgozása

Kliensről érkező input adatok

  • URI paraméterek
  • URI query része (GET paraméterek)
  • HTTP üzenettörzse

URI paraméterek

req.params.valtozo

// GET /user/adam
app.get('/user/:name', function (req, res) {
    var name = req.params.name; // => adam
    //...
});

URI paraméterek middleware

//Paraméter middleware
router.param('name', function (req, res, next, name, paramName) {
    console.log('paramName' + ': ' + name);
    next();
})

app.get('/user/:name', function (req, res) {
    var name = req.params.name; 
    //...
});

GET paraméterek

req.query.valtozo

// GET /users?id=42&ref=45428174v24t2
app.get('/users', function (req, res) {
    console.log(req.query);
    var id = req.query.id;
    var ref = req.query.ref;
})

POST paraméterek

req.body.valtozo

npm install body-parser --save

var bodyParser = require('body-parser');

//...

app.use(bodyParser.urlencoded({ extended: false }));

//...

// POST /users
app.post('/users', function(req, res) {
    var firstName = req.body.firstname;
    var lastName = req.body.lastname;
    //...
});

Űrlapkezelés

POST-REDIRECT-GET módszer

  1. GET metódussal az űrlap megjelenítése
  2. POST metódussal adatok felküldése
  3. Siker esetén átirányítás a sikeres oldalra
  4. GET sikeres oldal

Űrlapkezelés: hiba 1.

  1. GET metódussal az űrlap megjelenítése
  2. POST metódussal adatok felküldése
  3. Hiba esetén az űrlap újbóli megjelenítése hibaüzenetekkel és előre feltöltött mezőkkel.
  4. POST metódussal adatok felküldése
  5. Siker esetén átirányítás a sikeres oldalra
  6. GET sikeres oldal

Űrlapkezelés: hiba 2.

  1. GET metódussal az űrlap megjelenítése
  2. POST metódussal adatok felküldése
  3. Hiba esetén átirányítás az 1. pontra; a hibaüzenetek és az űrlapmezők adatait tárolni kell a két kérés között (munkamenet).
  4. POST metódussal adatok felküldése
  5. Siker esetén átirányítás a sikeres oldalra
  6. GET sikeres oldal

Küldött adatok ellenőrzése

express-validator modul használata

var expressValidator = require('express-validator');

app.use(express.bodyParser());
app.use(expressValidator());

app.post('/', function(req, res) {

    req.checkBody('age', 'Invalid age').notEmpty().isInt();

    var errors = req.validationErrors();
    if (errors) {
        //hibakezelés
    } else {
        //helyes ág
    }
});

Feladatok

Feladatok

  1. A mintaalkalmazás (Hibabejelentő) három oldalának megjelenítése (ld. az előző gyakorlat diái)
    1. Végponttal (res.sendFile())
    2. static middleware-rel
  2. A három oldal kliensoldali függőségeinek kielégítése
    1. CDN segítségével
    2. Kézzel letöltve
    3. bower segítségével (itt már az ajánlott mappaszerkezet: js és css mappa az alkalmazásspecifikus dolgoknak, a külső függőségek helye egy lib mappán belül)

Feladatok

  1. A három mintaoldal megjelenítése sablonmotor (Handlebars) segítségével. Az oldalak kijönnek a static middleware hatásköre alól, újra végpontok szolgálják ki. Az egyes nézetek a views mappán belül vannak, a belső mappastruktúra tükrözheti a végpontok neveit.
  2. Layout bevezetése (views/layout.hbs).
  3. Dinamikus tartalom megjelenítése. A listaoldalon dinamikusan tegyük ki a hibalistát. Az adatforrás egyelőre egy beégetett JavaScript tömb legyen.
  4. Azonosítsunk további dinamikus részeket az alkalmazásban!

Feladatok

  1. Az új hiba felvitele oldalon vegyünk fel egy új hibát. Végezzük el a hibaellenőrzést. Sikertelen adatfelvitel esetén jelenjen meg újra a hibás űrlap, siker esetén menjünk a hibaoldalra!