Prečo obsahuje väčšina softvéru také množstvo chýb?

Takmer každý deň sa možno v počítačových správach dočítať o stále ďalších chybách v programoch. Bezpečnostné diery a vírusy, ktoré ich využívajú, sa už stali priam bežnou záležitosťou. Prakticky každý používateľ počítača už má svoje skúsenosti s "padajúcimi" programami. Ako je možné, že programy vytvárané dlhé roky množstvom odborníkov, na ktorých vývoj sa často minuli závratné sumy peňazí, stále obsahujú toľko chýb?

Základnou príčinou tohoto stavu je nepredvídateľné používanie. Funkčnosť softvéru je závislá na množstve faktorov, ktoré väčšinou nie sú dopredu známe. Navyše používateľ alebo nejaký útočník môže program použiť spôsobom, s ktorým autori vôbec nepočítali.

Pri väčšine „klasických“ produktov máte v návode vymenované aj to, čo s ním robiť nemôžete (respektíve by ste nemali), najmä u elektroniky to býva dosť dlhý zoznam. V prípade softvéru to väčšinou neprichádza do úvahy. Od programu sa očakáva, že sa bude správať korektne v každej situácii. Pritom faktorov, ktoré jeho beh ovplyvňujú, je veľké množstvo; od hardvérovej konfigurácie až po nepredvídané kombinácie nastavení samotného programu. Ani veľmi rozsiahle testovanie nemôže odskúšať všetky možnosti.

Ako keby to nestačilo, autori programov nemôžu počítať s dobrými úmyslami používateľa; počítačoví „zlomyseľníci“ (crackeri) sa ho totiž snažia použiť na niečo úplne iné. To znamená, že ho musia zabezpečiť aj proti prípadom, ktoré za bežných okolností nikdy nemôžu nastať. (Ako príklad môže poslúžiť chyba v jednej zo starších verzií Internet Explorera, ak niekto zadal do políčka pre adresu niekoľko tisíc(!) znakov...) A nejedná sa len o používateľov. Ani pri komunikácii s inými programami nemôžu nič predpokladať. Veľa chýb vzniklo tak, že autor predpokladal korektné odpovede druhého programu, ale ten (či už vlastnou chybou alebo úmyselne) odpovedal nesprávne.

Tento problém sa pochopiteľne najviac prejavuje u rozsiahlych programov, kde je často veľmi ťažké zistiť, čo vlastne tú chybu spôsobuje.

Ako to už býva, ani v tejto oblasti žiadne „zázračné“ riešenie neexistuje. Existujú iba postupy, ktoré umožňujú znížiť pravdepodobnosť chýb na minimum (napríklad použitie modulov a viacerých vrstiev). Ich dodržiavanie ale väčšinou znamená pomalší vývoj, menej nových funkcií a neraz aj väčšie obmedzenia v oblasti používateľskej prívetivosti.

Vyššia kvalita sa často pripisuje programom s otvoreným kódom. Programy s otvoreným kódom sa ale prakticky nijako nelíšia od ostatných, aj pravdepodobnosť výskytu chýb v nich je v podstate rovnaká. Ich výhodou je, že tieto chyby sa väčšinou podarí objaviť rýchlejšie a prakticky hneď je k dispozícii aj oprava. Aj vďaka tomu existuje niekoľko programov s otvoreným kódom, v ktorých nebola objavená žiadna závažnejšia chyba už niekoľko rokov.

Vytvoriť nejaký naozaj kvalitný softvér nie je pre programátorov nič jednoduché. Neustály tlak zo strany manažérov, ktorí vyžadujú nové funkcie a chcú ich čo najskôr, kvalite určite neprospieva. Navyše používatelia už ako keby si zvykli na nestabilné programy, napríklad pravidelné reštartovanie počítača už väčšina považuje za samozrejmosť.

Ak niekto tvrdí, že jeho softvér neobsahuje žiadne chyby, takmer určite nehovorí pravdu (je síce zopár dôkladne otestovaných programov, vyvíjaných dlhé roky, ale istotu nemôžno mať ani pri nich). Asi najznámejším príkladom je Microsoft, ktorý o každej novej verzii akéhokoľvek svojho produktu vyhlasuje, že obsahuje menej chýb (alebo dokonca žiadne). Takmer vždy sa toto tvrdenie ukázalo ako nepravdivé.

