Ugrás a fő tartalomra

Összefoglalás


Az űrlap teteje
Az űrlap alja
Vissza az előzőleg látogatott oldalraVissza a modul kezdőlapjáraUgrás a tananyag előző oldaláraUgrás a tananyag következő oldalára(32)Fogalom megjelenítés bekapcsolvaFogalomlista megtekintéseOldal nyomtatásaOldaltérkép megtekintéseSúgó megtekintése
Tanulási útmutató
Összefoglalás
Az előző leckében megismert rendezési algoritmusok közül az „alap” rendezések megvalósítása és időbeli hatékonyságuknak a mérése C++ nyelven egy keretprogram felhasználásával.
Követelmény
Önállóan megoldható feladatok
{esszé}
Adja meg a rendezés feladat specifikációját!
{/esszé}
o    A feladat
o    A megoldás
o    Házi feladat
Rendezések implementálása, mérése
A feladat
Vizsgáljunk meg néhány egyszerű rendezési algoritmusFogalom magyarázata:undefined hatékonyságát, empirikusan! Mivel a rendezések hatékonysága a) a rendezendő sorozat hosszától, és b) a rendezettség fokától függ, ezért a programban ezeket igyekezni kell figyelembe vennünk. A következőképpen teszünk:
1. bekérjük a rendezendő elemek számát;
2. (esetleg véletlenszám-generátor használatával) feltöltjük a rendezésre váró tömböt megfelelő számú elemmel;
3. az összes számunkra érdekes rendezés eljárását ugyanarra a kezdő sorozatra lefuttatjuk, miközben mérjük és kiírjuk a hatékonysági jellemzőket.
A rendezettségi fokot definiáljuk négyféleképpen: rendezett, majdnem rendezett (azaz csak töredék számú elem lehet rossz helyen), véletlenszerűen feltöltött, illetve fordítva rendezett.
Hatékonysági jellemzők:
§  a rendezésre fordított idő,
§  a tömbelemek hasonlításainak a száma,
§  a tömbelemek mozgatásainak száma.
A vizsgálatban részt vevő rendezések:
§  egyszerű cserés,
§  minimumkiválasztásos,
§  buborék,
§  javított buborék,
§  beillesztéses,
§  javított beillesztéses.
A megoldás
Meggondolnivalók a megoldás előtt
Mi legyen a rendezendő elemek típusa? Mivel az a két jellegzetes művelet (hasonlítás, mozgatás) időigénye az elemtípus hosszától egyenes arányosan függ, ezért a rendezések összevetése szempontjából a legegyszerűbb számtípus (Egész) is éppolyan sokatmondó, mint bármi más, esetleg összetettebb. A kapott abszolút idők a típustól függhetnek, de az arányok nem.
Mivel számos függvényre bontjuk a programot, érdemes megfontolni a paraméterezés mikéntjét! Több lehetőséget ismertünk meg, amelyek közül a legegyszerűbbet választjuk most: a programFogalom magyarázata:utasítások sorozata, amelyben az utasítások egy adott nyelvben (pl. algoritmikus vagy programozási nyelvben) meghatározott alakú és működésű nyelvi elemek paraméterei legyenek globálisan deklaráltak, ami lehetővé teszi, hogy a függvények tényleges paraméterátadási „szertartás” nélkül elérhessék őket.
Hogyan töltsük föl a rendezendő tömböt? Növekvően, illetve csökkenően feltölteni a tömböt gyerekjáték. Javasolhatók például az alábbi algoritmusok.
Növekedve feltöltés
Csökkenve feltöltés
A növekedő elemekkel történő tömbfeltöltés algoritmusa, struktogrammal.
A csökkenő elemekkel történő tömbfeltöltés algoritmusa, struktogrammal.
A véletlenszerűen feltöltött is –mint látható– pofonegyszerű algoritmusú. A legbonyodalmasabb a „majdnem rendezett” algoritmusa. Két lépésből áll: 1) rendezetten feltöltjük, majd 2) néhány (mondjuk 10%-nyi) elemet a „jó helyéről” kimozgatunk. Lássuk egy lehetséges megoldás algoritmusát.
Véletlenszerűen feltöltés
Majdnem rendezve feltöltés
A véletlen elemekkel történő tömbfeltöltés algoritmusa, struktogrammal.
A 'csak majdnem' véletlen elemekkel történő tömbfeltöltés algoritmusa, struktogrammal.
Véletlen számok generálása C++ nyelvben: egyetlen formulát kell csak felidéznünk az előadásból.
Algoritmikusan
C++-ban
Véletlen(a..b)
1
rand() % (b-a+1) + a
Feladat
Ellenőrizze, hogy a C++ megoldás is teljesíti azt az elvárást, hogy az érték a és b között egész számokat ad!
Hogyan biztosítható, hogy a véletlen számok segítségével feltöltött tömbFogalom magyarázata:olyan összetett adatszerkezet, amely csak azonos típusú elemekből állhat; az elemeit indexelés útján lehet elérni ugyanaz legyen az összes rendezés számára? Miután föltöltöttük a rendezendő r tömböt, az első rendezés az eredeti sorrendet „elrontja” (hiszen épp ez a célja!). Ahhoz, hogy a következő rendező algoritmusFogalom magyarázata:undefined is az eredetin mutassa be képességeit, készítenünk kell egy másolatot a tömbről egy ssegéd tömbben.
A C++ nyelv nyújtotta lehetőségek az időmérésre: a clock() függvényFogalom magyarázata:olyan eljárásféle, amelynek a kimeneti értékét függvényhez "illően" juttatja vissza a hívás helyére egy egész szám formájában adja vissza a programFogalom magyarázata:utasítások sorozata, amelyben az utasítások egy adott nyelvben (pl. algoritmikus vagy programozási nyelvben) meghatározott alakú és működésű nyelvi elemek indulása óta „eltelt” processzoridőt. E függvényFogalom magyarázata:olyan eljárásféle, amelynek a kimeneti értékét függvényhez "illően" juttatja vissza a hívás helyérehasználatához „inkludálnunk” kell a <time.h> headerfájlt is.
(Ha ezt másodpercben szeretnénk kifejezni, akkor a
1
clock()/CLOCKS_PER_SEC
formulával kell számolnunk.)
A keretprogram
Azért, hogy ne kelljen sok időt fordítani a gépelésre, az alábbi keretprogramot adjuk közre. Ebben a kitöltendő részeket egy kommentárral jelöltük ki:
1
/*Ide jön az r rendezése*/
Lássuk a némi magyarázattal fűszerezett keretprogramot!
·         Fájl letöltése: A C++ keretprogram.című háttéranyag letöltése
·         Információ az állományról: A keretprogram, amelyből csak az alapvető rendzéseket megvalósító függvények törzsei hiányoznak.
·         Fájlméret: 0.01 MB
A szokásos „köteles” kommenteket most is mellőztük. Az „újdonság” a time.h headerfájl, amely nemcsak a clock() függvénynek, hanem a véletlenszám-generáláshoz is szükséges, ui. a time() függvényFogalom magyarázata:olyan eljárásféle, amelynek a kimeneti értékét függvényhez "illően" juttatja vissza a hívás helyére segítségével fogjuk inicializálni a generátort:
1
2
3
4
5
#include <iostream>
#include <time.h>     //a time és clock függvényekhez
#include <stdio.h>    //a printf függvényhez
#include <windows.h>  //a srand függvényhez, a HANDLE típushoz, a system-hez (pause és a cls DOS-parancsokhoz)
using namespace std;
A globális deklarációk következnek. A kiN szorul csak némi magyarázatra. A futás közben a tömböt ki fogjuk listázni a képernyőre, hogy ellenőrizhessük a rendezettséget. Viszont annak érdekében, hogy „emészthető” mennyiségben kapjuk e számsorozatot, a kiN-nel korlátozzuk a kiírandó elemek számát. Nyilván addig jelenthet előnyt ez a lista, amíg a rendezési algoritmusaink szemantikáját ellenőrizzük. Ekkor viszont az elemszámnak nem is célszerű túlon túl nagynak lennie.
1
2
3
4
5
6
const int maxN=8001;//a sorozat maximális hossza
const int kiN=120;//a megjelenítendő (rész)sorozat hossza
int s[maxN],r[maxN];//segéd és rendezendő elemek tömbje
int elemSzam;//tényleges elemszám
int kezdet,veg,elteltIdo;//futási idő kezdete, vége, hossza
int hSzam, mSzam;//hasonlítások száma, mozgatások szám
A függvényprototípusok (szignatúrák) következnek:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//beolvassa a min..max közötti egész számot (max<min => max=végtelen)
void be_int(string kerdes, int &n, int min, int max, string uzenet);
//feltöltésmód beolvasása:
int feltoltesMod();
//feltöltő eljárások:
void feltoltVeletlennel();
void feltoltNovekedve();
void feltoltCsokkenve();
void feltoltMajdnemRendezve();
//hatékonyságméréshez:
void oraIndul();
void oraAll();
//r-et rendező eljárások:
void egyszeruCseres();
void minimumKivalsztasos();
void buborek();
void javitottBuborek();
void beilleszteses();
void javitottBeilleszteses();
//cout<=r[1..min(kiN,elemSzam)]
void tombKiiras(string cim);
void kiertekeles(string cim);
//r<=s:
void masol();
//billentyű-lenyomásra várakozik
void billreVar();
//kurzor-pozícionálás a konzol-ablakban:
void curPos(int s, int o);
//képernyőtörlés:
void ujLap();
A főprogram következik. Mint látható lesz: a feltöltés különböző módszereit tartalmazza ugyan a programFogalom magyarázata:utasítások sorozata, amelyben az utasítások egy adott nyelvben (pl. algoritmikus vagy programozási nyelvben) meghatározott alakú és működésű nyelvi elemek, de közülük most mi, a programFogalom magyarázata:utasítások sorozata, amelyben az utasítások egy adott nyelvben (pl. algoritmikus vagy programozási nyelvben) meghatározott alakú és működésű nyelvi elemek írói választjuk ki azt az egyet, amely szerint végezzük a vizsgálatot. Érdemes ezen majd túllépni, és rábízni a döntést a programFogalom magyarázata:utasítások sorozata, amelyben az utasítások egy adott nyelvben (pl. algoritmikus vagy programozási nyelvben) meghatározott alakú és működésű nyelvi elemek használójára!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int main()
{
    srand(time(NULL));//véletlenszám-generátor inicializálása
    //a rendezendő tömb feltöltése:
    be_int("Elemszám:",elemSzam,11,maxN,"Nem jó elemszám!");
    switch (feltoltesMod())
    {
      case 0:
        feltoltNovekedve(); break;
      case 1:
        feltoltCsokkenve(); break;
      case 2:
        feltoltMajdnemRendezve(); break;
      case 3:
        feltoltVeletlennel(); break;
    }    //a rendezések:
    egyszeruCseres();
    minimumKivalasztasos();
    buborek();
    javitottBuborek();
    beilleszteses();
    javitottBeilleszteses();
    return 0;
}
A függvények definíciói jönnek. Először a jól ismert egész számot beolvasó, majd a feltöltési módot beolvasó függvényFogalom magyarázata:olyan eljárásféle, amelynek a kimeneti értékét függvényhez "illően" juttatja vissza a hívás helyére.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//beolvassa a min..max közötti egész számot (max<min => max=végtelen)
void be_int(string kerdes, int &n, int min, int max, string uzenet)
{
    bool hiba;
    string tmp;
    do
    {
      if (max>=min)
      {
        cout << kerdes << " (" << min << ".." << max << "):"; cin >> n;
        hiba=cin.fail() || n<min || n>max;
      }
        else
      {
        cout << kerdes << " (" << min << "..):"; cin >> n;
        hiba=cin.fail() || n<min;
      }
      if (hiba)
      {
        cout << uzenet << endl;
        cin.clear(); getline(cin,tmp,'\n');
      }
    }
    while(hiba);
}
//feltöltésmód beolvasása:
int feltoltesMod()
{
    int melyik;
    ujLap();
    cout << "Válasszon az a lábbi feltöltésmódok közül:" << endl;
    cout << "0: növekedően" << endl;
    cout << "1: csökkenve" << endl;
    cout << "2: majdnem (növekedően) rendezve" << endl;
    cout << "3: véletlenszerűen" << endl;
    do
    {
        curPos(9,9);
        cout << "Melyik (0..3): ";
        cin >> melyik;
    }
    while (0>melyik || melyik>3);
    return melyik;
}
A feltöltő függvények következnek. Annyit kell velük kapcsolatban észrevenni, hogy nem csupán az r tömböt állítják, hanem értelemszerűen a másolatként szolgáló s-et is.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
void feltoltNovekedve()
{
    s[1]=rand()%elemSzam+1;
    r[1]=s[1];
    for(int i=2;i<=elemSzam;++i)
    {
        s[i]=s[i-1]+rand()%3;
        r[i]=s[i];
    }
    tombKiiras("Feltölt növekedve");
}
void feltoltCsokkenve()
{
    s[1]=rand()%elemSzam+1;
    r[1]=s[1];
    for(int i=2;i<=elemSzam;++i)
    {
        s[i]=s[i-1]-rand()%3;
        r[i]=s[i];
    }
    tombKiiras("Feltölt csökkenve");
}
void feltoltMajdnemRendezve()
{
    int j,k,sv;
    s[1]=rand()%elemSzam+1;
    r[1]=s[1];
    for(int i=2;i<=elemSzam;++i)
    {
        s[i]=s[i-1]+rand()%3;
        r[i]=s[i];
    }
    for(int i=1;i<=elemSzam/10;++i)
    {
        j=rand()%elemSzam+1;
        do
        {
            k=rand()%elemSzam+1;
        }
        while (j==k);
        sv=s[j]; s[j]=s[k]; s[k]=sv;
        r[j]=r[k]; r[k]=sv;
    }
    tombKiiras("Feltölt majdnem rendezve");
}
void feltoltVeletlennel()
{
    for(int i=1;i<=elemSzam;++i)
    {
        s[i]=rand()%elemSzam+1;
        r[i]=s[i];
    }
    tombKiiras("Feltölt véletlennel");
}
A hatékonyságmérés két központi függvénye jön. Az „óraállításon” felül a hasonlítás és a mozgatás számlálókat is alaphelyzetbe hozzák.
1
2
3
4
5
6
7
8
9
10
void oraIndul()
{
    kezdet=clock();
    hSzam=0; mSzam=0;
}
void oraAll()
{
    veg=clock();
    elteltIdo=veg-kezdet;
}
A megjelenítő eljárásban az igényes táblázatolás kedvéért felhasználjuk a C++ C-ből származó formázott kiíró műveleteit, és az ujLap-ban a konzolt törlő, az operációs rendszertől kölcsönvett cls parancsot.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void tombKiiras(string cim)
{
    ujLap();
    cout << cim << endl << endl;
    int meddig; //ameddig listázza az elemeket... az ellenőrzés kedvéért
    if (elemSzam<kiN)
    {
        meddig=elemSzam;
    }
    else
    {
        meddig=kiN;
    }
    for(int i=1;i<=meddig;++i)
    {
        printf("%4d",i); printf(":%5d",r[i]);
    }
    cout << endl;
    billreVar();
}
void kiertekeles(string cim)
{
    tombKiiras(cim);
    cout << "\nEltelt ido:" << elteltIdo;
    cout << " | Hasonlítások száma:" << hSzam <<
            " | Mozgatások száma:" << mSzam << endl;
    billreVar();
}
Az alábbiakban a hatékonyságméréssel kapcsolatot nyitó és záró tevékenységgel kibővített rendező függvények definícióit találjuk. A rendezést ide kell beillesztenünk.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
void egyszeruCseres()
{
    oraIndul();
/*Ide jön az r rendezése*/
    oraAll();
    kiertekeles("Egyszerű cserés");
    masol(); /* Az eredeti érték visszaállítása*/
}
void minimumKivalasztasos()
{
    oraIndul();
/*Ide jön az r rendezése*/
     oraAll();
     kiertekeles("Minimumkiválasztásos");
     masol(); /* Az eredeti érték visszaállítása*/
}
void buborek()
{
    oraIndul();
/*Ide jön az r rendezése*/
    oraAll();
    kiertekeles("Buborékos");
    masol(); /* Az eredeti érték visszaállítása*/
}
void javitottBuborek()
{
    oraIndul();
/*Ide jön az r rendezése*/
    oraAll();
    kiertekeles("Javított buborékos");
    masol(); /* Az eredeti érték visszaállítása*/
}
void beilleszteses()
{
    oraIndul();
/*Ide jön az r rendezése*/
    oraAll();
    kiertekeles("Beillesztéses");
    masol(); /* Az eredeti érték visszaállítása*/
}
void javitottBeilleszteses()
{
    oraIndul();
 /*Ide jön az r rendezése*/
    oraAll();
    kiertekeles("Javított beillesztéses");
    masol(); /* Az eredeti érték visszaállítása*/
}
S végül néhány segédfüggvény definíciója zárja a programot.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//r<=s:
void masol()
{
    for (int i=1;i<=elemSzam;++i)
    {
        r[i]=s[i];
    }
}
//billentyű-lenyomásra várakozik
void billreVar()
{
    system("pause");//windows esetében!
}
//kurzor-pozícionálás a konzol-ablakban:
void curPos(int s, int o)
{
    HANDLE hkonzol;
    COORD hova;
    hova.X=o; hova.Y=s;
    SetConsoleCursorPosition (hkonzol,hova);
}
//képernyőtörlés:
void ujLap()
{
    system("cls"); //képernyőtörlés
}
·         Fájl letöltése: A C++ keretprogram.című háttéranyag letöltése
·         Információ az állományról: A keretprogram, amelyből csak az alapvető rendzéseket megvalósító függvények törzsei hiányoznak.
·         Fájlméret: 0.01 MB
A rendező függvények – a megoldás
A lényegi függvények megoldását alább mellékeljük. Ne felejtse a hSzam, mSzam számlálókat a megfelelő helyen a megfelelő értékkel növelni!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
void egyszeruCseres()
{
    oraIndul();
    int i,j,sv,n=elemSzam;
    for (i=1;i<=n-1;++i)
    {
        for (j=i+1;j<=n;++j)
        {
            if (r[i]>r[j])
            {
                ++hSzam;
                sv=r[i]; r[i]=r[j]; r[j]=sv;
                mSzam+=3;
            }
        }
    }
    oraAll();
    kiertekeles("Egyszerű cserés");
    masol(); /* Az eredeti érték visszaállítása */
}
void minimumkivalasztasos()
{
    oraIndul();
    int i,j,sv,minind,n=elemSzam;
    for (i=1;i<=n-1;++i)
    {
        minind=i;
        for (j=i+1;j<=n;++j)
        {
            if (r[j]<r[minind])
            {
                ++hSzam;
                minind=j;
            }
        }
        sv=r[minind]; r[minind]=r[i]; r[i]=sv;
        mSzam+=3;
     }
     oraAll();
     kiertekeles("Minimumkiválasztásos");
     masol(); /* Az eredeti érték visszaállítása */
}
void buborek()
{
    oraIndul();
    int i,j,sv,n=elemSzam;
    for(i=n;i>=2;--i)
    {
        for( j=1;j<=i-1;++j)
        {
            if(r[j]>r[j+1])
            {
                ++hSzam;
                sv=r[j]; r[j]=r[j+1]; r[j+1]=sv;
                mSzam+=3;
            }
        }
    }
    oraAll();
    kiertekeles("Buborékos");
    masol(); /* Az eredeti érték visszaállítása */
}
void javitottBuborek()
{
    oraIndul();
    int cs,i,j,sv,n=elemSzam;
    i=n;
    while (i>=2)
    {
        cs=0;
        for(j=1;j<=i-1;++j)
        {
            if (r[j]>r[j+1])
            {
                ++hSzam;
                sv=r[j]; r[j]=r[j+1]; r[j+1]=sv;
                cs=j;
                mSzam+=3;
            }
        }
        i=cs;
    }
    oraAll();
    kiertekeles("Javított buborékos");
    masol(); /* Az eredeti érték visszaállítása */
}
void beilleszteses()
{
    oraIndul();
    int i,j,sv,n=elemSzam;
    for (i=2;i<=n;++i)
    {
        j=i-1;
        while((j>0) && (r[j]>r[j+1]))
        {
            ++hSzam;
            sv=r[j]; r[j]=r[j+1]; r[j+1]=sv;
            --j;
            mSzam+=3;
        }
    }
    oraAll();
    kiertekeles("Beillesztéses");
    masol(); /* Az eredeti érték visszaállítása */
}
void javitottBeilleszteses()
{
    oraIndul();
    int i,j,sv,n=elemSzam;
    for (i=2;i<=n;i++)
    {
        j=i-1; sv=r[i];
        ++mSzam;
        while((j>0) && (r[j]>sv))
        {
            ++hSzam;
            r[j+1]=r[j];
            --j;
            ++mSzam;
        }
        r[j+1]=sv;
        ++mSzam;
    }
    oraAll();
    kiertekeles("Javított beillesztéses");
    masol(); /* Az eredeti érték visszaállítása */
}
A program „használatba vétele”
Feladat
A kész programmal végezheti végre a kitűzött vizsgálatot. Javasoljuk, hogy az alábbi táblázatot töltse ki a programFogalom magyarázata:utasítások sorozata, amelyben az utasítások egy adott nyelvben (pl. algoritmikus vagy programozási nyelvben) meghatározott alakú és működésű nyelvi elemek futtatása alapján, majd próbáljon következtetésekre jutni az egyes minőségi jellemzők elemszámtól való függését illetően!
Előrendezettség: rendezett
Elemszám
Futási idő
Hasonlításszám
Mozgatásszám
11



