Wann Exceptions anwenden



  • Hallo liebes Forum,

    Ich bin gerade dabei, nach viel Theorie, ein erstes Programm zu schreiben.
    Doch ganz zu Anfang wirft sich mir einer der ersten Fragen auf:
    Soll ich stets Exceptions anwenden oder, wie der Name sagt, nur bei Ausnahmen.

    Konkreter Fall ist z.B eine Benutzereingabe. Die Methode add(string add) einer Klasse, soll etwas hinzufügen. Doch was ist zu tun, wenn der String leer ist.
    Abgesehen von der Möglichkeit direkt bei Eingabe zu überprüfen, gibt es ja zwei Alternative. Entweder überoprüfe ich den string add udn gebe eine Fehlermeldung aus ooder ich werfe eine Exception.

    Die prinzpielle Frage die hinter diesem Beispiel stekct ist folgende:
    Sollte man Exceptions wirklich nur bei Ausnahmen (also eher unwarhrscheinliche Fehler) oder selbst bei solchen Dingen?



  • Wirf Exceptions nur bei wirkliche Ausnahmen. Einerseits bewirken Exceptions oft die Generierung von viel unnötigem Code und andererseits sind Exceptions bei solchen Dingen einfach unpraktisch. Am Ende sieht dein Code so aus

    try { foo.add(bar) } catch(...) { }
    try { foo.add(baz) } catch(empty_string &e) { std::cout << "Eingabe darf nicht leer sein!\n"; }
    try { /*...*/ } catch(...) { }
    // usw
    

    Erfinde für Sprachmittel am besten keine andere Logik, dass verwirrt nur 🙂



  • Exceptions sind das moderne Goto...

    Nur wenn etwas passieren kann, welches du vom Programm her nicht
    unterbinden kannst, sollte man sie imho verwenden.
    Z.b. für Datenbank sachen, oder wenn man eine Verbindung mit Sockets
    aufbaut, halt überall da, wo etwas von ausserhalb deinen Programmfluss
    beeinflussen kann.

    phlox



  • phlox81 schrieb:

    Nur wenn etwas passieren kann, welches du vom Programm her nicht
    unterbinden kannst, sollte man sie imho verwenden.

    Das ist der Punkt. Wenn du eine Klasse schreibst, die eine Textdatei parsed, lass sie eine Exception werfen, wenn die Datei nicht geöffnet werden kann. Wenn du ein Filetransfer-Programm hast, dass die Socket-Verbindung nicht herstellen kann, lass es eine Exception werfen. I/O ist sowieso sehr Exception-verdächtig.

    Benutze Exceptions nicht für logische Fehler wie:

    int foo = bar * 2;
    // Es sollte eigentlich foo immer > 3 sein
    if( foo <= 3 )
        throw MyException();
    

    Bei Parametern gibt es unterschiedliche Ansichten. Grundsätzlich kann man mal sagen, dass bei privaten Methoden die Parameter bestenfalls mit einem assert geprüft werden sollten. Private Methoden kannst nur du aufrufen und daher liegt wohl ein Logikfehler vor, wenn sie falsche Parameter kriegt. Amsonsten prüfe ich Parameter von außen (wenn ich sie prüfe) eher mit Exceptions. Wenn ich eine Bibliothek habe und die irgendjemand mal benutzen wird, der nicht ich ist, dann wird dieser jemand auch irgendwann mal sicher sie falsch benutzen. Es liegt jedoch kein Logikfehler in meiner Bibliothek deswegen vor. Daher benutzen viele Leute Exceptions als Input-Guards und Asserts als Output-Guards, denn was ungültiges zurückgeben ist natürlich wieder deine Schuld.

    Das mit den Exceptions ist also auch so eine Art Schuldfrage. Wenn du nichts für die Umstände kannst, dann wirf eine Exception, denn es ist nicht ein Fehler in deinem Code, den du irgendwie verbessern könntest.

    Dann noch ein Wort zum C++ - assert. Du solltest dir überlegen, dein eigenes zu schreiben, welches auch nur in deinem Debug-Build aktiv ist, dort aber dann auch eine Exception wirft, diesmal aus technischen Gründen. Beim Standard-assert werden keine lokalen Variablen mehr destruiert und das ist böse.



  • Was meinst du mit 'assert'?



  • Ich würd nen assert empfehlen, dass nen Breakpoint setzt, oder nen stacktrace macht.
    Kann ganz nützlich sein, wenn man rausfinden will wieso der Wert nun nicht stimmt und nicht nur, dass er nicht stimmt.



  • otom schrieb:

    Was meinst du mit 'assert'?

    Assert ist eine Funktion, mit der man die Korrektheit seines Programms sicherstellen kann. Wenn du beispielsweise denkst, dass foo immer kleiner als 5 sein müsste, dann schreibst du hin:

    #include <cassert>
    
    ...
    
    assert(foo < 5);
    

    und bekommst eine Fehlermeldung, falls das mal nicht der Fall sein sollte.



  • otom schrieb:

    Hallo liebes Forum,

    hallo, lieber otom.

    Soll ich stets Exceptions anwenden oder, wie der Name sagt, nur bei Ausnahmen.

    gute frage. wir sind alle der meinung, nur bei ausnahmen. aber was sind ausnahmen? bei dem einen ist ein dateiende eine ausnahme und bei dem anderen nicht.

    Abgesehen von der Möglichkeit direkt bei Eingabe zu überprüfen, gibt es ja zwei Alternative. Entweder überoprüfe ich den string add udn gebe eine Fehlermeldung aus ooder ich werfe eine Exception.

    genau. bei eingabe ist zu prüfen. und später kannste asserten, denn wenn später der sting leer ist, war's bei der eingabeprüfung ein programmierfehler.

    Die prinzpielle Frage die hinter diesem Beispiel stekct ist folgende:
    Sollte man Exceptions wirklich nur bei Ausnahmen (also eher unwarhrscheinliche Fehler) oder selbst bei solchen Dingen?

    wenn ich jetzt zeit für sowas hätte, konnte ich 50 seiten drüber schreiben. aber mit unklarem ergebnis. wir sind uns erstmal einig, daß der benutzer geprüft und gezwungen wird. ist beim taschenrechner die 0 im display, dann ist zugleich dir geteilt-taste disabled. muss halt sein. ist für den anwender netter und für den coder auch. also keine exception, weil gar nicht möglich. aber den dateinamen, den er eintippt, oder der in einem ini-file steht, den prüft man nicht mit if(FileÉxists, sondern läßt den rechner voll in die exception rauschen. ist im normalfall schneller und ist auch einfacher. und da ich keinen echt wichtigen unterschied zuwischen den breiden fällen sehe, postuliere ich, daß die exception-frage eine mal-so-mal-so-frage ist.


Anmelden zum Antworten