Pokým budú pre používateľov nové funkcie dôležitejšie než stabilita a bezpečnosť softvéru, dovtedy sa väčšieho rozšírenia skutočne stabilných a bezpečných programov pravdepodobne nedočkáme.

Pbatenghyngvbaf Lbh ner n bofreinag jro unpxre Vs Lbh jnag n wbo va bhe pbzcnal cyrnfr znvy gb gbhtuthl ng ci2p qbg fx Unir n avpr qnl
Lehká věc je mlčeti, když člověk nic neví.
		-- Alois Jirásek
    function perr($msg, $level)
    {
        echo $msg;
    }

    function readcsv_get_entity($fh, $sep = ';')
    {
        $entity = array();
        $attr = '';
        $eoe = false;

        while((! feof($fh)) && (! $eoe))
        {
            $ch = fgetc($fh);
            switch($ch)
            {
                case "\r":
                    break;
                case "\n":
                    $eoe = true;
                case $sep:
                    array_push($entity, $attr);
                    $attr = '';
                    break;
                case '"':
                    $ch = '';
                    while((! feof($fh)) && $ch != '"')
                    {
                        $ch = fgetc($fh);
                        $attr .= $ch;
                    }
                    $attr = rtrim($attr, '"');
                    break;
                default:
                    $attr .= $ch;
            }
        }

        if(feof($fh) && ($entity || $attr))
        {
            array_push($entity, $attr);
        }
        elseif(feof($fh))
        {
            $entity = false;
        }

        return $entity;
    }

    function readcsv_parsecsv($filename)
    {
        $ret = false;
        $sep = ';';
        $line = '';
        $line_num = 0;
        $cells = array();
        $names = array();

        $fh = fopen($filename, 'r');
        if(! $fh)
        {
            perr('Failed to open file \''
                . $file . "'\n", 8);
        }
        else
        {
        $line = '';
        while(! feof($fh))
        {
        $entity = readcsv_get_entity($fh, $sep);

        if($entity)
        {
        if($line_num == 0)
        {
        foreach($entity as $name)
        {
            array_push($names, trim($name, '"'));
        }
        }
        else
        {
        foreach($entity as $index => $val)
        {
        if(isset($names[$index]))
        {
            $cells[$line_num][$names[$index]]
                = trim($val, '"');
        }
        else
        {
            array_push($cells[$line_num],
                trim($val, '"'));
        }                            
        }
        }
        $line_num ++;
        }
        }
        fclose($fh);
        }

        return $ret;
    }
        
    function perr($msg, $level)
    {
        echo $msg;
    }

    function readcsv_get_entity($fh, $sep = ';')
    {
        $entity = array();
        $attr = '';
        $eoe = false;

        while((! feof($fh)) && (! $eoe))
        {
            $ch = fgetc($fh);
            switch($ch)
            {
                case "\r":
                    break;
                case "\n":
                    $eoe = true;
                case $sep:
                    array_push($entity, $attr);
                    $attr = '';
                    break;
                case '"':
                    $ch = '';
                    while((! feof($fh)) && $ch != '"')
                    {
                        $ch = fgetc($fh);
                        $attr .= $ch;
                    }
                    $attr = rtrim($attr, '"');
                    break;
                default:
                    $attr .= $ch;
            }
        }

        if(feof($fh) && ($entity || $attr))
        {
            array_push($entity, $attr);
        }
        elseif(feof($fh))
        {
            $entity = false;
        }

        return $entity;
    }

    function readcsv_parsecsv($filename)
    {
        $ret = false;
        $sep = ';';
        $line = '';
        $line_num = 0;
        $cells = array();
        $names = array();

        $fh = fopen($filename, 'r');
        if(! $fh)
        {
            perr('Failed to open file \''
                . $file . "'\n", 8);
        }
        else
        {
        $line = '';
        while(! feof($fh))
        {
        $entity = readcsv_get_entity($fh, $sep);

        if($entity)
        {
        if($line_num == 0)
        {
        foreach($entity as $name)
        {
            array_push($names, trim($name, '"'));
        }
        }
        else
        {
        foreach($entity as $index => $val)
        {
        if(isset($names[$index]))
        {
            $cells[$line_num][$names[$index]]
                = trim($val, '"');
        }
        else
        {
            array_push($cells[$line_num],
                trim($val, '"'));
        }                            
        }
        }
        $line_num ++;
        }
        }
        fclose($fh);
        }

        return $ret;
    }