22



44



88



110



1100




Előrendezettség: majdnem rendezett
Elemszám
Futási idő
Hasonlításszám
Mozgatásszám
11



22



44



88



110



1100




Előrendezettség: véletlenszeruen feltöltött
Elemszám
Futási idő
Hasonlításszám
Mozgatásszám
11



22



44



88



110



1100




Előrendezettség: fordítottan rendezett
Elemszám
Futási idő
Hasonlításszám
Mozgatásszám
11



22



44



88



110



1100



Mire következet? FutásIdő(N)=???, Hasonlításszám(N)= ???, …
Azt kapta, amit az előadáson elméleti megfontolások alapján hallott?
Házi feladat
Feladat
Az elkészült programot egészítse ki úgy, hogy A) a mérést akárhányszor (újraindítás nélkül) lehessen elvégezni, azaz a kilépés külön kérésre történjen; B) a mérési eredményeket „kulturált” szerkezetben egy szöveges fájlba írja ki! A B) feladatnál gondoljon arra, hogy könnyen lehessen a nyert nagyszámú adatot akár egy táblázatkezelő segítségével is feldolgozni!
ELTE és ELTE TáTK logó
ELTE és ELTE IK logó
Új Széchenyi terv
A projekt az Európai Unió támogatásával, az Európai Szociális Alap társfinanszirozásával valósul meg.

