Exceptions unübersichtlich?

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Exceptions unübersichtlich?

    Hallo Leute, ich setze mich gerade ein wenig mit Exceptions auseinander und finde irgendwie keine zufriedenstellende Lösung.
    Was das Script so alles macht, ist nicht wichtig, es geht mir nur uim die Exceptions!

    Ich habe hier mal ein Zend-Beispielscript, bei dem ich die Klasse zur Userauthentifizierung in eine Datei "class.userauth.php" gepackt habe.
    PHP-Code:

    // class definition 
    class userAuth 
        
    // define properties 
        
    private $username
        private 
    $passwd
        private 
    $passwdFile

        
    // constructor 
        // must be passed username and non-encrypted password 
        
    public function __construct($username$password) { 
                
    $this->username $username
                
    $this->passwd $password
        } 

        
    // set .htaccess-style file to check for passwords 
        
    public function setPasswdFile($file) { 
            
    $this->passwdFile $file
        } 

        
    // perform password verification 
        
    public function authenticateUser() { 
            
    // check that the file exists 
            
    if (!file_exists($this->passwdFile)) { 
                throw new 
    FileException("Password file cannot be found: " $this->passwdFile); 
            } 

            
    // check that the file is readable 
            
    if (!is_readable($this->passwdFile)) { 
                throw new 
    FileException("Unable to read password file: "$this->passwdFile); 
            } 

            
    // read file 
            
    $data file($this->passwdFile); 
         
            
    // iterate through file 
            
    foreach ($data as $line) { 
                
    $arr explode(":"$line); 
                
    // if username matches, test password 
                
    if ($arr[0] == $this->username) { 
                    
    // get salt and crypt(), assuming encryption 
                    
    $salt substr($arr[1], 02); 

                    
    // if match, user/pass combination is correct 
                    
    if ($arr[1] == crypt($this->passwd$salt)) { 
                        echo 
    "User was authenticated"
                        
    // do some other stuff 
                    

                    
    // otherwise return exception 
                    
    else { 
                        throw new 
    AuthException("Incorrect password"); 
                        break; 
                    } 
                } 
                else { 
                    
    // could not find a username match 
                    // return exception 
                    
    throw new AuthException("No such user"); 
                } 
            } 
        } 
    // end class definition 

    Und die index.php mit der Klasse arbeitet... sieht dann wie folgt aus:

    PHP-Code:

    require_once("class.userauth.php");

    // subclass exceptions 
    class FileException extends Exception {}; 
    class 
    AuthException extends Exception {}; 

    // try the code 
    try { 
        
    // create instance 
        
    $ua = new userAuth("joe""secret"); 

        
    // set password file 
        
    $ua->setPasswdFile("password.txt"); 

        
    // perform authentication 
        
    $ua->authenticateUser(); 


    // catch authentication failures, if any 
    catch (FileException $e) { 
        
    // print file errors 
        
    print "A file error occurred. ".$e->getMessage(); 

    catch (
    AuthException $e) { 
        
    // an authentication error occurred 
        
    print "An authentication error occurred. ".$e->getMessage(); 
        
    // more normally, redirect to new page on auth errors, e.g. 
        // header ('Location: login_fail.php'); 

    catch (
    Exception $e) { 
        print 
    "An unknown error occurred"

    Ich finde das ganze sehr unübersichtlich und auch irgendwie fehlerprovozierend. Überall, wo ich die Klasse "class.userauth.php" benutzen möchte (wie hier in der index.php) muss ich erst die subclass-exceptions erzeugen:

    // subclass exceptions
    class FileException extends Exception {};
    class AuthException extends Exception {};

    *....ANDERER CODE....*

    Dann muss ich die Klasse "class.userauth.php" analysieren, welche Exceptions alle ausgelöst werden können und diese alle einzeln abfangen:

    catch (FileException $e){
    *....*
    }
    catch (AuthException $e){
    *....*
    }
    catch (Exception $e) {
    *....*
    }

    Da passiert es doch leicht, dass ich mal einen Catch-Block vergesse, eine Sucbclasse nicht anlege o.ä.
    Zudem ist auch nicht gleich erkennbar, welcher Catch-Block jetzt welche Ausnahme behandelt, da diese ja in der Datei "class.userauth.php" ausgelöst werden?
    Mir kommt das sehr umständlich und unübersichtlich vor :-(
    Luxus Magazin
    Luxus Shops

  • #2
    Hi,

    zunächst mal reicht es die exception in einer datei zu definieren.
    Den rest regeln includes. Exceptions sind auch nur klassen.
    Zum zweiten musst du nicht zwingend wissen, von welchem typ
    die exception ist. Du kannst einfach einen catch-block schreiben, der
    als argument die basisklasse erwartet und schon fängst du auch
    alle abgeleiteten klassen.

    PHP-Code:
    class foo_ex extends Exception{}
    class 
    bar_ex extends Exception{}

    try{
              
    //throw new foo_ex('foo');
              
    throw new bar_ex('bar');
    }catch(
    Exception $ex){
       echo 
    $ex->getMessage();

    Weiterhin ist es so dass klassen in höheren layern nicht unbedingt
    etwas von den exceptions die unterhalb fliegen etwas
    mitbekommen müssen. Wenn die klassen darunter mit der
    ausnahme umgehen können und ihr system in einen definierten
    zustand zurück versetzen können, geht das die oberen klassen
    nichts an. (Exceptionsafety)

    Man muss sich auch überlegen, wann eine exception sinnvoll ist.
    Hier sollte man möglichst nah an der semantik bleiben. Es handelt
    sich um ausnahmen, also ereignisse die normalerweise nicht
    vorkommen (dürfen).

    In php ist das so eine sache mit exceptions. Die buildins benutzen
    afaik keine exceptions und so begegnet man ihnen ohnehin nur
    in fremden/eigenen klassen. Ob sie da immer notwendig sind, sei
    mal dahin gestellt. Normalerweise soll dem programmierer
    im catch-block die möglichkeit gegeben werden evtl. allokierte
    resourcen wieder frei zu geben. Da in php am ende eines
    scriptes ohnehin alles freigegeben wird und man selten wirklich
    variablen "unsetten" muss, sind exceptions hier etwas deplaziert.

    greets
    (((call/cc call/cc) (lambda (x) x)) "Scheme just rocks! and Ruby is magic!")

    Kommentar


    • #3
      Danke für die schnelle Antwort :-)

      Irgendwie bin ich von dieser ganzen Exceptions-Sache nicht so wirklich überzeugt und verstehe auch nicht so ganz die Vorteile davon
      Luxus Magazin
      Luxus Shops

      Kommentar


      • #4
        Hi,

        also die vorteile sind in php auch nicht so offensichtlich.

        Code:
        int main(){
             foo *inst= new foo("something");
             try{
                         inst->some_operation_that_may_throw();
        
             }catch(const std::exception &ex){
                  std::cerr<<"Something unexpected happened ...\n";
                  delete inst;   
             }catch(...){
                 std::cerr<<"armageddon has just begun";
                 delete inst;
             }
        }
        Ohne exception-handling, würden bei einer exception aus dem code
        der klasse ein memory-leak entstehen. Da inst nicht frei gegeben
        würde. Nun stelle man sich vor dass die klasse foo in einer dll
        imlementiert ist und man keine möglichkeit hat anders auf
        richtig böse fehler zu reagieren als exceptions zu werfen. Wie
        lösst man das dann ?

        greets
        (((call/cc call/cc) (lambda (x) x)) "Scheme just rocks! and Ruby is magic!")

        Kommentar


        • #5
          Also ist das für Otto-Normal-Fehlerbehandlungen dann eigentlich ein wenig übertrieben mit den Exceptions oder?
          Luxus Magazin
          Luxus Shops

          Kommentar


          • #6
            Hi,

            ja kann man so sehen, exceptions sind wie gesagt wirklich nur
            für ausnahmen gedacht. Wenn man irgendwie anders(besser) mit fehlern
            umgehen kann, dann sollte man das tun.

            Besonders wichtig sind exceptions in php beispielsweise in
            konstruktoren. Da der konstruktor für die aquisition der
            resourcen verantwortlich ist, ist es relativ wahrscheinlich, dass
            fehler passieren können. Als einfaches beispiel sei hier mal
            eine einfach datenbankklasse genannt. Nehmen wir an die
            verbindung zur db soll im ctor hergestellt werden, aber
            die operation schlägt fehl. Wie signalisiert man nun dass
            das objekt nicht erzeugt werden kann ?
            In php4 würde man einfach in jeder methode prüfen ob die klasse
            überhaupt ordnungsgemäß instanziert werden konnte bevor man
            irgendetwas anderes macht. Auch eine zuweisung ala
            PHP-Code:
            $this null
            fällt aus. Da $this seit php5 konstant ist(wie es sich gehört).

            Hier sind exceptions durchaus sinnvoll. Ein ctor hat keinen
            rückgabewert.

            greets
            (((call/cc call/cc) (lambda (x) x)) "Scheme just rocks! and Ruby is magic!")

            Kommentar


            • #7
              Ah, ok, dann ist es also aufgabenbezogen anzuwenden.
              Danke für die Hilfe :-)
              Luxus Magazin
              Luxus Shops

              Kommentar

              Lädt...
              X