Strings in Exceptions



  • Simon2 schrieb:

    Kannst Deine "Entscheider" ja mal hier vorbeischicken.

    *hehe* Wenn ich bei Problemen vorschlage (was ich manchmal tue) mal im Internet und in Foren wie dieses hier nachzusehen oder mal nachzufragen, dann ist die Antwort:

    "Das sind nur Freaks! Machen immer aus einer Mücke einen Elefanten und schießen mit Kanonen auf Spatzen! Das geht alles viel einfacher und unkomplizierter! Wir schauen nochmal in der (mitgelieferten!) MSDN nach (zum 1000x und finden wieder keine Lösung)!" (zwar kein O-Ton, aber der Inhalt stimmt wirklich!)

    Aber genug Off-Topic...

    @Dravere: So sehe ich das eigentlich auch, und wollte den Index eben haben, um (später) den Fehler zu beschreiben (loggen). Nur wusste ich nicht, ob es sinnig ist, für jeden Parametertyp eine eigene Exception-Klasse abzuleiten.

    Ihr erkennt aufgrund Eurer Erfahrung viel schneller, wenn irgendwas in Richtung Design-Fehler läuft, daher fragte ich.



  • pumuckl schrieb:

    @RogerWilco, da hilfts nur eins: Informier dich, bilde dich weiter und sei gut in dem was du tust, und zwar so dass die Schlipsträger irgendwann schnallen dass du davon mehr Ahnung hast als sie.

    Mit dieser Aussage wäre ich vorsichtig. Gerade wenn diese eingestaubten Meinungen zur Programmierung herrschen. Manchmal ist es in so einer Firma sinnvoller sich weiterzubilden und dann eine andere Firma zu suchen (Wenn Leistungen und Fähigkeiten nicht in irgendeiner Weise gewürdigt werden [das muss nicht zwangsweise Geld sein], braucht eine Firma einen auch nicht).

    cu André


  • Administrator

    Roger Wilco schrieb:

    @Dravere: So sehe ich das eigentlich auch, und wollte den Index eben haben, um (später) den Fehler zu beschreiben (loggen). Nur wusste ich nicht, ob es sinnig ist, für jeden Parametertyp eine eigene Exception-Klasse abzuleiten.

    Was ist ein Parametertyp? Wie sieht das Design aus? Es ist ziemlich schwer hier zu sagen, ob man mehrere Klassen erstellen sollte oder nicht.
    Im allgemeinen sagt man aber, nicht zu viel und nicht zu wenig 😉
    Oft kann man viele Informationen als Variablen in eine Exception packen. Sagt zum Beispiel der Index nicht schon etwas über den Parametertyp aus? Wie kann man einen Parametertyp bezeichnen? Womöglich ein zusätzliches Stringliteral? Und die wichtige Frage: Ist es überhaupt wichtig zu wissen, welcher Parametertyp es war?

    Bemerkung am Rande: Unterschätzt niemals Freaks! 😃

    Grüssli



  • Roger Wilco schrieb:

    Wobei diese Exceptions den std::string einfach kopieren und als private Member mitführen. Zumindest in der stdexcept meiner IDE (Visual C++ 6 *bäh*).

    VC6 verwendet AFAIK COW für std::string. Was zwar grundsätzlich schlecht ist, aber es ermöglicht, no-throw Kopien von Strings zu machen. Sogesehen ist das bei MSVC 6 auch kein Problem.
    Und ab 7.1/8 (die kein COW mehr für std::string verwenden) sind die Exception Klassen dann auch anders implementiert.



  • Dravere schrieb:

    Was ist ein Parametertyp? Wie sieht das Design aus?

    Mein "ConfigReader" ist eine Fabrik, die mir unterschiedliche Objekte liefert, die Daten aus einer Config-Datei oder Registry benötigen.

    Vereinfachtes Beispiel, das dem Prinzip aber entspricht:

    Parameter "LKW" (mit Bierkisten): Klasse LKW, Klasse Bierkasten, Klasse Bierflasche.

    config.ini:
    [LKW_1]
    AnzahlBierkisten=3
    FlaschenInBierkiste_1= 12 // Bin kein Biertrinker, was gibt es da für Größen?
    FlaschenInBierkiste_2= 24
    FlaschenInBierkiste_3= &  // *Ups* da hat sich wohl einer vertippt...
    Biersorte=Lieblingsbier
    [LKW_2]
    ...
    

    Innerhalb der Fabrik, werden die einzelnen Parameter-Objekte über Fabrikmethoden geladen. Ich möchte nun in meiner Fehlerbeschreibung stehen haben:

    ... ERROR: Konfigurationsfehler: LKW 1: Viel zu wenig Bier geladen!

    Ach Quatsch...

    ... ERROR: Konfigurationsfehler: LKW 1/Bierkiste 3/Anzahl Bierflaschen: Parameter nicht vorhanden oder fehlerhaft!

    So in der Art...

    Dravere schrieb:

    Unterschätzt niemals Freaks! 😃

    🙂 ICH tue das bestimmt nicht! Verstehe noch lange nicht alles hier im Forum und habe schon viel (mehr wie im Studium, würde ich behaupten) über sinniges C++ Programmieren gelernt! Vielen Dank an dieser Stelle für die ausgezeichnete Unterstützung! 👍


  • Administrator

    Mal deine Fehlermeldung auseinandernehmen:

    ... ERROR: Konfigurationsfehler: LKW 1/Bierkiste 3/Anzahl Bierflaschen: Parameter nicht vorhanden oder fehlerhaft!
    |              1                |  2  |     3     |                      4                                       |
    
    • Teil 1: Das kann der Fänger dazufügen.
    • Teil 2: int lkw -> könnte man über eine Variable lösen.
    • Teil 3: int bierkiste -> könnte man über eine Variable lösen.
    • Teil 4: Title/Betreff, also durch ein Stringliteral lösbar. Könnte man vielleicht noch weiter unterteilen.

    Das ist vielleicht möglich, hängt alles von deinem Code ab und was du alles genau wie rausparst.
    Allerdings würde ich die Sache sowieso ein wenig anders anpacken. Das Configfile muss einer bestimmten Grammatik folgen, nehme ich an. Ich würde daher eher das ganze auseinander nehmen, um es danach besser bearbeiten oder lesen zu können und dabei die Grammatik prüfen. Somit dann eher einen Gramatikfehler werfen mit Zeilen- und Zeichennummer.
    Wenn die Grammatik stimmt und das File entsprechend zerlegt wurde, dann kannst du anfangen die Konfiguration auf deine Klassen zu übertragen.

    Ist auch alles ein wenig relativ und kommt ganz auf den entsprechenden Fall an 🙂
    Und ich will hier jetzt auch nicht völlig gegen std::string in einer Exception sein, man sollte halt nur bei der Verwendung von std::string aufpassen, dass man die Fehlerbeschreibung nicht am falschen Ort generiert, also dass die Aufgaben korrekt getrennt sind. Das ein std::string eine Exception wirft, ist ziemlich unwahrscheinlich und wenn, dann ist es meistens "egal", wie hier schon mehrfach gesagt wurde.

    Grüssli



  • Dravere schrieb:

    Ich würde daher eher das ganze auseinander nehmen, um es danach besser bearbeiten oder lesen zu können und dabei die Grammatik prüfen. Somit dann eher einen Gramatikfehler werfen mit Zeilen- und Zeichennummer.
    Wenn die Grammatik stimmt und das File entsprechend zerlegt wurde, dann kannst du anfangen die Konfiguration auf deine Klassen zu übertragen.

    Könntest Du mir das etwas genauer erklären, wie Du das meinst?

    So dachte ich (würde dann vielleicht 4 verschiedene Exceptionklassen ergeben):

    Lkw Config::GetLkw(unsigned int lkwIndex){
    
       std::vector<Bierkiste> bierkisten;
       unsigned int anzahlBierkisten = GetConfigInt(LkwSection(lkwIndex), bierkistenAnzahlKey()); // -1 on Error
       if(anzahlBierkisten < 0){
           throw LkwConfigError(lkwIndex, "Anzahl Bierkisten");
       }
    
       for(unsigned int i = 0; i < anzahlBierkisten, ++i){
          bierkisten.push_back( GetBierkiste(lkwIndex, i) );
       }
    
       unsigned int ps = GetConfigInt(lkwSection(lkwIndex), psKey()); // -1 on Error
       if(ps < 0){
          throw LkwConfigError(lkwIndex, "PS");
       }
       return Lkw(bierkisten, ps);
    }
    
    Bierkiste Config::GetBierkiste(unsigned int lkwIndex, unsigned int bierkistenIndex){
    
        int anzahlFlaschen = GetConfigInt(lkwSection(lkwIndex), bierkistenKey(bierkistenIndex)); // -1 on Error
       if(anzahlFlaschen < 0){
           throw BierkistenConfigError(lkwIndex, bierkistenIndex, "Flaschenanzahl");
       }
    
       std::wstring bierSorte = GetconfigString(lkwSection(lkwIndex), bierSortenKey());
       if(bierSorte.empty()){
           throw BierkistenConfigError(lkwindex,lkwIndex, bierkistenIndex, "Flaschenanzahl");
       }
       return Bierkiste(anzahlFlaschen, bierSorte);
    }
    

  • Administrator

    Roger Wilco schrieb:

    Dravere schrieb:

    Ich würde daher eher das ganze auseinander nehmen, um es danach besser bearbeiten oder lesen zu können und dabei die Grammatik prüfen. Somit dann eher einen Gramatikfehler werfen mit Zeilen- und Zeichennummer.
    Wenn die Grammatik stimmt und das File entsprechend zerlegt wurde, dann kannst du anfangen die Konfiguration auf deine Klassen zu übertragen.

    Könntest Du mir das etwas genauer erklären, wie Du das meinst?

    Was willst du genauer erklärt haben? Grundsätzlich meine ich damit nur, dass dur dir einen Parser schreiben sollst, welcher die Grammatik prüft. Für ein *.ini File ist das ziemlich schnell erledigt und immer wieder verwendbar. Wenn du nicht weisst, was ich hier mit Grammatik oder Parser meine, dann müsstest du dich halt zuerst ein wenig in der Bereich von Parser einlesen. Ist ein Teil der theoretischen Informatik, falls du Lesestoff suchst, dann also gleich ein Buch über theoretische Informatik 😉

    Mal schauen, Wikipedia hat dazu:
    http://de.wikipedia.org/wiki/Parser
    http://de.wikipedia.org/wiki/Formale_Grammatik

    (Gott, wenn ich nur den Wikipedia Artikel der formalen Grammatik lese, dann kommt mir die ganze theoretische Informatik Vorlesung wieder hoch. War das vielleicht trocken ... :D)

    Roger Wilco schrieb:

    So dachte ich (würde dann vielleicht 4 verschiedene Exceptionklassen ergeben):

    Mach eine draus: ConfigError.
    Dann setzt du nur die Werte, welche auch benötigt werden. Die anderen werden mit einem ungültigen Defaultwert besetzt. Dann kannst du der Klasse noch Methoden schencken wie: isLkwConfigError . Anhand der Defaultwerte kann das ermittelt werden. Wäre zumindest eine Idee, um überflüssige Klassen zu eliminieren.
    Du könntest natürlich auch ein Template machen. Der Templateparameter erwartet eine Struktur, welche zusätzliche Werte hat.
    Also:

    struct LkwError
    {
      int lkwIndex;
    };
    
    struct BierkastenError
    {
      int lkwIndex;
      int bierkasten;
    };
    
    // ...
    
    LkwError err = { index };
    throw ConfigError<LkwError>(err, "bliblablub");
    
    // ...
    
    BierkastenError err = { lkwIndex, bier };
    throw ConfigError<BierkastenError>(err, "blubber");
    

    Gibt viele Möglichkeiten, wie man sich das Leben leichter machen kann 🙂

    Grüssli


Anmelden zum Antworten