Megjegyzések

Népszerű bejegyzések ezen a blogon

SW Documentation: Requirements

Requirements Nonfunctional Requirements Q&A FEBRUARY 17, 2010  ~  ANDREW STELLMAN ~  3 COMMENTS Non-functional requirements Q&A: We answer questions from readers about using  nonfunctional requirements  on a real software project, and how to use them on a real software project. Non-functional requirements: Planning out how well your software will work A couple of months ago I wrote a post called  Using nonfunctional requirements to build better software . It’s basically a step-by-step guide for creating an easy, practical technique to use nonfunctional requirements on a real software project, treating them in a way that’s similar to how a lot of Agile teams treat user stories, scenarios and other functional requirements: by sticking them on index cards and using them to do some lightweight planning. Since then, I’ve gotten a lot of questions about nonfunctional requirements (or, as some people call them, non functional requirements...

Privacy Notice for Visitors to Our Users’ Sites

Privacy Notice for Visitors to Our Users’ Sites Sections Who’s Who and What This Privacy Notice Covers Information We Collect About Visitors to Our Users’ Sites Information a Visitor Provides to a Site Information We Automatically Collect from the Site Other Information Provided by Our Users How We Use Visitor Information How We Share Visitor Information Other Tools Other Resources Hi there! This Privacy Notice explains how we, at Automattic, process information about the visitors of our users’ websites in connection with the services we provide through WordPress.com, Jetpack (including WooCommerce Services), IntenseDebate, Polldaddy.com, and Akismet. Read on! Who’s Who and What This Privacy Notice Covers Let’s talk first about who we are at Automattic, what we do, and what this Privacy Notice covers. We are the folks behind a variety of products and services designed to allow anyone–from bloggers, to small business owners, and enterprises–to create, publ...

THE RIGHT WAY TO WRITE A SINGLETON

THE RIGHT WAY TO WRITE A SINGLETON July 17, 2015 by   Hector Matos Even though I've written about the woes of managing state in my previous post, sometimes there's just no way we can avoid it. One example of managing state is something we're all quite acquainted with - The Singleton. The problem we find in Swift is that there are SEVERAL ways of implementing them. But which way is the right way? In this post I'm going to show you the history of the singleton and then show you the right way to implement the singleton in Swift. If you want to see the right way to implement the singleton pattern in Swift along with proof of it's "right-ness", you can scroll to the bottom of the post and see it there. :) A TRIP DOWN MEMORY LANE Swift is a natural evolution of Objective-C. In Objective-C, this is how we implemented the singleton: @interface Kraken : NSObject @end @implementation Kraken + ( instancetype ) sharedInstance { ...