Rückgabewert



  • @SeppJ sagte in Rückgabewert:

    1. void foo() throw(runtime_error)

    Ah verdammt, den wollte ich explizit ausschließen. Exceptions nehme ich grundsätzlich nicht für die normale Fehlerbehandlung sondern nur für Ausnahmesituationen.


  • Mod

    @Tyrdal sagte in Rückgabewert:

    Exceptions nehme ich grundsätzlich nicht für die normale Fehlerbehandlung sondern nur für Ausnahmesituationen.

    1. Warum machst du das so?
    2. Wo ist für dich der Unterschied zwischen einem Fehler , der nach außen kommuniziert wird, und einer "Ausnahme"?
    3. Hinterfrag doch mal selber deine Antworten zu 1 und 2, ob die wirklich Sinn machen, oder nur schlechte Angewohnheiten, von denen du dich nicht trennen möchtest.


  • @SeppJ

    1. Ich arbeite hier an an einem riesignen Programm mit ca 60 Entwicklern. Irgendwer verkackt immer die Exception-Sicherheit und niemand fühlt sich für das fangen von Exceptions zuständig. Dazu kommt, dass ich Exceptions halt als Ausnahme ansehe. Die heißen ja nicht Errors.
    2. Fehler sind Dinge, die typischerweise fehschlagen können ohne das irgendwas dramatisch schiefgelaufen ist.
    3. Hab ich und bin mir felsenfest sicher.

  • Mod

    @Tyrdal sagte in Rückgabewert:

    @SeppJ

    1. Ich arbeite hier an an einem riesignen Programm mit ca 60 Entwicklern. Irgendwer verkackt immer die Exception-Sicherheit und niemand fühlt sich für das fangen von Exceptions zuständig. Dazu kommt, dass ich Exceptions halt als Ausnahme ansehe. Die heißen ja nicht Errors.

    Ach, und das manuelle Errorhandling machen die zuverlässig immer richtig? Merkwürdig, dass die den schweren Fall, bei dem man viel falsch machen kann, tadellos hin bekommen, aber nicht den Standardfall aus dem Lehrbuch.

    1. Fehler sind Dinge, die typischerweise fehschlagen können ohne das irgendwas dramatisch schiefgelaufen ist.

    Wieso wird der Fehler dann unbehandelt nach draußen kommuniziert? Kann so harmlos ja wohl nicht gewesen sein.

    1. Hab ich und bin mir felsenfest sicher.

    Das ging aber schnell. Keine 5 Minuten, selbst wenn du meinen Beitrag sofort gelesen hast und sofort nur über Punkt 3 nachgedacht hast. Erstaunlich. Erweckt überhaupt nicht den Eindruck einer vorgefassten, unhinterfragten Meinung.



  • @Tyrdal sagte in Rückgabewert:

    Ich arbeite hier an an einem riesignen Programm mit ca 60 Entwicklern

    Und ihr habt keine einheitliche policy für die Felherbehandlung!?
    Oder ist das nur für dich so als Info?

    Zum Thema: Mein Code wird auch immer Exception lastiger.



  • @Jockelx Ja, haben wir. Exceptions nur in Ausnahmefällen.



  • @SeppJ

    1. Ja, das läuft tatsächlich besser so. Und persönlich empfinde ich Exceptions um Längen komplizierter.
    2. Was meinst du mit unbehandelt nach außen kommuniziert?
    3. Ich hab nicht erst heute darüber nachgedacht

    So und jetzt an alle: Ich habe oben eine vernünftige Frage gestellt. Könnte darauf bitte mal jemand antworten?



  • @Tyrdal sagte in Rückgabewert:

    @manni66 Hab ich irgendwo pair verwendet?

    Vielleicht denkst du noch mal nach ...



  • @manni66 Ich weiß was du meinst, habe aber bewusst tuple verwendet. Die Fragestellung kann man auf mehr als nur Fehlermeldungen beziehen.

    Bitte antwortet auf meine Frage und startet nicht x Metadiskussionen!



  • @Tyrdal sagte in Rückgabewert:

    @manni66 Ich weiß was du meinst, habe aber bewusst tuple verwendet. Die Fragestellung kann man auf mehr als nur Fehlermeldungen beziehen.

    Bitte antwortet auf meine Frage und startet nicht x Metadiskussionen!

    Nein



  • @manni66 Dann halt dich ganz aus dem Thread raus!



  • Du könntest auch sowas hier nehmen: https://github.com/TartanLlama/expected

    Wenn der Fehlerfall ein Fehlerfall ist, der aber durchaus vorkommen darf, finde ich Exceptions auch blöd - insbesondere wenn sie zu Code führen wie:

    bool ok = true;
    string error;
    try {
      attemptXY(some_value);
    } catch (const value_error &e) {
      ok = false;
      error += e.what();
    }
    ...
    if (ok) ...
    


  • @wob Danke, werd ich mir mal ansehen.



  • @SeppJ sagte in Rückgabewert:

    @Tyrdal sagte in Rückgabewert:

    Exceptions nehme ich grundsätzlich nicht für die normale Fehlerbehandlung sondern nur für Ausnahmesituationen.

    1. Warum machst du das so?
    2. Wo ist für dich der Unterschied zwischen einem Fehler , der nach außen kommuniziert wird, und einer "Ausnahme"?
    3. Hinterfrag doch mal selber deine Antworten zu 1 und 2, ob die wirklich Sinn machen, oder nur schlechte Angewohnheiten, von denen du dich nicht trennen möchtest.

    Ich mache es genauso.
    Warum mache ich das so:
    Es gibt "Fehler" und Fehler. Ich habe z.b. ein Modul, das agiert, wenn bestimmte Anforderungen erfüllt sind. Und wenn eine oder mehrere Anforderungen nicht erfüllt sind, sollte das dem Nutzer angezeigt werden. Die Steuerfunktion sieht dann meist so aus:

     {
         auto module_state = canModuleStartActing();
         if ( module_state.Success ) 
         {
            // Aktion kann beginnen
         }
    
         // Status an Client uebermitteln
    }
    
    ModuleStateResult canModuleStartActing() const
    {
        if ( !istBedingung1Erfuellt() )
           return ModuleStateResult( Fehler1 );
        if ( !istBedingung2Erfuellt() )
           return ModuleStateResult( Fehler2 );
        if ( !istBedingung3Erfuellt() )
           return ModuleStateResult( Fehler3 );
        if ( !istBedingung4Erfuellt() )
           return ModuleStateResult( Fehler4 );
       return ModuleStateResult( Success );
    }
    
    

    Das sind in dem Fall keine Fehler in Form einer Systemstörung, sondern einfach Fehler im Ablauf, die eben verhindern, dass das Modul tut, was der Client/Kunde erwartet. Aus jedem Fehler ergibt sich dann auch eine Art ModulStatus.

    Deswegen: keine Exception

    Würde man solche Fälle mit Exceptions erschlagen, wäre der Code voller Exception-Handling wodurch er aus meiner Sicht auch schnell unübersichtlich wird.



  • Edit: Ups! Habe gerade erst gesehen, dass @wob eine Variante von expected<T> bereits erwähnt hat. Nix für ungut, ich lass meine Gedanken dazu dennoch mal hier stehen:

    Ich würde bei dieser Diskussion einfach nochmal gerne Alexandrescu's expected<T> in den Raum werfen. Ein Typ ähnlich wie std::optional<T>, der entweder den erwarteten Wert enthält, oder einen Fehler, der beschreibt, warum der erwartete Wert nicht vorhanden ist (z.B. als gekapselte, jedoch noch nicht geworfene Exception).

    Eine Exception wird von expected<T> erst bei dem Versuch geworfen, auf einen nicht vorhandenen Wert zuzugreifen. Alternativ kann man den Fehler auch wie einen zurückgegebenen Errorcode behandeln.

    Die Flexibilität eines solchen hybriden Ansatzes hat es mir irgendwie schon angetan, da man oft nicht vorher wissen kann, ob ein Fehler in dem Kontext, in dem man die Funktion verwendet, wirklich eine "Ausnahme" oder vielleicht doch eher die Regel ist.

    Nehmen wir mal std::stoi als Beispiel. Diese Funktion wirft im Fehlerfall eine Exception. Wenn ich diese Funktion z.B. beim Parsen einer Konfigurationsdatei verwende, kann man durchaus argumentieren, dass es sich dabei um eine "Ausnahme" handelt. Der Regelfall ist eine syntaktisch korrekte Config, mit der das Programm starten kann.

    Verwende ich die Funktion hingegen in einem Programm, das z.B. wilde, unstrukturierte Daten-Dumps analysiert, kann ein std::stoi-Fehler in diesem Kontext durchaus etwas völlig Erwartetes sein, das sehr häufig auftritt. In diesem Fall wären die Exceptions keine gute Wahl und wirken sich sogar negativ auf die Laufzeit aus - tatsächlich geworfene Exceptions sind ja nicht gerade kostenlos.

    Ansätze wie expected<T> haben das Potenzial in beiden Situationen zu glänzen: Ich bin nicht gezwungen, die Errorcodes zu behandeln oder weiterzureichen und kann mich da auf den Exception-Mechanismus verlassen, aber ich kann es tun - z.B. aus Performancegründen oder weil der Fehler in meinem aktuellen Kontext gut lokal behandelbar ist.


Anmelden zum Antworten