Exception oder nullptr?



  • dot schrieb:

    Dann bau dir ein assert() dass eine Exception wirft?
    Wenn dein Programmdesign vom Testsystem bestimmt wird, dann ist das Testsystem Mist oder du verwendest es falsch, wenn du mich fragst.

    Könnte es nicht auch ein Hinweis darauf sein, dass das Design kein anständiges Testen zulässt? Ich schreibe zuerst Unittests, bevor ich den Produktiv-Code schreibe, und dort möchte ich halt auch Fehler provozieren, wo sie auftauchen sollen.

    Du brauchst auch nicht testen, was passiert, wenn man falsch programmiert.

    Ich denke schon, dass das sinnvoll ist. Ich möchte ja z.B. durch einen Testfall sicherstellen, dass eine Funktion bei falschen Werten fehlerhaft reagiert. Das wäre vergleichbar damit, als würde man nur testen, ob 15 / 5 = 3, aber nicht ob 15 / 0 = Fehler.

    Dass etwas bei anständigen Werten funktioniert, ist ja nur die halbe Miete. Oder aber ich mache es tatsächlich falsch, bin noch recht frisch beim test-driven development.



  • sboc schrieb:

    dot schrieb:

    Dann bau dir ein assert() dass eine Exception wirft?
    Wenn dein Programmdesign vom Testsystem bestimmt wird, dann ist das Testsystem Mist oder du verwendest es falsch, wenn du mich fragst.

    Könnte es nicht auch ein Hinweis darauf sein, dass das Design kein anständiges Testen zulässt? Ich schreibe zuerst Unittests, bevor ich den Produktiv-Code schreibe, und dort möchte ich halt auch Fehler provozieren, wo sie auftauchen sollen.

    Wenn du mich fragst soll das Testsystem sich dem Programm anpassen und nicht umgekehrt. Denn ich schreib das Programm ja nicht damit ich was zu testen hab, sondern aus anderen Gründen...
    Im konkreten Fall würd ich mal ganz definitiv sagen, dass mit Testsystem grob was im argen liegt, wenn es so grundlegende Entscheidungen wie das Verhalten einer Containerklasse beeinflusst oO



  • dot schrieb:

    Wenn du mich fragst soll das Testsystem sich dem Programm anpassen und nicht umgekehrt. Denn ich schreib das Programm ja nicht damit ich was zu testen hab, sondern aus anderen Gründen...

    Mit den Tests möchte ich auch nur sicherstellen, dass die Klasse sich genau so verhält wie gedacht. Das heißt, wenn ich die Tests schreibe, überlege ich, welche Fehler ich bei falschen Eingaben erwarte (neben den viel wichtigeren Erwartungen, was korrekterweise herauskommen soll, natürlich). Erst danach implementiere ich die Klasse nach diesem Schema.

    Im konkreten Fall würd ich mal ganz definitiv sagen, dass mit Testsystem grob was im argen liegt, wenn es so grundlegende Entscheidungen wie das Verhalten einer Containerklasse beeinflusst oO

    Ich weiß nicht genau, was du mit Beeinflussen meinst. Die Tests geben in meinem Fall das Design vor, da die Klasse so funktionieren soll wie die Tests sie nutzen (TDD, falls noch nicht bekannt).



  • sboc schrieb:

    dot schrieb:

    Wenn du mich fragst soll das Testsystem sich dem Programm anpassen und nicht umgekehrt. Denn ich schreib das Programm ja nicht damit ich was zu testen hab, sondern aus anderen Gründen...

    Mit den Tests möchte ich auch nur sicherstellen, dass die Klasse sich genau so verhält wie gedacht. Das heißt, wenn ich die Tests schreibe, überlege ich, welche Fehler ich bei falschen Eingaben erwarte (neben den viel wichtigeren Erwartungen, was korrekterweise herauskommen soll, natürlich). Erst danach implementiere ich die Klasse nach diesem Schema.

    Kann die Testumgebung denn nicht erwarten und testen, daß bei einem falschen Index ein assert zündet?
    Das wäre doch ok, dann könntest Du, wie es sich gehört, Programmierfehler mit assert begrenzen.



  • cooky451 schrieb:

    Shade Of Mine schrieb:

    Das Flag ist halt furchtbar, weil man nie weiss was jetzt passiert.

    Kannst du mir dafür mal ein Beispiel nennen?

    Klar:

    void foo(Klasse& obj) {
       obj.bar();
    }
    
    int main() {
       Klasse a;
       a.enable_exceptions(true);
       foo(a);
    
       Klasse b;
       b.enable_exceptions(false);
       foo(b);
    }
    

    Wie soll foo jetzt wissen wie es auf einen Fehler bei bar() reagieren soll? Jedesmal checken ob Exceptions aktiviert sind? Und wenn Exceptions aktiviert sind, wie ist dann isGood() oder failed() etc. definiert wenn eine Exception fliegt? Wird immer das fail bit immer gesetzt? Was wenn ich zwischen einem Fehler umschalte?

    Enorme Komplexität für keinen Mehrwert. Wenn du einfach sagst bar() wirft eine Exception, dann ist alles klar. Keine Probleme, keine Unsicherheit - auch robuster Code.

    Denn Stell dir vor du hast Unit Tests mit eingeschaltenen Exceptions und dann im Produktionscode werden sie irgendwo ausgeschalten. uU nur bei einem Objekt. Das führt zu unfindbaren Fehlern.

    Deshalb ist es ganz wichtig: ein Weg! Eine Art Fehler zu reporten. Nicht 2. Nicht 3. Nur eine Art. Weil sonst werden die anderen irgendwann/irgendwo einmal übersehen.



  • volkard schrieb:

    Kann die Testumgebung denn nicht erwarten und testen, daß bei einem falschen Index ein assert zündet?
    Das wäre doch ok, dann könntest Du, wie es sich gehört, Programmierfehler mit assert begrenzen.

    Hast Du völlig Recht, aber soweit ich weiß, bietet zumindest Boost.Test das nicht an (es gibt einen Weg über einen Hack, aber das ist immer so eine Sache..). Vielleicht schaue ich mich mal bei anderen Frameworks um, wie die das unterstützen.



  • cooky451 schrieb:

    bool set( std::size_t index, const Foo& value, bool throw_exception = false );
    const Foo* get( std::size_t index, bool throw_exception = false ) const;
    bool create( std::size_t index, bool throw_exception = false );
    

    Wenn die Klasse eh nur in einem größeren Kontext Sinn macht, in dem Exceptions auf höherer Ebene gefangen werden (z.B. in einem Spiel), dann kannst du auch gleich Variante 1 nehmen. Ansonsten weißt du nicht wie der "Nutzer" der Klasse diese Funktionen nutzen möchte, warum also nicht ihm die Wahl überlassen?

    Also abgesehen davon dass ich da beim hinschauen Kopfweh bekomm, widerspricht das doch rein prinzipiell komplett dem Sinn von Exceptions!?
    Der war doch eben genau dass man die Exception auf irgendeiner Ebene fangen kann und nicht immer direkt eine Ebene drüber behandeln muss. Mit deinem Parameter zwingst du aber erst wieder sämtliche Ebenen dazu, sich mit Exceptions zu befassen, nur halt von der anderen Richtung aus...



  • Du testest falsch. Wenn du z.B. den Zugriff aus Performancegründen so implementieren willst, dass die Gültigkeit von Parametern nicht überprüft wird, dann schreibts du in die Doku, dass falscher Zugriff zu undefiniertem Verhalten führt. Undefiniertes Verhalten brauchst du auch nicht testen. Wenn falsche Parameter zu einer Exception führen, dann schreibst du das in die Doku und testest es auch. Aber mach nicht überall Exceptions rein, nur damit du was zum Testen hast, sondern nur dann Exceptions verwenden, wenn es sinnvoll ist.



  • PS: Ging an sboc, niccht dot.



  • Smilies in diesem Beitrag schrieb:

    Du testest falsch. Wenn du z.B. den Zugriff aus Performancegründen so implementieren willst, dass die Gültigkeit von Parametern nicht überprüft wird, dann schreibts du in die Doku, dass falscher Zugriff zu undefiniertem Verhalten führt. Undefiniertes Verhalten brauchst du auch nicht testen. Wenn falsche Parameter zu einer Exception führen, dann schreibst du das in die Doku und testest es auch. Aber mach nicht überall Exceptions rein, nur damit du was zum Testen hast, sondern nur dann Exceptions verwenden, wenn es sinnvoll ist.

    Interessant! Also wäre das ein klarer Fall für assert() und kein Unittest für den Fall, richtig?


Anmelden zum Antworten